9.0 KiB
Table of Contents
Docker compose
- Purpose: Defines and manages multi-container Docker applications.
- Usage: Orchestrates multiple services (containers), networks, and volumes for an application.
- Key Features:
- Describes how to run one or more containers together.
- Can manage container networking and persistent storage.
- Useful for applications with multiple services (e.g., a web app + database).
- Output: A running application consisting of multiple containers.
docker-compose.yml is the file which includes all nescessary information. It can include multiple services like web (built from a Dockerfile) and db (pulled from Docker Hub).
docker-compose vs. docker compose
- If you're using a modern Docker installation (20.10+), use
docker compose. - If you're working on a system with an older Docker version or have compatibility concerns, use
docker-compose.
| Feature | docker compose | docker-compose |
|---|---|---|
| Integration | Integrated into Docker CLI | Standalone binary |
| Compose Specification | Supports Compose V2 | Supports older Compose V1 |
| Performance | Faster and more efficient | Slower compared to Compose V2 |
| Availability | Docker 20.10+ and Docker Desktop | Any Docker version, standalone |
| Future-proof | Actively developed and maintained | Legacy, less maintained |
check your docker compose version (examples):
docker compose version
Docker Compose version v2.32.1
# is installed together with docker v27.4.1
docker-compose --version
docker-compose version 1.25.0, build unknown
# separate installation for old version.
docker-compose.yaml version
Use version: "3.9" which is the latest version. Or, with Docker Compose v2 (the newer, built-in CLI plugin), you no longer need a version: line. If you remove it, Compose will simply default to the current spec.
Image location
Registry
In docker compose, use image to use an existing image from the registry.
services:
redis:
init: true
image: redis:latest
Local Image
If the image needs to be built, use build.
services:
my-local-app:
init: true
build: .
build: . tells Docker Compose to look for a Dockerfile in the same directory as the docker-compose.yml.
If the Dockerfile is in a subdirectory, specify the context and Dockerfile path:
services:
my-local-app:
init: true
build:
context: ./my-app
dockerfile: Dockerfile.dev
context:Specifies the directory containing the application code.dockerfile:Specifies the name of the Dockerfile if it’s not the default Dockerfile.
You can mix local builds and images from a registry in the same docker-compose.yml file:
services:
myapp:
init: true
build: ./my-app
ports:
- 8080:8080
redis:
init: true
image: redis:latest
webapp:
init: true
build: .
image: registry.cs.zi.uzh.ch/zi-adb-dba/export-digicert-report:latest
Docker Volumes
Bind mounts:
version: '3.9'
services:
caddy:
image: caddy:2.6.2
volumes:
- /opt/roger/ssl/certifcate.pem:/cert.pem:ro
# OR: Bind mounts of remote share which are defined through docker volumes
<code>version: '3.9'
services:
fedora:
init: true
image: docker.cloudsmith.io/docuteam/docker/fcrepo:6.2.0
volumes:
- fedora_data:/fcrepo_home
volumes:
fedora_data:
driver_opts:
type: cifs
device: //remote-hostname.com/path/to/share/fedora
o: addr=remote-hostname.com,username=user,password=mysuperpassword,nodev,noexec,nosuid,vers=2.1,uid=1000,gid=1000
Docker volumes:
version: '3.9'
services:
caddy:
init: true
image: caddy:2.6.2
volumes:
- caddy_data:/data
volumes:
caddy_data
Read-Only
Add :ro at the end of the line.
volumes:
- /opt/roger/ssl/certifcate.pem:/cert.pem:ro
Dependencies
If there is a special order of starting the containers, you can use depends_on, like this:
services:
myapp:
init: true
build: ./my-app
ports:
- 8080:8080
redis:
init: true
image: redis:latest
depends_on:
- myapp
You can also add conditions, like service_started, service_healthy and service_completed_successfully:
services:
myapp:
init: true
build: ./my-app
ports:
- 8080:8080
redis:
init: true
image: redis:latest
depends_on:
myapp:
condition: service_started
In the following example, Compose will first start the database service, execute the pg_isready command specified in the healthcheck.test property, start the migration service if the value returned by the test command is 0, and finally start the api service if the exit status of the migration service's container is also 0.
services:
api:
init: true
build: .
depends_on:
database:
condition: service_healthy
migration:
condition: service_completed_successfully
database:
init: true
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
migration:
init: true
image: migration-tool
Variables
Variables for docker-compose.yaml
Use ${VARIABLE_NAME}, like this:
services:
ui:
init: true
image: nginx:${NGINX_VERSION}-alpine
You can pass the variable when starting docker compose like this:
NINGX_VERSION=1.21.5 docker compose up -d
You can also use an environment file. If no variable is set on calling docker compose up, then it will use the value in the .env file.
touch .env
# then add the variables:
NINGX_VERSION=1.21.4
If the file has a different name or is located in a different path, you can specify the location when starting docker-compose.
docker compose --env-file /path/to/environmentfile up -d
Variables for containers
If a variable is already set in the shell, like PORT in this example, it will be automatically passed to docker compose, like this:
services:
ui:
init: true
image: nginx:1.21.5-alpine
environment:
- PORT
To specify the variable in docker compose:
services:
ui:
init: true
image: nginx:1.21.5-alpine
environment:
- PORT=81
You can also specify a file:
services:
ui:
init: true
image: nginx:1.21.5-alpine
environment:
- PORT=81
env_file:
- ./path/to/envfile
Profiles
Start only containers within a certain profile. Note that services WITHOUT a profile will always start!
services:
myapp:
init: true
build: ./my-app
ports:
- 8080:8080
profiles:
- blabla
ui:
init: true
image: nginx:1.21.5-alpine
profiles:
- profilename
start like this, and it will start only the "ui" service.
docker compose --profile profilename up -d
Networks
All containers in a docker compose setup can communicate with eachother. The services, like myapp or ui can be used as hostnames. This will make linking the containers easier.
If the network must be specialized, e.g. not all containers have connection to other containers, you need to build your own networks.
services:
myapp:
init: true
build: ./my-app
networks:
- test
ui:
init: true
image: nginx:1.21.5-alpine
profiles:
- profilename
networks:
- test
networks:
test:
driver: bridge
attachable: true # default; set to false, so that other containers can not be added to the network in the future.
Restart policy
ui:
init: true
image: nginx:1.21.5-alpine
restart: always # or other settings...
Commands
Config
The following command shows you the docker-compose.yaml as it is interpreted by docker.
docker compose config
Start
-d für das Ausführen im Hintergrund.
start
Startet nur bereits existierende, gestoppte Container neu. Baut NICHT neu, erstellt KEINE neuen Container. Wird ein Container zum ersten Mal gestartet, muss up verwendet werden.
docker-compose start -d
up
Verwendet, wenn möglich, vorhandene Images. Falls lokal schon ein Image mit dem passenden Namen und Tag existiert, wird NICHT neu gebaut. Nur wenn das Image nicht existiert, wird gebaut.
docker compose up -d
up mit build
Baut immer neu, auch wenn ein Image schon existiert (empfohlen nach jedem Code- oder Dockerfile-Update).
docker compose up --build -d
Stop
- The
docker compose stopcommand will stop your containers, but it won’t remove them. - The
docker compose killcommand will stop your containers faster, but it won’t remove them. - The
docker compose downcommand will stop your containers, but it also removes the stopped containers as well as any networks that were created. - You can take down 1 step further and add the
-vflag to remove all volumes too. This is great for doing a full blown reset on your environment by runningdocker compose down -v.
Events
docker compose events