This article is going to introduce Docker Compose and show how to put it to work for your needs. We will install it, write a simple Compose file and launch the container.
We will then see how to launch multiple containers. Then we will see how to build images and lately how to use multiple Compose files to launch containers in different environments, like development and production, for example.
In this tutorial you will learn:
- How to install Docker Compose
- How to write a simple Compose file
- How to execute docker-compose commands to start and stop containers
- How to launch multiple containers
- How to build images with Docker Compose
- How to override using multiple Docker Compose files
Software Requirements and Conventions Used
Category | Requirements, Conventions or Software Version Used |
---|---|
System | Ubuntu 18.04 |
Software | Docker Compose |
Other | Privileged access to your Linux system as root or via the sudo command. |
Conventions |
# – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux commands to be executed as a regular non-privileged user |
Introduction
We have so far seen how Docker is great for managing images and starting containers. But frequently applications require that different containers are up and communicating with each other. Connecting them through the network, making them share disk volumes, and passing environment variables can easily turn into a sequence of commands that are difficult to document and maintain over time. There enters Docker Compose. Let’s start installing it and then write the Compose file.
Installing Docker Compose
In Ubuntu 18.04 installing Docker Composer is straightforward:
# apt install docker-compose
To test it is installed you can check it’s version:
$ docker-compose -v docker-compose version 1.17.1, build unknown
Docker Engine and Docker Compose versions are important since their releases are frequent and features are added and removed. The version shown above (1.17.1) was released in November 2017. If you need a newer release, you may either enable Ubuntu’s Universe repository and get a newer package, or even download and install the latest release directly from the Docker Compose website:
# curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # sudo chmod +x /usr/local/bin/docker-compose
The Docker Compose File
Docker Compose reads a YAML file, which is usually named docker-compose.yml
.
version: "3"
services:
apache:
image: php:7.3-apache
container_name: 'apache'
ports:
- "80:80"
volumes:
- ./www:/var/www/html
In the beginning, the syntax version is informed as 3. Next, in the services section, only one container is specified (apache) and the tags image
, container_name
, ports
, and volumes
are used to describe how it shall be executed.
Now create a directory named www
and drop this index.html
file inside.
<html> <body> Hello </body> </html>
Next, to test PHP is working just drop this file inside www
.
<?php phpinfo(); ?>
Docker Compose Commands
The up
command will take care of everything: download the images from Docker Hub if they don’t still exist in the local cache, build custom images (which is not the case; we’ll cover that int he next section) and start the containers.
$ docker-compose up -d
The -d
switch instructs Docker Compose to run containers in the background. In case another filename is used, instead of docker-compose.yml
, it can be informed with -f
.
Notice that the launch command is much simpler than it’s docker
run counterpart. It has two more advantages: it doesn’t change regardless of the content of the Compose file, and if the Compose file specifies more than one container, all of them will be started. Just for comparison, the docker run command would be:
$ docker run -d --name='apache-alone' -p 80:80 -v $PWD/www:/var/www/html php:7.3-apache
Because the Compose file syntax is YAML, indentation matters. If you get syntax errors, check the YAML syntax with an online parser, like this one.
You can check the container is running.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3937d997e029 php:7.3-apache "docker-php-entrypoi…" 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp apache
Now access http://localhost
in your preferred browser and then http://localhost/phpinfo.php
.
Launching multiple containers
Let’s now see a more complex Compose file. Let’s imagine we are going to setup a local environment to develop a LAMP application. We need a container with Apache and PHP, another container with MySQL, and possibly a PHPMyAdmin container to interact with MySQL. The docker-compose.yml
will be:
version: "3"
services:
apache:
image: php:7.3-apache
container_name: 'apache'
restart: 'always'
ports:
- "80:80"
- "443:443"
volumes:
- ./www:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
- ./sites-enabled:/etc/apache2/sites-enabled
- apache-logs:/var/log/apache2
mysql:
image: mariadb:10.4
container_name: 'mysql'
restart: 'always'
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: somepassword
MYSQL_DATABASE: db_site
MYSQL_USER: user
MYSQL_PASSWORD: password
phpmyadmin:
image: phpmyadmin/phpmyadmin:4.8
container_name: 'phpmyadmin'
environment:
PMA_HOST: mysql
PMA_PORT: 3306
ports:
- '8080:80'
volumes:
apache-logs:
mysql-data:
This Compose file is launching three containers, each has a section under services. Notice we are defining some environment variables under environment
. The restart: always
definition is instructing Docker to start the containers automatically when the Docker service is started (in case of a reboot, for example).
The command to start the three containers is the same as in the previous simple example. Easy to remember, right?
$ docker-compose up -d
Check the containers are created.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f76ece3508fe phpmyadmin/phpmyadmin:4.8 "/run.sh supervisord…" 20 seconds ago Up 4 seconds 9000/tcp, 0.0.0.0:8080->80/tcp phpmyadmin
69b1b5054f3d mariadb:10.4 "docker-entrypoint.s…" 20 seconds ago Up 6 seconds 3306/tcp mysql
6747d7580dac php:7.3-apache "docker-php-entrypoi…" 2 days ago Up 14 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp apache
It’s interesting to notice that the containers can communicate through their names and access each other’s ports without the need to expose their ports to the host. For example, we didn’t expose port 3306 of MySQL service (as can be seen in the output above), but PHPMyAdmin is able to access this port. To access PHPMyAdmin, go to http://localhost:8080
and log in with user and password defined in MySQL service (user / password).
Building Images With Docker Compose
If you need to build an image, instead of using an existing one, just add a build
tag. In the example below, we are telling Docker Compose to look into the current directory for a Dockerfile. The image tag will be used to name the new image.
version: "3"
services:
apache:
build: .
image: my-image-name
container_name: 'apache'
restart: 'always'
ports:
- "80:80"
Override Using Multiple Docker Compose Files
Docker Compose makes easy to customize the launch of containers for different environments. You just need to create the called override files and launch the containers specifying them. They will overwrite previous definitions made in the base Compose file.
For example, let’s create an override file named docker-compose-prod.yml
and define a different password for MySQL.
version: "3"
services:
mysql:
environment:
MYSQL_ROOT_PASSWORD: somepassword_other
MYSQL_DATABASE: db_site_other
MYSQL_USER: user_other
MYSQL_PASSWORD: password_other
You can use another host to start the containers. If you are using the same host, it’s needed to delete the mysql container and it’s associated volume. Otherwise, the existing container with the old credentials will be used.
$ docker stop mysql $ docker rm mysql $ docker volume ls $ docker volume rm directory_mysql-data
And then you can execute the command below. It’s important to keep the order of the files. Multiple files can be used. In our example, only the environment
section of mysql
service will be overridden.
$ docker-compose -f docker-compose.yml -f docker-compose-prod.yml up -d
After checking the containers are running, try to access PHPMyAdmin using the new credentials.
Conclusion
This article introduced Docker Compose, a handy tool to orchestrate the launch of multiple containers in the same host. There are many possibilities and reading the Docker Compose manual is highly recommended. In the next articles, we are going to explore ways to orchestrate Docker containers among multiple hosts.