실험

실험

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 ...,어떤 일이 일어날 것입니다:

  1. dockerSIGTERM컨테이너의 기본 프로세스로 보냅니다 . 프로세스는 을 마스크/무시할 수 있으며 SIGTERM, 그렇게 하는 경우(또는 종료하지 않고 처리) "아무것도 아님" 일어날 것이다.
  2. 시간 초과(기본값 10초) 후 기본 프로세스로 docker보냅니다 . SIGKILL이 신호는 프로세스에 의해 가려질 수 없으므로 종료 절차를 실행할 기회 없이 즉시 종료됩니다.

이상적으로는 내부에서 실행되는 프로세스가 적시 docker에 응답하여 종료되기 전에 모든 관리 작업을 처리합니다.SIGTERM

프로세스에 수행할 관리 작업이 없거나(예: sleep) 에 제대로 응답하지 않는다는 것을 알고 있는 경우 SIGTERM플래그를 사용하여 더 짧은(또는 더 긴) 시간 제한을 지정할 수 있습니다 -t.

-t, --time=10
    Seconds to wait for stop before killing it

예를 들어, 귀하의 경우에는 docker stop -t 0 ${CONTAINER}.


이 신호 동작이 다른 이유는 sleepPID = 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을 다소 일반적인 작업으로 사용하는 것은 일반적으로 권장되지 않습니다.

관련 정보