본문 바로가기

Trouble Shooting

도커라이징 작업을 하며 겪은 트러블 슈팅

1) Nginx 사용 시 컨테이너 종료

문제 상황

Dockerfile에는 맨 아래에서 CMD로 passenger와 nginx가 뜨게 구성했는데, 도커 컨테이너가 실행하자마자 중지되는 현상이 발생했다.

CMD bundle exec passenger start -a localhost -p 10000 ~~(생략)~ --nginx-bin /opt/nginx/sbin/nginx && \
    nginx

로그를 봤을 때에는 실행하다 문제가 발생한 것은 아닌 것 같은데 직접 컨테이너로 들어가 docker ps 명령어로 컨테이너 상태를 확인하면 실행하는 컨테이너 목록에서 보이지 않는다.

 

문제 원인

Nginx의 작동 방식과 연관이 있다. 초기 프로세스가 마스터 Nginx 프로세스와 일부 워커 프로세스만 생성한 다음에 중지하는데, 도커는 원래 명령의 PID만 감시하기 때문에 초기 프로세스가 중지되면 작업이 종료된 것으로 인식하고 컨테이너를 중지하게 된다.

 

문제 해결

CMD bundle exec passenger start -a localhost -p 10000 ~~(생략)~ --nginx-bin /opt/nginx/sbin/nginx && \
    nginx -g 'daemon off;'

Nginx 실행 시 -g ‘daemon off’; 옵션을 주어 foreground로 실행되게 변경하면 된다. 이렇게 하면 초기 프로세스가 종료되지 않고 컨테이너가 계속 실행된다.

 

참고 링크

 


 

2) shell form vs exec form

문제 상황

Dockerfile에는 맨 아래에서 CMD로 shell script form으로 감싸서 실행하고 있다.

CMD bundle exec passenger start -a localhost -p 10000 ~~(생략)~~ --nginx-bin /opt/nginx/sbin/nginx && \     nginxCMD bundle exec passenger start -a localhost -p 10000 ~~(생략)~~ --nginx-bin /opt/nginx/sbin/nginx && \
    nginx

 

문제 원인

도커는 기본적으로 PID 1번으로 실행되는 프로세스에 SIGTERM 신호를 보내 컨테이너를 종료하는데, shell form(위 코드와 같이 지시문에 셸을 사용하는 형태)로 작성하면 셸 자체가 PID 1이 되고, 실제로 실행되는 프로세스는 PID 1인 셸의 자식 프로세스가 된다. 셸은 SIGTERM 신호를 받으면 신호를 넘기고 자식 프로세스에게 전달하지 않기 때문에 자식 프로세스는 고아 프로세스가 된다. 이렇게 되면 컨테이너가 즉시 종료되지 않는 문제가 있다.

 

문제 해결

exec form으로 변경한다. 나의 경우에는 추가로 dumb-init을 사용했다. dumb-init을 사용하면 본인의 자식 프로세스에게 SIGTERM 신호를 보내 고아 상태가 된 자식 프로세스를 거두는 역할도 수행한다.

 CMD ["dumb-init", "/start-server.sh"]
#!/bin/sh
bundle exec passenger start -a localhost -p 10000 ~~(생략)~~ --nginx-bin /opt/nginx/sbin/nginx
nginx -g 'daemon off;'

 

참고 링크


3) ARG SCOPE

문제 상황

망분리 작업을 하고 있을 때, 망분리 이후에 dockerfile을 수정할 일이 없게 FROM 절에 있는 base image를 동적으로 받을 수 있게 변경해 달라는 요청이 있었다. 그래서 docker build 시에 —build-argAWS_REGION를 넘겨주고 그 이후에는 환경 변수로 넣어주게 수정했는데, FROM 절까지만 해도 잘 받아오는 AWS_REGION 값이 이후에는 빈 값이 들어가는 문제가 발생했다.

docker build --platform linux/amd64 . --build-arg AWS_REGION="$AWS_REGION" ... -t $IMAGE_NAME
... (생략) ...
ARG AWS_REGION

FROM ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${AWS_BASE_IMAGE}
ENV AWS_REGION=${AWS_REGION}

RUN echo $AWS_REGION # 빈 값이 나옴

 

문제 원인

FROM절 이전에 선언된 ARG는 도커파일에서 빌드를 한 이후에는 정의된 빌드 단계의 범위(scope)에서 벗어나기 때문이다. 즉, ARG 명령의 범위는 빌드 단계로 제한된다.

 

문제 해결

빌드 단계 범위 내에서 사용할 수 있게 ARG를 재선언한다.

... (생략) ...
ARG REGION_ARG

FROM ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${AWS_BASE_IMAGE}

ARG REGION_ARG
ENV AWS_REGION=${AWS_REGION}

RUN echo $AWS_REGION # 값이 제대로 나옴

 

참고 링크