The basics of Docker

When docker run alpine ls is executed, Docker carries out the following steps behind the scenes:

  1. It finds the alpine image locally. If this is not found, Docker will try to locate and pull it from the public Docker registry to the local image storage.
  2. It extracts the image and creates a container accordingly.
  3. It executes the entry point defined in the image with commands, which are the arguments after the image name. In this example, the argument is ls. By default, the entry point is /bin/sh -c on Linux-based Docker.
  4. When the entry point process is finished, the container then exits.

An image is an immutable bundle of code, libraries, configurations, and everything else we want to put in it. A container is an instance of an image, which is executed during runtime. You can use the docker inspect IMAGE and docker inspect CONTAINER commands to see the difference between an image and a container.

Anything launched with docker run would take the foreground; the -d option (--detach) enables us to run a container in the detached mode. Sometimes, we may need to enter an active container to check the image or update something inside it. To do this, we could use the -i and -t options (--interactive and --tty). If we want to interact with a detached container, we can use the exec and attach command: the exec command allows us to run a process in a running container, while attach works as its name suggests. The following example demonstrates how to use these commands:

$ docker run busybox /bin/sh -c "while :;do echo 'meow~';sleep 1;done"
meow~
meow~
...

Your Terminal should now be flooded with meow~. Switch to another Terminal and run docker ps, a command to get the status of containers, to find out the name and the ID of the container. Here, both the name and the ID are generated by Docker, and you can access a container with either of them:

$ docker ps
CONTAINER ID IMAGE (omitted) STATUS PORTS NAMES
d51972e5fc8c busybox ... Up 3 seconds agitated_banach

$ docker exec -it d51972e5fc8c /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh -c while :;do echo 'meow~';sleep 1;done
19 root 0:00 /bin/sh
30 root 0:00 sleep 1
31 root 0:00 ps
/ # kill -s 2 1
## container terminated
As a matter of convenience, the name can be assigned upon create or run with the --name flag.

Once we access the container and inspect its processes, we'll see two shells: one is meowing and the other is where we are. Kill the first shell with kill -s 2 1 inside the container and we'll see the whole container stopped as the entry point is exited. Finally, we'll list the stopped containers with docker ps -a and clean them up with docker rm CONTAINER_NAME or docker rm CONTAINER_ID:

$ docker ps -a
CONTAINER ID IMAGE (omitted) STATUS PORTS NAMES
d51972e5fc8c busybox ... Exited (130) agitated_banach
$ docker rm d51972e5fc8c ## "agitated_banach" also works
d51972e5fc8c
$ docker ps -a
CONTAINER ID IMAGE (omitted) STATUS PORTS NAMES
## nothing left now

Since Docker 1.13, the docker system prune command has been introduced, which helps us clean up stopped containers and occupied resources with ease.

The PID 1 process is very special in UNIX-like operating systems. Regardless of what kind of process it is, it should reclaim its exited children and not take the SIGKILL signal. That's why the previous example uses SIGINT (2) instead of SIGKILL. Besides, most of the entry processes in a container don't handle terminated children, which may cause lots of un-reaped zombie processes in the system. If there's a need to run Docker containers in production without Kubernetes, use the --init flag upon docker run. This injects a PID 1 process, which handles its terminated children correctly, into the container to run.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset