I believe you must have used the docker stop command to stop a running container. Sometimes we may also use the docker kill command to forcefully close the container or pass a signal to the process in the container.
In fact, the operations we perform are essentially the interaction between the host and the program in the container by sending signals from the host to the container. For example, if we send a reload signal to the application in the container, then the application in the container will execute the corresponding handler to complete the task of reloading the configuration file after receiving the signal.
Signal (linux)
Signal is a form of inter-process communication. A signal is a message sent by the kernel to a process to tell the process that a certain event has occurred. When a signal is sent to a process, the process will immediately interrupt the current execution flow and start executing the signal handler (it is not accurate to say that the signal is processed at a specific time). If no handler is specified for this signal, the default handler is executed.
The process needs to register handlers for the signals it is interested in. For example, in order to allow the program to exit gracefully (to clean up resources after receiving the exit request), generally the program will handle the SIGTERM signal. Unlike the SIGTERM signal, the SIGKILL signal will violently end a process. Therefore, our application should implement a directory that captures and handles the SIGTERM signal to exit the program gracefully. If we fail, the user will have to resort to the SIGKILL signal as a last resort. In addition to SIGTERM and SIGKILL, there are signals like SIGUSR1 that specifically support user-defined behavior. The following code simply explains how to register a handler for a signal in nodejs:
process.on('SIGTERM', function() { console.log('shutting down...'); });
For more information about signals, the author mentioned it in the article "linux kill command" and will not be repeated here.
Signals in the container
Docker’s stop and kill commands are used to send signals to the container. Note that only process No. 1 in the container can receive the signal, this is very critical!
The stop command will first send the SIGTERM signal and wait for the application to end gracefully. If it is found that the application has not ended (the user can specify the waiting time), then send another SIGKILL signal to forcefully end the program.
The kill command sends the SIGKILL signal by default. Of course, you can specify any signal through the -s option.
Below we use a nodejs application to demonstrate the working process of signals in the container. Create an app.js file with the following content:
'use strict'; var http = require('http'); var server = http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }).listen(3000, '0.0.0.0'); console.log('server started'); var signals = { 'SIGINT': 2, 'SIGTERM': 15 }; function shutdown(signal, value) { server.close(function () { console.log('server stopped by ' + signal); process.exit(128 + value); }); } Object.keys(signals).forEach(function (signal) { process.on(signal, function () { shutdown(signal, signals[signal]); }); });
This application is an http server, listening on port 3000, with handlers registered for the SIGINT and SIGTERM signals. Next we will introduce how signals are handled when running programs in containers in different ways.
The application is used as process No. 1 in the container
Create a Dockerfile file and package the above application into the image:
FROM iojs:onbuild COPY ./app.js ./app.js COPY ./package.json ./package.json EXPOSE 3000ENTRYPOINT ["node", "app"]
Please pay attention to the way of writing the ENTRYPOINT instruction. This The way it is written will make node run as process No. 1 in the container.
Next create the image:
$ docker build --no-cache -t signal-app -f Dockerfile .
Then start the container and run the application:
请注意 ENTRYPOINT 指令的写法,这种写法会让 node 在容器中以 1 号进程的身份运行。 接下来创建镜像: $ docker build --no-cache -t signal-app -f Dockerfile . 然后启动容器运行应用程序: $ docker run -it --rm -p 3000:3000 --name="my-app" signal-app 此时 node 应用在容器中的进程号为 1:
At this time, the process number of the node application in the container is 1:
Now we let the program exit and execute the command:
$ docker container kill --signal="SIGTERM" my-app
At this time the application will exit in the way we expect:
The application is not process No. 1 in the container
Create a script file app1.sh that starts the application, with the following content:
#!/usr/bin/env bash node app
Then create a Dockerfile1 file with the following content:
FROM iojs:onbuild COPY ./app.js ./app.js COPY ./app1.sh ./app1.sh COPY ./package.json ./package.json RUN chmod +x ./app1.sh EXPOSE 3000 ENTRYPOINT ["./app1.sh"]
Next create the image:
$ docker build --no-cache -t signal-app1 -f Dockerfile1 .
Then start the container and run the application:
$ docker run -it --rm -p 3000:3000 --name="my-app1" signal-app1
At this time, the process number of the node application in the container is no longer 1:
现在给 my-app1 发送 SIGTERM 信号试试,已经无法退出程序了!在这个场景中,应用程序由 bash 脚本启动,bash 作为容器中的 1 号进程收到了 SIGTERM 信号,但是它没有做出任何的响应动作。
我们可以通过:
$ docker container stop my-app1 # or $ docker container kill --signal="SIGKILL" my-app1
退出应用,它们最终都是向容器中的 1 号进程发送了 SIGKILL 信号。很显然这不是我们期望的,我们希望程序能够收到 SIGTERM 信号优雅的退出。
在脚本中捕获信号
创建另外一个启动应用程序的脚本文件 app2.sh,内容如下:
#!/usr/bin/env bash set -x pid=0 # SIGUSR1-handler my_handler() { echo "my_handler" } # SIGTERM-handler term_handler() { if [ $pid -ne 0 ]; then kill -SIGTERM "$pid" wait "$pid" fi exit 143; # 128 + 15 -- SIGTERM } # setup handlers # on callback, kill the last background process, which is `tail -f /dev/null` and execute the specified handler trap 'kill ${!}; my_handler' SIGUSR1 trap 'kill ${!}; term_handler' SIGTERM # run application node app & pid="$!" # wait forever while true do tail -f /dev/null & wait ${!} done
这个脚本文件在启动应用程序的同时可以捕获发送给它的 SIGTERM 和 SIGUSR1 信号,并为它们添加了处理程序。其中 SIGTERM 信号的处理程序就是向我们的 node 应用程序发送 SIGTERM 信号。
然后创建 Dockerfile2 文件,内容如下:
FROM iojs:onbuild COPY ./app.js ./app.js COPY ./app2.sh ./app2.sh COPY ./package.json ./package.json RUN chmod +x ./app2.sh EXPOSE 3000 ENTRYPOINT ["./app2.sh"]
接下来创建镜像:
$ docker build --no-cache -t signal-app2 -f Dockerfile2 .
然后启动容器运行应用程序:
$ docker run -it --rm -p 3000:3000 --name="my-app2" signal-app2
此时 node 应用在容器中的进程号也不是 1,但是它却可以接收到 SIGTERM 信号并优雅的退出了:
结论
容器中的 1 号进程是非常重要的,如果它不能正确的处理相关的信号,那么应用程序退出的方式几乎总是被强制杀死而不是优雅的退出。究竟谁是 1 号进程则主要由 EntryPoint, CMD, RUN 等指令的写法决定,所以这些指令的使用是很有讲究的。
相关推荐:docker入门教程
The above is the detailed content of Do you know how to catch signals in docker containers?. For more information, please follow other related articles on the PHP Chinese website!

Docker simplifies application deployment and management on Linux. 1) Docker is a containerized platform that packages applications and their dependencies into lightweight and portable containers. 2) On Linux, Docker uses cgroups and namespaces to implement container isolation and resource management. 3) Basic usages include pulling images and running containers. Advanced usages such as DockerCompose can define multi-container applications. 4) Debug commonly used dockerlogs and dockerexec commands. 5) Performance optimization can reduce the image size through multi-stage construction, and keeping the Dockerfile simple is the best practice.

Docker is a Linux container technology-based tool used to package, distribute and run applications to improve application portability and scalability. 1) Dockerbuild and dockerrun commands can be used to build and run Docker containers. 2) DockerCompose is used to define and run multi-container Docker applications to simplify microservice management. 3) Using multi-stage construction can optimize the image size and improve the application startup speed. 4) Viewing container logs is an effective way to debug container problems.

Docker container startup steps: Pull the container image: Run "docker pull [mirror name]". Create a container: Use "docker create [options] [mirror name] [commands and parameters]". Start the container: Execute "docker start [Container name or ID]". Check container status: Verify that the container is running with "docker ps".

The methods to view Docker logs include: using the docker logs command, for example: docker logs CONTAINER_NAME Use the docker exec command to run /bin/sh and view the log file, for example: docker exec -it CONTAINER_NAME /bin/sh ; cat /var/log/CONTAINER_NAME.log Use the docker-compose logs command of Docker Compose, for example: docker-compose -f docker-com

You can query the Docker container name by following the steps: List all containers (docker ps). Filter the container list (using the grep command). Gets the container name (located in the "NAMES" column).

Create a container in Docker: 1. Pull the image: docker pull [mirror name] 2. Create a container: docker run [Options] [mirror name] [Command] 3. Start the container: docker start [Container name]

Four ways to exit Docker container: Use Ctrl D in the container terminal Enter exit command in the container terminal Use docker stop <container_name> Command Use docker kill <container_name> command in the host terminal (force exit)

Methods for copying files to external hosts in Docker: Use the docker cp command: Execute docker cp [Options] <Container Path> <Host Path>. Using data volumes: Create a directory on the host, and use the -v parameter to mount the directory into the container when creating the container to achieve bidirectional file synchronization.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

SublimeText3 Chinese version
Chinese version, very easy to use

SublimeText3 Linux new version
SublimeText3 Linux latest version

Zend Studio 13.0.1
Powerful PHP integrated development environment