2

I've tried passing NODE_ENV as an argument

ARG NODE_ENV
ENV NODE_ENV=${NODE_ENV}

I tried passing it as an environment variable on my docker-compose.yaml

services:
  app:
    build:
      context: .
      args:
        - NODE_ENV=development
    environment:
      - PORT=3000
      - NODE_ENV=development

Nothing works, inside my program, its value is "production"

My Dockerfile is based on node:18-slim, there is nothing special on it.

Complete example

Dockerfile

FROM node:18-slim AS base

FROM base AS build
WORKDIR /opt
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
RUN npm run prisma:generate

FROM base
WORKDIR /app
RUN apt-get update && \
  apt-get install --yes --no-install-recommends gettext-base supervisor nginx
COPY nginx.conf /etc/nginx/conf.d/configfile.template
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY --from=build /opt/node_modules node_modules
COPY --from=build /opt/dist .

ARG NODE_ENV
ENV NODE_ENV ${NODE_ENV}

ARG PORT=3000
ENV PORT $PORT
EXPOSE $PORT

CMD ["/usr/bin/supervisord"]

docker-compose.yaml

services:
  app:
    build:
      context: .
      args:
        NODE_ENV: ${NODE_ENV:-development}
    environment:
      - PORT=3000
      - DATABASE_URL=postgresql://docker:docker@postgres:5432/oidc?schema=public
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    ports:
      - 3000:3000
    depends_on:
      redis:
        condition: service_healthy
      postgres:
        condition: service_healthy
  redis:
    image: redis:7
    tmpfs:
      - /data
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      interval: 1s
      timeout: 5s
      start_period: 5s
      retries: 3
  postgres:
    image: postgres:14.3
    tmpfs:
      - /var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready --dbname $$POSTGRES_DB --username $$POSTGRES_USER"]
      interval: 1s
      timeout: 5s
      start_period: 5s
      retries: 3
    environment:
      POSTGRES_HOST: postgres
      POSTGRES_PORT: 5432
      POSTGRES_USER: docker
      POSTGRES_PASSWORD: docker
      POSTGRES_DB: oidc

If I build without docker compose, it works.

docker compose version
Docker Compose version v2.15.1

docker-compose --version
Docker Compose version v2.15.1

docker version

Client:
 Cloud integration: v1.0.31
 Version:           20.10.23
 API version:       1.41
 Go version:        go1.18.10
 Git commit:        7155243
 Built:             Thu Jan 19 17:35:19 2023
 OS/Arch:           darwin/arm64
 Context:           default
 Experimental:      true

Server: Docker Desktop 4.17.0 (99724)
 Engine:
  Version:          22.06.0-beta.0-926-g914b02ebaf.m
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.18.4
  Git commit:       914b02ebaf
  Built:            Thu Feb  9 12:31:06 2023
  OS/Arch:          linux/arm64
  Experimental:     true
 containerd:
  Version:          1.6.18
  GitCommit:        2456e983eb9e37e47538f59ea18f2043c9a73640
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

I read somewhere else, that docker-compose never overwrites the environment variables from the base image. Is it because of that? My base image is a node

What I'm doing wrong?

Rodrigo
  • 135
  • 4
  • 45
  • 107
  • 2
    Is that `DOCKER_ENV` there on purpose? How are you checking the value in your program? – AKX Apr 03 '23 at 09:04
  • Sorry. I've updated the question, it is NODE_ENV – Rodrigo Apr 03 '23 at 09:05
  • Again, how are you checking the value in your program? Can you reproduce this if you change the command you're running in the container to `node -e 'console.log(process.env.NODE_ENV)'`? – AKX Apr 03 '23 at 09:25
  • Do you have a more complete example showing what happens in this Dockerfile? (Is a multi-stage build involved?) – David Maze Apr 03 '23 at 09:43
  • I've updated it. I read somewhere else that docker-compose never overwrites the environment variables from the base image. Is it because of that? My base image is a node – Rodrigo Apr 03 '23 at 09:49
  • @AKX the output is production, no matter which value I put on it – Rodrigo Apr 03 '23 at 09:51
  • What commands are you running to boot those containers? – β.εηοιτ.βε Apr 03 '23 at 09:56
  • I'm using the supervisor, because it is a sidecar container – Rodrigo Apr 03 '23 at 10:11
  • You mention in your question that when running the app just with docker it is working properly, with the same `Dockerfile`? Please, could you include in your question information about your `nginx` and `supervisor` configuration files? – jccampanero Apr 06 '23 at 15:21
  • @jccampanero nginx or supervisor is irrelevant here. They don't make use of any env. variable, what matter is what I get on `RUN printenv` inside Docker – Rodrigo Apr 10 '23 at 12:26
  • Thank you for the feedback @Rodrigo. I asked because I think that the provided `Dockerfile` shouldn't work neither. Does it work as presented in the question? Please, where do you run `printenv`? Can you update your `Dockerfile` with that information? – jccampanero Apr 10 '23 at 15:56

2 Answers2

1

I think the problem could be related, not to docker-compose, but actually to the way the application is being deployed.

In the first stage of your Dockerfile you are building your node or SPA application.

In the next stage you are exposing the result of that build (by the way, probably you can safely don't copy the node_modules directory to the final image) through nginx and supervisor. But please, be aware that neither nginx nor supervisor have knowledge about the NODE_ENV variable: that variable is only managed at runtime when the application is served with node, not nginx(sorry if I am missing something at this point, this is why I asked you about the nginx and supervisor configuration, I am not aware if in any way you are proxying node, I hope you get the point).

In order to make this variable visible to the application you probably will need to tweak the build process, or trying providing a helper script. Please, consider read for instance this or this other related SO questions, or this great post for further reference.

jccampanero
  • 50,989
  • 3
  • 20
  • 49
0

See this answer docker-compose build environment variable

Are you setting the variable in your docker file? Something like:

ARG NODE_ENV
ENV NODE_ENV $NODE_ENV
silviup
  • 56
  • 4
  • Is your build expecting the node_env variable be set? Did you try move the variable definition before run build in your Dockerfile. See the accepted answer in the link I posted. – silviup Apr 03 '23 at 10:08
  • Yes. We have conditionals for when it is running in dev or prod – Rodrigo Apr 03 '23 at 10:10