Hands-On Docker for Microservices with Python
上QQ阅读APP看书,第一时间看更新

Executing commands

The previous container was not very exciting. It is definitively possible to create your own container totally from scratch, but, typically, you'll look for a baseline that contains some sort of Linux distribution that allows you to do something useful with the container.

As we saw with the FROM command, we can start with a previous container. We will use the Alpine Linux (https://alpinelinux.org/) distribution throughout the book, though other distributions are available, such as Ubuntu and CentOS. Check out the article at https://sweetcode.io/linux-distributions-optimized-hosting-docker/ for distributions aimed at Docker containers. 

Why Alpine Linux? It is arguably the most popular distribution for Docker systems because it has a very small footprint and it's aimed at security. It is well-maintained and regularly updated and patched. It also has a complete package management system that allows you to install most of the common tools for web services easily. The base image is only around 5 MB in size and contains a working Linux operating system.

It has a couple of quirks when working with it, such as using its own package management, called apk, but it's easy to use and is almost a straight-on drop replacement for common Linux distributions.

The following Dockerfile will inherit from the base alpine container and add the example.txt file:

FROM alpine

RUN mkdir -p /opt/
COPY example.txt /opt/example.txt

This container allows us to run commands, as the usual command-line utilities are included:

$ docker build -f Dockerfile.run --tag container-run .
Sending build context to Docker daemon 4.096kB
Step 1/3 : FROM alpine
---> 055936d39205
Step 2/3 : RUN mkdir -p /opt/
---> Using cache
---> 4f565debb941
Step 3/3 : COPY example.txt /opt/example.txt
---> Using cache
---> d67a72454d75
Successfully built d67a72454d75
Successfully tagged container-run:latest

$ # docker run <image name> <command>
$ docker run container-run cat /opt/example.txt
An example file

Note how the cat /opt/example.txt command line gets executed. This is actually happening inside the container. We print the result in stdout in our stdout console. However, if there's a file created, as the container stops, the file is not saved in our local filesystem, but only inside container:

$ ls
Dockerfile.run example.txt
$ docker run container-run /bin/sh -c 'cat /opt/example.txt > out.txt'
$ ls
Dockerfile.run example.txt

The file is actually saved in a stopped container. Once the container has finished its run, it remains stopped by Docker until removed. You can see the stopped container with the docker ps -a command. A stopped container is not very interesting, though its filesystem is saved on disk.

When running web services, the command being run won't stop; it will keep running until stopped. Remember what we said before about a container being a process with a filesystem attached. The command  running is the key to the container.

You can add a default command, which will be executed when no command is given, by adding the following:

CMD cat /opt/example.txt

Make it run automatically by using the following command:

$ docker run container-run
An example file

Defining a standard command makes the container really simple. Just run it and it will do whatever it is configured to do. Remember to include a default command in your containers.

We can also execute a shell in the container and interact with it. Remember to add the -it flag to keep the connection properly open, -i to keep stdin open, and -t to create a pseudo Terminal, you can remember it as interactive Terminal:

$ docker run -it container-run /bin/sh
/ # cd opt/
/opt # ls
example.txt
/opt # cat example.txt
An example file
/opt # exit
$

This is very useful when finding out problems or performing exploratory tests.