Home > OS >  How to make environment variables available at container build-time & runtime in docker?
How to make environment variables available at container build-time & runtime in docker?

Time:11-12

I am working on a nextjs docker project trying to pass my environment variables to be accessed at container build time and run time. I basically referred to Nextjs's template Dockerfile and passed my required env vars both as build args and environment in my docker-compose.yml as such

version: "3.7"
services:
  app:
    container_name: frontend
    build: 
      context: .
      args:
        - API_URL=http://path-to-my-external-api-url
        - NEXT_PUBLIC_CLIENT_API_URL=http://path-to-my-external-api-url
    environment:
      - NODE_ENV=production
      - API_URL=http://path-to-my-external-api-url
      - NEXT_PUBLIC_CLIENT_API_URL=http://path-to-my-external-api-url
    ports:
      - "3000:3000"
  nginx:
    depends_on: 
      - app
    container_name: frontend-nginx
    build: ./nginx
    ports:
      - "8080:8080"

Then I access these env vars in my Dockerfile like

...
FROM node:14-alpine AS builder
WORKDIR /app
COPY ./app .
COPY --from=deps /app/node_modules ./node_modules
ARG API_URL
ARG NEXT_PUBLIC_CLIENT_API_URL
ENV API_URL=${API_URL}
ENV NEXT_PUBLIC_CLIENT_API_URL=${NEXT_PUBLIC_CLIENT_API_URL}
RUN npm run build
...

Then the app is built in gitlab pipeline which fails at the build stage defined below

...
Build and Push App:
  image: docker:19.03.5
  services:
    - docker:19.03.5-dind
  stage: Build and Push
  script:
    - apk add python3
    - pip3 install awscli
    - docker build --compress -t $ECR_REPO:$CI_COMMIT_SHORT_SHA .
    - $(aws ecr get-login --no-include-email --region ap-south-1)
    - docker push $ECR_REPO:$CI_COMMIT_SHORT_SHA
    - docker tag $ECR_REPO:$CI_COMMIT_SHORT_SHA $ECR_REPO:latest
    - docker push $ECR_REPO:latest
  rules:
    - if: '$CI_COMMIT_BRANCH =~ /^(main|production)$/'
...

I was able to build and run my container locally. But it fails during the above gitlab ci pipeline stage with Error: connect ECONNREFUSED 127.0.0.1:80 at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:16) which I assume is related to inability to load these environment variables.

How do I fix this? Is is needed to even pass the variables as args and environment twice in the docker-compose file (I did this because I found that only when passing them both as args and environment works in building my container locally).

This is my first time working with ci/cd and docker and any corrections to my code or suggestions to optimize it is much appreciated. Thanks for you time.

EDIT: Fix hyperlink error

CodePudding user response:

In the Dockerfile you posted the args are declared, however, you do not load them at build time on the docker build command with the --build-arg flag, on a command similar to this:

 docker build --compress -t $ECR_REPO:$CI_COMMIT_SHORT_SHA --build-arg API_URL=<url> NEXT_PUBLIC_CLIENT_API_URL=<url> .  

Reference: https://docs.docker.com/engine/reference/commandline/build/#options

  • Related