Azure 상식

Dockerfile 기본 개념 및 레이어 구성 원리

ktzzang0601 2025. 8. 23. 03:08

1. 개념

  • 도커 이미지(Docker Image)를 자동으로 만드는 설계도(스크립트)
  • Dockerfile은 텍스트 파일로, 어떤 베이스 이미지를 쓰고, 어떤 패키지/파일/설정을 넣을지, 마지막에 어떻게 실행할지를 단계별로 적어놓은 문서입니다.
  • Docker는 이 파일을 읽어 위에서 아래로 순차 실행하면서 이미지를 빌드합니다.

2. 기본 명령

  • 실제 파일 변화를 만드는 명령: RUN, COPY, ADD → 읽기 전용 FS 레이어가 생성
  • 메타데이터/구성 변경 중심: ENV, WORKDIR, USER, EXPOSE, VOLUME, LABEL, ENTRYPOINT, CMD, ARG 등
  • 파일 내용을 늘리지는 않지만 이미지 구성(메타데이터) 는 바뀌고, 빌드 캐시 키에도 영향을 줍니다.
  • FROM 은 새 빌드 단계(stage) 를 시작합니다(멀티 스테이지에서 중요). 따라서 어떤 단계에서든 그 단계가 바뀌면 그 뒤의 모든 단계 캐시가 무효화되고 다시 빌드됩니다(계단식 무효화).

3. 빌드 캐쉬가 동작하는 방식

  • Docker/BuildKit은 “명령 + 입력(컨텍스트, 이전 레이어 해시 등)” 으로 캐시 키를 만들고, 같으면 재실행 없이 이전 레이어를 재사용합니다.
  • 파일 복사(COPY/ADD)복사되는 파일의 내용 해시가 바뀌면 캐시 무효.
  • ARG/ENV 값 변경 도 이후 단계 캐시를 깨뜨립니다.
  • 네트워크 의존 RUN(예: apt-get) 결과도 캐싱되지만, 베이스 이미지 업데이트 등은 --pull(베이스 최신화) 또는 --no-cache(모든 캐시 무시) 같은 옵션으로 제어합니다.

4.  Best Practice

    • 변동이 적은 것 → 위로, 자주 바뀌는 것 → 아래로
      - 의존성 설치(자주 안 바뀜) 레이어를 먼저 만들고, 소스 코드 COPY 등 자주 바뀌는 단계는 뒤로 배치 → 캐시 적중률↑
    • RUN 묶기 vs 가독성
      불필요한 레이어를 줄이려고 RUN 을 과도하게 한 줄로 합치기보다, 의미 단위로 적절히 묶되 레이어 수를 관리하세요.- - 패키지 매니저는 한 레이어에서 갱신/설치를 끝내고 캐시 파일 삭제까지 마무리
    • .dockerignore 적극 사용
      - node_modules, .git, 빌드 산출물 등 캐시를 자주 깨뜨리는 불필요 파일을 빌드 컨텍스트에서 제외.
    • ADD 대신 COPY
      - URL 자동 다운로드/압축 해제 등 암묵적 동작이 있는 ADD 대신, 예측 가능한 COPY 를 기본으로.
    • 멀티 스테이지 빌드 로 최종 이미지 슬림화
      - 빌드 도구·헤더 등 개발용 레이어는 중간 단계에 남기고, 최종 스테이지는 실행 파일만 가져갑니다.
    • BuildKit 고급 마운트
      - 캐시가 이미지에 포함되지 않도록
    • 버전 고정 & 재현성
      - 패키지 버전을 고정(pinning)해 캐시 안정성을 높이고 “어제와 오늘 빌드가 다른” 상황을 줄입니다.
    • VOLUME 주의
      - VOLUME /data 를 선언하면 해당 경로의 이후 변경은 컨테이너 볼륨에 매핑됩니다. VOLUME 선언 이전에 넣은 파일은 런타임에 보이지 않을 수 있으니 순서를 신중히.
    • 베이스 이미지 최신화
      - 태그가 같은데 내용이 바뀐 경우를 대비해 정기적으로 --pull 로 베이스를 갱신하거나, digest(sha256:...) 고정을 검토하세요.
    • 레이어/캐시 청소
      - 개발 환경 용량이 불어나면 docker system df, docker system prune, (BuildKit) docker builder prune 로 캐시/중간 레이어를 정리.

5. 레이어 구성 원리

  • Dockerfile의 각 RUN, COPY, ADD 명령은 새로운 레이어(layer) 를 만듭니다.
  • 레이어는 캐시로 재사용 가능하고, 불변이라서 한 번 만들어지면 바뀌지 않습니다.
  • 레이어를 많이 나누게 되면 얻는 이점/단점
    - 캐시 효율 증대
    - 문제 원인 추적이 쉬움
    - 이미지 레이어 수가 늘어나면 저장/전송할 때 관리해야 할 블롭(blob)이 많아져서 오버헤드가 조금 생김.
    - 불필요한 파일 누적 위험
  • 레이어를 적게 묶어서 만드는 이점/단점
    - 이미지 크기 최적화
    - 전송/저장 효율 증대 : 레이어 수가 적어서 속도 저장 효율 올라감
    - 캐시 효율이 떨어짐
    - 가독성이 낮음

6. Dockerfile 주요 명령어 개념 및 예시

  • `FROM`: 베이스 이미지 지정 (ex: `FROM ubuntu:20.04`)
  • `RUN`: 이미지 빌드 시 실행할 커맨드 (ex: `RUN apt update && apt install -y nginx`)
  • `COPY`, `ADD`: 로컬 파일을 이미지 안으로 복사
  • `ENV`: 환경 변수 설정
  • `EXPOSE`: 컨테이너에서 서비스할 포트 명시
  • `CMD` 또는 `ENTRYPOINT`: 컨테이너 시작 시 실행할 명령어
  • RUN 명령어에서 여러 명령 병합 방법
    - 여러 개 명령을 한 줄에서 실행할 때는 `&&`로 체이닝하여 이전 명령 성공 시 다음 명령 실행
       예) `RUN apt update && apt install -y nginx`
    - `\` (백슬래시) 사용해 여러 줄로 나눠 가독성 개선 가능
  • 컨테이너 실행 흐름
    1. Dockerfile 작성 (설치 및 설정 명령어 포함)
    2. `docker build` 명령으로 이미지 생성 (Dockerfile대로 순차적 실행)
    3. `docker run` 명령으로 이미지를 실행해 컨테이너 상태 시작
    4. 컨테이너 안에서 앱 또는 서비스 동작

7. 결론

  • Dockerfile은 컨테이너 이미지 만드는 레시피
  • `RUN`은 이미지 만드는 동안 실행할 명령어 입력 (명령어 묶는 기법은 `&&`가 일반적)
  • 빌드하면 `RUN` 명령어 순서대로 실행되며 이미지가 만들어짐
  • 이미지를 기반으로 컨테이너를 실행해 서비스 구동하는 구조입니다.

8. 참고 문서