Docker 컨테이너 적절한 종료 방법

DockerBeginner
지금 연습하기

소개

Docker 컨테이너는 현대 소프트웨어 개발 및 배포에 필수적인 요소가 되었습니다. 이러한 컨테이너를 적절하게 종료하는 것은 안정성 유지, 데이터 손실 방지 및 원활한 애플리케이션 수명주기 보장에 매우 중요합니다. 이 튜토리얼에서는 Docker 컨테이너 수명주기를 이해하고, 우아한 컨테이너 종료를 구현하며, 다양한 종료 시나리오를 처리하여 컨테이너 관리를 최적화하는 방법을 안내합니다.

Docker 컨테이너 수명주기 이해

Docker 컨테이너는 가볍고, 휴대 가능하며, 확장 가능하도록 설계되었습니다. 애플리케이션 실행을 위한 일관되고 격리된 환경을 제공하여 소프트웨어 개발, 배포 및 관리를 용이하게 합니다. 그러나 Docker 컨테이너의 수명주기를 이해하는 것은 실행 중인 프로세스의 적절한 종료 및 우아한 종료를 보장하는 데 중요합니다.

Docker 컨테이너 수명주기

Docker 컨테이너의 수명주기는 다음 단계로 나눌 수 있습니다.

  1. 생성 (Creation): Docker 컨테이너는 컨테이너의 템플릿 역할을 하는 Docker 이미지에서 생성됩니다.
  2. 실행 (Running): 컨테이너가 시작되고 이미지에 지정된 메인 프로세스가 실행을 시작합니다.
  3. 일시 중지 (Pausing): 컨테이너를 일시적으로 중지할 수 있으며, 메인 프로세스를 일시 정지하면서 컨테이너 상태를 유지합니다.
  4. 중지 (Stopping): 컨테이너가 중지되고 메인 프로세스에 SIGTERM 신호가 전송되어 우아하게 종료할 수 있도록 합니다.
  5. 재시작 (Restarting): 중지된 컨테이너를 재시작하여 메인 프로세스의 실행을 다시 시작할 수 있습니다.
  6. 제거 (Removing): 컨테이너를 제거하여 시스템에서 영구적으로 삭제합니다.
graph LR A[생성] --> B[실행] B --> C[일시 중지] B --> D[중지] D --> B[재시작] B --> E[제거]

컨테이너 종료 처리

Docker 컨테이너가 중지되면 컨테이너 내에서 실행 중인 메인 프로세스는 우아한 종료를 요청하는 데 사용되는 기본 신호인 SIGTERM 신호를 받습니다. 프로세스는 그런 다음 데이터 저장, 연결 종료 또는 리소스 해제와 같은 필요한 정리 작업을 수행한 후 종료해야 합니다.

메인 프로세스가 지정된 시간 제한 (기본값은 10 초) 내에 종료되지 않으면 Docker 는 프로세스를 강제 종료하는 SIGKILL 신호를 전송합니다. 이는 프로세스가 제대로 정리하지 못했을 경우 데이터 손실이나 기타 문제로 이어질 수 있습니다.

적절한 종료를 보장하려면 애플리케이션이 SIGTERM 신호를 처리하고 우아하게 종료하도록 설계하는 것이 중요합니다. 이는 애플리케이션 코드에 신호 처리기를 구현하거나 tini 또는 dumb-init와 같은 프로세스 관리자를 사용하여 메인 프로세스를 대신하여 신호를 처리하는 방법으로 달성할 수 있습니다.

## Docker 컨테이너의 엔트리포인트로 tini 사용 예시
ENTRYPOINT ["/usr/bin/tini", "--", "your-application-command"]

Docker 컨테이너 수명주기와 종료 프로세스를 올바르게 처리함으로써 Docker 컨테이너에서 실행되는 애플리케이션을 안전하게 중지 및 재시작하고 데이터 손실이나 기타 문제를 방지할 수 있습니다.

우아한 컨테이너 종료

Docker 컨테이너의 우아한 종료를 보장하는 것은 애플리케이션의 무결성과 관리하는 데이터를 유지하는 데 중요합니다. 컨테이너가 중지되면 컨테이너 내에서 실행 중인 메인 프로세스는 데이터 저장, 연결 종료 또는 리소스 해제와 같은 필요한 정리 작업을 수행할 기회를 가져야 합니다.

SIGTERM 신호 처리

기본적으로 Docker 컨테이너가 중지되면 컨테이너 내에서 실행 중인 메인 프로세스는 SIGTERM 신호를 받습니다. 이 신호는 프로세스의 우아한 종료를 요청하는 데 사용됩니다. 적절한 종료를 보장하려면 애플리케이션이 SIGTERM 신호를 처리하고 종료하기 전에 필요한 정리 작업을 수행하도록 설계되어야 합니다.

다음은 Python 애플리케이션에서 SIGTERM 신호를 처리하는 방법의 예입니다.

import signal
import time

def graceful_shutdown(signum, frame):
    print("SIGTERM 신호를 받았습니다. 우아한 종료를 수행 중입니다...")
    ## 여기에 정리 작업 수행
    time.sleep(5)  ## 정리 작업 시뮬레이션
    print("우아한 종료 완료.")
    exit(0)

signal.signal(signal.SIGTERM, graceful_shutdown)

## 메인 애플리케이션 로직
while True:
    print("애플리케이션 실행 중...")
    time.sleep(1)

이 예제에서 graceful_shutdown 함수는 SIGTERM 신호의 처리기로 등록됩니다. 컨테이너가 중지되면 이 함수가 호출되어 애플리케이션이 종료하기 전에 필요한 정리 작업을 수행할 수 있습니다.

종료 시간 제한 사용자 지정

기본적으로 Docker 는 메인 프로세스가 SIGTERM 신호를 받은 후 10 초 동안 종료되기를 기다립니다. 프로세스가 이 시간 제한 내에 종료되지 않으면 Docker 는 프로세스를 강제 종료하는 SIGKILL 신호를 보냅니다.

Docker 컨테이너를 시작할 때 --stop-timeout 플래그를 사용하여 종료 시간 제한을 사용자 지정할 수 있습니다.

docker run -d --stop-timeout 20 your-image

이렇게 하면 메인 프로세스가 우아한 종료를 수행할 시간을 더 주어 종료 시간 제한을 20 초로 늘립니다.

프로세스 관리자 사용

우아한 종료를 보장하는 또 다른 방법은 tini 또는 dumb-init와 같은 프로세스 관리자를 컨테이너의 엔트리포인트로 사용하는 것입니다. 이러한 프로세스 관리자는 신호를 처리하고 메인 프로세스로 전달하여 적절한 종료 시퀀스를 보장하도록 설계되었습니다.

## Docker 컨테이너의 엔트리포인트로 tini 사용 예시
ENTRYPOINT ["/usr/bin/tini", "--", "your-application-command"]

프로세스 관리자를 사용하면 애플리케이션의 신호 처리를 단순화하고 프로세스 관리자가 대신 종료 프로세스를 처리하도록 할 수 있습니다.

우아한 종료 메커니즘을 이해하고 구현함으로써 Docker 컨테이너를 안전하게 중지 및 재시작하고 데이터 손실이나 기타 문제를 방지할 수 있습니다.

종료 시나리오 처리

Docker 컨테이너를 사용할 때는 다양한 종료 시나리오가 발생할 수 있으며, 각각 다른 접근 방식이 필요합니다. 이러한 시나리오를 이해하고 처리하는 방법을 아는 것은 애플리케이션의 안정성과 신뢰성을 보장하는 데 중요합니다.

우아한 종료

이전 섹션에서 설명했듯이 Docker 컨테이너를 중지하는 권장 방법은 SIGTERM 신호를 처리하고 우아한 종료를 수행하는 것입니다. 이렇게 하면 메인 프로세스가 리소스를 정리하고 데이터를 저장하며 제어된 방식으로 종료할 수 있습니다.

강제 종료 (SIGKILL)

메인 프로세스가 지정된 종료 시간 제한 (기본값은 10 초) 내에 종료되지 않으면 Docker 는 프로세스를 강제 종료하는 SIGKILL 신호를 보냅니다. 프로세스가 제대로 정리하지 못했을 경우 데이터 손실이나 기타 문제가 발생할 수 있습니다.

이 시나리오를 처리하려면 다음을 수행할 수 있습니다.

  1. 컨테이너를 시작할 때 --stop-timeout 플래그를 사용하여 종료 시간 제한을 늘립니다.
  2. 애플리케이션이 할당된 시간 내에 SIGTERM 신호를 처리하고 우아한 종료를 수행하도록 설계되어 있는지 확인합니다.
  3. tini 또는 dumb-init와 같은 프로세스 관리자를 사용하여 애플리케이션을 대신하여 신호 전달 및 종료 프로세스를 처리합니다.

컨테이너 재시작 정책

Docker 는 컨테이너가 중지될 때 컨테이너가 어떻게 동작해야 하는지 결정하는 다양한 재시작 정책을 제공합니다. 이러한 정책은 --restart 플래그를 사용하여 컨테이너를 시작할 때 설정할 수 있습니다. 일반적인 재시작 정책은 다음과 같습니다.

  • no: 컨테이너는 자동으로 재시작되지 않습니다.
  • always: 종료 상태에 관계없이 컨테이너는 항상 재시작됩니다.
  • on-failure: 컨테이너는 0 이 아닌 상태로 종료된 경우에만 재시작됩니다.
  • unless-stopped: 명시적으로 중지되지 않았을 경우 (예: docker stop 사용) 컨테이너는 재시작됩니다.

적절한 재시작 정책을 선택하면 애플리케이션이 계속 사용 가능하고 예기치 않은 중지 또는 오류에 강력해집니다.

## 재시작 정책 설정 예시
docker run -d --restart=on-failure:5 your-image

이 예제에서 컨테이너는 0 이 아닌 상태로 종료된 경우 최대 5 번까지 재시작됩니다.

다양한 종료 시나리오를 이해하고 적절하게 처리함으로써 Docker 컨테이너를 안전하게 중지 및 재시작하고 데이터 손실이나 기타 문제 발생 위험을 최소화할 수 있습니다.

요약

이 튜토리얼에서는 Docker 컨테이너의 적절한 종료를 보장하는 방법을 배웠습니다. 컨테이너 수명 주기를 이해하고, 우아한 종료 기법을 구현하며, 다양한 종료 시나리오를 처리함으로써 컨테이너 관리를 최적화하여 신뢰성, 가동 시간 및 전체 애플리케이션 안정성을 향상시킬 수 있습니다. 이러한 최선의 관행을 적용하면 강력하고 탄력적인 Docker 기반 인프라를 유지하는 데 도움이 됩니다.