Use dotenvx with Docker Compose
Use dotenvx with Docker Compose
Find code examples for this guide on GitHub.
Initial setup
Install the necessary web server libraries in the language of your choice.
npm install express --save
Create a simple Hello World program.
// index.js
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000
app.get('/', (req, res) => {
res.send(`Hello ${process.env.HELLO || ''}`)
})
app.listen(PORT, () => {
console.log(`Server running on port:${PORT}`)
})
Create a Dockerfile.
# Dockerfile
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
Create a docker-compose.yml file.
# docker-compose.yml
version: "3.8"
services:
web:
build: .
command: node index.js
ports:
- "3000:3000"
environment:
DOTENV_PRIVATE_KEY: ${DOTENV_PRIVATE_KEY}
DOTENV_PRIVATE_KEY_PRODUCTION: ${DOTENV_PRIVATE_KEY_PRODUCTION}
Create .dockerignore.
.dockerignore
# .dockerignore
.env.keys
Build and run it with Docker Compose.
docker-compose up --build
Once built, your app will say 'Hello [blank]' as it doesn't have a way to access the environment variable yet. Let's do that next.
Run dotenvx
Install dotenvx to your Dockerfile.
# Dockerfile
FROM node:20
WORKDIR /app
# Install dotenvx
RUN curl -sfS https://dotenvx.sh/install.sh | sh
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
If you prefer, install directly form GitHub Releases or view the install.sh file before executing.
And prepend your app command with dotenvx run -- in docker-compose.yml.
# docker-compose.yml
version: "3.8"
services:
web:
build: .
command: dotenvx run -- node index.js
ports:
- "3000:3000"
environment:
DOTENV_PRIVATE_KEY: ${DOTENV_PRIVATE_KEY}
DOTENV_PRIVATE_KEY_PRODUCTION: ${DOTENV_PRIVATE_KEY_PRODUCTION}
Create a .env file in the root of your project.
.env
# .env
HELLO="World"
Build and run it with Docker Compose.
docker-compose up --build
Your app will say Hello World. The values from your .env file were successfully injected into your env. That covers local development. Let's solve for production next.
Add production environment
Create a .env.production file in the root of your project.
.env.production
# .env.production
HELLO="production"
Use dotenvx to load your .env.production file by updating your docker-compose.yml command:.
command: dotenvx run -f .env.production -- node index.js
Build and run it with Docker.
docker-compose up --build
Your app will say Hello production, simulating production. Solid. Let's encrypt your secrets next.
Encrypt production
dotenvx set HELLO production -f .env.production
Your .env.production file is now encrypted, and you have a .env.keys file.
.env.production
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY_PRODUCTION="0354d5293e40f78b8b44d6b5ded92719ef99d119a79093d6babd0ef9e80a9a7667"
# .env.production
HELLO="encrypted:BGo+chylmSbkHeDsn9gPy5LYvYUUpTstaUr8hDU0lgp4ssyH2MXav43ww+B3WNaYLZQpJdJdJ2F8qLbV4vDolF42ETQFu/xxhKA2/MRxiC/Vd1s/DMDjm9RSHOCQ5YHywLrUY9UySesbn58="
.env.keys
#/------------------!DOTENV_PRIVATE_KEYS!-------------------/
#/ private decryption keys. DO NOT commit to source control /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
# .env.production
DOTENV_PRIVATE_KEY_PRODUCTION="3c54363a4a678042d298660e2038df68aaa4a9383048d913d0e6db15e137020d"
You SHOULD commit .env.production to code. It is now encrypted, safe, and recommended to do so. But DO NOT commit .env.keys to code. Keep them somewhere safe like 1password or dotenvx ops.
We're ready to inject the encrypted .env.production secrets into Docker run.
Set decryption key
Set DOTENV_PRIVATE_KEY_PRODUCTION ahead of docker-compose using the production key in your .env.keys file.
DOTENV_PRIVATE_KEY_PRODUCTION=3c54363a4a678042d298660e2038df68aaa4a9383048d913d0e6db15e137020d docker-compose up --build
Your docker instance starts and env is successfully injected using the encrypted contents of .env.production.
[[email protected]] injecting env (2) from .env.production
Server running on port:3000
Visit your url and it says Hello production.
You succesfully add encryption to your .env files. This is safer than scattering your secrets across third-party platforms and tools. When you need to update a secret, run dotenvx set KEY value and redeploy.
Great job! That's pretty much it. See the bonus section(s) below to go a little deeper.
Bonus
Try changing the value of .env.production to your name.
dotenvx set HELLO Mot
Commit .env.production safely to code and re-run your Docker container.