← 전체 글로 돌아가기

Docker

Docker 컨테이너 exit code로 재시작 원인 좁히기

컨테이너가 재시작을 반복할 때 exit code만 봐도 앱 자체 문제인지, 설정 문제인지, OOM인지를 꽤 좁힐 수 있다.

컨테이너 재시작 루프를 디버깅할 때 로그보다 exit code를 먼저 보는 습관이 생겼다. exit code 하나로 원인의 범주를 빠르게 구분할 수 있기 때문이다.

exit code 확인

docker inspect <container_name> --format='{{.State.ExitCode}}'

자주 보는 코드들:

exit code의미
0정상 종료 (앱이 스스로 끝남)
1앱 에러 — 런타임 예외, 설정 오류 등
137SIGKILL — OOM 또는 docker kill
143SIGTERM — 정상 종료 요청을 앱이 처리하지 못한 경우
126명령 실행 권한 없음
127entrypoint 명령을 찾을 수 없음

exit code 1이면 앱 로그를 보면 된다. 137이면 OOM 또는 외부 강제 종료다. 127이면 Dockerfile의 CMD/ENTRYPOINT에 오타가 있거나 이미지에 실행 파일이 없는 것이다.

restart policy와의 관계

# docker-compose.yml
restart: "on-failure:5"

on-failure는 exit code가 0이 아닐 때만 재시작한다. 횟수 제한을 붙이지 않으면 무한 반복한다. Swarm에서는 deploy.restart_policy로 같은 설정을 한다.

deploy:
  restart_policy:
    condition: on-failure
    max_attempts: 5
    delay: 5s

always 정책을 쓰는 컨테이너는 exit code 0으로 끝나도 재시작한다. 개발 중에는 편하지만, 앱이 의도적으로 종료되어야 하는 경우에는 문제가 된다.

Swarm에서 실패한 태스크 기록 보기

Swarm에서 재시작이 계속 실패하면 서비스가 Failed 상태로 빠진다.

docker service ps <service_name> --no-trunc

--no-trunc를 빠뜨리면 에러 메시지가 잘려서 원인을 알 수 없는 경우가 있다. 각 태스크의 에러 메시지를 확인하고 원인을 고친 뒤 서비스를 강제로 재배포한다.

docker service update --force <service_name>

기존 설정을 그대로 두고 태스크만 새로 띄운다. 환경변수 같은 설정을 바꿨다면 해당 파라미터를 --env-add 등으로 명시해서 반영해야 한다.