Docker Compose — Defining Services

2 minute read

A service is a container definition in your compose file. This page covers all the common options you’ll use when defining services.


Basic Service Definition

services:
  web:                        # Service name (you choose this)
    image: nginx:alpine       # Docker image
    container_name: my-nginx  # Custom container name
    ports:
      - "80:80"               # Port mapping
    environment:
      NGINX_HOST: example.com # Environment variable
    volumes:
      - ./html:/usr/share/nginx/html  # Volume mount
    restart: unless-stopped   # Restart policy
    labels:
      app: web                # Container labels
      env: production

Service Options Reference

image

Specifies which Docker image to use:

services:
  # Full image reference
  db:
    image: postgres:16-alpine

  # Docker Hub official image
  cache:
    image: redis:7

  # Custom registry
  api:
    image: registry.example.com/myapp:v1.2.3

container_name

Override the default container name:

services:
  db:
    image: postgres:16
    container_name: my-database

Default name: <project>-<service>-<number> (e.g., myapp-db-1)

Warning: Custom container names prevent scaling — you can’t have two containers with the same name. Only use this when you need a specific name.

restart

Defines when Docker should restart the container:

services:
  web:
    image: nginx
    restart: unless-stopped
Policy Behavior
no Never restart (default)
always Always restart, even after manual stop
on-failure Restart only on non-zero exit code
unless-stopped Always restart except after manual docker stop

For development: use no or on-failure For production: use unless-stopped

environment

Set environment variables for the container:

services:
  db:
    image: postgres:16
    environment:
      # Map syntax (recommended)
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp

Or list syntax:

    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=myapp

labels

Add metadata labels to containers:

services:
  web:
    image: nginx
    labels:
      com.example.app: "web"
      com.example.env: "production"
      com.example.team: "platform"

Labels are useful for monitoring tools, reverse proxies (Traefik), and container management.


A Complete Multi-Service Example

services:
  frontend:
    image: nginx:alpine
    container_name: blog-frontend
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    restart: unless-stopped
    labels:
      app: blog
      tier: frontend

  backend:
    image: node:20-alpine
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      DB_HOST: database
    restart: unless-stopped
    labels:
      app: blog
      tier: backend

  database:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: blog
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: unless-stopped
    labels:
      app: blog
      tier: data

volumes:
  db-data:

Summary

Option Purpose Example
image: Docker image to use postgres:16
container_name: Custom name (prevents scaling) my-db
ports: Port mapping "80:80"
environment: Environment variables POSTGRES_PASSWORD: secret
volumes: Data mounts db-data:/var/lib/postgresql/data
restart: Restart policy unless-stopped
labels: Metadata app: web

Quick Reference

Item Detail
Service name You choose — becomes DNS hostname
image Docker image to pull and run
container_name Custom name — prevents scaling
restart unless-stopped for production
environment Key-value env vars for container
labels Metadata for tooling and management