Environment variables adjust settings for a single container. The same approach can be used to start a multi-tier application where one container or application works alongside the other:
Multi-tier application example
In a multi-tier application, both the application server container and database server container may need to share variables such as database login credentials. Of course, we can pass all database connectivity settings to the application container using environment variables. It is very easy to make a mistake while passing multiple -e options to the docker run command, and it is very time-consuming, not to mention that it is very ineffective. Another option is to use container IP addresses to establish connections. We can gather IP address information using docker inspect but it will be difficult to track this information in a multi-container environment.
This means that using environment variables is just not enough to build multi-tier applications where containers depend on each other.
Docker has a featured called linked containers to solve this problem. It automatically copies all environment variables from one container to another. Additionally, by linking containers, we can define environment variables based on the other container's IP address and exposed ports.
Using linked containers is done by simply adding the --link container:alias option to the docker run command. For example, the following command links to a container named MariaDB using the DB alias:
$ docker run --link mariadb:db --name my_application httpd
The new my_application container will then get all variables defined from the linked container mariadb. Those variable names are prefixed by DB_ENV_ so as not to conflict with the new container's own environment variables.
Please be aware that the aliases are all uppercase.
Variables providing information about container IP addresses and ports are named according to the following scheme:
- {ALIAS}_PORT_{exposed-port}_TCP_ADDR
- {ALIAS}_PORT_{exposed-port}_TCP_PORT
Continuing with the MariaDB image example, the application container would get the following variables:
- DB_PORT_3306_TCP_ADDR
- DB_PORT_3306_TCP_PORT
If the linked container exposes multiple ports, each of them generates a set of environment variables.
Let's take an example. We will be creating a WordPress container which needs access to a database server. This integration will require shared database access credentials. The first step in creating this application is to create a database server:
$ docker rm -f $(docker ps -qa)
$ docker run -d --name mariadb -e MYSQL_ROOT_PASSWORD=wordpress -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=password mariadb
221462288bc578511154fe79411de002e05f08642b63a72bc7a8f16f7102e52b
The next step is to run a WordPress container. In that command, we will link the wordpress container with the mariadb container:
$ docker run -d --name wordpress --link mariadb:mysql -p 8080:80 wordpress
Unable to find image 'wordpress:latest' locally
Trying to pull repository docker.io/library/wordpress ...
latest: Pulling from docker.io/library/wordpress
...
output truncated for brevity
...
Digest: sha256:670e4156377063df1a02f036354c52722de0348d46222ba30ef6a925c24cd46a
1f69aec1cb88d273de499ca7ab1f52131a87103d865e4d64a7cf5ab7b430983a
Let's check container environments with the docker exec command:
$ docker exec -it wordpress env|grep -i mysql
MYSQL_PORT=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
...
output truncated for brevity
...
You can see all these variables because the WordPress container startup script handles the mysql link. We can see here that the link set a number of MYSQL_ENV and MYSQL_PORT variables, which are used by the WordPress startup script.