도커 파일이란?
주어진 이미지를 빌드하는데 필요한 모든 커맨드를 텍스트 형식으로 작성한 파일
도커 이미지는 Dockerfile의 결과로 만들어진 읽기 전용 레이어들로 구성
- 읽기 전용 → 이전 레이어의 변경 내용이 다음 레이어가 되어 그 위에 쌓임
이미지
- 컨테이너를 실행하기 위해 필요한 파일 시스템 상태와 메타데이터를 포함한 불변(immutable) 객체
- 여러 개의 레이어로 구성되며, 각 레이어는 이미지의 파일 시스템 일부를 나타냄
레이어
- 도커 이미지의 한 부분
- 파일 시스템에 대한 특정 변경 사항을 포함하는 객체
- 각 레이어는 이전 레이어 위에 쌓이는 불변(immutable) 객체 → 계층 구조
- 이미지의 변화를 기록하기 위한 객체
- 레이어는 Copy-on-Write(CoW) 전략을 사용하여 파일 시스템에서 변경된 사항만을 저장함 → 각 레이어는 서로 중복되는 부분이 없음
작성 가이드라인
일회용(ephemeral)한 컨테이너 생성
Dockerfile에서 정의된 이미지는 가능한 일회용(ephemeral)한 컨테이너를 생성해야 함
- 컨테이너를 멈추고 삭제한 뒤, 재빌드해도 가능한 최소한의 설정을 바꾸는 것만으로 기존의 컨테이너를 대체할 수 있어야 함
빌드 컨텍스트에 대한 이해
빌드 컨텍스트: 빌드에 필요한 파일들이 저장된 장소
docker build -t test:proto . #> .이 빌드 컨텍스트로 인식됨
docker build 명령어를 입력하면 현재 작업 중인 디렉터리는 빌드 컨텍스트로 인식됨
- 기본적으로 Dockerfile은 이 디렉터리에 위치해있다고 가정 (-f 옵션으로 Dockerfile 지정 가능)
- Dockerfile의 위치와 상관없이 현재 디렉터리에 있는 모든 파일과 디렉터리는 도커 데몬에게 빌드 컨텍스트로 전달됨 → 따라서 빌드 컨텍스트에는 불필요한 파일들을 두지 않아야 함
이미지를 빌드하는데 필요하지 않은 파일들을 위치시키는 것은 빌드 컨텍스트와 이미지 크기 + 이미지 빌드 시간 + pull/push + 컨테이너 런타임 크기를 모두 증가시킴
확인 예제
# 빌드 컨텍스트 117B
mkdir project && cd project
echo "print('Hello, World!')" > hello.py
echo -e "FROM python:3.12.4\\nCOPY ./hello.py /\\nRUN python /hello.py" \\
> Dockerfile
docker build -t helloapp:proto .
# 빌드 컨텍스트 88B
mkdir dockerfiles context
mv Dockerfile dockerfiles && mv hello.py context
docker build --no-cache -t helloapp:v1 \\
-f dockerfiles/Dockerfile context
같은 이미지를 생성해도 두 번째 이미지의 빌드 컨텍스트가 더 낮은 용량을 가짐
- Dockerfile이 빌드 컨텍스트에 포함되어 있지 않기 때문!
=> [internal] load build context
=> => transferring context: 117B
.dockerignore: 빌드 컨텍스트에서 제외할 파일이나 디렉터리르 지정
- 문법은 .gitignore와 유사
Dockerfile 없이 stdin으로 이미지 생성
- 이미지 생성에 어떠한 파일도 필요하지 않을 때, 빌드 컨택스트를 보내지 않음으로써 빌드 속도를 향상시킬 수 있음
1. 파이프라인
echo -e 'FROM ubuntu:latest\\nRUN echo "hello world"' | \\
docker build -t echo:test -
2. 리다이렉션
docker build -t echo:test - <<EOF
FROM ubuntu:latest
RUN echo "hello world"
EOF
3. 빌드 컨택스트를 지정
docker build -f- PATH <<EOF
FROM ubuntu:latest
COPY somefile.txt .
RUN cat /somefile.txt
EOF
멀티 스테이지 빌드
이미지는 마지막 빌드 처리 과정에서 생성되기 때문에, 빌드 캐시를 사용해 이미지 레이어의 최소화가 가능
- 빌드 도구와 런타임 환경(최종 배포본)을 분리하고 실행에 필요한 최소한의 구성만 포함하여 이미지 크기를 최소화
# 빌드 단계(빌드 도구)
FROM golang:alpine AS build
WORKDIR /app
COPY . .
RUN go build -o myapp
# 최종 이미지(런타임 환경)
FROM alpine
COPY --from=build /app/myapp /myapp
ENTRYPOINT ["/myapp"]
필요없는 패키지는 설치 제한
응용프로그램 분할
각각의 컨테이너들은 하나의 주제만을 소유
- 응용프로그램을 여러 개의 컨테이너로 분할하는 것은 수평적 구조 + 컨테이너 재활용을 증가 ex) 웹 응용프로그램의 경우: 웹 + 데이터베이스 + 캐시 관리의 이미지(컨테이너)로 분할
레이어 수 최소화
RUN, COPY, ADD 명령어는 레이어를 생성하기 때문에 한 줄에 걸쳐 여러 가지를 수행하는 것이 좋음
- ex) RUN apt-get update && apt-get install -y package1 && apt-get clean
- 다른 명령어들(ENV, WORKDIR, EXPOSE 등)는 이미 존재하는 레이어에 설정을 추가하는 방식으로 동작 → 이미지 크기가 증가하지 않음
RUN apt-get update # 레이어 1: 패키지 목록 업데이트
RUN apt-get install -y vim # 레이어 2: vim 설치
-> 최종 레이어 2
RUN apt-get update && apt-get install -y vim # 레이어 1
-> 최종 레이어 1
가능한 멀티 스테이지 빌드를 사용
- 최종 이미지에서 하나의 복사만 하면, 여러 툴과 여러 중간 빌드 스테이지에 대한 디버그 정보를 최종 이미지 크기 증가 없이 포함 가능
여러 줄 인자 정렬
RUN apt-get update && apt-get install -y \\
bzr \\
cvs \\
git \\
mercurial \\
subv
빌드 캐시
이미지 빌드 시, 도커는 Dockerfile에 작성된 명령어들을 하나씩 순차적으로 실행시킴 → 각각의 명령어들이 검사되기 때문에, 도커는 새로운 이미지를 생성하는 대신 재사용할 수 있는 캐시 이미지가 존재하는지 확인
docker build . --no-cache
or
docker build . --no-cache=true
기본 개념
- 부모 이미지: FROM 명령어로 지정된 기본 이미지
- 자식 이미지: 부모 이미지에서 명령어(ADD, RUN, COPY 등)를 실행하여 생성된 이미지
- 도커는 빌드 속도 향상을 위해 이전에 빌드한 이미지의 레이어를 캐싱하고, 동일한 명령어가 다시 실행될 때 캐싱된 레이어를 재사용함
- 빌드 과정에서 새로운 명령어를 실행하기 전에 기존의 캐싱된 이미지와 비교하여, 동일한 명령어에 동일한 결과가 예상된다면 캐시를 사용함
캐시 비교 규칙
- 부모 이미지에서 시작하여, Dockerfile의 각 명령어가 캐시에 존재하는 이전 빌드의 명령어와 동일한지 비교
- 동일하지 않다면, 캐시는 사용되지 않고 명령어를 다시 실행하여 새로운 레이어를 생성
ADD, COPY 명령어 처리
- 파일의 내용을 검사하고, 각 파일의 검사합을 계산하여 이전 빌드의 캐시와 비교
- 검사합은 파일의 내용만을 기반하여 계산 파일의 최종 수정 시간, 접근 시간 등은 계산에 포함하지 않음 → 파일의 내용이 변경되지 않았다면 항상 동일한 검사합이 생성됨
- 검사합을 기준으로, 명령어에서 캐시된 레이어를 재사용할지 결정 → 파일의 내용이나 메타데이터가 변경되었다면, 기존에 캐시된 레이어를 사용하지 않고 새로운 레이어를 생성
RUN 명령어 처리
- 도커는 이미지를 빌드할 때, 임시 컨테이너를 실행하여 명령어를 수행하고 그 결과를 레이어로 저장함 → 이때 컨테이너 내부에서 변경된 파일의 내용 자체를 비교하는 것이 아닌 RUN 명령어의 문자열만을 비교함
- RUN 명령어의 문자열들이 동일하다면 다른 비교없이 캐싱된 레이어를 재사용함
빌드 캐시는 동일한 부모 이미지 사용 또는 동일한 명령어 시퀀스에서만 적용됨
'서버관리 > 도커' 카테고리의 다른 글
Dockerfile 명령어에 대해 알아보자 (0) | 2024.08.28 |
---|