[Docker 시리즈 3편] Ubuntu vs Alpine, 어떤 베이스 이미지를 고를까

English version

2편에서 Dockerfile이 이미지와 컨테이너를 잇는 다리라는 이야기를 했습니다. 이제 그 다리 위에서 어떤 길을 택할지, 즉 베이스 이미지를 무엇으로 고를지 살펴볼 차례입니다. 고등학생 입장에서 Docker를 실습해 보면 가장 많이 마주치는 이름이 ubuntualpine입니다. 두 이미지를 직접 비교하면서 언제 어떤 선택이 더 쉬운지 정리해 봅시다.

이 글의 흐름

  1. 베이스 이미지가 결정하는 것들
  2. Ubuntu 이미지를 선택할 이유와 실습
  3. Alpine 이미지를 선택할 이유와 실습
  4. 상황별 체크리스트와 Compose 예시
  5. 다음 글에서 다룰 멀티 스테이지 빌드 예고

읽기 카드

  • 예상 소요 시간: 15분
  • 사전 준비: Dockerfile 기초, apt/apk 명령 감각
  • 읽고 나면: 우분투와 알파인의 장단점을 상황별로 설명할 수 있습니다.

베이스 이미지가 결정하는 것들

베이스 이미지는 단순히 "어떤 OS인가"를 넘어서 다음 요소를 결정합니다.

  • 패키지 관리자: 우분투는 apt, 알파인은 apk를 씁니다.
  • 기본 셸과 유틸리티: 우분투는 bash와 익숙한 GNU 유틸이 대부분 있지만, 알파인은 BusyBox 기반이라 최소한만 있습니다.
  • 이미지 크기와 보안 업데이트 주기: 알파인은 수십 MB 수준으로 작고, 우분투는 그보다 무겁지만 익숙한 패치 흐름을 따릅니다.
  • 런타임 라이브러리: 알파인은 musl 기반이라, 일부 미리 빌드된 프로그램은 그대로 실행되지 않을 수 있습니다.

즉, "무조건 가벼우면 좋다" 혹은 "무조건 익숙한 게 좋다"가 아니라 작업 목적에 맞는 균형이 중요합니다.

여기서 muslglibc라는 말이 처음 나오면 어렵게 느껴질 수 있습니다. 초보자 단계에서는 내부 원리까지 외울 필요는 없고, 아래처럼 규칙으로 기억해도 충분합니다.

  • 우분투는 "대부분의 예제가 무난하게 잘 돌아가는 쪽"에 가깝습니다.
  • 알파인은 "가볍고 빠르지만, 어떤 패키지는 그대로는 안 돌아갈 수 있는 쪽"에 가깝습니다.

즉, 알파인에서 라이브러리 오류를 만나면 너무 깊게 파고들기 전에 "이 경우는 우분투 기반 이미지가 더 편하겠다"고 판단하는 것도 좋은 선택입니다. 배포 이미지를 아주 작게 만들어야 하는 상황이 아니라면, 초반 학습에서는 우분투가 더 덜 막힐 수 있습니다.

Ubuntu 이미지를 선택할 이유

학생들이 실습할 때 우분투 이미지를 자주 고르는 이유는 명확합니다.

  1. 교육 자료와 동일한 환경: 대부분의 리눅스 입문 문서가 우분투 LTS 기준으로 작성되어 있어 따라 하기 쉽습니다.
  2. 풍부한 패키지: apt install build-essential 같은 명령으로 즉시 필요한 도구를 설치할 수 있습니다.
  3. 디버깅 편의성: bash, curl, ping, systemctl 등 익숙한 도구가 기본 또는 간단한 설치로 준비됩니다.

Compose로 우분투 실습 컨테이너를 만들면 아래처럼 됩니다.

services:
  ubuntu-lab:
    image: ubuntu:24.04
    command: ["bash", "-lc", "sleep infinity"]
    stdin_open: true
    tty: true

Ubuntu 미니 실습

  1. 컨테이너 띄우기
docker run -it --name ubuntu-lab --rm ubuntu:24.04 bash
  1. 패키지 업데이트와 설치
apt update && apt install -y git curl
  1. 프로세스 확인
ps aux | head -5

이 실습만으로 apt, bash, 친숙한 GNU 유틸을 바로 다룰 수 있습니다. 맥 사용자라도 터미널 하나만 열면 곧바로 리눅스 서버를 체험하게 됩니다.

Alpine 이미지를 선택할 이유

알파인을 선택하는 이유는 조금 다릅니다.

  1. 이미지 크기 절감: alpine:3.20은 수십 MB 수준입니다. 배포 속도가 빨라지고, 데이터 요금이 줄어듭니다.
  2. 빠른 기동: 기본 패키지가 적어서 컨테이너가 매우 빠르게 뜹니다.
  3. 보안 표면 최소화: 불필요한 도구가 거의 없어 업데이트할 대상이 적습니다.

단, 아래를 기억하세요.

  • 기본 셸이 sh이므로 bash가 필요하면 직접 설치합니다.
  • apk add는 패키지 이름이 다소 다릅니다. 예: apk add curl.
  • 일부 바이너리는 glibc를 기대하므로 호환 패키지를 추가해야 합니다.

Alpine 미니 실습

docker run -it --name alpine-lab --rm alpine:3.20 sh
apk add --no-cache curl bash
cat /etc/os-release

짧은 명령 몇 줄만으로도 "경량 리눅스"가 어떤 느낌인지 체험할 수 있습니다. apk add --no-cache 패턴을 익히면 배포 이미지에서 불필요한 캐시 파일을 남기지 않을 수 있습니다.

프로젝트 상황에 맞춘 체크리스트

질문 우분투 추천 알파인 추천
리눅스 기초 실습이 목적인가?
이미지 크기가 100MB 이하여야 하나?
glibc 기반 언어/패키지를 쓰나?
단일 실행 파일만 배포하면 되나?
디버깅 유틸이 많이 필요한가?

Compose로 두 이미지를 동시에 다뤄 보기

services:
  ubuntu-lab:
    image: ubuntu:24.04
    command: ["bash", "-lc", "sleep infinity"]
    tty: true

  alpine-lab:
    image: alpine:3.20
    command: ["sh", "-lc", "sleep infinity"]
    tty: true

docker compose up -d로 두 환경을 동시에 띄우고 docker compose exec ubuntu-lab bash, docker compose exec alpine-lab sh로 각각 접속해 보세요. 같은 명령이라도 옵션이나 패키지 이름이 다르게 느껴진다는 사실을 직접 체험할 수 있습니다.

처음 선택할 때는 아래처럼 단순 규칙으로 시작해도 좋습니다.

  1. 리눅스 명령과 패키지 설치를 배우는 실습이면 우분투부터 시작합니다.
  2. 배포 이미지를 가볍게 만들고 싶으면 알파인을 먼저 검토합니다.
  3. 알파인에서 패키지 호환 오류가 나면 우분투로 되돌아가도 괜찮습니다.

다음 글 예고: 멀티 스테이지 빌드

베이스 이미지를 정한 뒤에는 "빌드 환경"과 "실행 환경"을 어떻게 분리할지가 숙제입니다. 다음 4편에서는 Node 앱을 예시로 멀티 스테이지 빌드를 구성하고, 어떤 스테이지를 만들면 이미지를 더 가볍게 유지할 수 있는지 실습 중심으로 이어가겠습니다.

💬 댓글

이 글에 대한 의견을 남겨주세요