Chapter 10. Docker Compose

In this chapter, we will be taking a look at Docker Compose. We will break the chapter down into the following sections:

  • Installing Docker Compose
  • Docker Compose YAML file
  • Docker Compose usage
  • The Docker Compose commands
  • The Docker Compose examples

Linking containers

One of the prominent features of the Docker technology is linking containers. That is, cooperating containers can be linked together to offer complex and business-aware services. The linked containers have a kind of source-recipient relationship, wherein the source container gets linked to the recipient container, and the recipient securely receives a variety of information from the source container. However, the source container would know nothing about the recipients to which it is linked to. Another noteworthy feature of linking containers, in a secured setup, is that the linked containers can communicate using secured tunnels without exposing the ports used for the setup, to the external world.

The Docker engine provides the --link option in the docker run subcommand to link a source container to a recipient container.

The format of the --link option is as follows:

--link <container>:<alias>

Here, <container> is the name of the source container and <alias> is the name seen by the recipient container. The name of the container must be unique in a Docker host, whereas alias is very specific and local to the recipient container, and hence, the alias need not be unique to the Docker host. This gives a lot of flexibility towards implementing and incorporating functionalities with a fixed source alias name inside the recipient container.

When two containers are linked together, the Docker engine automatically exports a few environment variables to the recipient container. These environment variables have a well-defined naming convention, where the variables are always prefixed with capitalized form of the alias name. For instance, if src is the alias name given to the source container, then the exported environment variables would begin with SRC_. Docker exports three categories of environment variables, as enumerated here:

  • NAME: This is the first category of environment variables. This variable takes the form of <ALIAS>_NAME, and it carries the recipient container’s hierarchical name as its value. For instance, if the source container’s alias is src and the recipient container’s name is rec, then the environment variable and its value would be SRC_NAME=/rec/src.
  • ENV: This is the second category of environment variables. These variables export the environment variables configured in the source container by the -e option of the docker run subcommand or the ENV instruction of Dockerfile. This type of an environment variable takes the form of <ALIAS>_ENV_<VAR_NAME>. For instance, if the source container’s alias is src and the variable name is SAMPLE, then the environment variable would be SRC_ENV_SAMPLE.
  • PORT: This is the final and third category of environment variables that is used to export the connectivity details of the source container to the recipient. Docker creates a bunch of variables for each port exposed by the source container through the -p option of the docker run subcommand or the EXPOSE instruction of the Dockerfile.

These variables take the form:

*<ALIAS>_PORT_<port>_<protocol>

This form is used to share the source’s IP address, port, and protocol as an URL. For example, if the source container’s alias is src, the exposed port is 8080, the protocol is tcp, and the IP address is 172.17.0.2, then the environment variable and its value would be SRC_PORT_8080_TCP=tcp://172.17.0.2:8080. This URL further splits into the following three environment variables:

  • <ALIAS>_PORT_<port>_<protocol>_ADDR: This form carries the IP address part of the URL (for example: SRC_PORT_8080_TCP_ADDR=172.17.0.2)
  • <ALIAS>_PORT_<port>_<protocol>_PORT: This form carries the port part of the URL (for example: SRC_PORT_8080_TCP_PORT=8080)
  • <ALIAS>_PORT_<port>_<protocol>_PROTO: This form carries the protocol part of the URL (for example: SRC_PORT_8080_TCP_PROTO=tcp)

In addition to the preceding environment variables, the Docker engine exports one more variable in this category, that is, of the form <ALIAS>_PORT, and its value would be the URL of the lowest number of all the exposed ports of the source container. For instance, if the source container’s alias is src, the exposed port numbers are 7070, 8080, and 80, the protocol is tcp, and the IP address is 172.17.0.2, then the environment variable and its value would be SRC_PORT=tcp://172.17.0.2:80.

Docker exports these auto-generated environment variables in a well-structured format so that they can be easily discovered programmatically. Thus, it becomes very easy for the recipient container to discover the information about the source container. In addition, Docker automatically updates the source IP address and its alias as an entry in the recipient’s /etc/hosts file.

In this chapter, we will take you deep into the mentioned features provided by the Docker engine for container linkage through a bevy of pragmatic examples.

To start with, let’s choose a simple container linking example. Here, we will show you how to establish a linkage between two containers, and transfer some basic information from the source container to the recipient container, as illustrated in the following steps:

  1. We begin by launching an interactive container that can be used as a source container for linking, using the following command:
    $ sudo docker run --rm --name example -it busybox:latest
    

    The container is named example using the --name option. In addition, the --rm option is used to clean up the container as soon as you exit from the container.

  2. Display the /etc/hosts entry of the source container using the cat command:
    / # cat /etc/hosts
    172.17.0.3      a02895551686
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    

    Here, the first entry in the /etc/hosts file is the source container’s IP address (172.17.0.3) and its hostname (a02895551686).

  3. We will continue to display the environment variables of the source container using the env command:
    / # env
    HOSTNAME=a02895551686
    SHLVL=1
    HOME=/root
    TERM=xterm
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    PWD=/
    
  4. Now that we have launched the source container, from another terminal of the same Docker host, let’s launch an interactive recipient container by linking it to our source container using the --link option of the docker run subcommand, as shown here:
    $ sudo docker run --rm --link example:ex -it busybox:latest
    

    Here, the source container named example is linked to the recipient container with ex as its alias.

  5. Let’s display the content of the /etc/hosts file of the recipient container using the cat command:
    / # cat /etc/hosts
    172.17.0.4      a17e5578b98e
    127.0.0.1       localhost
    ::1     localhost ip6-localhost ip6-loopback
    fe00::0 ip6-localnet
    ff00::0 ip6-mcastprefix
    ff02::1 ip6-allnodes
    ff02::2 ip6-allrouters
    172.17.0.3      ex
    

    Of course, as always, the first entry of the /etc/hosts file is the container’s IP address and its hostname. However, the noteworthy entry in the /etc/hosts file is the last entry, where the source container’s IP address (172.17.0.3) and its alias (ex) are added automatically.

  6. We will continue to display the recipient container’s environment variable using the env command:
    / # env
    HOSTNAME=a17e5578b98e
    SHLVL=1
    HOME=/root
    EX_NAME=/berserk_mcclintock/ex
    TERM=xterm
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    PWD=/
    

    Apparently, a new EX_NAME environment variable is added automatically to /berserk_mcclintock/ex, as its value. Here EX is the capitalized form of the alias ex and berserk_mcclintock is the auto-generated name of the recipient container.

  7. As a final step, ping the source container using the widely used ping command for two counts, and use the alias name as the ping address:
    / # ping -c 2 ex
    PING ex (172.17.0.3): 56 data bytes
    64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.108 ms
    64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.079 ms
    
    --- ex ping statistics ---
    2 packets transmitted, 2 packets received, 0% packet loss
    round-trip min/avg/max = 0.079/0.093/0.108 ms
    

Evidently, the source container’s alias ex is resolved to the IP address 172.17.0.3, and the recipient container is able to successfully reach the source. In the case of secured container communication, pinging between containers is not allowed. We have given more details on the aspect of securing containers in Chapter 11, Securing Docker Containers.

In the preceding example, we could link two containers together, and also, observe how elegantly, networking is enabled between the containers by updating the source container’s IP address in the /etc/hosts file of the recipient container.

The next example is to demonstrate how container-linking exports the source container’s environment variables, which are configured using the -e option of the docker run subcommand or the ENV instruction of Dockerfile, to the recipient container. For this purpose, we are going to craft a Dockerfile with the ENV instruction, build an image, launch a source container using this image, and then launch a recipient container by linking it to the source container:

  1. We begin with composing a Dockerfile with the ENV instruction, as shown here:
    FROM busybox:latest
    ENV BOOK=”Learning Docker” 
        CHAPTER=”Orchestrating Containers”

    Here, we are setting up two environment variables BOOK and CHAPTER.

  2. Proceed with building a Docker image envex using the docker build subcommand from the preceding Dockerfile:
    $ sudo docker build -t envex .
    
  3. Now, let’s launch an interactive source container with the name example using the envex image, we just built:
    $ sudo docker run -it --rm 
                      --name example envex
    
  4. From the source container prompt, display all the environment variables by invoking the env command:
    / # env
    HOSTNAME=b53bc036725c
    SHLVL=1
    HOME=/root
    TERM=xterm
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    BOOK=Learning Docker
    CHAPTER=Orchestrating Containers
    PWD=/
    

    In all the preceding environment variables, both the BOOK and the CHAPTER variables are configured with the ENV instruction of the Dockerfile.

  5. As a final step, to illustrate the ENV category of environment variables, launch the recipient container with the env command, as shown here:
    $ sudo docker run --rm --link example:ex 
                      busybox:latest env
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=a5e0c07fd643
    TERM=xterm
    EX_NAME=/stoic_hawking/ex
    EX_ENV_BOOK=Learning Docker
    EX_ENV_CHAPTER=Orchestrating Containers
    HOME=/root
    

Strikingly, in the preceding output, the variables that are prefixed with EX_ are the outcomes of container-linking. The environment variables of interest are EX_ENV_BOOK and EX_ENV_CHAPTER, which were originally set through the Dockerfile as BOOK and CHAPTER but modified to EX_ENV_BOOK and EX_ENV_CHAPTER, as an effect of container-linking. Though the environment variable names get translated, the values stored in these environment variables are preserved as is. We already discussed the EX_NAME variable name in the previous example.

In the preceding example, we could experience how elegantly and effortlessly Docker exports the ENV category variables from the source container to the recipient container. These environment variables are completely decoupled from the source and the recipient, thus the change in the value of these environment variables in one container does not impact the other. To be even more precise, the values the recipient container receives are the values set during the launch time of the source container. Any changes made to the value of these environment variables in the source container after its launch has no effect on the recipient container. It does not matter when the recipient container is launched because the values are being read from the JSON file.

In our final illustration of linking containers, we are going to show you how to take advantage of the Docker feature to share the connectivity details between two containers. In order to share the connectivity details between containers, Docker uses the PORT category of environment variables. The following are the steps used to craft two containers and share the connectivity details between them:

  1. Craft a Dockerfile to expose port 80 and 8080 using the EXPOSE instruction, as shown here:
    FROM busybox:latest
    EXPOSE 8080 80
  2. Proceed to build a Docker image portex using the docker build subcommand from the Dockerfile, we created just now, by running the following command:
    $ sudo docker build -t portex .
    
  3. Now, let’s launch an interactive source container with the name, example using the earlier built image portex:
    $ sudo docker run -it --rm 
                      --name example portex
    
  4. Now that we have launched the source container, let’s continue to create a recipient container on another terminal by linking it to the source container, and invoke the env command to display all the environment variables, as shown here:
    $ sudo docker run --rm --link example:ex 
                      busybox:latest env
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=c378bb55e69c
    TERM=xterm
    EX_PORT=tcp://172.17.0.4:80
    EX_PORT_80_TCP=tcp://172.17.0.4:80
    EX_PORT_80_TCP_ADDR=172.17.0.4
    EX_PORT_80_TCP_PORT=80
    EX_PORT_80_TCP_PROTO=tcp
    EX_PORT_8080_TCP=tcp://172.17.0.4:8080
    EX_PORT_8080_TCP_ADDR=172.17.0.4
    EX_PORT_8080_TCP_PORT=8080
    EX_PORT_8080_TCP_PROTO=tcp
    EX_NAME=/prickly_rosalind/ex
    HOME=/root
    

From the preceding output of the env command, it is quite evident that, the Docker engine exported a bunch of four PORT category environment variables for each port that was exposed using the EXPOSE instruction in the Dockerfile. In addition, Docker also exported another PORT category variable EX_PORT.

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

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