Orchestrating with Docker Compose

Launching multiple containers manually can be a hassle, especially when the infrastructure goes increasingly complex. Dependencies, shared variables, and common networking can be easily handled with the orchestration tool named Docker Compose. In a simply YAML file, we can describe what services are needed to run our application (proxy, application, databases, and so on). In this section, we'll show how to create a simple LAMP docker-compose file, then we'll show how we can iterate from that to build some staging and production specific changes.

Getting ready

To step through this recipe, you will need the following:

  • A working Docker installation
  • A working Docker Compose installation

How to do it…

To orchestrate multiple containers together using Docker Compose, let's start with an easy WordPress example. The team at WordPress built a container that auto-configures to some extent through environment variables similar to what we saw earlier in this chapter. If we just apply the documentation shipped with the WordPress Docker container, we end up with the following docker-compose.yml at the root of some new directory (it can be a Git repository if needed):

version: '2'

services:
  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_PASSWORD: example
  mysql:
    image: mariadb
    environment:
      MYSQL_ROOT_PASSWORD: example

This has the great advantage to work out of the box; the latest WordPress and MariaDB images get downloaded, local HTTP port 80 gets redirected on port 8080 on the host, and MySQL stays isolated. The WordPress container takes one environment variable in this case—the MySQL root password, which should match the environment variable from MySQL. We'll see that many more are possible.

Executing Docker Compose will automatically create a Docker network and run the containers:

$ docker-compose up
[...]
mysql_1      | 2016-12-01 20:51:14 139820361766848 [Note] mysqld (mysqld 10.1.19-MariaDB-1~jessie) starting as process 1 ...
[...]
mysql_1      | 2016-12-01 20:51:15 139820361766848 [Note] mysqld: ready for connections.
[...]
wordpress_1  | [Thu Dec 01 20:51:17.865932 2016] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.10 (Debian) PHP/5.6.28 configured -- resuming normal operations
wordpress_1  | [Thu Dec 01 20:51:17.865980 2016] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

Let's verify we can connect to the WordPress HTTP server locally, on the redirected port 8080:

$ curl -IL http://localhost:8080
HTTP/1.1 302 Found
[...]

HTTP/1.1 200 OK
[...]

More information can be seen using the ps command:

$ docker-compose ps
       Name                      Command               State          Ports
-----------------------------------------------------------------------------------
1basics_mysql_1       docker-entrypoint.sh mysqld      Up      3306/tcp
1basics_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8080->80/tcp

Let's ensure the password used for the MySQL root password is really the one provided by the docker-compose.yml file, using the docker-compose exec command, very similar to the docker run command (it takes docker-compose.yml names):

$ docker-compose exec mysql /usr/bin/mysql -uroot -pexample
[...]

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| wordpress          |
+--------------------+
4 rows in set (0.00 sec)

When we're done with our initial Docker Compose environment, let's destroy it; the containers and networks will be removed:

$ docker-compose down

Extending Docker Compose

Now we know the basics, let's extend the usage a little. We're not happy with the default password and would like to use a better one, so simulate the staging environment. Let's use the overriding feature of Docker Compose for that and create a docker-compose.staging.yml file that will simply override the concerned values:

version: '2'
services:
  wordpress:
    image: wordpress:4.6
    environment:
      WORDPRESS_DB_PASSWORD: s3cur3
  mysql:
    environment:
      MYSQL_ROOT_PASSWORD: s3cur3

The two environment variables WORDPRESS_DB_PASSWORD and MYSQL_ROOT_PASSWORD will be overridden when docker-compose is executed with multiple configuration files taken in order:

$ docker-compose -f docker-compose.yml -f docker-compose.staging.yml up

Verify that the new password is indeed working for MySQL:

$ docker exec -it 1basics_mysql_1 mysql -uroot -ps3cur3
Welcome to the MariaDB monitor.  Commands end with ; or g.
Your MariaDB connection id is 4

We're very easily overriding values with simple YAML files!

Suppose that we now want to include a reverse proxy to the mix, with a slightly earlier version of the Docker image and another MySQL password, to mimic a specific situation we have in production. We can use the excellent dynamic Nginx image from jwilder/nginx-proxy to do this job and add a new proxy service, sharing port 80 and the local Docker socket as read-only (to dynamically access running containers) on a docker-compose.production.yml file:

  proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

This nginx-proxy container needs a variable named VIRTUAL_HOST to know what to answer in case of multiple virtual hosts. Let's add it as localhost (or adapt to your local hostname), along with the better password and the WordPress image version:

  wordpress:
    image: wordpress:4.5
    environment:
      WORDPRESS_DB_PASSWORD: sup3rs3cur3
      VIRTUAL_HOST: localhost

Make the password match in the MySQL section as well and we'll be done with our production environment simulation:

$ docker-compose -f docker-compose.yml -f docker-compose.production.yml up

Confirm nginx-proxy is answering in HTTP/80 and forwarding a proper HTTP answer from the WordPress container:

$ curl -IL http://localhost/
HTTP/1.1 302 Found
Server: nginx/1.11.3
[...]
HTTP/1.1 200 OK
Server: nginx/1.11.3

We've seen how, with only a few lines of YAML, we can easily orchestrate containers, how it can be used to handle different cases and environments, and how it can also be successfully extended. This is, however, just a small introduction to what can be done with Docker Compose—it's quite a powerful tool!

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.121.101