[Docker] #5 Docker file 작성 시 유의사항

다채로운·2022년 6월 5일
0

Docker

목록 보기
5/6
post-thumbnail
post-custom-banner

Docker file 작성시 유의사항

도커 컨테이너를 구동하기 위해서는 이미지가 필수인것은 이미 다들 아시는 사실입니다.
그렇다면!🙋‍♀️ 이미지를 만드는 방법은 Dockerfile로 생성하거나 이미 구동되고 있는 컨테이너를 이미지화 하는 두가지 방법이 있는데, 뭐가 더 좋을까?🤔라는 의문이 생기실겁니다.(저만그런가요?)

사실 제가 이 두가지 방법을 알고 난 후 어떤것이 더 좋을까? 라는 의문이 생겨 찾아보았습니다.
찾아보니 대부분 Dockerfile을 통한 이미지 생성을 더 추천해주셨습니다.
그 이유는 추후 다른 개발자 혹은 관리자가 보았을 때 Dockerfile을 통해 컨테이너의 기능 혹은 실행되는 명령어를 구체적으로 확인할 수 있기 때문입니다.

실무에 대입해보면 관리자가 중간에 변경될 수도 있고, 혹은 기존에 사용하던 컨테이너의 기능을 추가 또는 수정하여 컨테이너를 재생성해야하는 업무도 빈번히 발생할 것입니다.

이런경우를 대비하여 우리는 처음부터 Dockerfile을 통해 이미지를 생성하고 컨테이너화해야합니다.

그럼 Dockerfile을 작성할 때 유의해야 하는 사항들을 살펴보겠습니다.

1. CMD vs ENTRYPOINT

▶ CMD : 컨테이너가 시작될 때 실행하는 명령어, Dockerfile에서 한번만 지정할 수 있음
▶ ENTRYPOINT : 컨테이너가 시작될 때 실행하는 명령어

Dockerfile을 생성할 때 사용되는 CMD, ENTRYPOINT의 설명을 살펴보면 두개가 동일한 기능을 하는 것 처럼 보여집니다. 그렇다면 파일을 직접 생성하여 두 형식의 차이점을 살펴보겠습니다.

vscode를 이용하여 2개의 파일을 생성합니다.

#file명 Dockerfile.cmd
FROM ubuntu
CMD [ "echo", "hello" ]
#file명 Dockerfile.entrypoint
FROM ubuntu
ENTRYPOINT [ "echo", "hello" ]

위 2개의 Dockerfile로 이미지를 생성해보겠습니다.

docker image build -t docker-cmd -f Dockerfile.cmd .
docker image build -t docker-entrypoint -f Dockerfile.entrypoint .

이미지가 생성되었다면 컨테이너를 구동해보겠습니다.

#1. 이미지로 컨테이너 생성
docker container run docker-cmd
docker container run docker-entryponit
#2. 명령어 인자값을 추가하여 컨테이너 생성
docker container run docker-cmd echo world
docker container run docker-entryponit echo world

1번 명령어로 컨테이너를 생성하면 2개의 컨테이너는 동일하게 hello를 출력하고 종료됩니다.
그러나 2번 명령어로 인자값을 추가하여 컨테이너를 생성하면 2개의 컨테이너는 다른 출력값을 보여주고 종료됩니다.

이를 통해, CMD와 ENTRYPOINT의 차이점을 살펴볼 수 있습니다.

CMD는 container run 명령에서 전달한 명령어가 Dockerfile의 CMD 항목의 명령어를 덮어씀
ENTRYPOINT는 contaienr run 명령에서 전달한 명령어가 ENTRYPOINT 항목의 명령어의 파라미터로 사용(echo hello echo world 실행 결과와 동일함)

2. 사용자 입력이 발생하지 않도록 하고, 포그라운드 프로세스로 실행되어야 함

FROM ubuntu
ENV  DEBIAN_FRONTEND=noninteractive
RUN  apt-get update
RUN  apt-get install apache2 -y
ADD  hello.html /var/www/html/
WORKDIR /var/www/html/
RUN  [ "/bin/bash", "-c", "echo hello2 >> hello2.html" ]
EXPOSE  80
CMD  apachectl -DFOREGROUND

이전 게시물에서 Dockerfile 형식의 예시파일로 활용되었던 코드입니다.
해당 파일의 기능은 아파치로 웹서버를 만들고 사용자에게 웹페이지를 출력해주는 것입니다.

사용자 입력이 발생하지 않도록 하고, 포그라운드 프로세스로 실행되어야 함 이라는 조건을 충족하는 Dockerfile이기 때문에 아무런 문제없이 컨테이너가 구동되었습니다.

그러면 해당 조건을 충족하지 않도록 Dockerfile을 수정한 뒤, 컨테이너를 구동해보겠습니다.

Dockerfile에서
ENV DEBIAN_FRONTEND=noninteractive 제거
RUN apt-get install apache2 -y에서 -y만 생략
CMD apachectl -DFOREGROUND에서 -DFOREGROUND를 생략

FROM ubuntu
RUN  apt-get update
RUN  apt-get install apache2
WORKDIR /var/www/html/
RUN  [ "/bin/bash", "-c", "echo hello2 >> hello2.html" ]
EXPOSE  80
CMD  apachectl 

#이미지 생성
docker image build -t web Dockerfile.web .

ENV DEBIAN_FRONTEND=noninteractive 제거, RUN apt-get install apache2 -y에서 -y만 생략
부분이 수정됨으로써 이미지 생성에서부터 에러가 발생하는 것을 볼 수 있습니다.
모듈을 설치하면서 사용자의 입력이 발생하는 구간에서 입력값을 정상적으로 받을 수 없어 에러가 발생하고 이미지 생성에 실패합니다.

위 2개의 조건을 수정한 뒤, 다시 이미지 파일을 빌드하여보겠습니다.

FROM ubuntu
ENV  DEBIAN_FRONTEND=noninteractive
RUN  apt-get update
RUN  apt-get install apache2 -y
WORKDIR /var/www/html/
RUN  [ "/bin/bash", "-c", "echo hello2 >> hello2.html" ]
EXPOSE  80
CMD  apachectl 

오! 위에서 발생했던 에러가 나오지 않고 정상적으로 이미지가 빌드되었습니다.
컨테이너를 구동해보겠습니다.

docker container run -d -P --name web apache_web
docker container ps
docker container ls -a

네!?분명 컨테이너를 생성했는데 docker conatiner ps명령어를 통해 실행중인 컨테이너를 출력해보니 아무것도 없네요...?? (있었는데 없습니다 이런느낌이네요)

그 이유는..
CMD apachectl -DFOREGROUND에서 -DFOREGROUND를 생략 했기 때문에
컨테이너는 아파치 서비스를 구동한 뒤 바로 종료하게됩니다🤦‍♀️

실제 업무환경에 대입해보자면, 웹서버를 구동하는 컨테이너를 생성해 배포했으나 웹서버가 한번 켜졌다고 바로 종료되어서 사용자는 페이지를 볼 수도 입력값을 넣을수도 없는 상태가 되는 것입니다.

이런 참사를 막기 위해서는... 웹서버와 같은 기능을 하는 컨테이너들은 포그라운드 프로세스로 실행될 수 있도록 해야합니다!(잘 기억해두고 장애가 나지 않도록 유의해주세요)

3. 도커 이미지가 커지지 않도록 유의

#3-1 레이어를 최소화

지금까지 Dockerfile로 이미지를 생성했던 것을 보면,
이미지가 생성될 때 [+] Building 1.9s (8/8) FINISHED 문구가 출력되고
단계적으로 명령어가 실행되는 것을 볼 수 있습니다.

단계적으로 명령어가 실행되는 것을 레이어라고 합니다.

그럼 실습을 통해서 레이어 최소화 방법을 살펴보겠습니다.
아래 코드를 통해 Dockerfile을 2개 생성합니다.

# 1. 레이어가 4개인 Dockerfile
FROM  ubuntu
RUN   mkdir /test
RUN   fallocate -l 100m /test/dumy
RUN   rm /test/dumy
# 2. 레이어가 2개인 Dockerfile
FROM  ubuntu
RUN   mkdir /test && RUN   fallocate -l 100m /test/dumy && RUN   rm /test/dumy

이미지를 생성한 뒤, 용량을 확인해 보면 차이를 확인할 수 있습니다.
분명 똑같은 기능을 하는 이미지이나 용량이 100MB 이상 차이나는 것을 볼 수 있습니다.

Dockerfile을 작성할 때 동일한 기능을 수행하는 명령어(예시파일에서는 RUN명령어)를 &&를 사용하여 조합하고 레이어를 최소하하는 것이 좋습니다.

#3-2 불필요한 도구를 설치하지 않음

앞서 살펴봤던 Dockerfile들을 보시면 웹서버 등 기능을 수행하기 위해 패키지를 설치하는 apt-get install명령어를 사용하시는 것을 볼 수 있습니다.

apt-get install 명령어를 통해 패키지를 설치하는 것은 좋으나, 필요로 하지 않는 다른 패키지들도 설치되어 용량,캐시를 많이 차지하게됩니다.

이를 방지하기 위해 아래와 같이 Dockerfile을 작성해주시는 것을 권고드립니다.

FROM ubuntu
RUN  apt-get update && \
     apt-get install --no-install-recommends -y nginx && \
     rm -rf /var/lib/apt/lists/*
profile
네트워크,보안 운영하는 일개미의 velog
post-custom-banner

0개의 댓글