Launch and Orchestrate Docker Containers With Docker Compose

Leave your reply

Introduction

Learn how to install and use Docker Compose. Docker Compose allows you to use a few simple commands to launch multiple containers running individual applications or components. Docker Compose can also be used to automatically link containers and set up container volumes.

If you find yourself using a long string of docker run commands to bring up a set of containers, Docker Compose will save you a lot of work.

Docker Compose Versus Fig

Docker Compose began as a third-party open source project called Fig. Fig proved so popular that the Docker team decided to build an official tool based on the Fig codebase.

Docker Compose replaces Fig, and Fig has been officially deprecated.

Requirements

  • A server running CentOS 7 or Ubuntu 14.04.
  • Docker installed and running on your machine.
  • Basic knowledge of Docker usage and commands.
  • Basic familiarity with using a Dockerfile.
  • Docker Engine installed and running.

Installing Docker Compose

To install Docker Compose, follow the instructions for your operating system.

On Ubuntu 14.04

Install Pip with the command:

sudo apt-get install python-pip

Then install Docker Compose with the command:

sudo pip install docker-compose

On CentOS 7

First, check the Docker Compose Github install page to get the most current URL for the download. The command will look something like:

sudo curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

After the download has completed, make the binary executable with the command:

sudo chmod +x /usr/local/bin/docker-compose

On Mac OS X

On Mac OS X, Docker Compose is installed as part of Docker Toolbox. If you have Docker Toolbox installed, there is no need to install Docker Compose separately.

However, you may want to update the Docker Compose binary to the most recent version before you begin. To do this, check the Docker Compose Github install page to get the most current URL for the download. The command will look something like:

sudo curl -L https://github.com/docker/compose/releases/download/1.7.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

After the download has completed, make the binary executable with the command:

sudo chmod +x /usr/local/bin/docker-compose

Using Docker Compose

Using Docker Compose is a four-step process:

  • Create a directory for the install files.

  • Create a YAML file named docker-compose.yml in that directory.

  • Put the application group launch commands into docker-compose.yml.

  • From inside that directory, use the command docker-compose up to launch the container(s).

For example, you might start by creating a directory for a simple project called hello-world:

sudo mkdir hello-world

And move into that directory:

cd hello-world

Now create a YAML file named docker-compose.yml with the command:

sudo nano docker-compose.yml

This file will contain all of the launch directives for your application group.

The first line of the file needs to read:

version: '2'

This specifies that the file will use Docker Compose version 2, the more recent version. Version 2 allows volumes, networks, and build arguments. It is the official recommended version.

For testing purposes, we will start with a service (container) named compose-test launched from the official CentOS 7 image. Put the following into the docker-compose.yml file:

version: '2'

services:

  compose-test:
    image: centos

Save and exit the file.

Note: Docker Compose is whitespace-sensitive. Be sure to use the correct amount of whitespace. The first line in each block should have no whitespace at the beginning. The other lines should be indented, typically with two spaces per indent level.

Use Docker Compose to launch this test container with the command:

sudo docker-compose up -d

This command runs docker-compose in the background. If you want to see all of the output of docker-compose, run this command without the -d flag.

Remember, you will need to issue this command from inside the hello-world directory.

Verify that the container was created by using the command:

sudo docker-compose ps

Stopping and Deleting Containers

To stop all the containers in an application group, use the command:

sudo docker-compose stop

After the containers have been stopped, you can remove all containers which were started with Docker Compose with the command:

sudo docker-compose rm

To both stop all containers in an application group and remove them all with a single command, use:

sudo docker-compose down

To remove all data volumes as well, add the -v flag:

sudo docker-compose down -v

Docker Compose Commands

There are many commands you can specify in the docker-compose.yml file. The official Docker website has a full list of the commands here. Some of the most popular commands include the following.

Run a Command

If there is a command you want a container to run on launch, add the following to your docker-compose.yml file:

command: [command and arguments]

Example: Launch and Ping

To have our test container ping localhost 5 times upon launch, create a YAML file named docker-compose.yml with the command:

sudo nano docker-compose.yml

Add the following to the file:

version: '2'

services:

  compose-test:
    image: centos
    command: ping -c 5 localhost

Save and exit the file.

To see the results of the ping command, start the application group with the command:

docker-compose up

This will run docker-compose in the foreground, so that the ping output is displayed. Use CTRL-c to exit if necessary.

Link Containers

To link to another service, add the following to your docker-compose.yml file:

links:
  - [service name]

Example: Link and Ping

To add a service named compose-db to our application group and link our test container to it, create a YAML file named docker-compose.yml with the command:

sudo nano docker-compose.yml

Add the following to the file:

version: '2'

services:

  compose-test:
    image: centos
    links:
      - compose-db
    command: ping -c 5 compose-db

  compose-db:
    image: redis

This will test the link by having the compose-test container ping compose-db on launch.

Save and exit the file.

To see the results of the ping command, start the application group with the command:

docker-compose up

This will run docker-compose in the foreground, so that the ping output is displayed. You should see a collection of messages about the containers being launched, ending with ping output which will look something like this:

compose-test_1  | PING compose-db (172.19.0.2) 56(84) bytes of data.
compose-test_1  | 64 bytes from helloworld_compose-db_1.helloworld_default (172.19.0.2): icmp_seq=1 ttl=64 time=0.078 ms
compose-test_1  | 64 bytes from helloworld_compose-db_1.helloworld_default (172.19.0.2): icmp_seq=2 ttl=64 time=0.049 ms
compose-test_1  | 64 bytes from helloworld_compose-db_1.helloworld_default (172.19.0.2): icmp_seq=3 ttl=64 time=0.052 ms
compose-test_1  | 64 bytes from helloworld_compose-db_1.helloworld_default (172.19.0.2): icmp_seq=4 ttl=64 time=0.062 ms
compose-test_1  | 64 bytes from helloworld_compose-db_1.helloworld_default (172.19.0.2): icmp_seq=5 ttl=64 time=0.047 ms
compose-test_1  |
compose-test_1  | --- compose-db ping statistics ---
compose-test_1  | 5 packets transmitted, 5 received, 0% packet loss, time 3998ms
compose-test_1  | rtt min/avg/max/mdev = 0.047/0.057/0.078/0.014 ms

Use CTRL-c to exit if necessary.

Expose Ports

Exposing a port makes the port accessible to linked services, but not from the host machine. To expose a port, add the following to your docker-compose.yml file:

expose: 
  - "[port number]"

Example: Expose a Port

To have our test database expose port 6379 (the default Redis port) and test this connection with a simple curl command from the linked container compose-test, create a YAML file named docker-compose.yml with the command:

sudo nano docker-compose.yml

Add the following to the file:

version: '2'

services:

  compose-test:
    image: centos
    links:
      - compose-db
    command: /usr/bin/curl compose-db:6379

  compose-db:
    image: redis
    expose:
      - "6379"

Save and exit the file.

To see the results of the curl command, start the application group with the command:

docker-compose up

This will run docker-compose in the foreground, so that the curl output is displayed. You should see a collection of messages about the containers being launched, ending with curl output which will look something like this:

compose-db_1    | 1:M 04 May 20:39:12.009 * The server is now ready to accept connections on port 6379
compose-test_1  |   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
compose-test_1  |                                  Dload  Upload   Total   Spent    Left  Speed

This indicates that the curl connection to the server was successful. (No content is returned because we haven't set up the compose-db container to deliver any.)

Use CTRL-c to exit and return to the command prompt.

Build From a Dockerfile

If you want to use a Dockerfile to build a container, put the Dockerfile into the same directory as the application group's docker-compose.yml file. Then use the build directive in place of image.

  build: .

Example: Build a Web Server

To launch a test container running the Apache server from a Dockerfile and test it with Curl from a linked container, begin by creating a directory where the HTML files for the website will be loaded from:

sudo mkdir public-html

Remember to issue this command from inside our hello-world directory, as all paths are relative to your location.

Next, create a simple "Hello world" file with the command:

sudo nano public-html/index.html

Put the following into this file:

Hello world!

Save and exit the file.

Now create the Dockerfile:

sudo nano Dockerfile

Put the following into this file:

FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

This tells Docker to load the contents of the hello-world/public-html directory on the host into /usr/local/apache2/htdocs on the container.

Save and exit the file.

Put the following into the docker-compose.yml file:

version: '2'

services:
  compose-test:
    image: centos
    links:
      - web-test
    command: /usr/bin/curl web-test:80

  web-test:
    build: .
    expose:
      - "80"

Save and exit the file.

To see the results of the curl command, start the application group with the command:

sudo docker-compose up

This will run docker-compose in the foreground, so that the curl output is displayed. You should see a collection of messages about the containers being launched, ending with curl output which will look something like this:

web-test_1      | 172.19.0.3 - - [04/May/2016:21:12:43 +0000] "GET / HTTP/1.1" 200 20
compose-test_1  |   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
compose-test_1  |                                  Dload  Upload   Total   Spent    Left  Speed
100    20  100    20    0     0   3157      0 --:--:-- --:--:-- --:--:--  3333
compose-test_1  | Hello world!

This indicates that the curl connection to the server was successful.

Use CTRL-c to exit and return to the command prompt.

Map Host Ports to Container Ports

To map a port on the container to a port on the host, add the following to your docker-compose.yml file:

ports:
  - "[host port]:[container port]"

Example: Build a Web Server and Map Ports to the Host

For this example we will launch a test container running the Apache server from a Dockerfile, map port 8080 on the container to port 80 on the host, and test it by visiting http://example.com:8080 in a browser.

Begin by creating a directory where the HTML files for the website will be loaded from:

sudo mkdir public-html

Remember to issue this command from inside our hello-world directory, as all paths are relative to your location.

Next, create a simple "Hello world" file with the command:

sudo nano public-html/index.html

Put the following into this file:

Hello world!

Save and exit the file.

Now create the Dockerfile:

sudo nano Dockerfile

Put the following into this file:

FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

This tells Docker to load the contents of the hello-world/public-html directory on the host into /usr/local/apache2/htdocs on the container.

Save and exit the file.

Put the following into the docker-compose.yml file:

version: '2'

services:
  web-test:
    build: .
    ports:
      - "8080:80"

Save and exit the file.

Launch the application group with the command:

sudo docker-compose up -d

Once the container has been launched, switch to a browser and go to the URL http://example.com:8080 or http://192.168.0.1:8080, replacing the domain name or IP address with your own.

You will see the simple "Hello world!" page.

Note: If you are running a firewall, you may need to allow external access to port 8080. If you are running another service on port 8080, feel free to substitute a different port number for this test.

  • You can also check the port mapping by using sudo docker-compose ps. The output for this example will look something like:

    Name                                   Befehl                          Status                   Ports
    -------------------------------------------------------------------------------------------------------------------------------
    helloworld_web-test_1      httpd-foreground      Up                         0.0.0.0.0:8080->80/tcpp

    As you can see, the command includes the port mapping information in the Ports column.

sudo docker-compose up -f filename.yml

This allows you to use multiple YAML files in the same build environment.

For example, you may want one YAML file production.yml for the production build, and another YAML file staging.yml for a staging build. You could then choose between using either:

sudo docker-compose up -f production.yml

or:

sudo docker-compose up -f staging.yml