This is part two of a two-part series about working with Docker containers. In part one, we focused on the many ways and options to run an image and how the host can interact with a Docker container.
In this part, we'll cover listing, starting, stopping and restarting containers as well as executing commands on running containers. In particular, you'll learn the difference between running and stopped (exited) containers, and how to control precisely the information and display when you list your containers by filtering and formatting.
Then, you'll get hands-on experience stopping, starting, restarting and attaching to your containers. Finally, you'll run one-off commands as well as gain interactive shell access to a running container.
Before we start, make sure that Docker is installed properly in your environment. Depending on how it installed and your user, you may need to run it as sudo. I'll skip the sudo.
Listing Containers
When working with containers, you often want to list, view and filter your containers. The docker ps
command is the key, and it has several interesting options.
Running Containers
The most basic command is plain docker ps
with no arguments, which shows all the currently running containers.
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2f542e1cb88b nginx "nginx -g 'daemon ..." 12 hours ago Up 12 hours 443/tcp, 0.0.0.0:9000->80/tcp nginx
You get a lot of information on each container, including the container id, the image, the command, when it was created, its current status, its ports, and its names. It's a little difficult to parse due to the wrapping. We'll see later how to filter and format the output. Note that the command is truncated (as well as the container id). To show the full command, add --no-trunc
:
$ docker ps --no-trunc IMAGE COMMAND nginx "nginx -g 'daemon off;'"
Now, the full command is visible: nginx -g 'daemon off;'
All Containers
As you recall, Docker keeps stopped containers around (unless you ran them with --rm
). Adding -a
shows all containers:
$ docker ps -a CONTAINER ID IMAGE STATUS NAMES cc797c61dc21 busybox Exited busybox 67f3cb5a9647 busybox Exited ecstatic_jones 898fb562e535 hello-world Exited hopeful_spence 6dd210fda2d8 hello-world Created infallible_curie 2f542e1cb88b nginx Up 12 hours nginx
Formatting
The output of docker ps
can be too verbose and often shows a lot of fields that are not interesting. You can use Go-template formatting to display just the fields you're interested in. Here is showing just the name and the command:
$ docker ps --no-trunc --format '{{.Names}}\t{{.Command}}' nginx "nginx -g 'daemon off;'"
That works, but to present it with the field names, add "table" to the beginning of the format string:
$ docker ps -a --no-trunc --format 'table {{.Names}}\t{{.Command}}' NAMES COMMAND busybox "cat /data/1.txt" ecstatic_jones "cat /data/1.txt" hopeful_spence "/hello" infallible_curie "ls -la" nginx "nginx -g 'daemon off;'"
The format name for the container id (not selected here) is {{.ID}}
(all caps).
Filtering
The docker ps
command supports many filters. They are pretty straightforward to use. The syntax is -f "<filter>=<value>"
. Supported filters are id, label, name, exited, status, ancestor, before, since, isolation, network, and health.
Here is filtering by container name and showing only the busybox container:
$ docker ps -a -f "name=busybox" \ --format 'table {{.ID}}\t{{.Status}}\t{{.Names}}' CONTAINER ID STATUS NAMES cc797c61dc21 Exited (0) 11 minutes ago busybox
The -q Flag
If all you want is the container id, use the -q flag
(quiet flag). It's simpler than --format 'table {{.ID}}'
. This is often needed when you want to perform operations on multiple containers (you'll see an example later).
$ docker ps -aq cc797c61dc21 67f3cb5a9647 898fb562e535 6dd210fda2d8 2f542e1cb88b
Stopping, Starting, and Restarting Containers
You can stop running containers and start a stopped container. There are several differences between starting a stopped container and running a new instance of the same image:
- You use the same environment variables, volumes, ports and other arguments of the original run command.
- You don't have to create yet another container.
- If the stopped instance modified its file system, the started container will use the same.
Let's stop the nginx container and then start it. When you refer to a container, you can use its name or an unambiguous prefix of its id. I usually name my long-running containers so I have a meaningful handle and don't have to deal with Docker's auto-generated names or containers' id prefixes.
$ docker stop nginx nginx $ docker ps -a -f "name=nginx" --format 'table {{.Names}}\t{{.Status}}' NAMES STATUS nginx Exited (0) 2 minutes ago
OK. Nginx is stopped (status is "Exited"). Let's start it:
$ docker start nginx nginx $ docker ps -a -f "name=nginx" --format 'table {{.Names}}\t{{.Status}}' NAMES STATUS nginx Up 33 seconds
Restarting a running container is another option, which is equivalent to docker stop
followed by docker start
.
$ docker restart nginx
nginx $ docker ps -a -f "name=nginx" --format 'table {{.Names}}\t{{.Status}}' NAMES STATUS nginx Up 2 seconds
Attaching to a Running Container
When you start a stopped container, or if you ran your container in detached mode (-d
command-line argument), you can't see the output. But you can attach to it.
$ docker attach nginx 172.17.0.1 - - [19/Mar/2017:08:40:03 +0000] "HEAD / HTTP/1.1" 200 0 "-" "HTTPie/0.8.0" "-"
Removing Containers
You can remove stopped containers with the command: docker rm <container id or name>
$ docker rm ecstatic_jones ecstatic_jones
If you want to remove a running container, you can either stop it first or use the -f
(force) command-line argument:
$ docker rm -nginx Error response from daemon: You cannot remove a running container 3dbffa955f906e427298fbeb3eadfd229d64365dd880c9771a31b0aedb879d6d. Stop the container before attempting removal or use -f $ docker rm -f -nginx nginx
If you want to remove all containers, here is a nice snippet:
docker rm -f $(docker ps -aq)
If you want to remove just the stopped container, remove the -f
(force) flag.
Executing a Command Inside a Running Container
Docker runs a single process inside a container, but you can execute additional commands against a running container. It is very similar to providing a custom command to the docker run
command, except that in this case it is running side by side with the run command.
Simple Commands
Running a simple command is done via docker exec
. You provide a running container id or name and the command you wish to execute. Let's check out the nginx.conf file inside the nginx container and see how many worker processes are configured.
$ docker exec nginx cat /etc/nginx/nginx.conf | grep worker_processes worker_processes 1;
Interactive Shell
One of the best troubleshooting techniques with Docker containers is to connect to an interactive shell and just explore the internal file system. In order to attach stdin and have a tty, you need to provide the -i -t
command-line arguments (can be grouped as -it
) and then the name of a shell executable (usually bash).
You end up with shell access to your container. Here is an example of checking the worker processes interactively from "inside" the container.
$ docker exec -it nginx bash root@b010e854bb98:/# cat /etc/nginx/nginx.conf | grep worker_processes worker_processes 1; root@b010e854bb98:/#
Conclusion
Docker is a powerful platform, and since the container is its unit of work, it provides a lot of tools to manage and work with containers. I described most of the important aspects of working with containers, but there are many more advanced features, options and nuances to the commands I covered, as well some additional commands.
If you work closely with Docker containers, take the time to dive in and learn all about them. It will pay off handsomely.
Comments