환경 구성 · Docker

Docker 이미지 빌드

Base & SageMaker Training — 2단계 전략으로 이미지를 만들고 ECR에 올리는 방법

Docker 이미지 빌드

2단계 전략으로 이미지를 만들고 ECR에 올리는 방법

"내 노트북에서는 됐는데 서버에서는 안 돼요." — 이 문제의 원인은 항상 환경 차이입니다.
문제Docker 없을 때Docker 있을 때
환경 재현"내 PC에서는 돼요"어디서나 동일한 환경
SageMaker Training매번 패키지 설치이미지 한 번 빌드로 끝
팀 공유설치 가이드 문서docker pull 한 줄

2단계 빌드 전략

"무거운 것은 한 번만, 가벼운 것은 자주."
Stage 1
Base Image
~25분 · 팀 공유
Stage 2
SM Training Image
~3분 · 개인 버전
실행
Training Job
Estimator.fit()
  • Base Image는 Python 소스 빌드와 무거운 패키지 설치로 30분이 걸림
  • 코드(run_pm.py)나 추가 패키지만 바꿀 때는 Stage 2만 다시 빌드하면 5분
  • Base Image는 여러 환경(boilerplate312, tabular312, streamlit314)이 공유함

Part 1 · Base Image 빌드

핵심 Dockerfile 분석

1. Ubuntu 미러를 KAIST로 교체

FROM ubuntu:20.04

RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|http://ftp.kaist.ac.kr/ubuntu/|g' \
        /etc/apt/sources.list \
    && apt-get update -o Acquire::ForceIPv4=true \
    && apt-get install -y --no-install-recommends \
        build-essential ca-certificates curl wget git ...
ℹ️ AWS EC2에서 Ubuntu 기본 미러(archive.ubuntu.com)는 느릴 수 있습니다. KAIST 미러는 국내 네트워크에서 훨씬 빠릅니다.

2. Python을 소스에서 직접 빌드

ARG PYTHON_VERSION=3.12.7

RUN wget https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz && \
    tar -xvf Python-$PYTHON_VERSION.tgz && cd Python-$PYTHON_VERSION && \
    ./configure --enable-loadable-sqlite-extensions && \
    make && make install && \
    cd .. && rm -rf Python-$PYTHON_VERSION*
⚠️ --enable-loadable-sqlite-extensions가 핵심입니다. Ubuntu 기본 Python은 SQLite 확장 기능이 비활성화되어 있어 일부 데이터 패키지에서 오류가 납니다.

3. 패키지 설치 — 4단계 폴백 전략

RUN ${PIP} install --no-cache-dir --no-deps --only-binary :all: -r /requirements.txt \
    || ${PIP} install --no-cache-dir --no-deps --prefer-binary -r /requirements.txt \
    || ${PIP} install --no-cache-dir --no-deps -r /requirements.txt \
    || ${PIP} install -r /requirements.txt
시도옵션의미
1순위--only-binary :all:바이너리(.whl)만 사용, 빠름
2순위--prefer-binary바이너리 우선, 없으면 소스
3순위--no-deps의존성 체크 건너뜀
4순위(기본)뭐든 설치

Base Image 빌드 & ECR 푸시

📋 복사해서 붙여넣기

# 1. ECR 로그인
AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=$(aws configure get region)
ECR_URI="${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com"

aws ecr get-login-password --region ${AWS_REGION} \
    | docker login --username AWS --password-stdin ${ECR_URI}

# 2. ECR 레포지토리 생성 (최초 1회만)
aws ecr create-repository \
    --repository-name gs-automl-base-containers/boilerplate312 \
    --region ${AWS_REGION}

# 3. 빌드 디렉토리 이동
cd ~/SageMaker/gs-ds-env/boilerplate312/base_docker/

# 4. 이미지 빌드
docker build -t boilerplate312-base .

# 5. 태그 & 푸시
docker tag boilerplate312-base \
    ${ECR_URI}/gs-automl-base-containers/boilerplate312:sean-base

docker push \
    ${ECR_URI}/gs-automl-base-containers/boilerplate312:sean-base

빌드 단계별 예상 시간:

Step 1/7: FROM ubuntu:20.04                          ~30초
Step 2/7: RUN sed -i ... apt-get install             ~3분
Step 3/7: RUN wget Python-3.12.7.tgz ... make       ~10분  ← 가장 오래 걸림
Step 4/7: RUN apt-get install fontconfig + 폰트      ~1분
Step 5/7: RUN pip install --upgrade                  ~30초
Step 6/7: COPY requirements.txt + RUN pip install    ~10분
Step 7/7: ENV 설정                                   ~1초
----------------------------------------------------------
합계                                                 ~25분
  • docker imagesboilerplate312-base 이미지가 있는가?
  • ECR 콘솔에서 boilerplate312:sean-base 태그가 보이는가?

Part 2 · SageMaker Training Image 빌드

Dockerfile.template → Dockerfile 생성

SM Training 이미지는 Jinja2 템플릿으로 Dockerfile을 생성합니다. 계정 ID와 리전을 코드에 하드코딩하지 않기 위해서입니다.

sm_docker/
├── Dockerfile.template    ← {{account_id}}, {{region_name}} 플레이스홀더
├── gen_dockerfile.py      ← boto3로 값 채워서 Dockerfile 생성
├── Dockerfile             ← gen_dockerfile.py가 생성 (git ignore)
├── run_pm.py              ← 컨테이너 안에서 실행될 파이프라인 러너
└── requirements.txt       ← 추가 패키지 (lightgbm, seaborn 등)

SageMaker Training 환경 변수 3가지

변수의미
SAGEMAKER_PROGRAMrun_pm.pyTraining Job 시작 시 SageMaker가 이 스크립트를 실행
SAGEMAKER_SUBMIT_DIRECTORY/opt/ml/code스크립트가 있는 위치
WORKDIR /opt/ml/(디렉토리)SageMaker가 input/output을 마운트하는 기준 경로

SM Training Image 빌드 & ECR 푸시

📋 복사해서 붙여넣기

# 1. sm_docker 폴더로 이동
cd ~/SageMaker/gs-ds-env/boilerplate312/sm_docker/

# 2. Dockerfile 생성 (계정 ID, 리전 자동 감지)
python gen_dockerfile.py \
    --env boilerplate312 \
    --base_version sean-base \
    --my_version hjsong-v1.5

# 3. 생성된 Dockerfile 확인
head -3 Dockerfile
# FROM 155954279556.dkr.ecr.us-east-1.amazonaws.com/gs-automl-base-containers/boilerplate312:sean-base

# 4. 이미지 빌드 (Base 레이어 캐시로 빠름)
docker build -t boilerplate312-sm:hjsong-v1.5 .

# 5. 태그 & 푸시
docker tag boilerplate312-sm:hjsong-v1.5 \
    ${ECR_URI}/gs-automl-base-containers/boilerplate312:hjsong-v1.5

docker push \
    ${ECR_URI}/gs-automl-base-containers/boilerplate312:hjsong-v1.5
✅ Base 캐시 활용으로 빌드 시간이 ~25분 → ~3분으로 단축됩니다.
  • gen_dockerfile.py 실행 후 Dockerfile의 FROM 줄에 올바른 계정 ID가 있는가?
  • SM Training 이미지가 ECR에 내 버전 태그로 올라갔는가?

Part 3 · SageMaker Training Job에서 컨테이너 실행

컨테이너 안에서 무슨 일이 일어나는가?

[SageMaker]
  컨테이너 실행
        ↓
  SAGEMAKER_PROGRAM=run_pm.py 확인
        ↓
  python /opt/ml/code/run_pm.py
      --conf-s3-path s3://gs-retail-awesome-conf-.../dev/hjsong/titanic/tuned-v1/
        ↓
[run_pm.py 파이프라인]
  1. S3 conf 경로에서 파일 다운로드
  2. S3 data 경로에서 데이터 다운로드
  3. Run ID 생성
  4. Papermill로 modeling.ipynb 실행
  5. 결과물 S3 업로드

SageMaker Estimator로 Training Job 실행

📋 복사해서 붙여넣기

import sagemaker
from sagemaker.estimator import Estimator

AWS_ACCOUNT  = "155954279556"    # 본인 계정으로 수정
AWS_REGION   = "us-east-1"
USER_ID      = "hjsong"          # ← 수정
MY_VERSION   = "hjsong-v1.5"     # ← 수정

ECR_URI = (
    f"{AWS_ACCOUNT}.dkr.ecr.{AWS_REGION}.amazonaws.com"
    f"/gs-automl-base-containers/boilerplate312:{MY_VERSION}"
)

CONF_S3_PATH = (
    f"s3://gs-retail-awesome-conf-{AWS_REGION}"
    f"/dev/{USER_ID}/titanic-survival-prediction/tuned-v1/"
)

estimator = Estimator(
    image_uri=ECR_URI,
    role=sagemaker.get_execution_role(),
    instance_count=1,
    instance_type="ml.m5.xlarge",
    hyperparameters={"conf-s3-path": CONF_S3_PATH},
    output_path=f"s3://gs-retail-awesome-model-{AWS_REGION}/dev/{USER_ID}/",
)

estimator.fit()

빠른 참조 — 명령어 치트시트

📋 복사해서 붙여넣기

# ECR 변수 설정
export AWS_ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
export AWS_REGION=$(aws configure get region)
export ECR_URI="${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com"
export REPO="gs-automl-base-containers/boilerplate312"

# ECR 로그인
aws ecr get-login-password --region ${AWS_REGION} \
    | docker login --username AWS --password-stdin ${ECR_URI}

# Base 이미지 빌드 & 푸시 (최초 1회)
cd ~/SageMaker/gs-ds-env/boilerplate312/base_docker/
docker build -t base . && \
docker tag base ${ECR_URI}/${REPO}:sean-base && \
docker push ${ECR_URI}/${REPO}:sean-base

# SM Training 이미지 빌드 & 푸시 (버전 바뀔 때마다)
MY_VER="hjsong-v1.5"
cd ~/SageMaker/gs-ds-env/boilerplate312/sm_docker/
python gen_dockerfile.py --env boilerplate312 --base_version sean-base --my_version ${MY_VER} && \
docker build -t sm:${MY_VER} . && \
docker tag sm:${MY_VER} ${ECR_URI}/${REPO}:${MY_VER} && \
docker push ${ECR_URI}/${REPO}:${MY_VER}

전체 체크리스트

단계확인 방법
ECR 레포지토리가 생성됐는가?AWS 콘솔 → ECR → Repositories
Base 이미지가 ECR에 :sean-base 태그로 올라갔는가?aws ecr describe-images --repository-name ${REPO}
gen_dockerfile.py 실행 후 Dockerfile의 FROM 줄에 올바른 계정 ID가 있는가?head -2 Dockerfile
SM Training 이미지가 ECR에 내 버전 태그로 올라갔는가?ECR 콘솔 확인
Estimator.fit() 실행 후 Training Job 상태가 Completed인가?SageMaker → Training jobs
S3 model 버킷에 결과가 업로드됐는가?aws s3 ls s3://gs-retail-awesome-model-...
2단계 빌드의 핵심 가치: Base 이미지는 팀 공유 자산입니다. 개인 실험마다 25분짜리 빌드를 반복하지 않아도 됩니다. 자신의 코드와 추가 패키지만 Stage 2에서 3~5분 안에 새 이미지로 만들 수 있습니다.