How to fix Ctrl+C inside a Docker container?


Introduction

The real problem statement for this article is that developer is not able to use the interrupt signals while running or creating a Docker container. This is not a bug in Docker but a Linux feature. The complete problem and methods to recreate the problem are explained with the solution.

Process in Linux

Currently running or executing a program is a process. This process can be foreground or in the background. To see these processes, we have some terminal commands like ps and top. The ps shows active processes and the top shows the real-time update of the processes.

$ps

The output gives you the process id, the linked tty, the time of the process, and the actual command or program running.

Output

PID TTY TIME CMD 2584 pts/0 00:00:00 bash 4146 pts/0 00:00:00 ps

To see all the processes running your system.

$ps –e

Output

PID TTY TIME CMD
   1 ? 00:00:02 systemd
   2 ? 00:00:00 kthreadd
   3 ? 00:00:00 rcu_gp
   4 ? 00:00:00 rcu_par_gp
   5 ? 00:00:00 netns
   .
   .
   .
   .
   3650 ? 00:00:01 kworker/1:0-cgroup_destroy
   3694 ? 00:00:00 kworker/u4:1-events_unbound
   4138 ? 00:00:00 kworker/0:1-cgroup_destroy
   4197 ? 00:00:00 kworker/0:2-events
   4198 pts/0 00:00:00 ps

Here we have more than four thousand programs running.

Signals on Linux Terminal

Signals or we could say interrupts. These are sent to the terminal using keyboard shortcuts. For example, to paste we use Ctrl+V. This will send an interrupt and prioritize itself over other ongoing processes and paste the text or image. Similarly, we have keyboard shortcuts to send various kinds of interrupts to the Linux terminal. These signals are mentioned below.

  • Tab

  • Ctrl+C

  • Ctrl+D

  • Ctrl+U

  • Ctrl+A

Tab

The tab is efficient to use. It helps in the auto-completion of commands. It recognizes the pattern of the command and when pressed it completes the command for you. For example, stop container 4b534b34h34b34, $docker stop 4b5, and press tab it will fetch the complete container ID.

Ctrl+C

This shortcut will terminate/abort/kill the currently executing process or command. This is useful when the command gets stuck in a loop or you forget something to add to the command. Just terminate the command using the shortcut and re-run with the edited command.

Ctrl+D

This interrupt will kill the current user terminal and backtrack to the last used user terminal.

Ctrl+U

This will delete the complete line and move the cursor to the start of the line.

Ctrl+A

This brings back the cursor to the start of the command without deleting the command.

Methods to recreate the problem

Implement the methods given below to recreate the problem on your machine. The problem is that the Docker container does not respond to the interrupt signal Ctrl+C.

Method 1

Run the container without any modes and give a command that would hold the process for some seconds.

$docker run busybox sleep 10

Output

No matter how many times you press the Ctrl+C, you get no response. This shortcut should have terminated the command sleep 10 running inside the container. The command gets completely executed.

Method 2

Run the container in interactive mode. The same sleep command should be passed and press the shortcut on the keyboard.

$docker run -i busybox sleep 10

Command gets executed inside the container.

Method 3

Now add the tty option using the -t flag and check if anything changes or not.

$docker run -t busybox sleep 10

The same result, the command gets completely executed.

Method 4

Use both interactive and tty

$docker run -it busybox sleep 10

Method 5

Include the detach flag.

$docker run -itd busybox sleep 10

The docker container will run for 10 seconds in the background. If you press Ctrl+C just after running the command, it will not respond to the interrupt.

Solution to Problem

Before getting to the solution, we must know the reason why the interrupt signal didn’t work in above methods. The command sleep we are passing to the container gets a process ID as PID 1. And PID 1 has some special power over other processes. That was the reason the interrupt was not able to terminate the PID 1 or sleep command.

To resolve this problem docker provides an option name --init. This will overcome all our problems with different interrupt signals.

$docker run --init busybox sleep 10

Now the Docker container will respond to the Ctrl+C interrupt and will terminate the command sleep 10 without being completely executed.

Proof of the above solution

Without --init

With --init

$docker run busybox ps

$docker run --init busybox ps

PID USER TIME COMMAND 1 root 0:00 ps

PID USER TIME COMMAND 1 root 0:00 /sbin/docker-init -- ps 7 root 0:00 ps

The PID of the ps command is 1 in the first case but in second case the PID 1 is for docker-init which is why we were able to terminate the ps command in the second case.

Conclusion

Sometimes small problems stuck your complete project. Here we discussed about various interrupt signals and how to connect them to the docker container in special cases. Docker is not only about learning containerization but also about using it in the most efficient way to achieve our goals.

Updated on: 11-Jan-2023

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements