Learnitweb

Docker Container

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:

FeatureContainerVirtual Machine
Operating systemShares the host operating system’s kernelHas its own kernel
PortabilityMore portableLess portable
SpeedFaster to start up and shut downSlower to start up and shut down
Resource usageUses fewer resourcesUses more resources
Use casesGood for portable and scalable applicationsGood 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.