IT-Wissen/docker/docker-compose.md
2025-04-24 15:50:34 +02:00

8.5 KiB
Raw Blame History

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 its 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

Ins Verzeichnis gehen wo docker-compose.yml liegt, und dann docker-compose start -d. Mit -d wird es im Hintergrund ausgeführt.

Stop

  • The docker compose stop command will stop your containers, but it wont remove them.
  • The docker compose kill command will stop your containers faster, but it wont 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