[Docker] 컨테이너를 Graceful 하게 종료하기

HyeJin Jeon·2021년 3월 8일
0
post-thumbnail

docker stop

하나 또는 다수의 컨테이너에 SIGTERM(정상 종료) 을 보내고, 유예 시간 뒤 SIGKILL(강제종료) 을 송신하는 명령어

docker stop [OPTIONS] CONTAINER [CONTAINER...]

OPTIONS

  • --time, -t : 강제 종료 전까지의 유예 시간 (단위: seconds / default: 10)

SIGTERM 수신 로그
SIGTERM 수신 후, 정상 종료된 로그

docker kill

하나 또는 다수의 컨테이너에 SIGKILL(default) 시그널을 송신하는 명령어
--singal 플래그로 송신할 UNIX SIGNAL 을 지정할 수 있다.

docker kill [OPTIONS] CONTAINER [CONTAINER...]

OPTIONS

  • --signal, -s : 컨테이너에 송신할 시그널 (default: SIGKILL)

이 때, /bin/sh -c 의 하위 프로세스로 실행되는 ENTRYPOINT 나 CMD 사용시 실행 파일이 컨테이너의 PID 1이 아니기 때문에, Unix Signal 을 수신하지 않는다.

SIGKILL 수신 로그
SIGKILL 수신 후, 강제 종료된 로그

PID 1 프로세스

https://docs.docker.com/engine/reference/commandline/kill/#extended-description

ENTRYPOINT and CMD in the shell form run as a child process of /bin/sh -c, which does not pass signals. This means that the executable is not the container’s PID 1 and does not receive Unix signals.

컨테이너에서 PID 가 1이 아닌 프로세스는 docker stop / kill 의 SIGTERM 시그널을 받지 못한다.
셸 형식 CMD,ENTRYPOINT 명령어나, RUN 명령을 사용할 시, /bin/sh 이 PID 1이 되기 때문에 /bin/sh 로 실행 된 프로세스까지 시그널이 도달하지 못한다.

이를 방지하기 위해, Dockerfile 에 exec 형식 CMD 로 컨테이너를 실행하게끔 설정해야한다.

# 셸 형식 CMD
CMD command param1 param2

# exec 형식 CMD
CMD [ "executable", "param1", "param2" ]

결론

컨테이너가 유예 시간 동안 정상 종료 시퀀스를 수행하고 이후 강제종료 되길 바라면 docker stop

컨테이너가 유예 시간 없이 정상 종료되길 바라면 docker kill 명령에 --signal 로 적절한 종료 시그널을 송신한다.

참고) 컨테이너 내부 PID 확인 및 종료

일반적으로 컨테이너 내부 PID를 host 머신에서 확인할 수 없다. (PID namespace가 분리되어 있기 때문)

host 머신에서 컨테이너 내부 PID를 확인하고 싶을 경우, --pid host 플래그로 pid namespace를 host 로 지정하여 컨테이너를 실행시켜야 한다.

$ docker run -dit --name demo --pid host demo:2

ps -efc | grep catalina
호스트에서 컨테이너 내부에서 실행된 명령으로 프로세스가 생성됨

sudo kill -15 PID
호스트에서 컨테이너 프로세스로 정상 종료 시그널을 보낸 후, 컨테이너 목록에서 제거됨

container stop logs
컨테이너 내부에서 시그널을 수신해 정상 종료됨

출처:
https://docs.docker.com/engine/reference/
https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/

profile
Backend Developer

0개의 댓글