
sleep
물론 가장 복잡한 프로세스를 대신하는 것입니다.
이 Dockerfile(exec 형식을 사용하여 볼 수 있듯이 하나의 프로세스만 실행되고 하위 프로세스는 없음 bash
):
FROM busybox
CMD ["/bin/sleep", "100000"]
중단할 수 없는 컨테이너를 생성합니다.
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
중지하려고 할 때:
time docker stop kill-sleep
kill-sleep
real 0m10.449s
user 0m0.021s
sys 0m0.027s
컨테이너가 종료되기 10초 전에 명령 시간이 초과됩니다.
문제는 sleep
신호를 처리하지 않는다는 것이 아닙니다. 왜냐하면 호스트에서 실행하면 다음과 같기 때문입니다.
sleep 100000
# in another shell
ps faxww | grep sleep
kill -TERM 31333 # the PID
프로세스가 즉시 중지됩니다.
문제는 이것이 컨테이너에서 PID 1로 실행된다는 사실과 관련이 있을 수 있지만 아직 이에 대한 참조 문서를 볼 수 없습니다.
답변1
당신이 실행할 때 docker stop ...
,어떤 일이 일어날 것입니다:
docker
SIGTERM
컨테이너의 기본 프로세스로 보냅니다 . 프로세스는 을 마스크/무시할 수 있으며SIGTERM
, 그렇게 하는 경우(또는 종료하지 않고 처리) "아무것도 아님" 일어날 것이다.- 시간 초과(기본값 10초) 후 기본 프로세스로
docker
보냅니다 .SIGKILL
이 신호는 프로세스에 의해 가려질 수 없으므로 종료 절차를 실행할 기회 없이 즉시 종료됩니다.
이상적으로는 내부에서 실행되는 프로세스가 적시 docker
에 응답하여 종료되기 전에 모든 관리 작업을 처리합니다.SIGTERM
프로세스에 수행할 관리 작업이 없거나(예: sleep
) 에 제대로 응답하지 않는다는 것을 알고 있는 경우 SIGTERM
플래그를 사용하여 더 짧은(또는 더 긴) 시간 제한을 지정할 수 있습니다 -t
.
-t, --time=10 Seconds to wait for stop before killing it
예를 들어, 귀하의 경우에는 docker stop -t 0 ${CONTAINER}
.
이 신호 동작이 다른 이유는 sleep
PID = 1로 실행되기 때문입니다.
일반적으로(예: PID != 1로 실행) 프로세스가 명시적으로 처리하지 않는 신호는 프로세스가 종료되도록 합니다. a 를 보내 sleep
보세요 SIGUSR1
.
그러나 PID = 1로 실행하면 처리되지 않은 신호가 무시됩니다. 그렇지 않으면 커널 패닉이 발생합니다.
Kernel panic - not syncing: Attempted to kill init!
Docker 도구를 사용하여 Docker 컨테이너에 신호를 보낼 수 있습니다. 예를 들면 다음과 같습니다.
docker kill -s TERM kill-sleep
보시다시피 이는 원하는 효과를 얻지 못하는 반면 다음과 같은 효과가 있습니다.
docker kill -s KILL kill-sleep
실험
도커파일
FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
run.sh
#!/bin/sh
echo "sleeping"
sleep 100000
이제 실행
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
그리고 이것은 다른 터미널에서:
docker stop kill-sleep
우리는 동일한 10초 지연/시간 초과를 관찰합니다.
해결책
이제 SIGTERM
. POSIX 쉘이 신호를 처리하는 방식에 따라 배경화 및 wait
호출이 발생합니다(참조:sleep
이것이상).
run.sh
#!/bin/sh
die_func() {
echo "oh no"
sleep 2
exit 1
}
trap die_func TERM
echo "sleeping"
sleep 100000 &
wait
명령을 다시 실행하면 우리가 추구하는 바가 무엇인지 알 수 있습니다!
$ time docker stop kill-sleep
kill-sleep
real 0m2.515s
user 0m0.008s
sys 0m0.044s
답변2
추가 옵션:
--init
컨테이너 실행 명령에 스위치를 추가합니다 . 이런 식으로 sleep은 PID 1이 아니며 init는 TERM에서 올바른 작업을 수행합니다.--stop-signal=KILL
컨테이너 실행 명령에 추가합니다 . 그러나 KILL을 다소 일반적인 작업으로 사용하는 것은 일반적으로 권장되지 않습니다.