X
Popular Searches

How to Use Service Profiles to Simplify Stacks in Docker Compose

Docker Compose now supports profiles for selective use of services. Services in your docker-compose.yml can be linked to one or more named profiles. Passing a profile name to docker-compose up will start just the services in that profile, letting you create variants of your stack for specific environments and configurations.

Compose has previously focused on defining a single stack that’s a canonical distribution of your application. Profiles add more room for customizing which parts of the stack to use, making complex sets of services more modular and configurable.

Why Use Profiles?

Use of profiles is entirely optional. Your existing Docker Compose files will continue to function and there’s no need to adopt profiles straightaway.

Service profiles solve several common frustrations with Docker Compose development and testing flows. You might have services which you only want to use in development, such as a debug container or logging service. When you’re in production, you don’t need those services and want to avoid starting them.

Previously, achieving this required splitting your service definitions across multiple files. You’d then need an unwieldy up command to start everything in development:

# docker-compose.yml
version: "3"
services:
  app:
    image: my-app:latest
 
# docker-compose-dev.yml
version: "3"
services:
  debug:
    image: my-app-debug:latest
# start in production
docker-compose up -d

# start in development
docker-compose -f docker-compose.yml -f docker-compose-dev.yml up -d
Advertisement

Profiles let you combine both service definitions into one file. You can use a flag or environment variable to select a specific profile, without manually typing out file paths. This creates a more convenient experience that’s less hassle to document, write, and run.

Defining Profiles

Profiles are created by setting the profiles field on services in your docker-compose.yml. Profiles are specified as a list. Each service can be given one or many profiles.

version: "3"
services:
  app:
    image: my-app:latest
  debug:
    image: my-app-debug:latest
    profiles:
      - dev

Profile instances are created implicitly from the names given to your profiles fields. Services which share a profile are automatically joined.

To start the services included in a profile, add the --profile flag to docker-compose up:

docker-compose up --profile dev

This command would start both the app and debug services from the above Compose file. If you ran docker-compose up, omitting the --profile flag, only the app service would start.

You can start multiple profiles simultaneously by repeating the --profile flag. Compose also supports the COMPOSE_PROFILES environment variable as an alternative to --profile. This accepts a comma-separated list of profile names.

Advertisement

Services with no profiles field will always be started, irrespective of any requested profile. Once a service has been given a profile, it will only start if that profile has been requested. For services with multiple profiles, requesting any one of them will allow the service to start.

Implicit Profile Starts

Profiles will always be ignored if you manually start a service using docker-compose run. In this case, Compose will also start any services which the requested service depends upon, if they share a profile or have no profile assigned.

Here, running docker-compose run debug would start the debug-utils service, even though the dev profile hasn’t been explicitly selected:

version: "3"
services:
  app:
    image: my-app:latest
  debug-utils:
    image: my-app-debug-utils:latest
    profiles:
      - dev
  debug:
    image: my-app-debug:latest
    depends_on: debug-utils
    profiles:
      - dev

Implicit starts only apply to direct dependents of the specified service. If debug-utils also had a depends_on, and that service didn’t share the dev profile, it would not start up correctly.

For dependency resolution to work properly with docker-compose run, all services in the tree must share a profile of the top-most service, or be permanently enabled. If neither of those conditions hold, you’ll need to add the --profile flag to explicitly activate any additional required profiles.

Summary

Service profiles are a convenient Compose feature that make it easier to manage different combinations of services. By using profiles, you can avoid splitting services into multiple Compose files. Adding --profile usually feels more natural than merging multiple YAML files together.

Advertisement

Profiles let you build out sub-stacks within your main Compose application. Their introduction as part of the Compose spec is a recognition that stacks in development often incorporate extra services beyond those used in production.

More generally, profiles make Compose more versatile by facilitating stack customization. While envisioned as an approach to environment management, profiles could also help the community create different variations of popular images. Think of a WordPress docker-compose.yml with mysql and mariadb profiles: now you can easily switch between pre-configured database services to select the engine that matches your preference.

Docker Compose 1.28 introduced profiles earlier this year. As long as you’ve got a recent version of the Compose binary, or Docker Desktop for Windows and Mac, you can add profiles to your Compose files to start selectively enabling services.

James Walker James Walker
James Walker is a CloudSavvy IT contributor. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows with DevOps, CI/CD, Docker, and Kubernetes. Read Full Bio »

The above article may contain affiliate links, which help support CloudSavvy IT.