환경 구성 · 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 images에boilerplate312-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_PROGRAM | run_pm.py | Training 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분 안에 새 이미지로 만들 수 있습니다.