Docker 컨테이너에서 신호를 잡는 방법을 알고 있나요?
실행 중인 컨테이너를 중지하려면 docker stop 명령을 사용해야 한다고 생각합니다. 때로는 컨테이너를 강제로 닫거나 컨테이너의 프로세스에 신호를 전달하기 위해 docker kill 명령을 사용할 수도 있습니다.
사실 우리가 수행하는 작업은 본질적으로 호스트에서 컨테이너로 신호를 전송하여 호스트와 컨테이너에 있는 프로그램 간의 상호 작용입니다. 예를 들어 컨테이너의 애플리케이션에 다시 로드 신호를 보내면 컨테이너의 애플리케이션은 해당 핸들러를 실행하여 신호를 받은 후 구성 파일을 다시 로드하는 작업을 완료합니다.
신호(linux)
신호는 프로세스 간 통신의 한 형태입니다. 신호는 특정 이벤트가 발생했음을 프로세스에 알리기 위해 커널이 프로세스에 보내는 메시지입니다. 신호가 프로세스에 전송되면 프로세스는 즉시 현재 실행 흐름을 중단하고 신호 처리기 실행을 시작합니다(특정 시간에 신호가 처리된다고 말하는 것은 정확하지 않습니다). 이 신호에 대해 핸들러가 지정되지 않으면 기본 핸들러가 실행됩니다.
프로세스는 관심 있는 신호에 대한 핸들러를 등록해야 합니다. 예를 들어 프로그램이 정상적으로 종료되도록(종료 요청을 받은 후 리소스를 정리하기 위해) 일반적으로 프로그램은 SIGTERM 신호를 처리합니다. SIGTERM 신호와 달리 SIGKILL 신호는 프로세스를 강제로 종료합니다. 따라서 우리 애플리케이션은 프로그램을 정상적으로 종료하기 위해 SIGTERM 신호를 캡처하고 처리하는 디렉터리를 구현해야 합니다. 실패하면 사용자는 최후의 수단으로 SIGKILL 신호를 사용해야 합니다. SIGTERM 및 SIGKILL 외에도 사용자 정의 동작을 특별히 지원하는 SIGUSR1과 같은 신호가 있습니다. 다음 코드는 nodejs에서 신호에 대한 핸들러를 등록하는 방법을 간단히 설명합니다.
process.on('SIGTERM', function() { console.log('shutting down...'); });
신호에 대한 자세한 내용은 작성자가 "linux kill 명령" 기사에서 언급했으며 여기서는 반복하지 않습니다.
컨테이너의 신호
Docker의 stop 및 kill 명령은 컨테이너에 신호를 보내는 데 사용됩니다. 컨테이너의 프로세스 1번만 신호를 받을 수 있다는 점에 유의하세요. 이는 매우 중요합니다!
stop 명령은 먼저 SIGTERM 신호를 보내고 애플리케이션이 정상적으로 종료될 때까지 기다립니다. 애플리케이션이 종료되지 않은 것으로 확인되면(사용자가 대기 시간을 지정할 수 있음) 또 다른 SIGKILL 신호를 보내 프로그램을 강제로 종료합니다.
kill 명령은 기본적으로 SIGKILL 신호를 보냅니다. 물론 -s 옵션을 통해 모든 신호를 지정할 수 있습니다.
아래에서는 nodejs 애플리케이션을 사용하여 컨테이너의 신호 작업 프로세스를 보여줍니다. 다음 콘텐츠로 app.js 파일을 만듭니다.
'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]); }); });
이 앱은 SIGINT 및 SIGTERM 신호에 등록된 핸들러를 사용하여 포트 3000에서 수신 대기하는 http 서버입니다. 다음으로 컨테이너에서 프로그램을 다양한 방식으로 실행할 때 신호를 처리하는 방법을 소개합니다.
애플리케이션은 컨테이너에서 프로세스 1번 역할을 합니다.
Dockerfile 파일을 생성하고 위 애플리케이션을 이미지에 패키징합니다.
FROM iojs:onbuild COPY ./app.js ./app.js COPY ./package.json ./package.json EXPOSE 3000ENTRYPOINT ["node", "app"]
ENTRYPOINT 명령어 작성에 주의하세요. 이렇게 작성하면 노드가 컨테이너의 1번 프로세스를 실행합니다.
다음으로 이미지 생성:
$ docker build --no-cache -t signal-app -f Dockerfile .
그런 다음 컨테이너를 시작하고 애플리케이션을 실행합니다.
请注意 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:
이때 컨테이너에 있는 노드 애플리케이션의 프로세스 번호는 1입니다.
이제 프로그램을 종료합니다.
$ docker container kill --signal="SIGTERM" my-app
이 시점에서 애플리케이션은 예상대로 종료됩니다.
애플리케이션은 컨테이너의 1번 프로세스가 아닙니다.
다음을 시작하는 스크립트 파일 app1.sh를 생성합니다.
#!/usr/bin/env bash node app
그런 다음 Dockerfile1 파일을 생성합니다. 내용은 다음과 같습니다.
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"]
다음으로 이미지를 생성합니다.
$ docker build --no-cache -t signal-app1 -f Dockerfile1 .
그런 다음 컨테이너를 시작하여 애플리케이션을 실행합니다.
$ docker run -it --rm -p 3000:3000 --name="my-app1" signal-app1
이때, 컨테이너에 있는 노드 애플리케이션의 프로세스 번호가 더 이상 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入门教程
위 내용은 Docker 컨테이너에서 신호를 잡는 방법을 알고 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Docker 버전을 얻으려면 다음 단계를 수행 할 수 있습니다. Docker 명령 "Docker -version"을 실행하여 클라이언트 및 서버 버전을 볼 수 있습니다. Mac 또는 Windows의 경우 Docker Desktop GUI의 버전 탭 또는 Aff Docker Desktop 메뉴를 통해 버전 정보를 볼 수도 있습니다.

Docker 이미지 생성 단계 : 빌드 지침이 포함 된 Dockerfile을 작성하십시오. Docker 빌드 명령을 사용하여 터미널에 이미지를 빌드하십시오. Docker 태그 명령을 사용하여 이미지를 태그하고 이름과 태그를 지정하십시오.

Docker Desktop을 사용하는 방법? Docker Desktop은 로컬 머신에서 Docker 컨테이너를 실행하는 도구입니다. 사용 단계는 다음과 같습니다. 1. Docker Desktop 설치; 2. Docker Desktop을 시작하십시오. 3. Docker 이미지를 만듭니다 (Dockerfile 사용); 4. Docker Image 빌드 (Docker 빌드 사용); 5. 도커 컨테이너를 실행하십시오 (Docker Run 사용).

국내 거울 소스로 전환 할 수 있습니다. 단계는 다음과 같습니다. 1. 구성 파일 /etc/docker/daemon.json 편집 및 미러 소스 주소를 추가하십시오. 2. 저장 및 종료 후 Docker Service Sudo SystemCTL Docker를 다시 시작하여 이미지 다운로드 속도 및 안정성을 향상시킵니다.

단계를 따르면 Docker 컨테이너 이름을 쿼리 할 수 있습니다. 모든 컨테이너 (Docker PS)를 나열하십시오. 컨테이너 목록을 필터링합니다 (GREP 명령 사용). 컨테이너 이름 ( "이름"열에 위치)을 가져옵니다.

Docker Logs를 보는 방법에는 다음이 포함됩니다. Docker Logs 명령 사용 : Docker Logs Container_name Docker Exec 명령을 사용하여 RUN /BIN /SH를 사용하여 로그 파일을 봅니다. cat /var/log/container_name.log docker-compose logs docker compose의 명령 : docker-compose -f docker-com 사용

Docker 이미지를 업데이트하는 단계는 다음과 같습니다. 최신 이미지 태그 가져 오기 새 이미지 특정 태그의 이전 이미지 삭제 (선택 사항) 컨테이너를 다시 시작하십시오 (필요한 경우)

Docker Container Startup 단계 : 컨테이너 이미지를 당기기 : "Docker Pull [Mirror Name]"을 실행하십시오. 컨테이너 생성 : "docker"[옵션] [미러 이름] [명령 및 매개 변수]를 사용하십시오. 컨테이너를 시작하십시오 : "Docker start [컨테이너 이름 또는 ID]"를 실행하십시오. 컨테이너 상태 확인 : 컨테이너가 "Docker PS"로 실행 중인지 확인하십시오.
