[도커] DockerFile 기본 개념

Woonil·2025년 8월 16일
0

도커

목록 보기
4/4

DockerFile은 base image를 바탕으로 image를 커스터마이징한 것을 기록해 놓은 문서(파일)이다. 이 문서가 준비되면, docker build 명령어를 통해 이미지를 빌드할 수 있다. 이때, Dockerfile 내의 지시어들이 순서대로 실행되어 최종 이미지가 생성된다. Dockerfile 은 애플리케이션의 빌드와 배포 과정을 표준화하고 자동화할 수 있으며, 이는 개발의 효율성을 높이는 데 기여할 수 있다.

  • 장점
    • 좋은 재현성: 동일한 도커파일로부터 동일한 환경을 반복적으로 생성하는데 유리
    • 버전 관리에 용이: 수동으로 이미지를 설정하는 것보다 버전 관리에 용이
    • 협업에 유리: 팀원들과 쉽게 동일한 이미지를 공유

🤔개념

지시어

FROM

base image(기반 이미지)를 지정하며, 모든 DockerfileFROM 명령어로 시작해야 하며, 이는 빌드 과정의 기점이 되는 이미지(base image)를 정의한다.

FROM base image 
# FROM ubuntu:18.04

LABEL

이미지에 컨테이너의 메타데이터를 추가한다.

LABEL maintainer = "name@example.com"

RUN

이미지 빌드 과정 중에 명령어를 실행하며, 주로 패키지 설치나 설정 파일 변경에 사용된다.

  • 특징
    • 쉘 스크립트 문법 사용 가능 ⇒ FROM base image 에 포함된 /bin/sh 를 사용하여 처리 ⇒ /bin/sh 로 처리하지 않는 경우 배열로 명시
    • 실행 결과는 캐싱 후, 다음 빌드 시 재사용한다.
RUN apt-get update && apt-get install -y python

COPY

COPY <source_file> <image 내 절대경로>

컨테이너 빌드 시, 호스트(로컬)의 파일이나 디렉토리를 이미지(도커) 내부로 복사하며, 애플리케이션의 소스 코드를 이미지에 추가할 때 주로 사용된다.

  • 특징
    • source_file은 절대경로 지정 불가
    • file URL 사용 불가
    • 압축 해제하지 않는다.
    • target 경로가 /path/ 와 같이 / 로 끝나는 경우 path 경로(디렉토리)를 한 번 더 감싸서 생성
COPY . /app

ADD

COPY 명령어와 유사하지만, 원격 URL에서 파일을 추가하거나 로컬의 압축 파일을 압축 해제하며 파일을 추가할 수 있다.

  • 특징
    • source_file은 절대경로 지정 불가
    • file URL 사용 가능
    • 압축 해제한다.
    • target 경로가 /path/ 와 같이 / 로 끝나는 경우 path 경로(디렉토리)를 한 번 더 감싸서 생성
ADD https://example.com/big.tar.xz /usr/src/things/
ADD *.txt /tmp/
ADD project.tar.gz /project
ADD ./ /project

CMD

컨테이너가 시작될 때 실행할 기본 명령어를 정의하며,  Dockerfile 내에서 한 번만 사용할 수 있다.

  • 특징
    • /bin/sh 기반 실행
    • /bin/sh 없이 처리할 때는 배열 형태로 작성
    • ENTRYPOINT 와 같이 사용 시 매개 변수만 전달하는 기능

[출처: 유튜브 - 얄팍한 코딩사전]

CMD ["python", "./app/app.py"] # 배열 형태

ENTRYPOINT

CMD와 함께 사용하며, 명령어 지정 시 사용한다. 컨테이너가 시작될 때 실행할 명령어를 설정하며, CMD와 함께 사용되어 애플리케이션의 실행 방식을 정의할 수 있다.

ENTRYPOINT ["python"]
CMD ["app.py"]

CMD vs ENTRYPOINT

컨테이너 실행 시 넘기는 인자를 CMD는 덮어쓰기, ENTRYPOINT는 인자로 전달

동일한 이미지로 테스트, 운영 환경 각각의 엔트리포인트를 다르게 주어 초기에 읽는 스크립트를 다르게 하여 서로 다른 동작을 지정할 수 있다.

EXPOSE

컨테이너가 리스닝할 포트를 지정한다. host와 연결만을 목적으로 하며 외부로 노출되지는 않는다. 따라서 컨테이너 실행 시 host의 포트와 매핑 과정이 필요하다.

EXPOSE 80

ENV

환경 변수를 설정하며, 애플리케이션 설정에 사용된다. 컨테이너 실행 시 -e 옵션으로 재지정(덮어쓰기)도 가능하다. RUN, CMD, ENTRYPOINT 에 적용가능하다.

ENV API_KEY="YOUR_API_KEY"

WORKDIR

RUNCMDENTRYPOINTCOPYADD 명령어가 실행될 작업 디렉토리를 설정한다.

WORKDIR /app

USER

명령을 실행할 사용자를 정의하며, 웬만하면 root 외의 사용자를 지정하는 것이 보안에 좋다. 사용자가 지정된 이후의 라인에서 처리되는 CMD , RUN , ENTRYPOINT 는 해당 사용자의 행위로 해석된다.

FROM ubuntu
RUN mkdir -m 1777 /share
RUN touch /share/hello.txt
RUN useradd student

USER student
RUN touch /share/student.txt
CMD ls -l /share

VOLUME

볼륨 경로를 지정한다. 만약 호스트의 특정 경로와 연결하지 못한다면 docker run -v 옵션으로 볼륨을 설정한다.

  • 특징
    • 영구적으로 저장해야 할 데이터가 있을 경우 유용하다.
    • 컨테이너 간 데이터 공유를 가능하게 한다.
    • 커밋 시 이미지에 포함되지 않는다.

레이어

도커 이미지의 빌드는 도커파일에 명시된 나열된 명령어 순으로 수행되기 때문에 도커파일의 명령어의 순서는 중요하다. 각 명령어 라인은 하나의 이미지 레이어에 대응되며, 아래 그림에서도 알 수 있듯이 이러한 레이어들이 여러 층으로 쌓여 컨테이너 이미지를 형성한다.

[출처: 도커 공식 홈페이지]

[출처: https://subicura.com/]

도커 파일 빌드 시, 베이스 이미지로부터 한층 한층 레이어를 쌓게 되는데, 이때 레이어의 명령어 수행 후 컨테이너를 종료하고 해당 시점의 파일시스템을 이미지로 저장한다. 이후 새로운 명령어가 실행되면 이전 이미지 위에 새로운 레이어가 추가되는 방식으로 최종 이미지를 완성한다.

도커 이미지 최적화

  • 경량 베이스 이미지 사용하기: 가능한 가장 경량의 베이스 이미지를 사용한다. 예를 들어, alpine 이미지는 매우 작은 크기로 필요한 최소한의 기능만 포함한다.
  • 멀티 스테이지 빌드 사용하기: Dockerfile에서 멀티 스테이지 빌드를 사용하여 빌드 단계에만 필요한 도구를 최종 이미지에서 제외시킨다. 이 방식을 사용하면 최종 이미지에는 애플리케이션 실행에 필요한 파일과 디펜던시만 포함된다. 멀티 스테이지 빌드는 여러 개의 FROM 명령어를 사용하여 구현되며, 각 스테이지는 독립적인 베이스 이미지를 가질 수 있다. 첫 번째 스테이지에서는 빌드에 필요한 도구와 소스 코드를 컴파일하는 데 필요한 작업을 수행한다. 이후 스테이지에서는 첫 번째 스테이지에서 생성된 아티팩트만을 가져와서 최종 이미지를 생성한다. 이렇게 하면 불필요한 빌드 도구나 중간 생성물을 최종 이미지에서 제외할 수 있어 이미지 크기가 상당히 줄어든다.
  • 필요없는 파일 제거하기: 빌드 과정에서 생성되는 임시 파일, 캐시 파일 등 필요 없는 파일은 RUN 명령어에서 && rm -rf /path/to/temporary/files와 같이 제거하여 이미지 크기를 줄인다.
  • 레이어 수 최소화하기: RUNCOPYADD 명령어는 새로운 레이어를 생성한다. 이러한 명령어를 적절히 조합하여 가능한 한 적은 수의 레이어를 생성하도록 Dockerfile을 최적화한다.
    FROM ubuntu
    RUN mkdir -m 1777 /share \
    && touch /share/hello.txt \
    && useradd student
  • COPY와 ADD 명령어를 신중하게 사용하기: COPY와 ADD는 필요한 파일만 이미지에 추가하도록 사용한다. .dockerignore 파일을 사용하여 불필요한 파일이 이미지에 포함되지 않도록 설정할 수 있다.
  • 환경 변수를 이용한 설정: 가능한 설정 파일 대신 환경 변수를 사용하여 애플리케이션을 구성한다. 이 방법은 설정 변경이 필요할 때 이미지를 다시 빌드하지 않아도 되므로 이미지 크기를 줄이는 데 도움이 된다.
  • 적절한 태그 사용하기: 필요한 소프트웨어의 적절한 버전을 지정하여 불필요한 업데이트로 인한 크기 증가를 피한다.

😎실습

도커 이미지 최적화를 통해 이미지 용량 줄이기

프로젝트 진행 중 쿠버네티스 환경에서 무거운 패키지를 설치할 때마다 워커노드(2GB 메모리 용량 지님)가 다운되는 현상이 발생했다. 따라서 메모리 사용량 확인 결과 기존 백엔드 이미지로 올라간 컨테이너의 파드가 많은 용량(1GB 이상)을 차지하고 있었음을 확인하였다. 따라서 npm ci, 경량 베이스 이미지, 멀티 스테이지 빌드를 활용하여 이미지 최적화 결과 기존 1.15GB의 이미지를 202MB까지 줄일 수 있었다.

# 1단계: 빌드 스테이지
FROM node:alpine AS build

WORKDIR /app

COPY package*.json ./

RUN npm ci --only=production

COPY . .

# 2단계: 런타임 스테이지
FROM node:alpine

WORKDIR /app

# 빌드 단계에서 production dependencies만 복사
COPY --from=build /app /app

EXPOSE 8080

CMD ["node", "server.js"]

profile
프론트 개발과 클라우드 환경에 관심이 많습니다:)

0개의 댓글