Labels are key-value metadata attached to containers. They cost nothing at runtime but unlock powerful filtering, organization, and tool integrations.
Adding labels to services
services:
api:
image: myapp-api
labels:
com.example.team: "backend"
com.example.env: "production"
com.example.version: "2.1.0"
worker:
image: myapp-worker
labels:
com.example.team: "backend"
com.example.env: "production"
com.example.role: "async-processing"
You can also use the list syntax:
services:
api:
image: myapp-api
labels:
- "com.example.team=backend"
- "com.example.env=production"
Filtering with labels
Labels become powerful with docker compose ps:
# Find all containers from the backend team
docker compose ps --filter "label=com.example.team=backend"
# Find all production containers
docker compose ps --filter "label=com.example.env=production"
# Combine filters
docker compose ps --filter "label=com.example.team=backend" --filter "label=com.example.env=production"
Traefik integration
Traefik uses labels for automatic routing configuration:
services:
web:
image: myapp
labels:
traefik.enable: "true"
traefik.http.routers.web.rule: "Host(`app.example.com`)"
traefik.http.routers.web.tls: "true"
traefik.http.services.web.loadbalancer.server.port: "3000"
traefik:
image: traefik:v3
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
Prometheus integration
Prometheus can discover targets using container labels:
services:
api:
image: myapp-api
labels:
prometheus.scrape: "true"
prometheus.port: "9090"
prometheus.path: "/metrics"
worker:
image: myapp-worker
labels:
prometheus.scrape: "true"
prometheus.port: "9091"
Organization patterns
Use a consistent naming convention across your team:
services:
api:
image: myapp-api
labels:
# Ownership
com.example.team: "platform"
com.example.contact: "platform-team@example.com"
# Environment
com.example.env: "${ENV:-dev}"
com.example.version: "${VERSION:-latest}"
# Operational
com.example.backup: "true"
com.example.log-level: "info"
Pro tip
Labels on containers are different from labels on networks and volumes:
services:
app:
image: myapp
labels:
app.tier: "frontend" # Container label
networks:
frontend:
labels:
network.purpose: "public-facing" # Network label
volumes:
data:
labels:
volume.backup: "daily" # Volume label
Each resource type has its own labels, and you can filter each independently.