Wait, Containers Are Kind of Like Linux Processes!
Wait, Containers Are Kind of Like Linux Processes!
These short exercises will show you the conceptual similarities between containers and Linux processes, to help you understand containers.
Join the DZone community and get the full member experience.Join For Free
DevOps involves integrating development, testing, deployment and release cycles into a collaborative process. Learn more about the 4 steps to an effective DevSecOps infrastructure.
Of course, containers are not the same as processes you find in operating systems, but at a conceptual level, there are many similarities. In this article, I aim to explore this notion at the expense of getting my hands a little dirty. Let’s dive in.
A process is an atomic component of a program (or a complete program) in execution. In Linux, each process has its own unique id (Process ID) and is capable of creating child processes (forking). This, in turn, makes a process's PID into a PPID (parent PID). The PIDs allow the operating system to get ahold of the process and run it through its various process states as need be.
The concept of containers derives from the wonderful world of Docker, where a bunch of super smart geeks figured out ways of extending and building up on process isolation, packaging mechanisms/concepts present in Linux; they should also be credited for building an awesome product range out of their advancements and making them available to the masses. A container is a dockerized image(s) in execution (technically, the images stay immutable and it is a completely new layer called the container layer that provides access to the immutable content, but for simplicity sake, let's say a container is an image in execution).
Note: To try out the examples in this article, you will need to have Docker configured in a Linux distribution (I’m using Ubuntu Trusty with Docker 17.06.0-ce), have internet access, and be logged in with a user that has permissions to use Docker and the other commands listed (you may also require root access for some of the commands listed).
In one terminal, type in the command found below. The command will start printing its message on the terminal you typed it in, every two seconds, indefinitely!
Command Block 1
echo -e "#\!/bin/bash\nwhile true; do echo hi there.. I’m a process; sleep 2; done" > processtestscript.sh; chmod u+x processtestscript.sh; bash processtestscript.sh
Output Block 1
hi there.. I’m a process hi there.. I’m a process hi there.. I’m a process
In the second terminal, type in the command found below, assuming you have not used the tomcat:8.0 on your box before, Docker will pull the required image (a layer at a time) from Docker Hub and perform the predefined run sequence for the container. Bam! You got a container running.
Command Block 2
docker container run tomcat:8.0
Output Block 2
Unable to find image 'tomcat:8.0' locally 8.0: Pulling from library/tomcat ad74af05f5a2: Pull complete 2b032b8bbe8b: Pull complete 99a5213ead46: Pull complete 7de34ca31efd: Pull complete 9b22e57d98bb: Pull complete 12cd7a66c3fd: Pull complete 880bb942de44: Pull complete 6ada99602995: Pull complete 90451a97de52: Pull complete 646677f3b1ed: Pull complete c10d6538fe29: Pull complete 63e2edd468f7: Pull complete Digest: sha256:1f34d503e3e339433a84df80615fb658ab16491361353b6d7e1342b2b80cf7f0 Status: Downloaded newer image for tomcat:8.0 16-Aug-2017 12:27:17.573 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version: Apache Tomcat/8.0.45 16-Aug-2017 12:27:17.577 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jun 26 2017 20:06:07 UTC … … 16-Aug-2017 12:27:20.596 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-apr-8080"] 16-Aug-2017 12:27:20.635 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-apr-8009"] 16-Aug-2017 12:27:20.667 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 2787 ms
Let’s turn to the third terminal to peer into the mannerisms of these two creators. Run the following two commands to get a few top level details about the process and the container.
Command Block 3
ps -ef | head -n 1 ; ps -ef | grep processtestscript.sh | head -n 1 docker container ls -l
Output Block 3
UID PID PPID C STIME TTY TIME CMD dumiduh 3163 3087 0 16:56 pts/7 00:00:00 bash processtestscript.sh CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1ad06cfbc91 tomcat:8.0 "catalina.sh run" 24 seconds ago Up 21 seconds 8080/tcp happy_banach
In the output of the two commands, pay attention to the PID of the processtestscript.sh and the Container ID of the tomcat:80 container. These two identifiers serve the same purpose, which is to uniquely identify these in execution entities.
Of Process States and Container States
A Linux process is birthed when a parent process forks a child process into being. This new process may then be transitioned into various different states as need be. From these, the most common states are running, sleeping, and stopped.
A parent process typically goes into a sleep state when it forks a child process; these processes wait for signals to move along their execution paths. Keeping with the topic of discussion of this article, we will concentrate on the two states and the transition between these two states that are similar in concept to that what’s found in the world of containers.
As mentioned earlier on, a container is a collection of immutable layers with a mutable layer put on top to provide access to the contents of these immutable layers. There are various strategies for providing access to the contents of the immutable layer, which we will not get into in this article. A crude state representation of this state transfer would look much like that of a process going from stopped to running,
Let’s switch back to the first terminal running the processes and change the process state to stopped and then back to running.
Go back to the output you received in Command Block 3 and find the PID for the processtestscript.sh process. Switch to the third terminal and run the next command block with the PID you just extracted. To me it's,
Command Block 4
Kill -19 3163
Observe that as soon as you sent the STOP signal(19) to the process, the script stopped printing the message.
Output Block 4
hi there.. I’m a process hi there.. I’m a process hi there.. I’m a process + Stopped bash processtestscript.sh
Now, send a CONT signal(18) to the process to resume it.
Command Block 5
Kill -18 3163
You will notice that the process resumes and starts printing its message again. Back from the dead, picking up from where it left off.
Now let’s do something similar with our container and observe how it behaves. To make sure, it has preserved its state when it transitions from Stopped to Running, let’s go into the container and add a new file. Take the Container ID from Output Block 3 and run Command Block 6 to go into the container. Once inside the container run the echo command to create a new file.
Command Block 6
docker container exec -it d1ad06cfbc91 bash echo “life inside a container” > file1
Now switch to back to the third terminal and run command block 7 to stop the container, observe that the container has stopped.
Command Block 7
docker container stop d1ad06cfbc91 docker container ls -la
Output Block 7
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d1ad06cfbc91 tomcat:8.0 "catalina.sh run" 7 hours ago Exited (143) 16 seconds ago fervent_stone
Finally, let’s start the stopped container, go into it and check if the file we created is still there.
Command Block 8
docker container start d1ad06cfbc91 docker container exec -it d1ad06cfbc91 bash
Output Block 8
root@d1ad06cfbc91:/usr/local/tomcat# ls LICENSE NOTICE RELEASE-NOTES RUNNING.txt bin conf file1 include lib logs native-jni-lib temp webapps work root@d1ad06cfbc91:/usr/local/tomcat# cat file1 life inside a container
In this article, we looked at two ways in which Linux processes and Docker containers are similar. These being, first, containers and processes are both atomic computational resource representations. Second, containers and processes both can be stopped and then resumed to carry on from where they left off.
In a future article, I will expand this analogy further.
Opinions expressed by DZone contributors are their own.