401 lines
9.0 KiB
Markdown
401 lines
9.0 KiB
Markdown
---
|
||
gitea: none
|
||
include_toc: true
|
||
---
|
||
# 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 `condition`s, 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 stop` command will stop your containers, but it won’t remove them.
|
||
- The `docker compose kill` command will stop your containers faster, but it won’t remove them.
|
||
- The `docker compose down` command 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 `-v` flag to remove all volumes too. This is great for doing a full blown reset on your environment by running `docker compose down -v`.
|
||
|
||
### Events
|
||
|
||
```
|
||
docker compose events
|
||
```
|