You learned about Docker. It's awesome and you're excited. You go and create a Dockerfile:

FROM ubuntu:16.04 RUN apt-get install all_my_dependencies ADD my_app_files /my_app CMD ["/my_app/start.sh"]

Cool, it seems to work. Pretty easy, right?

Not so fast.

You just built a container which contains a minimal operating system, and which only runs your app. But the operating system inside the container is not configured correctly. A proper Unix system should run all kinds of important system services. You're not running them, you're only running your app.

"What do you mean? I'm just using Ubuntu in Docker. Doesn't the OS inside the container take care of everything automatically?"

Not quite. You have Ubuntu installed in Docker. The files are there. But that doesn't mean Ubuntu's running as it should.

When your Docker container starts, only the CMD command is run. The only processes that will be running inside the container is the CMD command, and all processes that it spawns. That's why all kinds of important system services are not run automatically – you have to run them yourself.

Furthermore, Ubuntu is not designed to be run inside Docker. Its init system, Upstart, assumes that it's running on either real hardware or virtualized hardware, but not inside a Docker container, which is a locked down environment with e.g. no direct access to many kernel resources. Normally, that's okay: inside a container you don't want to run Upstart anyway. You don't want a full system, you want a minimal system. But configuring that minimal system for use within a container has many strange corner cases that are hard to get right if you are not intimately familiar with the Unix system model. This can cause a lot of strange problems.

"What important system services am I missing?"

A correct init process Main article: Docker and the PID 1 zombie reaping problem Here's how the Unix process model works. When a system is started, the first process in the system is called the init process, with PID 1. The system halts when this processs halts. If you call CMD ["/my_app/start.sh"] in your Dockerfile, then start.sh is your init process. But the init process has an extra responsibility. It inherits all orphaned child processes. It is expected that the init process reaps them. Most likely, your init process is not doing that at all. As a result your container will become filled with zombie processes over time. Furthermore, docker stop sends SIGTERM to the init process, which is then supposed to stop all services. If your init process is your app, then it'll probably only shut down itself, not all the other processes in the container. The kernel will then forcefully kill those other processes, not giving them a chance to gracefully shut down, potentially resulting in file corruption, stale temporary files, etc. You really want to shut down all your processes gracefully. syslog Syslog is the standard Unix logging service. A syslog daemon is necessary so that many services - including the kernel itself - can correctly log to /var/log/syslog. If no syslog daemon is running, a lot of important messages are silently swallowed. You don't want warnings and errors to be silently swallowed, do you? The syslog daemon is not run automatically. You have to start it yourself. cron Many apps use cron services. But cron jobs never get run until the cron daemon is running in your container. The cron daemon is not run automatically. You have to start it yourself. SSH daemon (sometimes) Occasionally, you may want to run a command inside the container for contingency reasons. For example you may want to debug your misbehaving app. docker exec provides a great way of doing this, but unfortunately there are a number of drawbacks. For example, users who run docker exec must have access to the Docker daemon, and that way they essentially have root access over the Docker host. If that is problematic, then you should use SSH to log into the container instead. SSH has its own issues, like requiring key management, but that way you can prevent people from getting root access on the Docker host.

"Does all this apply too if I'm using CentOS inside the container, or another Linux distribution?"

Yes. The problem exist in those cases too.

"But I thought Docker is about running a single process in a container?"

Absolutely not true. Docker runs fine with multiple processes in a container. In fact, there is no technical reason why you should limit yourself to one process – it only makes things harder for you and breaks all kinds of essential system functionality, e.g. syslog.

We encourage you to use multiple processes.

Managing multiple processes can be painful, but it doesn't have to. We have a solution for that, so read on.