
Running Docker Containers
Containers in Docker are considered ephemeral environments where executables are run, and no state is kept. This is partially true, since the data generated inside the container is only available in the same container. However, Docker Engine provides methods that allow you to share data between the host system and containers. In addition, the services inside the containers are reachable between the host system and other containers.
In this section, we will explain how to run Docker containers using volume and port mapping in order to show how containers are used for stateful services. Running a container starts by running processes, which are packaged as Docker images, as isolated containers. This could be initiated by the docker run command, or programmatically by using the Docker API on local or remote host systems. Docker Engine provides more than just running processes and it can attach networks or volumes, ensure runtime constraints on resources, or add Linux privileges. In this section, the two fundamental capabilities that are presented are port mapping and volume mapping:
Port Mapping: Docker Engine allows containers to connect to the outside world by default, however, it does not allow incoming traffic to containers. There are a couple of docker run options to allow incoming traffic to containers; the first option is to use the --publish-all=true flag to enable all the ports exposed in the container. The required ports for this application can be exposed in Dockerfiles by using the EXPOSE command, and then the --publish-all flag can be used while running them. The second option is to explicitly use the --publish flag with a map of host and container ports; for instance, --publish=8080:80 will map the host port 8080 to the container port 80, as demonstrated in Figure 2.17. Since microservices are designed to implement business operations, having an API and being reachable from the outside world is expected behavior. Docker and container orchestration tools provide reliably-running containers while also enabling network access:

Figure 2.17: Port mapping in Docker
Volume Mapping: Docker is designed so that containers do not contain persistent data. If any data is stored in the writable layer of a container, it will be unavailable when the container is stopped. In order to solve this issue, Docker provides volume-mounting options in the docker run command. It is possible to mount a file or folder from the host filesystem to a running command using the --volume flag. For instance, the --volume=/var/data:/db/data flag will mount the /var/data folder of the host system to the /db/data folder of the container. Mounted files and folders are writable from inside the container so that they are reusable when the containers are restarted.
Mounted volumes from the host system and ephemeral temporary storage in memory are demonstrated in Figure 2.18. Although containers are considered for ephemeral business operations, containerization with volume capabilities makes it possible to run and manage stateful applications such as databases:

Figure 2.18: Volume mapping in Docker containers
In the following exercise, we will run the Docker image of the web server from the previous exercise using host volume mapping and port sharing. By doing so, we will demonstrate how you can manage the data and networking of containers when they run at scale.
Exercise 7: Running Docker Containers, Volume Mapping, and Port Sharing
In this exercise, we aim to run the web server container using host volume mapping and port sharing.
To complete this exercise, we need to ensure the following steps are executed:
- Create a text file with the index.html name, and the following content.
This file consists of a simple HTML page with a Hello DevOps World header:
<html>
<body>
<h1>Hello DevOps World</h1>
</body>
</html>
Note
index.html is already available at https://github.com/TrainingByPackt/Introduction-to-DevOps-with-Kubernetes/blob/master/Lesson02/index.html
- Start the container using the following command:
docker run -it \
-p 8080:8080 \
-v ${PWD}:/usr/apps/hello-world/ \
<USERNAME>/webserver:latest
Figure 2.19: The output of the docker run command
Using this command, a volume is mapped from the pathname of the current Working Directory ($PWD) to /usr/apps/hello-world/, where the web server inside the container is running. Additionally, port 8080 from the host system is mapped to port 8080 of the container. This indicates that the container will be reachable from the 8080 port of the host system.
- Check the running containers in another Terminal, as follows:
docker ps
Figure 2.20: The output of the docker ps command
You can expect to see an instance of <USERNAME>/webserver with a status that is similar to Up About a minute and the published ports.
- Open http://localhost:8080 in a browser, as follows:
Figure 2.21: The web server in the browser
This shows that the web server is working and that the container is reachable through host port mapping. In addition, the output shows the file created in Step 1, which also indicates that volume mapping is working.
- Stop the container started in Step 2 using the Ctrl + C command.
In this exercise, we demonstrated how you can run a stateful container that is reachable from the host system. In the following activity, we will create a stateful database instance using Docker containers and a WordPress blog instance to connect to the database and run coherently.
Activity 2: Installing a WordPress Blog and Database Using Docker
The aim of this activity is to install and manage a MySQL database and WordPress blog using Docker containers. WordPress is based on PHP and is a free and open source content management system. It needs a MySQL database as its data source for user and content management. In this activity, both the database and blog containers should be ephemeral, however, persistent data should be kept on the host system. Additionally, these two containers should interact with each other using Docker functionalities.
Note
WordPress is the most popular content management system on the internet, and it is used by more than 60 million websites, including 30.6% of the top 10 million websites as of April 2018. It can be found at https://wordpress.org/.
MySQL is an open source relational database, which was first released in 1995, and is still one of the most popular database management systems with more than six million installations. It can be found at https://www.mysql.com/.
Using the Docker commands from the previous exercises in this chapter, you can expect to have two containers running and communicating with each other. With the successful start of the WordPress container, you should see the setup screens as follows:

Figure 2.22: The setup steps for installing WordPress
After setup, the new blog should be up and running, as follows:

Figure 2.23: The home page of the WordPress blog
Execute the following steps to complete this activity:
- Create a folder named data. This folder will keep the stateful state of the database in the next steps.
- Start a MySQL container using the official Docker image and the following specifications:
Use the data folder from Step 1 as the database file. Publish port 3306 to the local system. Set the MYSQL_ROOT_PASSWORD environment variable as rootPassword. Set the MYSQL_DATABASE environment variable as database. Set the MYSQL_USER environment variable as user. Set the MYSQL_PASSWORD environment variable as password. Use mysql as the name of the container. Use the mysql:5.7 container image
Wait for the MySQL container to be ready using a similar logline to [Note] mysqld: ready for connections.
- Start a WordPress container using the following specification:
Publish port 80 of the container to port 8080 of the host system. Link the mysql container using the db name. Set the WORDPRESS_DB_HOST environment variable as db:3306. Set the WORDPRESS_DB_NAME environment variable as database. Set the WORDPRESS_DB_USER environment variable as user. Set the WORDPRESS_DB_PASSWORD environment variable as password. Use WordPress as the name of the container. Use the latest WordPress container image.
- Open http://localhost:8080 in the browser and fill out the WordPress setup form.
- Open http://localhost:8080 in the browser and check that your new blog is running in the containers.
- Stop the running containers and remove the data folder.
Note
The solution of this activity can be found on page 304.
In this activity, we have presented how to operate a WordPress blog and its database on the same host using Docker. With this basic activity of running a single instance blog, you can imagine how difficult it is to run and manage hundreds of blogs and databases in a cloud environment. For instance, it is a fundamental problem if two blog containers are using the same HTTP ports and running on the same host. Additionally, consider running a database container with volume mapping and what will happen if the node is broken; in this instance, the container could start running on another node, but its node will not have the data at all. Operational problems like this and many more are already being embraced by Kubernetes in order to run reliable and scalable applications, and this will be explained in Chapter 3, Introduction to Kubernetes.