1. Introduction
A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. Images become containers at runtime and in the case of Docker containers – images become containers when they run on Docker Engine. Containers isolate software from its environment and ensure that it works uniformly despite differences for instance between development and staging. You can create one or more containers from a single image.
2. Difference between container and VM
Both containers and virtual machines are technologies used to run software applications, but they differ in their approach. Containers encapsulate applications or services on a host system, sharing the same operating system. In contrast, virtual machines are fully isolated environments that simulate an entire operating system on a physical host, where they run applications or services independently.
Containers have a smaller footprint compared to virtual machines because they share the host’s operating system kernel, while virtual machines each have their own kernel. This allows containers to start and stop more quickly and use fewer resources. On the other hand, virtual machines are fully isolated from one another, providing an added layer of security that can prevent attacks from spreading between them.
Another thing to consider is application start times. Containers start a lot faster than VMs because they only have to start the application — the kernel is already up and running on the host. In the VM model, each VM needs to boot a full OS before it can start the app.
Containers and virtual machines can also complement each other. For instance, a container might be used to run an application, while a virtual machine supplies the underlying infrastructure. This combination offers the benefits of both: the portability and efficiency of containers, along with the security and isolation of virtual machines.
Below is a table outlining the key differences between containers and virtual machines:
Feature | Container | Virtual Machine |
Operating system | Shares the host operating system’s kernel | Has its own kernel |
Portability | More portable | Less portable |
Speed | Faster to start up and shut down | Slower to start up and shut down |
Resource usage | Uses fewer resources | Uses more resources |
Use cases | Good for portable and scalable applications | Good for isolated applications |
3. Starting a container
The simplest way to start a container is to use the docker run <image> <app>
command. This command starts a simple container that will run a containerized version of Ubuntu Linux.
C:\>docker run -it ubuntu /bin/bash root@cd6c49937beb:/#
The -it
flags connect your current terminal window to the container’s shell. /bin/bash
is the application to run in the container. The long number after the @ is the first 12 characters of the container’s unique ID.
When you press Return, the Docker client bundles the command and sends it via a POST request to the API server running on the Docker daemon. The daemon receives the command and checks the host’s local image repository to determine if the image is already available. In this case, the image wasn’t found locally, so the daemon reached out to Docker Hub, located the image, downloaded it, and stored it in the local cache. Once the image is pulled, the daemon instructs containerd
to start the container. containerd
tasks runc
with creating the container and starting the app.
Containers run until the main app exits. In the previous example, the container will exit when the Bash shell exits.
The running ubuntu is the bare minimum OS. It does not contain all packages and libraries. To demonstrate try this:
root@cd6c49937beb:/# ping www.google.com bash: ping: command not found
You can observe that ping is not found.
4. Container processes
When we started the container, we started only the bash so that is the only process running. You can check this by running the ps -elf
command.
The second process ps -elf
is a short lived process and exits as soon as the out put is displayed on the screen. Typing exit while logged in to the container will terminate the Bash process and the whole container will exit (terminate). This is due to the fact that a container relies on its designated main process to run. Whether it’s a Linux or Windows container, terminating the main process will result in the container shutting down.
Press Ctrl-PQ
to exit the container without stopping its main process. This action returns you to the Docker host’s shell while keeping the container running in the background.
Run the docker ps
command to check if the container is still running.
C:\>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd6c49937beb ubuntu "/bin/bash" About an hour ago Up About an hour xenodochial_jennings
Note that the container is still running and you can re-attach your terminal to it with the docker exec
command.
C:\>docker exec -it cd6c bash root@cd6c49937beb:/#
Run the ps -elf
command again.
root@cd6c49937beb:/# ps -elf F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD 4 S root 1 0 0 80 0 - 1145 core_s 15:43 pts/0 00:00:00 /bin/bash 4 S root 17 0 0 80 0 - 1145 do_wai 16:48 pts/1 00:00:00 bash 0 R root 25 17 0 80 0 - 1982 - 16:49 pts/1 00:00:00 ps -elf
Note that the docker exec
command created a new Bash process.
5. Stopping the container
You can stop a container using the docker stop
command.
C:\>docker stop xenodochial_jennings xenodochial_jennings
Now run a docker ps
to list all running containers.
C:\>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Stopped container is not listed here. To list all the containers, including those that are stopped use the -a
flag.
C:\>docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd6c49937beb ubuntu "/bin/bash" 16 hours ago Exited (137) About a minute ago xenodochial_jennings 57286a019e9f simple-node-app "docker-entrypoint.s…" 2 days ago Exited (255) 30 hours ago 0.0.0.0:3000->3000/tcp amazing_gagarin
A stopped container can be started anytime. Use the docker start
to start a stopped container.
C:\>docker start xenodochial_jennings xenodochial_jennings C:\>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd6c49937beb ubuntu "/bin/bash" 16 hours ago Up 23 minutes xenodochial_jennings
Stopping a container does not destroy the container or the data inside of it.
Important points to note:
Containers are designed to be immutable and it is not a good practice to write data to them. If you create data in a container then this data is created on the Docker host’s file system. If the Docker host fails, the data will be lost.
For this reason, Docker provide volumes, which are external to the container but can be mounted.
6. Delete a container
You can use docker rm
command to delete the container.
C:\>docker stop xenodochial_jennings xenodochial_jennings C:\>docker rm xenodochial_jennings xenodochial_jennings C:\>docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 57286a019e9f simple-node-app "docker-entrypoint.s…" 2 days ago Exited (255) 31 hours ago 0.0.0.0:3000->3000/tcp amazing_gagarin
You can see that the container xenodochial_jennings
is not visible in the list of containers and is deleted.
7. Stopping containers gracefully
You can forcefully kill a container using the following command:
docker rm <container> -f
When you do that, the container and the application running in it does not get time to graceful stop. So you should use docker stop
without -f
flag to allow container to gracefully stop. Then you can use the docker rm
command to remove the container.
When you run the docker stop command, it sends a SIGTERM signal to the main application process inside the container (PID 1). This gives the process an opportunity to clean up and shut down gracefully. If the process is still running after 10 seconds, it receives a SIGKILL to forcibly terminate it. On the other hand, the docker rm -f
command skips the SIGTERM altogether and immediately issues a SIGKILL, forcefully stopping the container without a graceful shutdown.
8. Container restart policies
A restart policy allows the Docker engine to restart the failed container. This is the very basic form of self-healing.
A restart policy is applied per container. A restart policy can be declared imperatively on the command line as part of docker run
command or can be specified declaratively in YAML file for use in tools such as Docker Swarm, Docker Compose and Kubernetes.
There are following three restart policies:
- always
- unless-stopped
- on-failure
8.1 ‘always’ restart policy
The ‘always’ restart policy always restarts the container unless explicitly stopped. Following are the simple steps to observe this:
- Start a container with
--restart always
and run a shell process. - Exit the shell using the
exit
command. This will kill the process and the container. The docker will automatically restart the container.
C:\>docker run --name alwayspolicycontainer -it --restart always ubuntu /bin/bash root@87268e06d534:/# exit exit C:\>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 87268e06d534 ubuntu "/bin/bash" 15 seconds ago Up 3 seconds alwayspolicycontainer
You can observe that the container was created was 15 seconds ago but is up 3 seconds. One point to note here is that the Docker restarts the same container.
A notable aspect of the --restart always
policy is that even if you stop a container using docker stop and then restart the Docker daemon, the container will automatically be restarted.
8.2 ‘unless-stopped’ restart policy
The key distinction between the always
and unless-stopped
restart policies is that containers using the --restart unless-stopped
option won’t be restarted when the Docker daemon is restarted if they were previously in the Stopped (Exited) state.
8.3 ‘on-failure’ restart policy
The on-failure
policy will restart a container if it exits with a non-zero exit code. Additionally, it will restart containers when the Docker daemon restarts, including those that were previously in the stopped state.
9. Remove all containers
To delete all containers from the shell of your Docker host, run the following command:
docker rmi $(docker ps -aq) -f
It will delete all containers without warning and therefore this is not recommended to run on production systems.
10. Conclusion
In conclusion, Docker containers provide a powerful, lightweight solution for packaging and running applications consistently across different environments. They offer efficient resource usage by sharing the host’s operating system kernel and enable rapid deployment, scaling, and portability. Docker’s flexibility with features like restart policies, container management, and integration with Docker Hub simplifies both development and production workflows. By learning the core concepts, commands, and best practices of Docker containers, users can harness the full potential of containerization for modern application development and infrastructure management.