Skip to content
This repository has been archived by the owner on Aug 26, 2021. It is now read-only.

Docker Compose Support

Miroslav Shipkovenski edited this page Apr 19, 2017 · 8 revisions

Intro

Docker Compose

Docker Compose is a tool that lets you define complex multi-container applications in YAML formatted text files (usually named docker-compose.yml) and then deploy these application with a single simple command:

docker-compose up

In the docker-compose file it is possible to define multiple services (containers) with their specific properties (e.g. volume mounts port mappings, links, etc.). Is is also possible to specify a Docker file that defines how to build specific images that cannot be found in existing registries.

Docker Compose in Admiral

It is possible to import docker-compose templates in Admiral by navigating to the templates view and clicking on the "Import template or Docker Compose" button.

Import docker-compose template in Admiral

You will be prompted to either to upload the docker-compose template or to enter its contents yourself. Both options lead to the same result - after pressing the import button, the docker-compose is converted to a template and stored in Admiral. However, the current version of Admiral started its development when there was no networking in Docker. Since networking is now the recommended way to provide means of communication between containers, most of the docker-compose files that one may find on the Internet (e.g. in Docker hub containers' documentation) need some slight modifications to work correctly in Admiral. In the following sections the differences between standard and Admiral supported docker-compose files will be discussed.

Differences between current Docker Compose and Admiral

In all of the following, only Docker Compose file format version 2 is considered.

Admiral supports only single-file docker-compose templates

This means that the following are currently not going to work:

  • Define environment variables in separate .env file
  • Splitting docker-compose file in separate files that extend one another
  • Other similar use-cases

It is not possible to build images in Admiral

In Docker Compose there is an option to specify instructions on how to build a specific image that cannot be found in existing registries by using the build key. In the simplest case, the value of this key is the path to the build context (e.g. directory that contains a Dockerfile). In Admiral building images is not possible as this feature makes more sense for development and testing purposes. The recommended way to deal with compose files the build key is to actually build the images and push them to a registry that is accessible from all Docker hosts.

Docker Compose file modifications in examples

Wordpress template

The current Wordpress docker-compose template can be found on https://hub.docker.com/_/wordpress/:

Original Wordpress docker-compose.yml

version: '2'

services:

  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: example

  mysql:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example

This template can be successfully imported and even provisioned in Admiral. However, this template implies that wordpress and mysql services are in the same Docker network, so wordpress will be able to connect to mariadb using th mysql hostname. Since Admiral currently does not support creation of implicit networks, one needs to be declared.

Below is shown the modified version of the docker-compose file that can be imported in Admiral and will result in a working provisioned wordpress application. All the mandatory changes are documented with a Added for Admiral comment.

Modified Wordpress docker-compose.yml

version: '2'

services:

  wordpress:
    image: wordpress
#   Mapped to random host port instead of 8080 (optional)
    ports:
      - 80
    environment:
      WORDPRESS_DB_PASSWORD: example
#   Added for Admiral
    networks:
      - wpnet

  mysql:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example
#   Added for Admiral
    networks:
      - wpnet

#   Added for Admiral
networks:
  wpnet: {}

Example voting application

This is a simple multi-container application that can be found on GitHub. Schematic representation is shown (source: GitHub page of the project) voting app architecture

The developers of this application describe the architecture of the application as follows:

  • A Python webapp which lets you vote between two options
  • A Redis queue which collects new votes
  • A Java worker which consumes votes and stores them in…
  • A Postgres database backed by a Docker volume
  • A Node.js webapp which shows the results of the voting in real time

Building the images and pushing to registry

The example voting application features five containers, three of which are build from sources: vote, worker and result. As we explained before, it is not possible to build images in Admiral. Thus, we need to manually build these images and push them to a registry of our choice before doing any modifications to the docker-compose file.

First of all, we need a registry. It is possible to use Docker hub or any other registry. This has been tested with Docker registry deployed in a container on a virtual host.

Then we need to build the three custom images. Clone the project from GitHub and from the project root execute the following (replace 192.168.99.101:5000 with the IP/hostname and port of your registry. If you are using docker hub, you can omit the address but need to specify your username instead of test):

docker build -t 192.168.99.101:5000/test/vote vote/ && docker build -t 192.168.99.101:5000/test/worker worker/ && docker build -t 192.168.99.101:5000/test/result result/

This will build the images and will also tag them so you can easily push them with the following command (again tweak this according to your registry):

docker push 192.168.99.101:5000/test/vote && docker push 192.168.99.101:5000/test/worker && docker push 192.168.99.101:5000/test/result

Edit the docker-compose file

Original example-voting-app docker-compose.yml

version: "2"

services:
  vote:
    image: eesprit/voting-app-vote
    command: python app.py
    ports:
      - "80"
    networks:
      - front-tier
      - back-tier

  result:
    image: eesprit/voting-app-result
    command: nodemon --debug server.js
    ports:
      - "80"
      - "5858"
    networks:
      - front-tier
      - back-tier

  worker:
    image: eesprit/voting-app-worker
    networks:
      - back-tier

  redis:
    image: redis:alpine
    container_name: redis
    ports: ["6379"]
    networks:
      - back-tier

  db:
    image: postgres:9.4
    container_name: db
    volumes:
      - "db-data:/var/lib/postgresql/data"
    networks:
      - back-tier

volumes:
  db-data:
    driver: local

networks:
  front-tier: {}
  back-tier: {}

Replace build with image key

Since it is not possible to build images with Admiral, every build declaration must be dropped. Here the images that were previously pushed to some private registry can be used instead. Just do the following:

...
#    build: ./vote
    image: 192.168.99.101:5000/test/vote
...
#    build: ./worker
    image: 192.168.99.101:5000/test/worker
...
#    build: ./result
    image: 192.168.99.101:5000/test/result
...

Publish ports. Optionally map them to random host ports

Actually, the original docker-compose.yml file specifies most of the ports that are being in use. Optionally, you may drop the host ports declarations. This way the application will still be working as expected, but it will be possible to provision more than one instance of this application on a single host.

Comment out or tweak volumes (optional)

The original docker-compose.yml file sets up a volume mapping that allows the developer to actually change the code that is running in the containers without redeploying the application. This implies that the code is being developed on the same host that the docker daemon runs (or least that there is a filesystem mount over the network). If this is not the case, just comment out the volumes declarations and everything will work fine. If you want to have the volume mappings, specify an absolute path mappings.

Modified docker-compose file

All the discussed modifications (including the optional ones) can be seen in this modified docker-compose.yml file Modified example-voting-app docker-compose.yml

version: "2"
services:
  vote:
#    build: ./vote
    image: 192.168.99.101:5000/test/vote
#   command: python app.py
    command: ["python", "app.py"]
#    volumes:
#     - ./vote:/app
    ports:
      - "80"
    networks:
      - front-tier
      - back-tier
  redis:
    image: redis:alpine
#   added host port for test purposes
    ports: ["6379"]
    networks:
      - back-tier
  worker:
#    build: ./worker
    image: 192.168.99.101:5000/test/worker
    networks:
      - back-tier
  db:
    image: postgres:9.4
    networks:
      - back-tier
  result:
#    build: ./result
    image: 192.168.99.101:5000/test/result
#   command: nodemon --debug server.js
    command: ["nodemon", "--debug", "server.js"]
#    volumes:
#      - ./result:/app
    ports:
      - "80"
      - "5858"
    networks:
      - front-tier
      - back-tier

networks:
# {} is Added for Admiral
  front-tier: {}
  back-tier: {}

Provision the example voting application

These changes should result in a template that will be successfully imported in Admiral and will provision working applications. To test the application, click the link on the vote container and vote for your favorite pet. Check your vote by clicking on the results container link.