Multi-Environment Variable Management in Gitlab CI

Using Gitlab CI, Docker and Docker Compose (No Kubernetes)

The Objective

The Setup

For the sake of clarity we have a docker-compose.<env>.yml file for each environment (development/staging/production).

To share environment variables across our containers we want to define a env_file that keeps all our environment variables in one place.

docker-compose.(development/staging/production).yml

The corresponding .env file in this case would include all environment variables being used in and across our two containers (nodejs and postgres).

.env.(development/staging/production)

As we all know, we should never publicly share any .env files containing sensitive information (like the postgres password in this case). To prevent them from being committed the repository we usually add them to our .gitignore file.

ignore .env* but commit .env.sample* files.

What we usually do provide instead is a .env.sample file that functions as a blueprint for our actual .env file since we leave sensitive information blank.

Gitlab CI Variables

Setting a variable come with a protect and a mask flag that ensures the value never to be displayed anywhere. (Even if the branch is public accessible to other collaborators the value will only be visible for administrators!)

Now we have stored our sensitive information in a Gitlab variable and our insensitive in a .env.sample but our docker-compose.yml is still expecting a single .env.staging file containing all environments in one place! So, what do we do?!

The Script

Finally, we run this script in the deploy job in our gitlab-ci.yml file before docker-compose.

Doing so, docker compose will find the env_file we defined in our docker-compose.staging.yml containing all the environment variables our containers need in one place while our sensitive can easily be managed and kept safe using Gitlab CI Variables!

Hope this was helpful — feel free to leave a comment.

Digital Artist & Software Developer