내가 설정한 환경과 애플리케이션을 그대로 묶어 배포하기 위한 Docker Image 생성 방법을 두 가지 관점에서 정리했습니다.
실행 중인 베이스 컨테이너에 직접 쉘 접속하여 프로그램 설치 및 환경 설정을 마치고, 그 상태 그대로 '스냅샷'을 떠서 이미지를 만드는 직관적인 방식입니다.
작업 과정:
docker exec -it [컨테이너명] /bin/bash 로 접속하여 필요한 작업 수행docker commit [컨테이너명] my_custom_image:1.0 (이미지 굽기)docker tag my_custom_image:1.0 my_registry/my_custom_image:1.0 (태그 설정)docker push my_registry/my_custom_image:1.0 (원격 저장소에 업로드)단점:
'Infrastructure as Code' 철학에 맞춰 이미지를 조립하는 설명서(Dockerfile)를 코드로 작성하고 버전 관리를 하는 방식입니다.
docker.io 공식 베스트 프랙티스에서 가장 권장하는 방식으로, 애플리케이션을 빌드하는 환경과 실제 운영(Run)하는 환경을 분리하여 최종 이미지 용량을 극적으로 줄입니다.
# 1단계: 빌드 환경 (Builder)
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp main.go
# 2단계: 실행 환경 (Production) - 아주 가벼운 OS 사용
FROM alpine:latest
WORKDIR /app
# 빌드 단계에서 생성된 순수 바이너리 실행 파일만 복사
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]entry.sh를 활용한 고난도 커스텀 이미지컨테이너 기동 시점에 DB 연결 대기, 초기 마이그레이션 스크립트 실행, 동적 환경변수에 따른 Config 파일 템플릿 렌더링 등 복잡한 '전처리' 과정이 필요할 때는 쉘 스크립트를 진입점(Entrypoint)으로 삼습니다.
FROM openjdk:17-slim
WORKDIR /app
COPY myapp.jar /app.jar
# 전처리 쉘 스크립트 복사 및 실행 권한 부여
COPY entry.sh /entry.sh
RUN chmod +x /entry.sh
# 컨테이너가 시작될 때 무조건 스크립트 실행
ENTRYPOINT ["/entry.sh"]docker-entrypoint.sh 표준 패턴 예시 (공식 이미지 참조):
#!/bin/bash
set -e # 명령어 실패 시 스크립트 즉시 중단 (안전성 확보)
echo "1. 데이터베이스 연결을 대기합니다..."
# (DB 연결 확인 로직)
echo "2. 최신 설정 정보를 환경변수로부터 적용합니다..."
# (sed, awk 등을 활용한 config 치환 로직)
# 사용자가 CMD로 넘긴 인자가 특정 서비스 실행 명령인 경우
if [ "$1" = 'my-service' ]; then
echo "3. 메인 애플리케이션을 실행합니다."
# exec를 사용하여 쉘 프로세스를 자바 프로세스로 교체 (PID 1 유지)
exec java -jar /app.jar
fi
# 그 외 커스텀 명령(예: bash)을 넘긴 경우 그대로 실행되도록 패스스루(Pass-through)
exec "$@"exec "$@" 패턴은 Postgres, MySQL 등 도커 허브의 공식 이미지들이 공통적으로 채택하는 베스트 프랙티스로, docker run [이미지] bash 처럼 커스텀 인자를 넘길 때 유연하게 처리해 줍니다.