Ubuntu에서 마이그레이션하기

Ubuntu에서 마이그레이션하기

Ubuntu 기반 이미지에서 Docker Hardened Images(DHI)의 Debian 기반 변형으로 마이그레이션하는 방법과 주요 차이점을 알아봐요.

출처: 문서

본문

Docker Hardened Images(DHI)는 Alpine 기반과 Debian 기반 변형으로 제공돼요. Ubuntu 기반 이미지에서 마이그레이션할 때는 Debian 기반 DHI 변형으로 마이그레이션해야 해요. Ubuntu와 Debian은 동일한 패키지 관리 시스템(APT)과 기본 아키텍처를 공유하므로 마이그레이션이 간단해요.

이 가이드는 기존 Ubuntu 기반 이미지에서 DHI로 마이그레이션하도록 도와줘요.

주요 차이점(Key differences)

Ubuntu 기반 이미지에서 DHI Debian으로 마이그레이션할 때 다음 핵심 차이점을 주의하세요.

항목 Ubuntu 기반 이미지 Docker Hardened Images
패키지 관리(Package management) 이미지마다 다름. 어떤 것은 APT 패키지 매니저를 포함하고 어떤 것은 없음 패키지 매니저는 일반적으로 dev 태그 이미지에만 있음. 런타임 이미지에는 패키지 매니저가 없음. 멀티 스테이지 빌드를 사용하고 필요한 아티팩트를 빌드 단계에서 런타임 단계로 복사해요.
비루트 사용자(Non-root user) 이미지마다 다름. 어떤 것은 root로, 어떤 것은 non-root로 실행됨 런타임 변형은 기본적으로 nonroot 사용자로 실행됨. 필요한 파일과 디렉터리가 nonroot 사용자에게 접근 가능한지 보장해요.
멀티 스테이지 빌드(Multi-stage build) 권장됨 권장됨. 빌드 단계에는 dev 또는 sdk 태그 이미지를, 런타임에는 non-dev 이미지를 사용해요.
포트(Ports) root로 실행할 때 권한 있는 포트(1024 미만)에 바인딩 가능 기본적으로 nonroot 사용자로 실행됨. Kubernetes나 20.10 이전 버전의 Docker Engine에서 실행할 때 애플리케이션이 권한 있는 포트(1024 미만)에 바인딩할 수 없음. 컨테이너 내부에서 애플리케이션이 1025 이상의 포트에서 수신하도록 구성해요.
엔트리포인트(Entry point) 이미지마다 다름 Ubuntu 기반 이미지와 다른 엔트리포인트를 가질 수 있음. 엔트리포인트를 검사하고 필요하면 Dockerfile을 업데이트해요.
셸(Shell) 이미지마다 다름. 어떤 것은 셸을 포함하고 어떤 것은 없음 런타임 이미지에는 셸이 없음. 셸 명령을 실행하려면 빌드 단계에서 dev 이미지를 사용한 다음 아티팩트를 런타임 단계로 복사해요.
패키지 저장소(Package repositories) Ubuntu 패키지 저장소 사용 Debian 패키지 저장소 사용. 대부분의 패키지는 이름이 비슷하지만 일부는 다를 수 있음.

마이그레이션 단계(Migration steps)

1단계: Dockerfile의 베이스 이미지 업데이트

애플리케이션 Dockerfile의 베이스 이미지를 강화된 이미지로 업데이트해요. 패키지와 의존성을 설치하는 데 필요한 도구가 있으므로 보통 dev 또는 sdk 태그가 붙은 이미지가 될 거예요.

다음 Dockerfile의 diff 스니펫은 이전 Ubuntu 기반 이미지를 새 DHI Debian 이미지로 바꾼 예시예요.

[!NOTE]

Docker Hardened Images를 풀하기 전에 dhi.io에 인증해야 해요. Docker ID 자격 증명(Docker Hub에 사용하는 동일한 사용자 이름과 비밀번호)을 사용해요. Docker 계정이 없다면 무료로 계정을 만들어요.

인증하려면 docker login dhi.io를 실행해요.

- ## Original Ubuntu-based image
- FROM ubuntu/go:1.22-24.04

+ ## Updated to use hardened Debian-based image
+ FROM dhi.io/golang:1.25-debian13-dev

올바른 태그를 찾으려면 DHI Catalog에서 사용 가능한 태그를 살펴보세요.

2단계: 패키지 설치 명령 업데이트

Ubuntu와 Debian 모두 패키지 관리를 위해 APT를 사용하므로 대부분의 패키지 설치 명령은 비슷해요. 하지만 런타임 이미지에는 패키지 매니저가 없으므로 패키지 설치가 dev 또는 sdk 이미지에서만 발생하도록 해야 해요.

- ## Ubuntu: Installing packages
- FROM ubuntu/go:1.22-24.04
- RUN apt-get update && apt-get install -y \
-     git \
-     && rm -rf /var/lib/apt/lists/*

+ ## DHI: Use a language-specific dev image with package manager
+ FROM dhi.io/golang:1.25-debian13-dev
+ RUN apt-get update && apt-get install -y \
+     git \
+     && rm -rf /var/lib/apt/lists/*

대부분의 Ubuntu 패키지는 동일한 이름으로 Debian에서 사용할 수 있어요. 누락된 패키지가 있다면 Debian package search 웹사이트에서 동등한 패키지를 검색할 수 있어요.

3단계: Dockerfile의 런타임 이미지 업데이트

[!NOTE]

최종 이미지를 최소화하고 안전하게 유지하려면 멀티 스테이지 빌드를 권장해요. 싱글 스테이지 빌드도 지원되지만 전체 dev 이미지를 포함하므로 더 큰 이미지와 더 넓은 공격 표면이 생겨요.

최종 이미지를 가능한 한 최소화하려면 멀티 스테이지 빌드를 사용해야 해요. Dockerfile의 모든 단계는 강화된 이미지를 사용해야 해요. 중간 단계는 보통 dev 또는 sdk 태그 이미지를 사용하지만, 최종 런타임 단계는 런타임 이미지를 사용해야 해요.

빌드 단계에서 의존성을 설치하고 애플리케이션을 준비한 다음, 결과 아티팩트를 최종 런타임 단계로 복사해요. 이렇게 하면 최종 이미지가 최소화되고 안전해져요.

다음 예시는 Ubuntu에서 DHI Debian으로 마이그레이션한 멀티 스테이지 Dockerfile을 보여줘요.

# Build stage
FROM dhi.io/golang:1.25-debian13-dev AS builder
WORKDIR /app

# Install system dependencies (only available in dev images)
RUN apt-get update && apt-get install -y \
    git \
    && rm -rf /var/lib/apt/lists/*

# Copy application files
COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags="-s -w" -o main .

# Runtime stage
FROM dhi.io/golang:1.25-debian13
WORKDIR /app

# Copy compiled binary from builder
COPY --from=builder /app/main /app/main

# Run the application
ENTRYPOINT ["/app/main"]

언어별 예시(Language-specific examples)

언어별 마이그레이션 예시는 예시 섹션을 참조해요.

더 알아보기 (Learn more)