Docker-compose variable is not passed into a production vue app

Viewed 4556

Docker-compose environment variables don't seem to be set at all. I have tried using env_file and environment fields but when printing process.env in my vue app the only visible variables are NODE_ENV and BASE_URL

Here is my docker-compose code:

    frontend:
    container_name: "Frontend"
    build:
        context: .
        dockerfile: frontend.dockerfile
    env_file:
        - ./frontend.env
    environment: 
        VUE_APP_BACKEND_URL: "django"
    ports: 
        - 8000:80
    command: echo $VUE_APP_BACKEND_URL

Frontend Dockerfile:

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY ./front/package*.json ./
RUN npm install
COPY ./front .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

My frontend.env code (This was added as I was trying to debug the problem):

VUE_APP_BACKEND_URL=django
VUE_APP_BACKEND_PORT=9000

Here is my js code

export function getEnvironmentVar(key,defaultVal){
  window.console.log(process.env)
  window.console.log(process.env.VUE_APP_BACKEND_URL)
  var result = process.env[`VUE_APP_${key}`];
  window.console.log(`Trying to read environment variable: ${key}, got: ${result}`)
  if(result!= undefined)
    return result
  else 
    return defaultVal
}

The output:

{NODE_ENV: "production", BASE_URL: "/"}
NODE_ENV: "production"
BASE_URL: "/"
__proto__: Object

This is the output with the command line in docker-compose added:

WARNING: The VUE_APP_BACKEND_URL variable is not set. Defaulting to a blank string.
Starting Frontend ... done
Attaching to Frontend
Frontend              | 
Frontend exited with code 0

What am I doing wrong?

2 Answers

The environment variables you are setting are applied to the runtime environment of the container, and not to the container at build time. Since your web app is built and served statically the environment variables will not be available on the frontend as they were not set when the app was built.

To make the environment variables visible to vue-cli when it builds your app, you need to use build arguments in your Dockerfile. You can then set an environment variable in your build stage with the same value as the build argument, before you run npm run build.

frontend.dockerfile

# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
ARG VUE_APP_BACKEND_URL                       # <-- these two lines have
ENV VUE_APP_BACKEND_URL=$VUE_APP_BACKEND_URL  #      been added
COPY ./front/package*.json ./
RUN npm install
COPY ./front .
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

docker-compose.yml

services:
  frontend:
    container_name: "Frontend"
      build:
        context: .
        dockerfile: frontend.dockerfile
        args:
          - VUE_APP_BACKEND_URL=django
    ports: 
      - 8000:80

Since VUE_APP_BACKEND_URL is being set before npm run build is executed, the environment variables will be embedded in your built app.

Sources:

You can try the dotenv package

npm i dotenv

Add to the top of the file

require('dotenv').config()
Related