CAPITULO 3 3 RESULTADOS Y DISCUSIÓN
3.1 DESARROLLO DE RUTINAS DE MANTENIMIENTO
So far, we have discussed the four distinct methods to publish a service running inside a container to the outside world. In all these four methods, the port binding decision is taken during the container launch time, and the image has no information about the ports on which the service is being offered. It has worked well so far because the image is being built by us, and we are pretty much aware of the port in which the service is being offered. However, in the case of third-party images, the port usage inside a container has to be published unambiguously. Besides, if we build images for third-party consumption or even for our own use, it is a good practice to explicitly state the ports in which the container offers its service. Perhaps, the image builders could ship a readme document along with the image. However, it is even better to embed the port details in the image itself so that you can easily find the port details from the image both manually as well as through automated scripts. The Docker technology allows us to embed the port information using the EXPOSE instruction in the Dockerfile, which we introduced in Chapter 3, Building Images. Here, let's edit the Dockerfile we used to build the apache2 HTTP server image earlier in this chapter, and add an EXPOSE instruction, as shown in the following code. The default port for the HTTP service is port 80, hence port 80 is exposed:
########################################### # Dockerfile to build an apache2 image ########################################### # Base image is Ubuntu
FROM ubuntu:14.04 # Author: Dr. Peter
MAINTAINER Dr. Peter <[email protected]> # Install apache2 package
apt-get install -y apache2 && \ apt-get clean
# Set the log directory PATH
ENV APACHE_LOG_DIR /var/log/apache2 # Expose port 80
EXPOSE 80
# Launch apache2 server in the foreground
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
Now that we have added the EXPOSE instruction to our Dockerfile, let's move to the next step of building the image using the docker build command. Here, let's reuse the image name apache2, as shown here:
$ sudo docker build -t apache2 .
Having successfully built the image, let's inspect the image to verify the effects of the EXPOSE instruction to the image. As we learnt earlier, we can resort to the docker inspect subcommand, as shown here:
$ sudo docker inspect apache2
On close review of the output generated by the preceding command, you will realize that Docker stores the exposed port information in the ExposedPorts field of the Config object. The following is an excerpt to show how the exposed port information is being displayed:
"ExposedPorts": {
"80/tcp": {} },
Alternatively, you can apply the format option to the docker inspect subcommand in order to narrow down the output to very specific information. In this case, the ExposedPorts field of the Config object is shown in the following example: $ sudo docker inspect --format='{{.Config.ExposedPorts}}' \
apache2 map[80/tcp:map[]]
To resume our discussion on the EXPOSE instruction, we can now spin up containers using an apache2 image, that we just crafted. Yet, the EXPOSE instruction by itself cannot create port binding on the Docker host. In order to create port binding for the port declared using the EXPOSE instruction, the Docker engine provides a -P option in the docker run subcommand.
In the following example, a container is launched from the apache2 image, which was rebuilt earlier. Here, the -d option is used to launch the container in the detached mode, and the -P option is used to create the port binding in the Docker host for all the ports declared, using the EXPOSE instruction in the Dockerfile: $ sudo docker run -d -P apache2
fdb1c8d68226c384ab4f84882714fec206a73fd8c12ab57981fbd874e3fa9074
Now that we have started the new container with the image that was created using the EXPOSE instruction, like the previous containers, let's review the port mapping as well as the NAT entry for the preceding example:
• The following text is an excerpt from the output of the docker ps subcommand that shows the details of this container:
ea3e0d1b18cf apache2:latest "/usr/sbin/apache2ct 5 minutes ago Up 5 minutes 0.0.0.0:49159->80/tcp nostalgic_morse
• The following text is an excerpt from the output of the iptables -t nat -L -n command that shows the DNAT entry created for this container:
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:49159 to:172.17.0.19:80
The -P option of the docker run subcommand does not take any additional
arguments, such as an IP address or a port number; consequently, fine tuning of the port binding is not possible, such as the -p option of the docker run subcommand. You can always resort to the -p option of the docker run subcommand if fine tuning of the port binding is critical to you.
Summary
Containers do not deliver anything in an isolated or solo way substantially. They need to be systematically built and provided with a network interface along with a port number. This leads to a standardized exposition of containers to the outside world, facilitating other hosts or containers to find, bind, and leverage their unique capabilities on any network. Thus, network-accessibility is paramount for containers to get noticed and utilized in innumerable ways. This chapter is dedicated to showcasing how containers are being designed and deployed as a service, and how the aspect of container networking comes in handy by precisely and profusely empowering the peculiar world of container services as the days unfold. In the forthcoming chapters, we will deal and dwell at length on the various capabilities of Docker containers in software-intensive IT environments.