Containerization/Docker

[Docker] 도커 이미지 만드는 법! (feat. Dockerfile)

쉬지마 이굥진 2024. 5. 17. 14:39

이 글은 2024 05월 원티드 프리온보딩 BE 챌린지 '도커'편 2주차 수업을 회고하며 정리한 글입니다.


지난 번 포스팅들에서는 이미지들을 도커 허브와 같은 레지스트리에서 다운받아 실행시키는 방법들을 알아봤다. 이번 포스팅에서는 이미지를 다운받아서만 실행하는 게 아닌, '나만의' 이미지를 만들어서 실행시키는 방법은 뭐가 있을지 정리해보려 한다.

 

이미지 만드는 방법

방법은 크게 두 가지이다. 

 

첫째, 우리가 쓰는 컨테이너를 대상으로 commit 명령어를 주어 컨테이너를 이미지화 시킨다.

둘째, 도커 파일(Dockerfile, 제목에 써져 있는 그것 맞습니다)을 작성하는 것이다.

 

도커파일은 대충 이렇게 생겼다. (자세한 정의 및 의미는 이따 알아보도록 하고)

FROM python:3.8-slim
WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

ENTRYPOINT ["python"]

CMD ["app.py"]

 

도커 파일의 형식에 맞게 적어준 후, build 명령을 주면 도커는 Dockerfile을 바탕으로 새로운 이미지를 만들게 된다.

 

 

commit 과 build 의 차이

그럼 위에서 언급된 명령어 commit과 build의 차이는 뭘까?

결과적으로는 둘 다 이미지를 만드는 명령어라는 점에선 동일하나,

 

commit은 이미 우리가 이미 사용 중인 컨테이너를 이미지로 만드는 백업같은 느낌을 갖고있다. (즉, 이미지를 만들기 위해 기존의 컨테이너를 사용하며 컨테이너가 실행 중인 상태여야 함)

 

반면 build는 Dockerfile을 통해서 우리가 만들고 싶은 이미지를 '구체적으로, 시간의 순서에 따라 기록'해서 지정된 내요에 따라 이미지를 생성하는 느낌이라고 할 수 있다.

 

보통은 build 명령어를 사용해서 이미지를 만드는 것이 좀 더 일반적이고 권장되는 방법이다.


Dockerfile이란?

본격적으로 실습해보기 전에, 도커 파일이 무엇인지 자세히 알아보고 가자. 도커 파일이란?

  • 도커 이미지를 빌드하고 설정하는 데 사용되는 텍스트 파일
  • 도커 이미지를 어떻게 구성할지를 정의함
  • 도커 이미지를 만들기 위한 명령어와 설정 정보를 담고 있음
    • 베이스 이미지
    • 빌드 시 실행할 명령어
    • 복사할 파일
    • 환경 변수

공식 문서를 참조해서 상단에 대충 맛보기로만 명시해 둔 도커 파일의 용어들의 의미를 가지고 와 봤다.

도커파일 예시

  • FROM: 베이스 이미지 선정
    • 반드시! 있어야 하는 명령어
    • 여러겹의 이미지를 쌓아 가는데, 그 층 중 가장 기본이 되는 이미지
  • WORKDIR: work directory 선정
    • 도커파일 뒤에 오는 모든 지시자(RUN, CMD, COPY, ADD 등)에 대한 작업 디렉토리를 설정
    • 리눅스 명령어의 cd와 비슷한 역할
  • COPY: 복사할 파일 선정 (ex: 작업한 서비스 파일들)
    • 현재 로컬 컴퓨터에 있는 파일을 도커 컨테이너 안으로 복사하는 기능
  • RUN: "이미지 빌드 시" 실행할 명령어
    • 여러번 사용 가능
    • 보통 라이브러리 설치할 때 쓰임
  • CMD: "컨테이너 생성 시" 실행할 명령어
    • 이미지로부터 컨테이너를 생성해서 최초로 실행할 때 수행됨
  • ENTRYPOINT: "컨테이너가 생성되고 최초로" 실행할 명령어 (ex: 서버 실행)

도커 파일과 더불어 알아야 할 개념인 도커 이미지 레이어 구조는 아래 포스팅에 상세히 정리 해 두었다.

 

[Docker] Dockerfile에서 명령어 순서가 중요한 이유 (w/ 도커 이미지 레이어 구조)

Dockerfile이란?도커파일로 이미지를 만들어보기 전에, 도커 파일이 무엇인지 자세히 알아보고 가자. 도커 파일이란?도커 이미지를 빌드하고 설정하는 데 사용되는 텍스트 파일도커 이미지를 어떻

developer-jinnie.tistory.com


✏️이미지 만들기 - commit

이제 이미지를 만들어 보자! 실습은 Ubuntu 22.04 환경에서 진행했다.

docker run --name web-server -it ubuntu:22.04

Ubuntu 22.04 라는 이미지를 web-server 라는 이름을 가지도록 한 명령어를 실행시켜주었다. 

docker ps -a 명령어로 컨테이너가 잘 만들어 졌음을 확인했다.

 

docker commit web-server web-server-commit

 

web-server라는 이름을 가진 컨테이너에서, web-server-commit (commit을 통해 만들었다는 의미로 이렇게 지었다)라는 이름의 이미지를 만들어줘 라는 의미의 명령어다.

 

docker images 명령어로 web-server-commit 이미지가 성공적으로 잘 만들어짐을 확인할 수 있다.

 


✏️이미지 만들기 - build

위와 똑같은 과정을 이제 build 명령어를 통해 만들려면 어떻게 만들어야 할까.

먼저 Dockerfile 작성을 VSC 툴로 작성하기 위해 VSC에서 터미널을 열고 아래와 같은 명령어를 입력하고 실행해 줬다.

docker build -t web-server-build .

 

web-server-build 라고 이름 붙이고, 현재 디렉토리에 있는 Dockerfile을 사용해서 이미지를 빌드하겠다는 뜻으로 . 을 마지막에 붙여줬다. 

빌드 완료 !!

 

이미지도 잘 생성된 것을 볼 수 있다.

++ 해당 UI는 VSC 에서 Docker 관련 확장 프로그램을 설치하면 볼 수 있다. (Dockerfile 가독성도 좋게 해주니 설치하는 것을 권장한다)

 

도커 파일 작성

RUN

컨테이너 안에 파이썬3를 설치해서 파이썬3 안에 내장되어 있는 웹 서버를 사용할 거다. 이를 위한 터미널 명령어는 아래와 같은데,

# 파이썬을 설치하기 위한 apt update
apt update

# 파이썬3 설치
apt install python3

 

 

 위 명령어와 동일한 의미를 갖고 있는 도커 파일 지시어는 이 부분이다.

RUN apt update
RUN apt install -y python3

이렇게 작성해도 되는데, Dockerfile의 특성 상 이런 명령어가 실행될 때 마다 '레이어'가 생성되기 때문에 이렇게 작성하는 것은 효율적이지 않아서 && 기호를 통해 하나로 연결해 쓰는걸 권고한다. 관련 포스팅 링크

 

++ -y : 파이썬을 설치하는 과정에서 '정말로 설치할 건지'를 물어보는 화면이 뜨는데, 이 화면이 뜨면 정상적으로 도커 빌드가 작동하지 않기 때문에 자동으로 yes를 누르도록 하는 명령어

 

WORKDIR

# /var/www/html 디렉토리 생성
mkdir -p /var/www/html

# /var/www/html 로 이동
cd /var/www/html

이 명령어는 도커 파일에서 이 부분과 같다. 

 

즉, WORKDIR 명령어는

  • 저 /var/www/html 디렉토리가 없다면 디렉토리를 만들고,
  • 사용자를 그 디렉토리로 이동시켜 주고,
  • 앞으로 실행할 RUN이나 CMD, ENTRYPOINT 명령어들을 저 /var/www/html 디렉토리를 대상으로 실행되도록 만들어 주는 것

이다.

 

COPY

이제 사용자의 요청에 응답해 줄 기본 html 페이지를 하나 만들어 줄 차례다.

터미널에서 하는 방법은 이렇다.

# html 만든 후 실행하기
echo "Hello, <strong>Docker</strong>"

# 실행된 것을 index.html 파일에 저장하기
echo "Hello, <strong>Docker</strong>" > index.html

# 잘 만들어 졌는지 확인
ls

 

이 명령어는 도커 파일에선 이렇게 작성하면 된다.

 

이렇게 작성해도 되지만!!! 위 텍스트는 아래 텍스트와 동일하다. (호스트에 있는 index.html을 /var/www/html 로 복사하라는 뜻)

 

CMD

이제 파이썬3에 내장된 웹 서버를 실행시켜 보자. 터미널에서는 이렇게 써 주면 된다. 이러면 파이썬 내장 서버의 기본 포트 8000번으로 리스닝할 수 있게 된다.

# 파이썬 웹서버 실행
python3 -m http.server

 

이와 동일한 의미로 도커 파일에서는 CMD 명령어가 있다.

 

++  -u : 도커 컨테이너에서 실행되고 있는 파이썬 프로세스의 로그가 출력

      -m : http.server 모듈(= 파이썬의 내장 HTTP 서버)을 실행하라는 의미

 

도커 파일 작성 끝 !!! 다시 빌드 터미널로 가서 아래 명령어들을 입력해 주어야만 이미지가 올바르게 생성된다.

docker build -t web-server-build .;

# web-server-build를 바탕으로 web-server라는 이름의 컨테이너를 생성하고, 호스트는 8888, 컨테이너엔 8000번 포트를 연결해라
docker run -p 8888:8000 --name web-server web-server-build;

서버 잘 돌아가는 중

우리가 설정해 준 대로 이미지와 컨테이너가 잘 돌아가고 있는 것까지 확인 🐳👍

 

완성된 도커 파일

 


정리

  • commit과 build의 차이?
    • commit은 백업과 같은 느낌, build는 Dockerfile을 이용해서 이미지를 만들어가는 느낌
    • 둘 다 이미지를 생성한다는 것은 동일
    • Dockerfile 을 이용하면 우리가 만드는 이미지들이 어떤 과정을 통해서 만들어지는지 '분명하게' 나도 독자도 알 수 있음
  • RUN과 CMD 명령어의 차이?
    • RUN은 build가 되는 시점에 실행
      • RUN에서 실행된 결과는 이미지에 반영
    • CMD는 컨테이너가 실행될 때 실행
      • CMD에서 실행된 결과는 컨테이너에 반영