Compose
  • Deploy multiple containers on a single host
  • A YAML file defining version (DEPRECATED), services (REQUIRED), networks, volumes, configs and secrets
  • Default path is compose.yaml (or compose.yml, docker-compose.yaml, docker-compose.yml) in working directory
  • Build and Compose
  • 1. Build an image from local
  • 2. Compose containers
    1. version: "3.9" # version of Docker Compose
    2. services:
    3. webapp: # container
    4. image: lchenlangley/count # image name [domain/image:tag]
    5. build: . # search local, if image does not exist, build image from local
    6. ports:
    7. - 8000:5000 # host port : container port
    8. environment:
    9. - MYREDIS_HOST=redisserver # environment variable
    10. redisserver: # container
    11. image: redis:alpine # if image exist in local, use the local image
    12. # a bridge network is created by default
    Fetch and Compose
  • 1. Fetch images from repositories
  • 2. Compose containers
    1. version: "3.9"
    2. services:
    3. webapp:
    4. image: lchenlangley/count # fetch image from Docker Hub
    5. ports:
    6. - 8000:5000
    7. environment:
    8. - MYREDIS_HOST=redisserver
    9. redisserver:
    10. image: "redis:alpine" # fetch image from Docker Hub
    Multiple Compose Files
    1. # compose_1.yaml
    2. version: "3.9"
    3. services:
    4. webapp: # container
    5. image: lchenlangley/count
    6. #build: .
    7. volumes:
    8. - type: volume
    9. source: voltemp
    10. target: /code
    11. volumes:
    12. voltemp:
    1. # compose_2.yaml
    2. version: "3.9"
    3. services:
    4. webapp: # container
    5. ports:
    6. - target: 5000
    7. published: 8000
    8. protocol: tcp
    9. mode: host
    10. environment:
    11. MYREDIS_HOST: redisserver
    12. redisserver: # container
    13. image: redis:alpine
    1. docker-compose -f compose_1.yaml -f compose_2.yaml up
    2. docker-compose -f compose_1.yaml -f compose_2.yaml down
    Configuration Extension
  • re-use a common configuration
    1. # compose.yaml
    2. version: "3.9"
    3. services:
    4. webapp: # container
    5. extends:
    6. file: common.yaml
    7. service: template
    8. image: lchenlangley/count
    9. #build: .
    10. volumes:
    11. - type: volume
    12. source: voltemp
    13. target: /code
    14. redisserver: # container
    15. image: redis:alpine
    16. volumes:
    17. voltemp:
    1. # common.yaml, contains a common configuration
    2. version: "3.9"
    3. services:
    4. template: # container
    5. ports:
    6. - target: 5000
    7. published: 8000
    8. protocol: tcp
    9. mode: host
    10. environment:
    11. MYREDIS_HOST: redisserver
    1. docker-compose up
    2. docker-compose down
    Services
  • Abstract concept implementing docker run
  • image
    1. image: redis # [domainName/imageName:tag]
  • ports
    1. ports:
    2. - 8000:5000 # host_port:container_port
  • build
    1. services:
    2. webapp:
    3. image: awesome/webapp # image name
    4. build: . # path for source code and Dockerfile
    1. services:
    2. webapp:
    3. image: awesome/database # image name
    4. build:
    5. context: . # source code path
    6. dockerfile: ../Dockerfile # Dockerfile path
    1. services:
    2. webapp:
    3. build: . # source code path
  • environment
    1. services:
    2. webapp:
    3. ...
    4. environment:
    5. MYREDIS_HOST: redisserver
    1. services:
    2. webapp:
    3. ...
    4. environment:
    5. - MYREDIS_HOST=redisserver
  • networks
    1. services:
    2. webapp:
    3. ...
    4. networks:
    5. - frontend-network
    6. - backend-network
  • restart
    1. restart: always
  • env_file
    1. # .env, default environment file
    2. MYREDIS_HOST=redisserver
    3.  
    4. # compose.yml
    5. services:
    6. webapp:
    7. ...
    8. environment:
    9. - MYREDIS_HOST=${MYREDIS_HOST}
    1. # env/webapp.env
    2. MYREDIS_HOST=redisserver
    3.  
    4. # compose.yml
    5. services:
    6. webapp:
    7. ...
    8. environment:
    9. - MYREDIS_HOST=${MYREDIS_HOST}
    10.  
    11. # compose
    12. docker-compose --env-file env/webapp.env up
    13.  
    14. # turn off compose
    15. docker-compose --env-file env/webapp.env down
  • profiles and depends_on
    1. services:
    2. foo:
    3. image: foo
    4. bar:
    5. image: bar
    6. profiles:
    7. - test
    8. baz:
    9. image: baz
    10. depends_on:
    11. - bar
    12. profiles:
    13. - test
    14. zot:
    15. image: zot
    16. depends_on:
    17. - bar
    18. profiles:
    19. - debug
    1. # enable test (bar, baz) and foo
    2. docker-compose --profile test up
    3.  
    4. # invalid, profile debug (zot) is enabled, but zot depends on bar which is in the profile test
    5. docker-compose --profile debug up
    6.  
    7. # enable test(bar, baz), debug(zot) and foo
    8. docker-compose --profile debug --profile test up
    9.  
    10. # enable bar, profile test is active, but baz is not enabled
    11. docker-compose up bar
    12.  
    13. # enable baz, profile test is active, bar is enabled by depends_on constraint
    14. docker-compose up baz
    15.  
    16. # enable zot and test, bar is enabled by depends_on constraint
    17. docker-compose --profile test up zot
  • command
    1. command: python app.py
  • expose
    1. expose:
    2. - "5000"
  • container_name
    1. container_name: redis-container
  • hostname
    1. hostname: redis-host
    Networks
  • Capability abstraction to establish an IP route between containers, analogous to docker network create
  • By default, docker-compose sets up a single network, containers join the network for communication
    1. version: "3.9"
    2. services:
    3. webapp: # container
    4. image: lchenlangley/count
    5. #build: .
    6. volumes:
    7. - type: volume
    8. source: voltemp
    9. target: /code
    10. ports:
    11. - target: 5000
    12. published: 8000
    13. protocol: tcp
    14. mode: host
    15. environment:
    16. MYREDIS_HOST: ${MYREDIS_HOST}
    17. networks:
    18. - app-net
    19. redisserver: # container
    20. image: redis:alpine
    21. networks:
    22. - app-net
    23. volumes:
    24. voltemp:
    25. networks:
    26. app-net: # create a network named [directory]_app-net
    Volumes
  • Analogous to docker volume create
  • Volume
    1. # Short Syntax
    2. services:
    3. app:
    4. # ...
    5. volumes: # volumes for a particular service
    6. - [source]:[target]:[mode]
    7. # source, named volume, defined in the top level "volumes"
    8. # target, an absolute path in container
    9. # mode, read-only or read-write
    10.  
    11. volumes: # define volumes
    1. version: "3.9"
    2. services:
    3. webapp:
    4. image: lchenlangley/count
    5. build: .
    6. ports:
    7. - 8000:5000
    8. volumes:
    9. - voltemp:/code
    10. environment:
    11. - MYREDIS_HOST=redisserver
    12. - FLASK_ENV=development
    13. depends_on:
    14. - redisserver
    15. redisserver:
    16. image: "redis:alpine"
    17. volumes:
    18. voltemp: # volume name length should greater than five
    1. # Syntax
    2. services:
    3. app:
    4. # ...
    5. volumes: # volumes for a particular service
    6. - type: volume
    7. source: [volume_name]
    8. target: [path]
    9.  
    10. volumes: # define volumes
    1. version: "3.9"
    2. services:
    3. webapp:
    4. image: lchenlangley/count
    5. build: .
    6. ports:
    7. - 8000:5000
    8. volumes:
    9. - type: volume
    10. source: voltemp
    11. target: /code
    12. environment:
    13. - MYREDIS_HOST=redisserver
    14. - FLASK_ENV=development
    15. depends_on:
    16. - redisserver
    17. redisserver:
    18. image: "redis:alpine"
    19. volumes:
    20. voltemp:
  • Bind Mount
    1. # Short Syntax
    2. services:
    3. app:
    4. # ...
    5. volumes: # volumes for a particular service
    6. - [source]:[target]:[mode]
    7. # source, a path (absolute or relate)
    8. # target, an absolute path in container
    9. # mode, read-only or read-write
    1. version: "3.9"
    2. services:
    3. webapp:
    4. image: lchenlangley/count
    5. build: .
    6. ports:
    7. - 8000:5000
    8. volumes:
    9. - .:/code
    10. environment:
    11. - MYREDIS_HOST=redisserver
    12. - FLASK_ENV=development
    13. depends_on:
    14. - redisserver
    15. redisserver:
    16. image: "redis:alpine"
    1. # Syntax
    2. services:
    3. app:
    4. # ...
    5. volumes: # volumes for a particular service
    6. - type: bind
    7. source: [path]
    8. target: [path]
    1. version: "3.9"
    2. services:
    3. webapp:
    4. image: lchenlangley/count
    5. build: .
    6. ports:
    7. - 8000:5000
    8. volumes:
    9. - type: bind
    10. source: .
    11. target: /code
    12. environment:
    13. - MYREDIS_HOST=redisserver
    14. - FLASK_ENV=development
    15. depends_on:
    16. - redisserver
    17. redisserver:
    18. image: "redis:alpine"
    Configs
  • Grant access to configs on a per-service basis
    Secret
  • Grant access to secrets on a per-service basis
    Example

  • 2 services, backed by Docker images: webapp and database
  • 1 secret (HTTPS certificate), injected into the frontend
  • 1 configuration (HTTP), injected into the frontend
  • 1 persistent volume, attached to the backend
  • 2 networks: front-tier and back-tier
    1. services:
    2. frontend:
    3. image: awesome/webapp
    4. ports:
    5. - "443:8043"
    6. networks:
    7. - front-tier
    8. - back-tier
    9. configs:
    10. - httpd-config
    11. secrets:
    12. - server-certificate
    13.  
    14. backend:
    15. image: awesome/database
    16. volumes:
    17. - db-data:/etc/data
    18. networks:
    19. - back-tier
    20.  
    21. volumes:
    22. db-data:
    23. driver: flocker
    24. driver_opts:
    25. size: "10GiB"
    26.  
    27. configs:
    28. httpd-config:
    29. external: true
    30.  
    31. secrets:
    32. server-certificate:
    33. external: true
    34.  
    35. networks:
    36. # The presence of these objects is sufficient to define them
    37. front-tier: {}
    38. back-tier: {}
    docker-compose
    1. # get command help
    2. docker-compose --help
    3.  
    4. # start services
    5. # --build, build images from source code instead of loading built images before starting containers
    6. # -d, detached
    7. # docker-compose up [service list]
    8.  
    9. docker-compose up # start all services
    10. docker-compose up webapp # start service webapp
    11. docker-compose -f [composeFileName] up # specify compose file
    12.  
    13. # turn off and remove services
    14. docker-compose down
    15.  
    16. # build images in compose file
    17. docker-compose build
    18.  
    19. # list images of the current compose
    20. docker-compose images
    21.  
    22. # list service of the current compose
    23. docker-compose ps
    24.  
    25. # stop services of the current compose
    26. docker-compose stop [serviceName] # stop a specific service
    27. docker-compose stop # stop services in the current compose
    28.  
    29. # start services
    30. docker-compose start [serviceName] # start a specific service
    31. docker-compose start # start services in the current compose
    32.  
    33. # one-off command
    34. # docker-compose run [serviceName] [command]
    35. docker-compose run webapp env
    36.  
    37. # view the compose file
    38. docker-compose config
    Reference
  • Docker Compose Tutorial: advanced Docker made simple
  • docker-compose CLI
  • Compose File Reference
  • The Compose Specification
  • User Guide