시작하기 전에
이번엔 Docker를 어떻게 사용해야 하는지 정리해보고자 한다. 출처는 저번과 동일하다.
개념은 아래 링크에서 확인할 수 있다 : Docker란?
핵심
- 도커 이미지 실행이 목적이다.
- 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 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가 발생하는 것을 막기 위해서다.
'개발 > 백엔드' 카테고리의 다른 글
[백엔드] Docker (3) - 컨테이너 실행 (0) | 2024.10.07 |
---|---|
[백엔드] Docker (1) - Docker란? (0) | 2024.09.11 |
[백엔드] 개발 도서관을 만들어보자 (0) | 2024.02.03 |