고급 Dockerfile 기술

DockerBeginner
지금 연습하기

소개

이 실습에서는 Dockerfile 기술을 더 깊이 파고들어, 더욱 효율적이고 유연한 Docker 이미지를 만드는 데 도움이 되는 고급 개념들을 살펴봅니다. 상세한 Dockerfile 지시어, 멀티 스테이지 빌드, 그리고 .dockerignore 파일의 활용법을 다룰 것입니다. 또한 Docker 이미지의 핵심 개념인 레이어 (layer) 에 대해서도 알아봅니다. 이 실습을 마치면 이러한 고급 Dockerfile 기술을 종합적으로 이해하고 여러분의 프로젝트에 직접 적용할 수 있게 될 것입니다.

이 실습은 초보자를 염두에 두고 설계되었으며, 상세한 설명과 함께 혼동하기 쉬운 부분들을 짚어줍니다. 모든 파일 편집 작업에는 WebIDE(VS Code) 를 사용하여 브라우저에서 직접 파일을 생성하고 수정할 수 있도록 구성했습니다.

Dockerfile 지시어와 레이어의 이해

다양한 지시어를 활용하는 Dockerfile 을 만드는 것부터 시작해 보겠습니다. Flask 를 사용하는 Python 웹 애플리케이션용 이미지를 빌드하면서, 각 지시어가 Docker 이미지의 레이어 구성에 어떻게 기여하는지 살펴보겠습니다.

  1. 먼저 프로젝트를 위한 새 디렉토리를 생성합니다. WebIDE 터미널에서 다음을 실행하세요:
mkdir -p ~/project/advanced-dockerfile && cd ~/project/advanced-dockerfile

이 명령은 project 폴더 안에 advanced-dockerfile이라는 새 디렉토리를 만들고 해당 디렉토리로 이동합니다.

  1. 이제 애플리케이션 파일을 생성합니다. WebIDE 파일 탐색기 (보통 화면 왼쪽) 에서 advanced-dockerfile 폴더를 마우스 오른쪽 버튼으로 클릭하고 "New File"을 선택합니다. 파일 이름은 app.py로 지정합니다.

  2. app.py를 열고 다음 Python 코드를 추가합니다:

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello():
    return f"Hello from {os.environ.get('ENVIRONMENT', 'unknown')} environment!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

이것은 실행 중인 환경 정보를 포함한 인사말 메시지를 응답으로 보내는 간단한 Flask 애플리케이션입니다.

  1. 다음으로 Python 의존성을 명시하기 위해 requirements.txt 파일을 생성해야 합니다. 같은 디렉토리에 requirements.txt라는 새 파일을 만들고 다음 내용을 추가합니다:
Flask==2.0.1
Werkzeug==2.0.1

여기서는 호환성을 보장하기 위해 Flask 와 Werkzeug 의 정확한 버전을 지정했습니다.

  1. 이제 Dockerfile 을 작성해 보겠습니다. 같은 디렉토리에 Dockerfile(첫 글자 대문자 'D') 이라는 새 파일을 만들고 다음 내용을 추가합니다:
## 공식 Python 런타임을 베이스 이미지로 사용
FROM python:3.9-slim

## 컨테이너 내 작업 디렉토리 설정
WORKDIR /app

## 환경 변수 설정
ENV ENVIRONMENT=production

## requirements 파일을 컨테이너로 복사
COPY requirements.txt .

## 필요한 패키지 설치
RUN pip install --no-cache-dir -r requirements.txt

## 애플리케이션 코드를 컨테이너로 복사
COPY app.py .

## 컨테이너 시작 시 실행할 명령 지정
CMD ["python", "app.py"]

## 앱이 실행되는 포트 노출
EXPOSE 5000

## 메타데이터를 위한 라벨 추가
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="1.0"
LABEL description="Flask app demo for advanced Dockerfile techniques"

이제 이 지시어들이 Docker 이미지의 레이어에 어떻게 기여하는지 분석해 보겠습니다:

  • FROM python:3.9-slim: 항상 첫 번째 지시어입니다. 빌드의 기준이 되는 베이스 이미지를 지정합니다. 이는 Python 런타임을 포함하는 이미지의 첫 번째 레이어를 생성합니다.
  • WORKDIR /app: 이후 지시어들이 실행될 작업 디렉토리를 설정합니다. 새 레이어를 생성하지는 않지만, 이어지는 지시어들의 동작 방식에 영향을 줍니다.
  • ENV ENVIRONMENT=production: 환경 변수를 설정합니다. 환경 변수는 새 레이어를 만들지 않고 이미지 메타데이터에 저장됩니다.
  • COPY requirements.txt .: 호스트의 requirements 파일을 이미지로 복사합니다. 이 파일만을 포함하는 새 레이어가 생성됩니다.
  • RUN pip install --no-cache-dir -r requirements.txt: 빌드 과정 중에 컨테이너 내에서 명령을 실행합니다. Python 의존성 패키지들을 설치하며, 설치된 모든 패키지를 포함하는 새 레이어를 생성합니다.
  • COPY app.py .: 애플리케이션 코드를 이미지로 복사하여 또 다른 레이어를 생성합니다.
  • CMD ["python", "app.py"]: 컨테이너가 시작될 때 실행할 명령을 지정합니다. 레이어를 생성하지는 않으며, 컨테이너의 기본 실행 명령을 설정합니다.
  • EXPOSE 5000: 실제로는 문서화의 일종입니다. 컨테이너가 런타임에 이 포트를 사용할 것임을 Docker 에 알리지만, 실제로 포트를 외부에 게시 (publish) 하지는 않습니다. 레이어를 생성하지 않습니다.
  • LABEL ...: 이미지에 메타데이터를 추가합니다. ENV 지시어와 마찬가지로 새 레이어를 생성하지 않고 이미지 메타데이터에 저장됩니다.

Dockerfile 의 각 RUN, COPY, ADD 지시어는 새로운 레이어를 생성합니다. 레이어는 이미지의 효율적인 저장과 전송을 가능하게 하는 Docker 의 핵심 개념입니다. Dockerfile 을 수정하고 이미지를 다시 빌드할 때, Docker 는 변경되지 않은 레이어에 대해 캐시를 재사용하여 빌드 속도를 높입니다.

  1. Dockerfile 의 역할을 이해했으니 이제 이미지를 빌드해 보겠습니다. 터미널에서 다음을 실행하세요:
docker build -t advanced-flask-app .

이 명령은 advanced-flask-app이라는 태그로 새 Docker 이미지를 빌드합니다. 끝에 있는 .은 현재 디렉토리에서 Dockerfile 을 찾으라는 의미입니다.

빌드 과정의 각 단계가 출력되는 것을 볼 수 있습니다. 각 단계가 Dockerfile 의 지시어와 어떻게 일치하는지, 그리고 빌드 명령을 여러 번 실행할 경우 변경되지 않은 단계에서 Docker 가 "Using cache"라고 표시하는 것을 확인해 보세요.

  1. 빌드가 완료되면 새 이미지를 기반으로 컨테이너를 실행할 수 있습니다:
docker run -d -p 5000:5000 --name flask-container advanced-flask-app

이 명령의 의미는 다음과 같습니다:

  • -d: 컨테이너를 백그라운드 (데몬 모드) 에서 실행합니다.
  • -p 5000:5000: 호스트의 5000 번 포트를 컨테이너의 5000 번 포트로 매핑합니다.
  • --name flask-container: 새 컨테이너에 이름을 부여합니다.
  • advanced-flask-app: 컨테이너 생성에 사용할 이미지 이름입니다.

실행 중인 컨테이너 목록을 확인하여 정상 작동 여부를 알 수 있습니다:

docker ps
  1. 애플리케이션이 제대로 작동하는지 테스트하기 위해 curl 명령을 사용합니다:
curl http://localhost:5000

"Hello from production environment!"라는 메시지가 표시되어야 합니다.

curl 사용이 어렵다면 새 브라우저 탭을 열고 http://localhost:5000에 접속해도 동일한 메시지를 확인할 수 있습니다.

문제가 발생하면 다음 명령으로 컨테이너 로그를 확인할 수 있습니다:

docker logs flask-container

여기에는 Flask 애플리케이션의 출력 내용이나 오류 메시지가 표시됩니다.

멀티 스테이지 빌드

기본적인 Dockerfile 지시어와 레이어를 이해했으니, 이제 더 고급 기술인 멀티 스테이지 빌드 (multi-stage builds) 를 살펴보겠습니다. 멀티 스테이지 빌드를 사용하면 하나의 Dockerfile 에서 여러 개의 FROM 문을 사용할 수 있습니다. 이는 한 단계 (stage) 에서 필요한 결과물만 다음 단계로 복사함으로써 최종 이미지의 크기를 획기적으로 줄이는 데 매우 유용합니다.

실제로 이미지 크기를 줄일 수 있도록 기존 Dockerfile 을 멀티 스테이지 빌드 방식으로 수정해 보겠습니다:

  1. WebIDE 에서 이전에 만든 Dockerfile을 엽니다.
  2. 전체 내용을 다음으로 교체합니다:
## 빌드 단계 (Build stage)
FROM python:3.9-slim AS builder

WORKDIR /app

COPY requirements.txt .

RUN pip install --user --no-cache-dir -r requirements.txt

## 최종 단계 (Final stage)
FROM python:3.9-slim

WORKDIR /app

## builder 단계에서 설치된 패키지만 복사
COPY --from=builder /root/.local /root/.local
COPY app.py .

ENV PATH=/root/.local/bin:$PATH
ENV ENVIRONMENT=production

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

EXPOSE 5000

LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="1.0"
LABEL description="Flask app demo with multi-stage build"

이 멀티 스테이지 Dockerfile 에서 일어나는 일을 분석해 보겠습니다:

  1. builder 단계로 시작합니다:

    • 처음부터 크기를 작게 유지하기 위해 python:3.9-slim 이미지를 베이스로 사용합니다.
    • pip install --user를 사용하여 Python 의존성을 설치합니다. 이는 패키지를 사용자 홈 디렉토리에 설치합니다.
  2. 최종 단계 (Final stage) 를 구성합니다:

    • 다시 깨끗한 python:3.9-slim 이미지로 시작합니다.
    • builder 단계에서 pip install --user가 패키지를 저장한 /root/.local 디렉토리만 복사해 옵니다.
    • 애플리케이션 코드를 복사합니다.
    • Python 이 설치된 패키지를 찾을 수 있도록 로컬 bin 디렉토리를 PATH에 추가합니다.
    • 이전과 동일하게 나머지 설정 (ENV, CMD, EXPOSE, LABEL) 을 완료합니다.

이 방식의 핵심 장점은 최종 이미지에 pip 설치 과정에서 발생한 빌드 도구나 캐시가 포함되지 않는다는 것입니다. 오직 최종적으로 필요한 결과물만 포함되므로 이미지 크기가 훨씬 작아집니다.

  1. 이 새로운 멀티 스테이지 이미지를 빌드합니다:
docker build -t multi-stage-flask-app .
  1. 빌드가 완료되면 두 이미지의 크기를 비교해 봅니다:
docker images | grep flask-app
multi-stage-flask-app         latest     7bdd1be2d1fb   10 seconds ago   129MB
advanced-flask-app            latest     c59d6fa303cc   10 minutes ago   136MB

multi-stage-flask-app이 이전에 빌드한 advanced-flask-app보다 크기가 작은 것을 확인할 수 있습니다.

  1. 이제 더 가벼워진 새 이미지로 컨테이너를 실행합니다:
docker run -d -p 5001:5000 --name multi-stage-container multi-stage-flask-app

이전 컨테이너와의 충돌을 피하기 위해 호스트 포트를 5001 로 변경했습니다.

  1. 애플리케이션을 테스트합니다:
curl http://localhost:5001

여전히 "Hello from production environment!" 메시지가 잘 나타나야 합니다.

  1. 단일 스테이지 이미지와 멀티 스테이지 이미지의 차이점을 더 자세히 이해하기 위해 docker history 명령을 사용할 수 있습니다:
docker history advanced-flask-app
docker history multi-stage-flask-app

출력 결과를 비교해 보세요. 멀티 스테이지 빌드 결과물의 레이어 수가 더 적고 일부 레이어의 크기가 더 작은 것을 확인할 수 있습니다.

멀티 스테이지 빌드는 효율적인 Docker 이미지를 만드는 강력한 기술입니다. 빌드 과정에서만 필요한 도구와 파일을 최종 이미지에 남기지 않고 깔끔하게 제거할 수 있게 해줍니다. 이는 컴파일 언어나 빌드 과정이 복잡한 애플리케이션에서 특히 유용합니다.

여기서는 Python 애플리케이션에서 빌드 아티팩트나 캐시를 제외하고, 오직 필요한 설치 패키지와 코드만 복사하여 더 작은 이미지를 만드는 데 활용했습니다.

.dockerignore 파일 활용하기

Docker 이미지를 빌드할 때, Docker 는 현재 디렉토리의 모든 파일을 Docker 데몬으로 전송합니다. 이미지 빌드에 필요 없는 대용량 파일이 포함되어 있으면 빌드 속도가 느려질 수 있습니다. .dockerignore 파일은 Docker 이미지를 빌드할 때 제외해야 할 파일과 디렉토리를 지정할 수 있게 해줍니다.

.dockerignore 파일을 만들고 어떻게 작동하는지 확인해 보겠습니다:

  1. WebIDE 를 사용하여 advanced-dockerfile 디렉토리에 .dockerignore라는 새 파일을 만듭니다.
  2. .dockerignore 파일에 다음 내용을 추가합니다:
**/.git
**/.gitignore
**/__pycache__
**/*.pyc
**/*.pyo
**/*.pyd
**/.Python
**/env
**/venv
**/ENV
**/env.bak
**/venv.bak

각 패턴의 의미는 다음과 같습니다:

  • **/.git: 디렉토리 구조 어디에 있든 .git 디렉토리와 그 안의 모든 내용을 무시합니다.
  • **/.gitignore: .gitignore 파일을 무시합니다.
  • **/__pycache__: Python 의 캐시 디렉토리를 무시합니다.
  • **/*.pyc, **/*.pyo, **/*.pyd: 컴파일된 Python 파일들을 무시합니다.
  • **/.Python: 가상 환경에서 주로 생성되는 .Python 파일을 무시합니다.
  • **/env, **/venv, **/ENV: 가상 환경 디렉토리들을 무시합니다.
  • **/env.bak, **/venv.bak: 가상 환경 디렉토리의 백업 복사본을 무시합니다.

각 라인 시작 부분의 **는 "모든 디렉토리에서"라는 의미입니다.

  1. .dockerignore 파일의 효과를 확인하기 위해 무시 대상이 될 파일들을 생성해 봅니다. 터미널에서 다음을 실행하세요:
mkdir venv
touch venv/ignore_me.txt
touch .gitignore

이 명령들은 venv 디렉토리와 그 안의 파일, 그리고 .gitignore 파일을 생성합니다. 이들은 보통 Python 프로젝트에 포함되지만 Docker 이미지에는 필요 없는 요소들입니다.

  1. 이제 이미지를 다시 빌드합니다:
docker build -t ignored-flask-app .
  1. 무시된 파일들이 빌드 컨텍스트에 포함되지 않았는지 확인하기 위해 docker history 명령을 사용합니다:
docker history ignored-flask-app

venv 디렉토리나 .gitignore 파일을 복사하는 단계가 보이지 않아야 합니다.

.dockerignore 파일은 Docker 이미지를 깨끗하게 유지하고 빌드 프로세스를 효율적으로 만드는 강력한 도구입니다. 최종 이미지에 필요하지 않은 파일이 많은 대규모 프로젝트에서 특히 유용합니다.

고급 Dockerfile 지시어

마지막 단계에서는 Docker 이미지를 더 안전하고 유지보수하기 쉬우며 사용하기 편리하게 만드는 추가적인 Dockerfile 지시어와 모범 사례를 살펴보겠습니다. 또한 각 단계의 프로세스를 검증하고 문제를 해결하는 방법에도 집중해 보겠습니다.

  1. WebIDE 에서 Dockerfile을 다시 엽니다.

  2. 내용을 다음으로 교체합니다:

## 빌드 단계
FROM python:3.9-slim AS builder

WORKDIR /app

COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

## 최종 단계
FROM python:3.9-slim

## 루트가 아닌 일반 사용자 생성
RUN useradd -m appuser

## 헬스체크를 위한 curl 설치
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

WORKDIR /app

## Python 버전과 site-packages 경로를 동적으로 결정
RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && \
    SITE_PACKAGES_PATH="/home/appuser/.local/lib/python${PYTHON_VERSION}/site-packages" && \
    mkdir -p "${SITE_PACKAGES_PATH}" && \
    chown -R appuser:appuser /home/appuser/.local

## 변수를 사용하여 site-packages와 바이너리 복사
COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}"
COPY --from=builder /root/.local/bin /home/appuser/.local/bin
COPY app.py .

ENV PATH=/home/appuser/.local/bin:$PATH
ENV ENVIRONMENT=production

## 애플리케이션을 실행할 사용자 설정
USER appuser

## ENTRYPOINT와 CMD 함께 사용
ENTRYPOINT ["python"]
CMD ["app.py"]

EXPOSE 5000

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:5000/ || exit 1

ARG BUILD_VERSION
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="${BUILD_VERSION:-1.0}"
LABEL description="Flask app demo with advanced Dockerfile techniques"

이 Dockerfile 에 도입된 새로운 개념들을 분석해 보겠습니다:

  • RUN useradd -m appuser: 컨테이너 내에 appuser라는 새 사용자를 생성합니다. 애플리케이션을 루트 (root) 가 아닌 사용자로 실행하는 것은 보안 모범 사례입니다. 이는 애플리케이션이 침해당했을 때 발생할 수 있는 잠재적 피해를 제한합니다. -m 플래그는 사용자의 홈 디렉토리를 생성합니다.
  • RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*: HEALTHCHECK 지시어가 작동하는 데 필요한 curl 패키지를 설치합니다. 또한 이미지 크기를 줄이기 위해 설치 후 apt 캐시를 삭제합니다.
  • RUN PYTHON_VERSION=$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') && ...: 컨테이너 내의 Python 버전을 동적으로 파악하여 appuser를 위한 올바른 site-packages 디렉토리를 생성합니다. 또한 해당 디렉토리에 대해 사용자 권한을 올바르게 설정합니다.
  • COPY --from=builder /root/.local/lib/python3.9/site-packages "${SITE_PACKAGES_PATH}": builder 단계에서 설치된 Python 패키지들을 최종 이미지 내의 동적으로 결정된 site-packages 경로로 복사하여, appuser가 패키지를 사용할 수 있는 올바른 위치에 배치합니다.
  • COPY --from=builder /root/.local/bin /home/appuser/.local/bin: pip에 의해 설치된 실행 가능한 스크립트 (예: Flask CLI 등) 를 builder 단계에서 appuser의 로컬 bin 디렉토리로 복사합니다.
  • ENTRYPOINT ["python"]CMD ["app.py"]: 이 둘을 함께 사용하면 ENTRYPOINT는 컨테이너의 주 실행 파일 (여기서는 python) 을 정의하고, CMD는 해당 실행 파일에 전달할 기본 인자 (app.py) 를 제공합니다. 이 패턴은 유연성을 제공합니다. 사용자는 기본적으로 app.py를 실행할 수도 있고, CMD를 덮어써서 다른 Python 스크립트나 명령을 실행할 수도 있습니다.
  • HEALTHCHECK: 컨테이너의 상태 확인을 구성합니다. Docker 는 지정된 명령 (curl -f http://localhost:5000/) 을 주기적으로 실행하여 컨테이너의 건강 상태를 판단합니다. --interval=30s--timeout=3s는 각각 확인 간격과 타임아웃을 설정합니다. curl 명령이 실패 (0 이 아닌 종료 코드 반환) 하면 컨테이너는 "unhealthy" 상태로 간주됩니다.
  • ARG BUILD_VERSION: BUILD_VERSION이라는 이름의 빌드 인자를 정의합니다. 빌드 인자를 사용하면 빌드 시점에 Docker 이미지 내부로 값을 전달할 수 있습니다.
  • LABEL version="${BUILD_VERSION:-1.0}": Docker 이미지에 version 라벨을 설정합니다. BUILD_VERSION 빌드 인자를 사용하며, 빌드 시 값이 제공되지 않으면 기본값으로 1.0을 사용합니다 (:- 구문 활용).
  1. 이제 빌드 버전을 지정하여 새 이미지를 빌드합니다:
docker build -t advanced-flask-app-v2 --build-arg BUILD_VERSION=2.0 .

--build-arg BUILD_VERSION=2.0 플래그를 통해 이미지 빌드 과정에서 BUILD_VERSION 인자에 2.0이라는 값을 전달합니다. 이 값은 이미지의 version 라벨을 설정하는 데 사용됩니다.

  1. 빌드가 완료되면 이미지가 성공적으로 생성되었는지 확인합니다:
docker images | grep advanced-flask-app-v2

출력 목록에서 새 이미지 advanced-flask-app-v2와 해당 태그, 이미지 ID, 생성일, 크기를 확인할 수 있어야 합니다.

  1. 이제 새 이미지로 컨테이너를 실행합니다:
docker run -d -p 5002:5000 --name advanced-container-v2 advanced-flask-app-v2

이 명령은 컨테이너를 백그라운드에서 실행하고, 호스트의 5002 번 포트를 컨테이너의 5000 번 포트에 매핑하며, 이름을 advanced-container-v2로 지정합니다.

  1. 컨테이너가 실행 중인지 확인합니다:
docker ps | grep advanced-container-v2

컨테이너가 성공적으로 실행 중이라면 목록에 나타납니다. 만약 목록에 없다면 컨테이너가 종료되었을 수 있습니다. 중지된 컨테이너까지 포함하여 확인해 봅니다:

docker ps -a | grep advanced-container-v2

상태가 "Up"이 아니라면 로그를 확인하여 오류를 진단합니다:

docker logs advanced-container-v2

이 명령은 Flask 애플리케이션의 로그를 보여주며, 시작 시 발생한 문제나 런타임 오류를 파악하는 데 도움을 줍니다.

  1. 컨테이너가 정상 실행 중이라면, 시작될 때까지 잠시 기다린 후 건강 상태 (health status) 를 확인합니다:
docker inspect --format='{{.State.Health.Status}}' advanced-container-v2

잠시 후 (헬스체크가 최소 한 번 실행될 시간) "healthy"라는 출력이 나타나야 합니다. 처음에 "unhealthy"가 보인다면 30 초 (체크 간격) 정도 더 기다린 후 다시 실행해 보세요. 계속 "unhealthy" 상태라면 docker logs를 통해 Flask 애플리케이션에 문제가 있는지 확인하세요. 특별한 문제가 없다면 "unhealthy" 상태를 무시하고 진행해도 좋습니다.

  1. 빌드 버전 라벨이 올바르게 적용되었는지도 확인해 봅니다:
docker inspect -f '{{.Config.Labels.version}}' advanced-container-v2

출력 결과로 "2.0"이 나타나야 합니다. 이는 BUILD_VERSION 빌드 인자가 라벨 설정에 성공적으로 사용되었음을 증명합니다.

  1. 마지막으로 애플리케이션에 요청을 보내 테스트합니다:
curl http://localhost:5002

"Hello from production environment!" 메시지가 출력되어야 합니다. 이는 Flask 애플리케이션이 Docker 컨테이너 내부에서 정상적으로 작동하고 있으며 호스트의 5002 번 포트를 통해 접근 가능하다는 것을 의미합니다.

이러한 고급 기술들을 통해 더욱 안전하고 설정 가능하며 운영 환경에 적합한 Docker 이미지를 만들 수 있습니다. 루트가 아닌 사용자를 사용하면 보안이 강화되고, HEALTHCHECK는 컨테이너 오케스트레이션과 모니터링에 도움을 주며, 빌드 인자는 유연한 버전 관리를 가능하게 합니다.

요약

이 실습에서는 더욱 효율적이고 안전하며 유지보수가 용이한 Docker 이미지를 만드는 데 도움이 되는 고급 Dockerfile 기술들을 살펴보았습니다. 우리가 학습한 내용은 다음과 같습니다:

  1. 상세한 Dockerfile 지시어와 이미지 레이어에 미치는 영향: 각 지시어가 이미지 구조에 어떻게 기여하는지, 그리고 레이어에 대한 이해가 이미지 최적화에 어떻게 도움이 되는지 배웠습니다.
  2. 멀티 스테이지 빌드: 빌드 환경과 실행 환경을 분리하여 최종 이미지 크기를 줄이는 기술을 적용해 보았습니다.
  3. .dockerignore 파일 활용: 빌드 컨텍스트에서 불필요한 파일을 제외하여 빌드 속도를 높이고 이미지 크기를 줄이는 방법을 익혔습니다.
  4. 고급 Dockerfile 지시어: USER, ENTRYPOINT, HEALTHCHECK, ARG 와 같은 지시어를 탐구하여 더욱 안전하고 유연한 이미지를 만드는 방법을 배웠습니다.

이러한 기술들을 통해 여러분은 다음을 수행할 수 있습니다:

  • 더욱 최적화되고 작은 크기의 Docker 이미지 생성
  • 루트가 아닌 사용자로 애플리케이션을 실행하여 보안 강화
  • 더 나은 컨테이너 오케스트레이션을 위한 상태 확인 (health check) 구현
  • 유연한 이미지 빌드를 위한 빌드 시점 변수 활용

실습 전반에 걸쳐 WebIDE(VS Code) 를 사용하여 파일을 편집함으로써, 브라우저에서 직접 Dockerfile 과 애플리케이션 코드를 편리하게 생성하고 수정해 보았습니다. 이러한 방식은 Docker 를 활용한 개발 과정에서 매끄러운 경험을 제공합니다.