2 Running software in containers
This chapter builds a practical foundation for running software in containers with Docker. It walks through creating both detached (daemon) and interactive containers, using a simple but realistic monitoring setup composed of an NGINX web server, a mailer, and a watcher agent. Along the way, it covers essential commands and workflows—running and naming containers, attaching/detaching terminals, listing and inspecting running containers, viewing logs (and the pitfalls of unbounded log growth), stopping/restarting services, and using exec for ad‑hoc commands—so you can verify behavior and iterate confidently while keeping container output and lifecycle under control.
With the basics in place, the chapter explains how Linux PID namespaces isolate processes so each container sees its own PID 1 and process list, improving security and eliminating many software conflicts (for example, port and file clashes) by scoping resources per container. It then tackles scaling and coordination concerns you hit as you run more containers: flexible identification via auto‑generated names and unique IDs (including truncated IDs and CID files), understanding container states (created, running, restarting, exited), and respecting dependency order when starting services. These ideas are applied to expand the single site into a small “farm” architecture while avoiding metaconflicts at the Docker layer.
The chapter then shows how to make systems environment‑agnostic and resilient. It uses read‑only filesystems with targeted writable exceptions (such as volumes and tmpfs) and environment variable injection to configure software like WordPress cleanly, decoupling it from specific hosts and co‑deployed services (for example, database host, credentials, and per‑site database names). To increase durability, it introduces restart policies with exponential backoff, clarifies the implications of the restarting state, and demonstrates when to prefer lightweight init systems or entrypoint/startup scripts to supervise child processes and validate preconditions. It closes with cleanup best practices—stopping/removing containers, understanding signal differences, using auto‑removal for short‑lived tasks, and composing quick commands to reclaim resources—so experimentation doesn’t leave behind stray state.
The three containers that you’ll build in this example
A fleet of web server containers and related monitoring agents
The state transition diagram for Docker containers
Each WordPress and agent container uses the same database and mailer.
Summary
The primary focus of the Docker project is to enable users to run software in containers. This chapter shows how you can use Docker for that purpose. The ideas and features covered include the following:
- Containers can be run with virtual terminals attached to the user’s shell or in detached mode.
- By default, every Docker container has its own PID namespace, isolating process information for each container.
- Docker identifies every container by its generated container ID, abbreviated container ID, or its human-friendly name.
- All containers are in any one of four distinct states: running, paused, restarting, or exited.
- The docker exec command can be used to run additional processes inside a running container.
- A user can pass input or provide additional configuration to a process in a container by specifying environment variables at container-creation time.
- Using the --read-only flag at container-creation time will mount the container file system as read-only and prevent specialization of the container.
- A container restart policy, set with the --restart flag at container-creation time, will help your systems automatically recover in the event of a failure.
- Docker makes cleaning up containers with the docker rm command as simple as creating them.
Docker in Action, Second Edition ebook for free