본문 바로가기
개발/백엔드

[백엔드] Docker (2) - 이미지 빌드

by 헤이즐넛 좋아하는 개발자 2024. 9. 13.

시작하기 전에

이번엔 Docker를 어떻게 사용해야 하는지 정리해보고자 한다. 출처는 저번과 동일하다.

출처: https://docs.docker.com/

 

개념은 아래 링크에서 확인할 수 있다 : Docker란?

 

[백엔드] Docker란?

시작하기 전에오늘의집 회사에서 파트타임으로 일하면서 Docker를 사용해볼 기회가 생겼다.앞으로도 유용하게 사용할 개념이니 이번에 확실하게 정리해보고자 한다.출처: https://docs.docker.com/Docker

hazel-nut-library.tistory.com


핵심

  • 도커 이미지 실행이 목적이다.
  • Dockerfile 코드가 이미지를 이렇게 생성해주세요 하는 가이드가 된다.
  • Build->Tag->Publish 과정을 통해 이미지를 실행할 수 있다.
    docker build -t my-username/my-image .
    docker push my-username/my-image

Dockerfile

Dockerfile은 Docker Image를 생성하기 위한 스크립트이다. 각 instruction이 생성된 이미지의 layer가 된다.

파일 이름은 그대로 Dockerfile이며, 빌드할 때 필요한 모든 파일을 참조할 수 있게 애플리케이션의 루트 디렉토리에 생성한다.

아래 예시는 내가 실무에서 활용한 Dockerfile 코드이다. ChatGPT에게 요청하면 잘 적어준다.

# 베이스 이미지
FROM python:3.11-slim

# 작업 디렉토리 설정
WORKDIR /app

# 시스템 패키지 설치
RUN apt-get update && apt-get install -y \
    gcc \
    libssl-dev \
    libffi-dev \
    libxml2-dev \
    libxslt-dev \
    zlib1g-dev \
    libjpeg-dev \
    libpng-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# requirements.txt 복사
COPY requirements.txt .

# requirements.txt 파일의 Python 패키지 설치
RUN pip install --no-cache-dir -r requirements.txt

# 현재 프로젝트 파일들 복사
COPY . .

 


Instruction

각 instruction에는 아래와 같은 내용들이 들어간다.

  • FROM <image>
    이미지를 빌드할 때 사용할 기본 이미지를 지정한다. 이 이미지를 깔고 위에 필요한 구성 요소를 설치하거나 설정을 추가한다.
  • WORKDIR <path>
    파일이 복사되고 명령어가 실행될 path를 지정해준다.
  • COPY <host-path> <image-path>
    파일을 host로부터 컨테이너의 이미지로 복사한다.
  • RUN <command>
    명령어를 실행한다.
  • ENV <name> <value>
    환경 변수를 설정한다. 예를 들어, ENV APP_ENV=production 이렇게 사용한다.
    production이면, 애플리케이션이 프로덕션(실제 서비스) 모드로 동작
    development이면, 개발 모드로 동작
    staging이면, 프로덕션에 배포하기 전에 마지막으로 테스트하는 환경,
    test면, CI/CD 파이프라인에서 자동화된 테스트를 실행하는 환경이다.
  • EXPOSE <port-number>
    컨테이너가 이 이미지를 사용하려는 외부와 통신하기 위해 열려 있는 포트를 지정한다.
  • USER <user-or-uid>
    컨테이너 내에서 명령어를 실행할 사용자를 설정한다. 기본적으로 도커 컨테이너는 root 사용자로 실행되지만, 보안상의 이유로 권장되지 않는다. 따라서 일반 사용자를 지정하여 시스템 자원을 직접적으로 제어하지 못하게 하여 보안을 강화한다.
  • CMD ["<command>", "<arg1>"]
    컨테이너가 시작될 때 실행되는 명령어이다. 한 이미지에 하나만 있을 수 있다.

Dockerfile을 실행하면 스크립트에 작성된 여러 instruction이 모두 실행되고 도커 이미지가 빌드된다.


빌드 후 배포까지의 과정

  • Build : Dockerfile을 활용하여 빌드
  • Tag : 이미지에 이름을 붙임, 이미지가 어디에 배포될지 결정
  • Publish : 레지스트리에 배포

Build

가장 기본적인 docker build 명령어다.

docker build .

. 부분에는 빌드할 파일의 경로 또는 URL이 들어간다. 위 명령어는 현재 위치에서 Dockerfile과 참조할 파일들을 찾는다.

빌드를 실행하면, 기본 이미지를 가져와 Dockerfile의 instruction을 실행한다.

결과는 아래와 같다. 위 명령어로는 이미지의 이름은 결정되지 않고 가장 아래줄에 ID는 제공된다.

docker build . 명령어 결과

아래 명령어를 통해 이미지가 빌드되었는지 확인할 수 있다.

docker image ls

 

빌드된 이미지를 사용하여 컨테이너를 시작할 수 있다.

docker run sha256:9924dfd9350407b3df01d1a0e1033b1e543523ce7d5d5e2c83a724480ebe8f00

Tag

Build 결과에서 만족스럽지 않은 점은 이미지의 이름이 너무 어렵다는 것이다. 따라서 이름을 붙여주는 과정이 필요하다.

이미지 이름의 형식은 아래와 같다.

[HOST[:PORT_NUMBER]/]PATH[:TAG]
  • HOST
    이미지가 위치한 레지스트리 호스트 네임이다. 만약 호스트가 구체화되어 있지 않다면, docker.io가 기본으로 설정되어 있다.
  • PORT_NUMBER
    호스트 네임의 포트 번호다.
  • PATH
    이미지의 경로이며, Docker Hub에서 [NAMESPACE/]REPOSITORY 구조를 따른다. Namespace는 유저나 조직의 이름이다. 만약 namespace가 구체화되어 있지 않다면, Docker official image의 namespace인 library가 사용되는 것이다.
  • TAG
    배포한 여러 버전 중 하나를 명시해주는 것이다. 구체화되어 있지 않다면, latest가 사용된다.

아래 명령어를 통해 빌드와 태그를 동시에 진행할 수도 있다.

docker build -t my-username/my-image .

 

 

※ docker.io란?

더보기

※ docker.io란?

 

  • Linux에서 Docker를 설치할 때, docker.io는 Docker 엔진을 설치하는 패키지 이름이다.
    Ubuntu에서 Docker를 설치하는 명령어: 
  • sudo apt install docker.io
  • docker.io는 Docker Hub를 나타내는 도메인이기도 하다.

 


Publish

이미지 빌드, 태그 후 Publish는 아래 명령어로 가능하다.

docker push my-username/my-image

Build Cache

  • 위에서 Dockerfile의 각 instruction이 이미지의 layer를 형성한다는 것을 얘기했다.
  • Dockerfile 수정 후 이미지 재빌드를 하면, 원래 이미지의 각 layer로부터 수정사항이 있는지 확인한다.
  • 수정사항이 발견되지 않은 layer는 build cache로부터 가져와 빌드를 진행하지 않는다.
  • 수정사항이 발견되는 첫 layer부터 마지막 layer까지 모두 재빌드를 진행한다. 첫 layer 뒤의 수정 여부를 확인하지 않는 이유는 inconsistency가 발생하는 것을 막기 위해서다.