Many Docker Compose files referenced throughout this series define a fixed set of services that all start together every time. As a homelab grows, you often want more flexibility — starting only certain services for testing, or separating a “core” stack from optional add-ons without maintaining entirely separate Compose files. Docker Compose profiles solve exactly this, letting a single file define multiple selectively-startable groups of services.
What Are Compose Profiles?
Profiles let you tag services within a single docker-compose.yml file, then choose at startup time which tagged groups (profiles) should actually run. Services without any profile assigned always start normally; services with a profile assigned only start when that specific profile is explicitly requested.
Why This Matters for a Growing Homelab
Rather than maintaining separate Compose files for “core services” versus “optional monitoring stack” versus “testing environment,” profiles let you keep everything in one organized file while still controlling exactly what starts in a given situation — useful for testing a new service addition without also restarting your entire existing stack, or for maintaining a genuinely optional monitoring layer you don’t always want running.
Basic Profile Syntax
yaml
services:
nginx-proxy-manager:
image: jc21/nginx-proxy-manager:latest
# No profile - always starts
netdata:
image: netdata/netdata:latest
profiles: ["monitoring"]
grafana:
image: grafana/grafana:latest
profiles: ["monitoring"]
test-app:
image: myapp:testing
profiles: ["testing"]
Starting Services with a Specific Profile
docker compose --profile monitoring up -d
This starts both the un-profiled services (nginx-proxy-manager) and anything tagged with the monitoring profile (netdata, grafana), while leaving testing-profiled services stopped.
Starting Multiple Profiles Simultaneously
docker compose --profile monitoring --profile testing up -d
Setting a Default Profile via Environment Variable
Rather than specifying --profile on every command, set it as an environment variable for your current shell session or in a .env file:
COMPOSE_PROFILES=monitoring
A Practical Example: Separating Core and Optional Services
Building on the various services covered throughout this series, a single Compose file might organize things like:
yaml
services:
nginx-proxy-manager:
# core - always runs
pihole:
# core - always runs
netdata:
profiles: ["monitoring"]
grafana:
profiles: ["monitoring"]
loki:
profiles: ["monitoring"]
n8n:
profiles: ["automation"]
freshrss:
profiles: ["automation"]
Running just docker compose up -d starts only your genuinely essential core services, while docker compose --profile monitoring --profile automation up -d brings up everything.
Using Profiles for a Testing/Staging Setup
For testing a new version or configuration change before applying it to your actual running service (relevant to the general caution encouraged throughout this series’ more impactful changes), define a profile-tagged test variant alongside your production service definition:
yaml
services:
myapp-production:
image: myapp:stable
# core - always runs
myapp-testing:
image: myapp:latest
profiles: ["testing"]
ports:
- '8081:8080' # Different port to avoid conflicting with production
Stopping Only Profile-Specific Services
docker compose --profile monitoring down
This stops only the services tagged with that profile, leaving your always-on core services running undisturbed.
Combining Profiles with .env Files
For different homelab contexts (a “home” environment versus perhaps a secondary test server), separate .env files can define different default COMPOSE_PROFILES values, letting the same underlying Compose file behave differently depending on which environment file is active when you run commands.
Profiles vs Separate Compose Files
Profiles work well for services that are genuinely related and might reasonably share configuration or networking within one file. For truly independent stacks with no meaningful relationship (Vaultwarden versus Immich, for instance, covered in separate earlier guides), separate Compose files per service often remains the clearer, more maintainable organizational choice rather than combining everything into one large profile-tagged file.
