maeng0830
뇌 채우기 운동
maeng0830
전체 방문자
오늘
어제
  • maeng0830-note (91)
    • 자바 (3)
    • 스프링 (39)
      • Core (21)
      • DB (16)
      • Security (2)
      • Test (0)
    • 자료구조 & 알고리즘 (19)
      • 자료구조 (12)
      • 알고리즘 (7)
    • 다른 개발 도구들 (10)
      • Git&Github (1)
      • Redis (3)
      • Docker (6)
    • 프로젝트 (9)
      • Album (9)
    • CS (10)
      • 운영체제 (5)
      • 데이터베이스 (5)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • JPA
  • spring security
  • docker
  • JPQL
  • 트랜잭션
  • 자료구조

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
maeng0830

뇌 채우기 운동

다른 개발 도구들/Docker

도커 이미지 빌드(Docker Image Build)

2025. 10. 7. 15:48

도커 이미지를 생성하는 방법에는 크게 두 가지가 있다.

하나는 실행 중인 컨테이너의 상태를 그대로 이미지로 저장하는 커밋 방식이다.

다른 하나는 도커파일(Dockerfile)이라는 명세서를 바탕으로 이미지를 생성하는 빌드 방식이다.

이미지 커밋(Image Commit)

개념

기존 이미지를 통해 컨테이너를 실행하면, 이미지의 맨 위에 쓰기 가능한 컨테이너 레이어가 추가된다.

컨테이너 레이어에는 컨테이너 실행 중 발생한 파일의 변경사항들이 저장된다.

이 상태에서 docker commit 명령어를 사용하면, 컨테이너 레이어를 포함하는 새로운 이미지가 생성된다.

명령어

docker commit -m "[메시지]" [실행 중인 컨테이너 이름 또는 ID] [생성할 이미지 이름]

docker commit -m "add config change" mycontainer myimage:latest

이미지 빌드(Image Build)

개념

도커 이미지 빌드는 Dockerfile이라는 명세서를 기반으로 이뤄진다.

Dockerfile에는 이미지 생성에 필요한 베이스 이미지, 실행 명령어, 복사할 파일, 환경 변수 설정 등의 정보가 단계별로 정의되어 있다.

 

Dockerfile에 사용할 수 있는 다양한 지시어들이 있다.

도커는 이러한 지시어들이 작성된 Dockerfile을 위에서 아래로 순차적으로 읽으면서 실행하고, 대부분의 지시어는 실행 시 하나의 레이어를 생성하게 된다.

 

이러한 레이어들은 서로 상호 독립적이며, 이미 존재하는 레이어는 변경할 수 없으며 항상 새로운 레이어로 변경사항을 기록한다.

또한 이미 존재하는 레이어와 동일한 레이어(지시어, 실행 명령어, 파일 구성이 동일)를 포함하는 이미지를 빌드할 경우, 도커는 기존 레이어를 캐시하여 재사용하므로 빌드 성능을 최적화 할 수 있다.

# Dockerfile 예시(nginx)

# 1단계: 베이스 이미지 지정 (레이어 1)
# nginx 공식 이미지를 기반으로 한다. 베이스 이미지는 최상위 레이어로 사용되며, 이 위에 추가 명령어들이 쌓인다.
FROM nginx:latest

# 2단계: 빌드 시 인자로 사용할 값 정의 (메타데이터)
# 빌드 타임 인자(ARG)는 빌드 중에만 사용 가능하며, 이미지에는 포함되지 않는다.
# 예: docker build --build-arg APP_VERSION=2.0 .
ARG APP_VERSION=1.0

# 3단계: 환경 변수 설정 (레이어 2)
# 위에서 정의한 빌드 인자 값을 환경 변수로 전환. ENV는 이미지 내부에서 항상 사용 가능하고, RUN, CMD, ENTRYPOINT 등에 전달된다.
ENV APP_VERSION=${APP_VERSION}

# 4단계: 작업 디렉터리 설정 (레이어 3)
# 이후의 명령어(COPY, RUN 등)가 실행될 기본 디렉터리를 설정한다.
# 디렉터리가 존재하지 않으면 자동 생성된다.
WORKDIR /usr/share/nginx/html

# 5단계: 커스텀 index.html 복사 (레이어 4)
# 호스트의 index.html 파일을 컨테이너의 WORKDIR 위치로 복사한다.
# 파일이 변경되면 캐시가 무효화되어 이후 레이어도 재빌드된다.
COPY index.html .

# 6단계: 포트 노출 설정 (메타데이터)
# 도커에게 컨테이너가 사용하는 포트를 알려준다. 네트워크 기능에는 직접 영향을 주지 않으며, 단지 메타데이터로만 존재한다.
EXPOSE 80

# 7단계: 실행 명령어 정의 (메타데이터)
# 컨테이너 시작 시 실행할 기본 실행 파일 또는 명령을 정의한다.
# ENTRYPOINT는 CMD와 결합되며, "불변의 실행 대상"으로 사용되는 경우가 많다.
ENTRYPOINT ["nginx"]

# 8단계: 기본 실행 옵션 지정 (메타데이터)
# ENTRYPOINT에 전달할 기본 인자를 설정한다.
# ENTRYPOINT가 생략되면 CMD만 단독으로 실행되지만, ENTRYPOINT가 있을 경우 CMD는 그 인자로 전달된다.
CMD ["-g", "daemon off;"]

# 9단계: 추가적인 설정 실행 (레이어 5)
# 이미지를 빌드할 때 실행할 셸 명령을 정의한다.
# 이 명령은 컨테이너 실행 시가 아닌, 이미지 생성 시에만 실행되며 해당 결과가 레이어로 남는다.
RUN echo "Custom nginx image with version $APP_VERSION"

명령어

docker build -t [이미지이름:태그] [Dockerfile 경로]

# 예시
docker build -t myimage:latest .

# 이미지의 지시어, 레이어 구성 확인
docker image history [이미지이름]

빌드 컨텍스트(Build Context)

빌드 컨텍스트란 이미지 빌드에 필요한 Dockerfile과 기타 관련 파일들이 포함된 디렉토리를 의미한다.

이미지를 빌드할 때, 도커 클라이언트는 빌드 컨텐스트 전체를 도커 데몬에게 전송하고, 이 컨텍스트를 기반으로 이미지 빌드가 진행된다.

 

이때 .dockerignore 파일을 통해 컨텍스트 디렉토리에는 존재하지만, 빌드에는 불필요한 파일이나 디렉토리를 제외할 수 있다.

멀티 스테이지 빌드

멀티 스테이지 빌드는 하나의 Dockerfile에 여러 개의 FROM 지시어를 사용하여 여러 스테이지를 정의하는 빌드 방식이다.

주로 빌드 스테이지와 실행 스테이지를 분리하여, 최종 이미지에 실행에 필요한 구성요소들만 포함시키는데 목적이 있다.

 

멀티 스테이지 빌드는 아래와 같은 장점이 있다.

  • 최종 이미지의 크기를 줄일 수 있다.
  • 빌드 도구나, 임시 파일이 실행 환경에 남지 않아 보안과 유지보수 측면에서 유리하다.
  • 빌드와 런타임의 책임을 분리하여 이미지 구성을 명확히 할 수 있다.

동일한 Maven 프로젝트를 싱글 스테이지 방식과 멀티 스테이지 방식으로 비교한 예제를 살펴보자.

<싱글 스테이지 빌드>
FROM maven:3.6-jdk-11
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package
RUN cp /app/target/*.jar ./app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]


<멀티 스테이지 빌드>
# 빌드를 위한 스테이지, 최종 이미지에는 포함되지 않음
FROM maven:3.6 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package

# 런타임을 위한 스테이지, 최종 이미지에 포함
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=build /app/target/*.jar ./app.jar # from=build를 통해 실행에 필요한 빌드 결과물만 가져옴.
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]

 

멀티 스테이지 Dockerfile은 FROM 지시어로 시작되는 각각의 스테이지를 독립적으로 처리하며, 마지막 스테이지만 이미지에 포함한다.

 

즉, 최종 스테이지 이전의 스테이지는 이미지에 포함되지 않으며, COPY --from=... 지시어를 통해 명시적으로 복사한 이전 스테이지의 파일들만 이미지에 포함된다.

    '다른 개발 도구들/Docker' 카테고리의 다른 글
    • 도커 네트워크(Docker Network)
    • 도커 볼륨 & 바인드 마운트(Docker Volume & Bind Mount)
    • 도커 이미지 레지스트리(Docker Image Registry)
    • 도커 이미지(Docker Image)와 도커 컨테이너(Docker Container)
    maeng0830
    maeng0830

    티스토리툴바