In the first post, a repository image was download from the Docker Hub Repository. Then a container was run from the repository image and the echo command was executed. In this post, container networking will be introduced and a web browser will be used to access a web server running in a container.
For this walkthrough, the following prerequisites must be met:
- Docker installed for the appropriate platform:
- Mac – Docker for Mac
- Windows with Hyper-V – Docker for Windows
- Windows with Oracle VirtualBox – Docker Toolbox
- At least 4GB of free memory (RAM)
- Available disk space for downloading repository images and running containers (for this post, 1GB will be more than enough)
Note: for this walkthrough, all commands will be illustrated in a PowerShell prompt on Windows. Alternatively, a command prompt on windows or a shell/terminal prompt for Mac can be used as necessary.
In the last post, the Alpine Linux repository container named ‘alpine’ was used to execute the echo command to show the execution of a Docker container. In this post, a new repository image will be used to launch a container that is running a web server (d) on Alpine Linux.
To start the container, use the following command:
docker run d:alpine
After entering the command, Docker will download the repository image (unless it has already been downloaded locally) and then run the container. The difference this time is that the web server process is started and because it has not exited, the container is still running. Furthermore, control has not been returned back to the shell and instead Docker is displaying the logging messages from the d process.
If a new command prompt is opened and the command docker ps is executed (as covered in the previous blog post) the resulting list of running containers will list the container that was just launched:
From this listing, Docker is providing the unique Container ID, the name and tag of the repository image used to launch the container, what command was used at launch, and then statistics about the container’s lifetime. The ‘Names’ value is a randomly generated name for the container. There is a command line option for the Docker command that allows for explicit naming of containers, but that is not necessary for this post.
At this point, it might be believed that a browser can connect to port 80 to see the default paged served by the web server. However, if a browser is used to connect to ://localhost, no site can be reached. Why is that? Read on to find out more.
Before going into specifics as to why the browser cannot access the container’s web server, a brief introduction to how Docker is running on the local computer is in order.
What was likely not noticed at install time is that, when Docker is installed and started, Docker creates a virtual machine (guest) on the computer (host). This guest machine (aka Docker machine) is either a Hyper-V or Oracle VirtualBox Virtual Machine and, for the purposes of this blog series is running a version of Linux. This Docker machine is setup with an internal, virtual network (called DockerNAT on Hyper-V installs) that displays in the host computer’s network adapter list as a virtual network adapter. This virtual network adapter is given an internal IP address allowing the host computer to communicate with the guest virtual machine.
Taking things a step further, the docker pull and docker run commands are downloading the requested repository images into the Docker machine (guest) and creating the containers in the guest machine as well. This means that when a container is started, it can expose a TCP port (such as 80 listed above for the container), but exposing the port, does not make it available to the host system where the web browser is running.
So, to recap, the host computer is running a guest virtual machine (Docker machine) which in turn is locally caching the repository images and running the containers. This is also why if the host computer is searched, there will be no traces of the containers or the repository images. These objects solely exist inside the guest virtual machine.
To access the d processes running in the Docker container, the container port of 80 must be mapped to a port on the guest virtual machine. Since the container is already running without this mapping, it should be stopped and removed. Using the Docker container listing above from the docker ps command, the relevant Docker commands would be:
docker stop 41ee7826a607
docker rm 41ee7826a607
docker rm -f 41ee7826a607
Now, to start the container again with a port mapping, the same docker run command will be used, but the optional ‘-p’ argument is required. The syntax of the argument is ‘-p <external port>:<container port>’. The following command will expose the default port 80 of the d process to the host on port 8080:
docker run -p 8080:80 d:alpine
Like before, the container will be started and the d logs will be displayed without returning control to the shell. Additionally, if the docker ps command is used in another shell instance, there new container will now additionally show the port mapping (as well as have a new Container ID and Name):
This is showing port 8080 of all IP addresses of the host system will be mapped to the container’s port 80 and result in the displaying of the default web page hosted by the web server. Connecting to ://localhost:8080 in a browser on the host computer will now display a web page that succinctly says: “It works!” Additionally, in the command window showing the output of the d process, a web trace line will be written for request to the web server (i.e. an HTTP Get for the default page and likely an HTTP Get for the file favicon.ico).
Like the earlier post, this post would not be complete without a discussion stopping and cleaning up the container.
Stopping and removing the container
The current container is different from the one we discussed in the first post in that the container is still running. At this point, the initial command window displaying the d logs can be returned to the command prompt by pressing CTRL+C. Using the CTRL+C command only exits back to the console prompt, it does not stop the container. To stop and remove the container, refer back to the Port Mapping section above where the container was stopped and removed before adding the ‘-p’ parameter to map the port (docker stop and docker rm commands or docker rm -f).
The next post will look at running Microsoft SQL Server 2017 for Linux in a container for development purposes and, specifically, data persistence with the use of volumes.
Need help deploying or automating containers on-premise or in the cloud? check out our Cloud & Hybrid IT offerings or reach out. We’d love to get you started.