It’s been a while since my previous blog post, long enough for dockercon 2021 to suprise us with some exciting features. My review of some of the features is on the way but for this post I would like to discuss one of my most anticipated compose features, profiles.
If you remember my previous docker blog post,
in order to modularize container services, I decided to use docker-compose.yml
overriding to start different
services for different environments. You can finally add services to one or multiple profiles and then
start one or multiple profiles.
Demo
Let’s say we have three environments:
dev
: Hotreloading with typescript without building.test
: Running integration tests.prod
: Running in the production environment in a lightweight container.
The setup used here is the same as in the previous post,
where we have a node app, postgres as database with docker volumes and a multistage Dockerfile
.
We can now setup our new single docker-compose.yml
with 3 profiles: api-dev
, api-test
, api-prod
as follows:
version: "3.9"
services:
db:
image: postgres:13-alpine
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DB}
container_name: db-dev
ports:
- '5432:5432'
volumes:
- dbdata:/var/lib/postgresql/data/
- ./dbscripts:/docker-entrypoint-initdb.d
api-dev:
image: yzia2000/temp-api:dev
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
build:
context: .
target: base
container_name: api-dev
command: npm run dev
volumes:
- ./src:/app/src
- ./package.json:/app/package.json
depends_on:
- db
ports:
- '5000:5000'
profiles: ['api-dev']
api-test:
image: yzia2000/temp-api:test
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
- NODE_ENV=test
build:
context: .
target: builder
container_name: api-test
command: ./wait-for-it.sh db:5432 -- /bin/sh -c "npm run test"
depends_on:
- db
ports:
- '5000:5000'
profiles: ['api-test']
api-prod:
image: yzia2000/temp-api:latest
environment:
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
- NODE_ENV=production
build:
context: .
container_name: api
depends_on:
- db
ports:
- '5000:5000'
profiles: ['api-prod']
volumes:
dbdata:
To run a profile, simply:
docker-compose --profile api-dev up
If you have some knowledge of docker-compose.yml
, this will look self-explanatory. Profiles
are easy to understand too. You might find the lack of a profile attached to the db container
interesting. Containers that do not have a profile attached to them start automatically. Since, all
our profiles depend on the db container, we do not need to attach multiple profiles to it.
Profiles can be especially useful when onboarding new members into your team as they no longer need to worry about starting or stopping different containers and can get to work immediately. This is one of the ways you can reduce developer cold start (new post coming soon).
To learn more about docker compose profiles you can read the docker documentation.
Conclusion
Now you longer need to maintain multiple docker-compose.yml
, though I would recommend
doing that if you different teams on a monorepo setup (separated by feature and not environment).
Having a single docker-compose.yml
means that you spend less time moving through different files
when changing things as simple as environment variables.
More docker features from the dockercon 2021 will be discussed soon in my upcoming blog posts and I hope you look forward to them.