Compose Profiles
A Docker Compose feature that tags services with profile names, allowing them to be selectively started. Services without a profile always start — services with a profile only start when that profile is explicitly activated with --profile.
Compose Profiles — Selectively Starting Services
What Is a Compose Profile in Simple Terms?
Not every developer needs every service running every time. A frontend developer working on the UI does not need the data analytics pipeline running. A backend developer does not always need the email service running. Compose profiles let you mark optional services with a label, and they only start when you explicitly request that profile.
version: "3.8" services: api: image: payment-api:latest # no profile = ALWAYS starts postgres: image: postgres:15 # no profile = ALWAYS starts analytics: image: analytics-service:latest profiles: - analytics # only starts with --profile analytics mailhog: image: mailhog/mailhog profiles: - email # only starts with --profile email debug-ui: image: adminer profiles: - debug # only starts with --profile debug - tools # also starts with --profile toolsUsing Profiles
# Start only base services (api + postgres)docker compose up -d# analytics, mailhog, debug-ui do NOT start # Start with analytics pipelinedocker compose --profile analytics up -d# api, postgres, analytics all start# mailhog, debug-ui do NOT start # Start with multiple profilesdocker compose --profile analytics --profile email up -d# api, postgres, analytics, mailhog all start # Start everythingdocker compose --profile "*" up -d # List services that would start for a profiledocker compose --profile analytics config --servicesPractical Profile Patterns
services: api: # always on postgres: # always on redis: # always on # Only for developers who need to receive emails locally mailhog: profiles: [email] # Only for debugging database queries adminer: profiles: [debug] # Only in CI for integration tests test-runner: profiles: [ci] command: ["npm", "run", "test:integration"] # Only for load testing k6: image: grafana/k6 profiles: [loadtest] volumes: - ./k6:/scripts command: ["run", "/scripts/payment-load-test.js"]TipUse profiles for any service that is not always needed in development — database admin UIs, email catchers, monitoring tools, test runners, load testing tools. This keeps
docker compose upfast for daily development while making all optional tools available when needed.
Frequently Asked Questions
What problem do Compose profiles solve that separate compose files don't?
Before profiles, teams either ran every service in a compose file regardless of need (wasting resources on tools like a debug UI or seed-data job that aren't needed every time) or maintained parallel compose files to exclude them. Profiles let one file describe everything, with optional services tagged by profile name and only started when that profile is explicitly activated — so a single `docker compose up` stays lean by default while `--profile debug` pulls in the extras on demand.
What's a common mistake when using Compose profiles?
Forgetting that a profiled service is also skipped by `docker compose up <service-name>` unless its profile is active — engineers sometimes assume naming a service directly bypasses the profile gate, and get confused when it doesn't start. Also, a service with no profile listed always runs, so retrofitting profiles onto an existing file requires auditing every service, not just the ones you intend to make optional.