For typical server processes, we can conveniently use a variety of tools on the host machine to debug; however, containers often contain only the necessary application and usually do not include common debugging tools. So how do we debug processes inside a container online? The simplest method is to start a new container that includes debugging tools.
Let's take a look at how to debug a basic web container.
docker run -itd --name webserver -p 80:80 feisky/hello-world
Visit the mapped port 80; the webserver container correctly returns "Hello World":
# curl http://$(hostname):80
Hello World
Create a New Container to Debug the webserver
Create a new container with an image that includes debugging tools or allows easy installation of debugging tools (such as alpine). To facilitate access to the status of the webserver process, the new container shares the pid namespace and net namespace of the webserver container, and adds necessary capabilities:
docker run -it --rm --pid=container:webserver --net=container:webserver --cap-add sys_admin --cap-add sys_ptrace alpine sh
/ # ps -ef
PID USER TIME COMMAND
1 root 0:00 /webserver
13 root 0:00 sh
18 root 0:00 ps -ef
This allows the new container to directly attach to the webserver process for online debugging, such as tracing the webserver process with strace:
# Continue in the shell of the newly created container
/ # apk update && apk add strace
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz
v3.5.1-34-g1d3b13bd53 [http://dl-cdn.alpinelinux.org/alpine/v3.5/main]
v3.5.1-29-ga981b1f149 [http://dl-cdn.alpinelinux.org/alpine/v3.5/community]
OK: 7958 distinct packages available
(1/1) Installing strace (4.14-r0)
Executing busybox-1.25.1-r0.trigger
OK: 5 MiB in 12 packages
/ # strace -p 1
strace: Process 1 attached
epoll_wait(4,
^Cstrace: Process 1 detached
<detached ...>
It is also possible to get the network status of the webserver container:
# Continue in the shell of the newly created container
/ # apk add lsof
(1/1) Installing lsof (4.89-r0)
Executing busybox-1.25.1-r0.trigger
OK: 5 MiB in 13 packages
/ # lsof -i TCP
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
webserver 1 root 3u IPv6 14233 0t0 TCP *:http (LISTEN)
Of course, you can also access the filesystem of the webserver container:
/ # ls -l /proc/1/root/
total 5524
drwxr-xr-x 5 root root 360 Feb 14 13:16 dev
drwxr-xr-x 2 root root 4096 Feb 14 13:16 etc
dr-xr-xr-x 128 root root 0 Feb 14 13:16 proc
dr-xr-xr-x 13 root root 0 Feb 14 13:16 sys
-rwxr-xr-x 1 root root 5651357 Feb 14 13:15 webserver
After translation and rephrasing:
A Guide to Container Troubleshooting
When dealing with typical server processes, swift and effective debugging is often facilitated by a slew of handy tools on our host machine. But imagine you're navigating the lean world of containers—stripped down to essential apps and often devoid of our go-to debugging utilities. The conundrum then becomes: how do you perform live debugging within this contained environment? The key lies in booting up a new container—one that's armed with all the debugging toolkit you'll need.
Let's dive into the nitty-gritty of troubleshooting a no-frills web container.
For the adaptation to the Linux scene, you'd compile:
GOOS=linux go build -o webserver
Next up, whip up a Docker image, lining up the following build commands:
FROM scratch
COPY ./webserver /
CMD ["/webserver"]
Running the build might look like this:
# docker build -t feisky/hello-world .
Merely sending the context to the Docker daemon sparks the creation sequence.
---> The foundation is laid down with Step 1/3: FROM scratch.
Then, we move to securely placing the webserver in this digital vessel.
---> The command sequence culminates in Step 3/3: CMD /webserver.
Your new webserver container is primed and ready after a successful build.
This cued the stage for the webserver container to be unleashed into action:
docker run -itd --name webserver -p 80:80 feisky/hello-world
Now, when you hit the newly mapped port 80, be greeted by the "Hello World" from your crisp webserver container:
# curl http://$(hostname):80
Hello World
Spawning a New Container to Peer Inside the webserver
Craft a fresh container using an image rich with debugging tools, or one that welcomes tool installation with ease—alpine being a case in point. This new discovery box shares the webserver's PID and networking space for a deep insight into the webserver’s pulse, supplemented with enhanced capabilities:
docker run -it --rm --pid=container:webserver --net=container:webserver --cap-add sys_admin --cap-add sys_ptrace alpine sh
--> Whale of a time perusing the processes of your server-bound voyage.
Embark on a real-time debugging spree by hitching to the webserver's process—unraveling the mysteries with strace:
# In the freshly spawned container's shell:
--> First, we refresh the tool repertoire with apk update and welcome strace aboard.
Here's to a seamless attachment to process 1, embarking upon an epoll_wait...
--> Should you need to disengage, a quick Ctrl+C detaches from the chase.
Thrill in the ability to sleuth through the webserver's networking activities:
# Staying the course in our discovery shell:
--> We enlist lsof into our crew to oversee the TCP connections.
There lays the humble webserver, ears perked up and listening on http.
Venturing further, the filesystem within the webserver's container isn't out of reach:
Through the window of "/proc/1/root/", glimpse into the container's inner hold.
The Kubernetes community is also proposing adding a kubectl debug command to start a new container in a Pod in a similar way to debug running processes. More details can be found at .
On a broader horizon, the Kubernetes community sails towards simplifying such troubleshooting with a proposed kubectl debug command. This would introduce new debugging containers into Pods with similar ease, illuminating the way through the often opaque waters of runtime processes. You can chart these developing waters at .