Best practices for adding .env-File to Docker-Image during build in Gitlab CI

4/21/2020

I have a node.js Project which I run as Docker-Container in different environments (local, stage, production) and therefor configure it via .env-Files. As always advised I don't store the .env-Files in my remote repository which is Gitlab. My production- and stage-systems are run as kubernetes cluster.

What I want to achieve is an automated build via Gitlab's CI for different environments (e.g. stage) depending on the commit-branch (named stage as well), meaning when I push to origin/stage I want an Docker-image to be built for my stage-environment with the corresponding .env-File in it.

On my local machine it's pretty simple, since I have all the different .env-Files in the root-Folder of my app I just use this in my Dockerfile

COPY .env-stage ./.env

and everything is fine.

Since I don't store the .env-Files in my remote repo, this approach doesn't work, so I used Gitlab CI Variables and created a variable named DOTENV_STAGE of type file with the contents of my local .env-stage file.

Now my problem is: How do I get that content as .env-File inside the docker image that is going to be built by gitlab since that file is not yet a file in my repo but a variable instead?

I tried using cp (see below, also in the before_script-section) to just copy the file to an .env-File during the build process, but that obviously doesn't work.

My current build stage looks like this:

image: docker:git

services:
  - docker:dind

build stage:
  only:
    - stage
  stage: build
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - cp $DOTENV_STAGE .env
    - docker pull $GITLAB_IMAGE_PATH-$CI_COMMIT_BRANCH || true
    - docker build --cache-from $GITLAB_IMAGE_PATH/$CI_COMMIT_BRANCH --file=Dockerfile-$CI_COMMIT_BRANCH -t $GITLAB_IMAGE_PATH/$CI_COMMIT_BRANCH:$CI_COMMIT_SHORT_SHA .
    - docker push $GITLAB_IMAGE_PATH/$CI_COMMIT_BRANCH

This results in

 Step 12/14 : COPY .env ./.env
 COPY failed: stat /var/lib/docker/tmp/docker-builder513570233/.env: no such file or directory

I also tried cp $DOTENV_STAGE .env as well as cp $DOTENV_STAGE $CI_BUILDS_DIR/.env and cp $DOTENV_STAGE $CI_PROJECT_DIR/.env but none of them worked.

So the part I actually don't know is: Where do I have to put the file in order to make it available to docker during build?

Thanks

-- Daniel
continuous-integration
docker
environment-variables
gitlab
kubernetes

2 Answers

4/22/2020

You should avoid copying .env file into the container altogether. Rather feed it from outside on runtime. There's a dedicated prop for that: env_file.

web:
  env_file:
    - .env

You can store contents of the .env file itself in a Masked Variable in the GitLabs CI backend. Then dump it to .env file in the runner and feed to Docker compose pipeline.

-- jayarjo
Source: StackOverflow

4/22/2020

After some more research I stumbled upon this support-forum entry on gitlab.com, which exactly describes my situation and it got solved by the same approach I was trying to use, namely this:

...
script:
- cp $DOTENV_STAGE $CI_PROJECT_DIR/.env
...

in my .gitlab-ci.yml

The part I was actually missing was adjusting my .dockerignore-File accordingly (removing .env from it) and then removing the line

COPY .env ./.env

from my Dockerfile

An alternative approach I thought about after joyarjo's answer could be to use a ConfigMap for Kubernetes. But I didn't try it yet

-- Daniel
Source: StackOverflow