Learn Docker With My Newest Course

Dive into Docker takes you from "What is Docker?" to confidently applying Docker to your own projects. It's packed with best practices and examples. Start Learning Docker →

Docker Tip #94: Docker Compose v2 and Profiles Are the Best Thing Ever

docker-tips-and-tricks.jpg

I switched to v2 because it's faster and profiles let you easily start specific services in different environments.

Prefer video? Here’s a recorded version of this tip on YouTube which demonstrates using profiles and more.

Docker Compose v2 was marked generally available in April 2022, its timeline is:

  • October 2022: v2 will be on by default and you can opt-out of it in Docker Desktop
  • April 2023: v2 will be the only option with Docker Desktop

The 3 biggest reasons on why I’ve switched to it are:

  • Containers start and stop faster than Docker Compose v1
  • Docker Compose profiles support with seamless optional depends_on to make it easy to control running specific containers in different environments (it’s a pure upgrade to the override file pattern)
  • v2 is a Docker plugin written in Go, there’s no need for a Python environment anymore (btw even the curl version of Docker Compose v1 uses PyInstaller to bundle it up)

I’ve updated all of my example Docker web apps to use Docker Compose v2 with profiles and also updated my Ansible role to install Docker Compose v2 by default. It works nicely on native Linux without Docker Desktop since it’s just a system package to install.

With profiles imagine having a docker-compose.yml such as this (simplified to demo profiles):

services:
  postgres:
    profiles: ["postgres"]
  redis:
    profiles: ["redis"]
  web:
    profiles: ["web"]
    depends_on: ["postgres", "redis"]
  worker:
    profiles: ["worker"]
    depends_on: ["postgres", "redis"]
  assets:
    profiles: ["assets"]

In development you can set this environment variable in an .env file to start everything:

export COMPOSE_PROFILES=postgres,redis,assets,web,worker

In production you can set this instead:

export COMPOSE_PROFILES=web,worker

You can also use the docker compose --profile web,worker up flag instead of an environment variable but I prefer using the environment variable approach to avoid needing to run custom commands on different servers.

The above expects your assets would be built beforehand in production instead of running various asset watcher containers like esbuild or tailwind in development.

The above also expects you may want to run managed versions of Postgres and Redis on your cloud provider of choice, but you don’t have to do this. Even with depends_on defined on your web and worker services it doesn’t matter. Docker Compose v2 is smart enough to know to ignore the dependent services because you didn’t specify the postgres or redis profiles to run.

You could even choose to run your web and worker on separate servers by only specifying each one individually such as export COMPOSE_PROFILES=web and export COMPOSE_PROFILES=worker on each server.

Update: Docker Compose v2.19 broke this behavior but v2.20.2+ addressed it by allowing you to set required: true or required: false on a depends_on service. This post goes into more details.

Profiles are very flexible, they’re great! I switched over to this combo for both development and production in August 2022.

Free Intro to Docker Email Course

Over 5 days you'll get 1 email per day that includes video and text from the premium Dive Into Docker course. By the end of the 5 days you'll have hands on experience using Docker to serve a website.



Comments