In the article Introduction to Docker I talked about the general purpose of docker – providing a platform to run software in a controlled environment. In this article I will show how to create Docker containers from images, running Docker containers and providing the required arguments.
To create a Docker container, you first need to decide which Image to take as a base. This will usually be a specific software solution (e.g. a webserver or a database server), or it can even be an empty base linux system (e.g. Debian Jessie).
In Docker, there is a convention for image names: [REGISTRY_HOST/][USERNAME/]NAME[:TAG]
- REGISTRY_HOST can be a custom URL of the registry where the image is hosted. If the image is hosted on official Docker-Hub, it can be left empty, as Docker will find and download the image automatically. Otherwise it can be a domain of your organization, e.g. docker.yourcompany.com , where docker will search for the image if it is not already available on the host machine.
- USERNAME is an optional argument, if the image is not an official one. Everone can create an account on Docker Hub and provide images with their username as prefix, e.g. johndoe/myimage .
- NAME: This is the general name for the image. For Docker images containing server service programs it is usual to use the name of the program as image name, e.g. “ mysql ” for the official image containing a MySQL database server.
- TAG: With tags you can differentiate between multiple version of the same image. E.g. you can create a new tag each time new version of the software is released, e.g. “mysql:5.5”, “mysql:5.6”. Tags can be either numeric or alphanumeric (e.g. also “mysoftware:5-5-CR2~alpha9” or even “mysoftware:noteventested”).
If the TAG is not given, “latest” is implied as Tag. So you should provie a version of your image with this tag which will be chosen if no tag is provided (e.g. “ mysoftware ” really means “ mysoftware:latest “).
Once you create a container, you can specify how the container behaves and interacts with the host system:
- Container name:
Once the container is cerated, it is persistent on the system and can be stopped/started like a service. To make handling containers easier, you can provide a container name, which you can use for further commands regarding this container. If you don’t provide a name, a random name will be generated by Docker, e.g. “happy_elion” or “desperate_nobel”)
To provide a name, add the --name <myname> argument to docker run .
- Host name:
In order to communicate from one docker container to another, it can be very useful to specify the virtual hostname of a container. If not given, a random hexadecimal host name will be generated.
E.g.: name the hostname of your database server “database”: docker run -h database mysql
Although the container root directory is virtualized, you can bind specific paths in it to paths on the host system (like linux “mounts”). In this way, you can give the container a persistent storage on the host system which will remain even if the container is deleted. You can also use it to make files on the host system available to the container, even single files like sockets. Volumes can be marked as read-only, by adding “ :ro ” to the volume mapping. To specify a volume mapping, add the -v parameter, together with as mapping ( <path-on-host>:<path-in-container> ).
docker run -v /var/run/docker.sock:/tmp/docker.sock:ro myimage
docker run -v /opt/persistentdata:/var/lib/mysql -v /opt/dblogs:/var/logs/mysql mysql
To use a TCP service of the Docker container, you can add a port mapping to the host system by the “ -p ” parameter, followed by a port mapping specification. In the most simple form this might be “ <port-on-host>:<port-in-container> “, e.g. “ docker run -p 80:8080 myservice “, which means that the service listening on port 8080 inside the container (e.g. an application server) will be available as port 80 (webserver) on the host system. This can easily be used for Port reassignment, e.g. you can have 10 different containers running which each of them providing a web service, and then reassign them as Port 1080-1089 on the host system so they all are available.
If you want a port mapping to be only available to a specific network interface, you can specify the target bind IP address as prefix before the port mapping, e.g. “ -p 127.0.0.1:3306:3306 ” to make the MySQL service only available from localhost on the host system. To specify multiple port mappings, just add the “ -p ” parameter multiple times.
Usually you want to run the docker container in the background (like a system service). To achieve this, add the -d parameter, which will run the docker container in a “detached” state, so the shell will not be connected to it.
Most images declare which program should be run in the container (e.g. the mysql container has a specific shellscript which prepares and starts up MySQL when the container is run). To override this, you can enter a custom executable after the image name in “docker run“, but in the most cases this will not be necessary.
Some images need some kind of parameters when started. E.g. the MySQL image will require a default root password when initialized on an empty storage directory. For this you can add key-value pairs with the -e parameter which will be available inside the container as environment variable. Images can also define default values for some environment variables, which will be used if not provided when running the container. You can add as many environment variables as you want, by adding -e multiple times:
docker run -e MYSQL_ROOT_PASSWORD="secret" -e MYSQL_DATABASE="mydb" mysql
Example for Docker Run:
docker run -d \
--name "database" \
-v /opt/dockerdata/mysql/data:/var/lib/mysql/ \
-v /opt/dockerdata/mysql/conf:/etc/mysql/conf.d/ \
-p 127.0.0.1:3306:3306 \
-e MYSQL_ROOT_PASSWORD="secret" \
-e MYSQL_DATABASE="appdb" \
-h "database" mysql