초보자를 위한 Dockerfile Ubuntu 환경 구축 가이드 | 기본·Python까지 완전 안내

目次

1. 소개

Docker와 Dockerfile이란?

최근 개발 환경 정비와 애플리케이션 배포를 효율화하는 수단으로서 Docker가 급속히 보급되고 있습니다. Docker는 애플리케이션과 그 의존 환경을 하나의 “컨테이너”로 패키징하여 어디서든 동일한 환경에서 실행할 수 있는 특징을 가지고 있습니다. 이 Docker 컨테이너를 구축하려면 “Dockerfile”이라는 설계도가 필요합니다. Dockerfile은 기반이 되는 OS 이미지 지정, 설치할 소프트웨어, 환경 변수 설정 등을 기술하는 텍스트 파일입니다. 개발자는 이 파일을 사용해 맞춤형 환경을 자동으로 구축할 수 있습니다.

Ubuntu를 기반으로 하는 이유

Dockerfile을 만들 때는 먼저 기반이 되는 OS 이미지를 지정해야 합니다. 그 중에서도 특히 인기가 높은 것이 Ubuntu입니다. Ubuntu는 Debian 기반의 Linux 배포판으로, 사용 편의성과 풍부한 패키지를 통한 유연한 환경 구축이 가능합니다. Ubuntu를 기반으로 한 Dockerfile은 다음과 같은 장점이 있습니다:
  • 풍부한 공식·커뮤니티 문서가 존재하여 학습 비용이 낮다
  • 많은 패키지와 도구를 APT로 쉽게 설치할 수 있다
  • 경량의 미니멀 이미지(ubuntu:20.04, ubuntu:24.04 등)가 공식적으로 제공된다

본 기사(글)의 목적과 대상 독자

본 기사에서는 “Dockerfile Ubuntu”라는 키워드를 주제로, Ubuntu 기반 Dockerfile 작성 방법을 초보자도 이해하기 쉽게 설명합니다. 구체적으로는 Dockerfile의 기본 구조부터 실제 Ubuntu 환경을 구축하는 절차, Python 등 애플리케이션 환경 도입 예시, 그리고 흔히 발생하는 오류와 그 대응 방법까지 포괄적으로 소개합니다. 다음과 같은 분들에게 추천하는 내용입니다:
  • Dockerfile을 처음 사용해 환경을 구축하고 싶은 분
  • Ubuntu에서 개발 환경을 재현성 높게 만들고 싶은 분
  • 문제 발생 시 대응 방법까지 포함해 지식을 깊게 배우고 싶은 분
侍エンジニア塾

2. Dockerfile의 기본 구성

Dockerfile이란? 그 역할을 이해하자

Dockerfile은 Docker 이미지를 만들기 위한 레시피와 같은 것입니다. 구체적으로는 어떤 베이스 OS를 사용하고, 어떤 소프트웨어를 설치하며, 어떤 설정을 하는지를 기록하는 텍스트 파일입니다. 이 파일을 기반으로 docker build 명령을 실행하면, 재현성이 높은 개발 환경 및 애플리케이션 실행 환경을 쉽게 구축할 수 있습니다. Dockerfile을 사용하면 얻는 이점:
  • 환경 구축 자동화(수작업 재현 불필요)
  • 여러 사람이 개발할 때 환경 차이가 없어짐
  • CI/CD 파이프라인에도 쉽게 통합 가능

Dockerfile에서 자주 사용되는 기본 명령(디렉티브)

Dockerfile에는 여러 명령(디렉티브)이 있지만, 아래가 대표적인 것입니다. 이를 적절히 조합하여 Ubuntu 기반 Dockerfile을 만들어 나갑니다.
명령설명
FROM베이스가 되는 Docker 이미지를 지정합니다. 예: FROM ubuntu:24.04
RUN쉘 명령을 실행합니다. 패키지 설치 등에 사용
COPY로컬 파일을 이미지 내부에 복사
ADDCOPY와 비슷하지만, URL에서 가져오거나 아카이브를 풀어낼 수도 있음
WORKDIR작업 디렉터리를 지정
ENV환경 변수를 설정
CMD컨테이너 시작 시 실행되는 명령을 정의(덮어쓰기 가능)
ENTRYPOINTCMD와 비슷하지만, 강제로 실행되는 명령을 정의

Ubuntu 기반 Dockerfile의 최소 예시

아래는 Ubuntu를 기반으로 한 아주 기본적인 Dockerfile 예시입니다.
FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    curl 
    vim

CMD ["/bin/bash"]
이 Dockerfile은 Ubuntu 24.04를 기반으로 curlvim이라는 두 유틸리티를 설치하고, 마지막에 bash 쉘을 실행하도록 구성되었습니다.

Ubuntu 태그 선택에 대해

Ubuntu Docker 이미지는 Docker Hub 공식 레포지토리에서 공개됩니다. ubuntu:latest를 지정하면 최신 버전이 사용되지만, 버전을 명시적으로 고정하는 것이 권장됩니다. 예를 들어:
  • ubuntu:22.04 (LTS: 장기 지원 버전, 안정성 중시)
  • ubuntu:24.04 (최신 LTS 후보, 기능 중시)
목적에 따라 안정성을 우선할지 새로운 기능을 우선할지 검토해봅시다.

3. 실전: Ubuntu 기반 Dockerfile 만들기

Ubuntu 환경에 필요한 패키지를 설치하기

Dockerfile을 사용해 Ubuntu 환경을 구축할 때, 대부분의 경우 추가 패키지를 설치해야 합니다. 예를 들어, 개발 환경을 갖추기 위해 다음과 같은 유틸리티가 자주 사용됩니다:
  • curl: 파일 가져오기 및 API 확인용
  • vim: 간단한 텍스트 에디터
  • git: 버전 관리 도구
  • build-essential: C/C++ 빌드에 필요한 기본 도구 모음
Dockerfile에서 이를 설치하려면 RUN 명령을 사용합니다.
FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    curl 
    vim 
    git 
    build-essential
apt-get update를 먼저 실행함으로써 최신 패키지 목록을 가져온 후 설치할 수 있게 됩니다.

비대화형 설치 설정

Ubuntu에서는 apt-get install 시에 사용자 입력이 필요할 수 있지만, Docker 빌드 프로세스에서는 대화형 작업을 할 수 없습니다. 따라서 아래와 같이 환경 변수를 설정하고 비대화 모드로 설치하는 것이 권장됩니다.
ENV DEBIAN_FRONTEND=noninteractive
이렇게 하면 패키지 설정 시 표시되는 “지역 설정” 등의 입력을 건너뛰고 원활하게 설치가 진행됩니다.

불필요한 캐시를 삭제하여 경량화하기

APT를 사용하면 다운로드된 임시 파일(캐시)이 이미지 내부에 남아 최종 Docker 이미지가 무거워집니다. 아래와 같이 캐시를 삭제함으로써 이미지 크기를 줄일 수 있습니다.
RUN apt-get update && apt-get install -y 
    curl 
    vim 
    && rm -rf /var/lib/apt/lists/*
이와 같이 여러 명령을 하나의 RUN 문으로 합치는 것으로 불필요한 레이어 증가를 방지할 수도 있습니다.

베스트 프랙티스: Dockerfile 정리 방법

실제 개발 현장에서는 다음과 같은 Dockerfile 작성에 관한 베스트 프랙티스가 권장됩니다:
  • RUN 명령은 가능한 한 합쳐서 레이어 수를 줄인다
  • ENV로 명시적으로 버전 및 설정을 정의한다
  • 주석을 사용해 처리 목적을 명시한다
  • 불필요한 파일을 남기지 않도록 rm이나 --no-install-recommends를 사용한다
예:
RUN apt-get update && apt-get install -y --no-install-recommends 
    curl 
    git 
    && rm -rf /var/lib/apt/lists/*
이와 같이 하면 보다 경량화되고 유지보수가 쉬운 Dockerfile을 구축할 수 있습니다.

4. Docker 이미지 빌드와 확인

Dockerfile에서 Docker 이미지를 빌드하기

Dockerfile을 작성했으면, 다음 단계는 Docker 이미지 빌드입니다. 이는 docker build 명령을 사용하여 수행합니다. Dockerfile이 있는 디렉터리에서 아래 명령을 실행합니다。
docker build -t my-ubuntu-image .
  • -t 옵션은 이미지에 이름(태그)을 붙이기 위한 것입니다. 예에서는 my-ubuntu-image라는 이름을 붙이고 있습니다。
  • .는 Dockerfile이 존재하는 현재 디렉터리를 의미합니다。
이 명령을 실행하면 Docker는 Dockerfile의 명령을 차례대로 읽고, 그에 따라 새로운 이미지를 구축합니다。

빌드한 Docker 이미지 확인

이미지 생성이 완료되면, 다음 명령으로 확인할 수 있습니다。
docker images
이렇게 하면 로컬에 존재하는 Docker 이미지 목록이 표시되고, 아래와 같은 정보들을 확인할 수 있습니다:
  • REPOSITORY(이미지 이름)
  • TAG(태그)
  • IMAGE ID(고유 식별자)
  • CREATED(생성 일시)
  • SIZE(크기)
예:
REPOSITORY        TAG       IMAGE ID       CREATED          SIZE
my-ubuntu-image   latest    abcd1234abcd   5 minutes ago    189MB
이와 같이, 생성한 이미지가 정상적으로 등록되어 있음을 확인할 수 있습니다。

Docker 컨테이너를 실행하여 동작 확인

생성한 이미지가 올바르게 동작하는지 확인하기 위해, Docker 컨테이너를 실행해 봅시다. 아래와 같은 명령을 사용합니다。
docker run -it my-ubuntu-image
  • -it 옵션을 지정하면 인터랙티브 모드로 터미널을 실행할 수 있습니다。
  • 정상적으로 시작되면, 컨테이너 내부의 bash 프롬프트가 표시되어 Ubuntu 환경에 로그인한 것과 같은 상태가 됩니다。
컨테이너 내부에서 아래와 같은 명령을 실행하여, 설치한 도구가 올바르게 동작하는지 확인할 수 있습니다:
curl --version
vim --version
문제가 없으면, Dockerfile의 작성은 성공입니다。

불필요한 이미지와 컨테이너 정리

빌드와 실험을 반복하면, 로컬에 불필요한 Docker 이미지와 컨테이너가 남게 될 수 있습니다. 정기적으로 아래와 같은 명령으로 정리하는 것을 권장합니다。
  • 중지된 컨테이너 삭제:
docker container prune
  • 사용되지 않는 이미지 삭제:
docker image prune
  • 모든 사용되지 않는 데이터(주의!):
docker system prune
이러한 작업을 통해 디스크 용량 절약 및 문제 방지에 도움이 됩니다。

5. 응용: Python 환경 구축

Ubuntu 기반 Dockerfile에서 Python을 사용할 수 있게 하기

Dockerfile을 사용해 Ubuntu 환경을 구축할 때, Python 실행 환경을 추가함으로써 개발·검증·머신러닝 등 다양한 용도에 대응할 수 있습니다. Ubuntu에는 원래 Python이 설치되어 있는 경우도 있지만, 버전 관리와 패키지 관리 관점에서 직접 명시적으로 구축하는 것이 일반적입니다.

apt를 사용하여 Python을 설치하는 방법

가장 간단한 방법은 APT 패키지를 사용해 Python을 설치하는 것입니다. 아래는 그 예시입니다:
FROM ubuntu:24.04

RUN apt-get update && apt-get install -y 
    python3 
    python3-pip 
    && rm -rf /var/lib/apt/lists/*
이 방법으로는 시스템에 설치된 안정 버전의 Python(보통 Python 3.10이나 3.12 등)을 사용할 수 있습니다. 또한, pip 명령으로 Python 패키지를 추가하는 것도 가능합니다。

pyenv로 Python 버전 관리를 수행하기

특정 Python 버전을 사용하고 싶거나, 여러 버전 간 전환을 하고 싶을 때는 pyenv를 사용하는 것이 편리합니다。 아래는 Dockerfile에서 pyenv를 사용해 Python 3.11.6을 설치하는 예시입니다:
FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y 
    git 
    curl 
    make 
    build-essential 
    libssl-dev 
    zlib1g-dev 
    libbz2-dev 
    libreadline-dev 
    libsqlite3-dev 
    wget 
    llvm 
    libncurses5-dev 
    libncursesw5-dev 
    xz-utils 
    tk-dev 
    libffi-dev 
    liblzma-dev 
    && rm -rf /var/lib/apt/lists/*

# pyenv의 설치
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

ENV PYENV_ROOT="$HOME/.pyenv"
ENV PATH="$PYENV_ROOT/bin:$PATH"

RUN echo 'eval "$(pyenv init --path)"' >> ~/.bashrc

# 원하는 Python 버전 설치
RUN pyenv install 3.11.6 && pyenv global 3.11.6
이와 같이 하면 보다 유연하게 Python 환경을 구축·관리할 수 있습니다。

requirements.txt를 사용한 패키지 관리

실제 프로젝트에서는 대부분 여러 Python 라이브러리가 필요합니다. 이를 관리하기 위해 사용되는 것이 requirements.txt입니다。 먼저, 프로젝트 루트 디렉터리에 requirements.txt 파일을 준비합니다:
flask==2.3.2
requests>=2.25.1
pandas
다음으로 Dockerfile에 아래와 같이 기술합니다:
COPY requirements.txt /app/requirements.txt
WORKDIR /app

RUN pip install --no-cache-dir -r requirements.txt
이를 통해 필요한 라이브러리를 한 번에 설치할 수 있어 개발 환경의 재현성이 높아집니다。

베스트 프랙티스

  • Python을 사용할 경우, virtualenvvenv로 가상 환경을 구축하면 의존 관계 충돌을 방지하기 쉽습니다。
  • 캐시 삭제(--no-cache-dir)를 수행하면 Docker 이미지가 경량화됩니다。
  • Python 패키지를 설치하기 전에 pip install --upgrade pip으로 최신 버전으로 업데이트하면 오류를 방지할 수 있습니다。

6. 자주 발생하는 문제와 해결 방법

권한 오류

예:

Permission denied
이는 복사된 파일에 실행 권한이 없거나, 스크립트의 소유자·실행 사용자가 적절하지 않은 경우에 발생합니다.

해결 방법:

  • 파일을 실행 가능하게 만들기:
  RUN chmod +x script.sh
  • 필요에 따라 사용자를 변경하기:
  RUN chown root:root /path/to/file

패키지를 찾을 수 없거나 설치할 수 없음

예:

E: Unable to locate package xxx
이 오류는 apt-get update를 실행하지 않았거나, 지정한 패키지 이름이 잘못된 경우에 발생합니다.

해결 방법:

  • apt-get update를 반드시 install 앞에 작성한다:
  RUN apt-get update && apt-get install -y curl
  • 패키지 이름을 확인하고 오타가 없는지 체크한다

네트워크 관련 오류

예:

Temporary failure resolving 'deb.debian.org'
이러한 오류는 빌드 중 DNS 해석이 원활하지 않은 경우에 발생합니다.

해결 방법:

  • Docker 데몬을 재시작하면 개선될 수 있습니다:
  sudo systemctl restart docker
  • Docker의 DNS 설정을 재검토한다 (/etc/docker/daemon.json에 DNS 지정 추가):
  {
    "dns": ["8.8.8.8", "8.8.4.4"]
  }

캐시 영향으로 오래된 상태 그대로의 빌드

Docker는 속도 향상을 위해 레이어별 캐시를 사용합니다. 그 결과 Dockerfile을 변경해도 의도대로 빌드되지 않을 수 있습니다.

해결 방법:

  • 캐시를 비활성화하고 다시 빌드한다:
  docker build --no-cache -t my-image .

컨테이너 내에서 시작 명령이 실행되지 않거나 바로 종료되는 경우

원인:

  • CMDENTRYPOINT로 지정한 명령이 오류가 발생하고 있다
  • CMD["/bin/bash"] 등을 지정해도 인터랙티브하지 않으면 바로 종료한다

해결 방법:

  • 컨테이너를 디버그용으로 실행하여 확인한다:
  docker run -it my-image /bin/bash
  • CMDENTRYPOINT의 차이를 이해하고 목적에 맞게 사용한다
이러한 문제들을 경험함으로써 Dockerfile 설계 능력은 확실히 향상됩니다. 문제에 직면했을 때는 오류 메시지를 차분히 읽고, 어떤 레이어·어떤 명령이 원인인지 꼼꼼히 추적해 보세요.

7. 요약

Ubuntu 기반 Dockerfile 작성 포인트 재확인

이 기사에서는 Dockerfile을 사용하여 Ubuntu 환경을 구축하는 방법에 대해 기본부터 응용까지 단계적으로 설명했습니다. 여기서 다시 한 번 중요한 포인트를 정리해 보겠습니다.
  • Dockerfile의 기본 구성을 이해하는 것이 첫걸음 FROM, RUN, CMD, ENV 등 명령을 조합하여 환경 구축을 자동화할 수 있습니다.
  • Ubuntu는 안정성·유연성이 높은 베이스 이미지 풍부한 패키지, 넓은 사용자층, LTS 버전의 존재로 인해 개발 환경의 기반으로 적합합니다.
  • 실용적인 패키지 관리를 통해 필요한 도구와 라이브러리를 설치할 수 apt-get 사용법 및 캐시 삭제, 비대화식 설치 등이 핵심이 됩니다.
  • Python과 같은 실용적인 환경 구축도 Dockerfile로 가능 pyenvpip, requirements.txt 같은 도구로 재현성이 높은 개발 환경을 구현할 수 있습니다.
  • 문제 대응 능력이 안정된 운영에 직결된다 권한, 네트워크, 빌드 캐시 등 흔히 걸리는 포인트를 이해함으로써 개발 효율을 크게 향상시킬 수 있습니다.

Dockerfile 학습의 다음 단계

Dockerfile을 다룰 수 있게 되면 개발뿐만 아니라 테스트·프로덕션 환경에 배포 등 다양한 용도에 대응할 수 있게 됩니다. 앞으로의 학습으로는 다음 주제로 진행하면 좋습니다.
  • Docker Compose를 사용한 다중 컨테이너 구성 관리
  • CI/CD 도구(GitHub Actions, GitLab CI 등)와의 연동
  • Kubernetes 등 컨테이너 오케스트레이션 도구와의 연동

공식 문서·참고 링크

8. FAQ(자주 묻는 질문)

Q1. Dockerfile에서 Ubuntu 버전을 어떤 것을 선택해야 할까요?

A1. 기본적으로는 안정성과 장기 지원을 중시하는 경우에는 LTS(Long Term Support)버전을 선택하는 것이 일반적입니다. 예를 들어 ubuntu:22.04ubuntu:20.04는 많은 개발 현장에서 사용되고 있으며, 5년간의 지원 기간이 있어 안심하고 이용할 수 있습니다. 반면에 최신 패키지나 언어 버전을 사용하고 싶은 경우에는 ubuntu:24.04와 같은 새로운 릴리스를 선택할 수도 있지만, 사전 검증을 권장합니다.

Q2. apt-get install에서 “패키지를 찾을 수 없습니다” 라는 메시지가 나오는 이유는 무엇인가요?

A2. 가장 흔한 원인은 apt-get update를 사전에 실행하지 않은 것입니다. 패키지 리스트를 업데이트하지 않고 설치를 시도하면, 오래된 리스트 상태로 해당 패키지를 찾지 못해 오류가 발생합니다. 올바른 작성 예:
RUN apt-get update && apt-get install -y curl
또한, 패키지 이름의 오기나, 더 이상 권장되지 않는 패키지 이름(예: python이 아니라 python3)에도 주의해야 합니다.

Q3. Dockerfile에서 환경 변수를 설정하는 방법은?

A3. 환경 변수는 ENV 명령을 사용하여 설정합니다. 이는 빌드 시 및 컨테이너 실행 시에 유효한 환경 변수가 됩니다. 예:
ENV DEBIAN_FRONTEND=noninteractive
이는 APT 설치 시 대화형 프롬프트를 억제하기 위해 사용되는 전형적인 설정입니다. 또한, 애플리케이션 설정이나 API 키 등을 Dockerfile 내에서 설정할 때 활용됩니다.

Q4. Dockerfile에서 CMDENTRYPOINT의 차이는 무엇인가요?

A4. 둘 다 컨테이너 시작 시 실행되는 명령을 지정하는 것이지만, 사용 방법과 동작에 차이가 있습니다.
항목CMDENTRYPOINT
덮어쓰기 가능성docker run 명령으로 덮어쓰기 가능기본적으로 덮어쓰기되지 않음(인수로 처리)
용도기본 실행 명령을 설정항상 실행하고 싶은 명령을 정의
예:
CMD ["python3", "app.py"]
# vs
ENTRYPOINT ["python3"]
CMD ["app.py"]
후자의 경우, docker run my-image another_script.py 형태로 CMD를 인수로 전달할 수 있습니다.

Q5. Dockerfile을 편집했는데 변경 사항이 반영되지 않습니다. 왜인가요?

A5. Docker는 빌드 시 캐시를 사용하기 때문에, Dockerfile에 작은 변경을 가해도 캐시된 레이어가 그대로 사용되는 경우가 있습니다. 대응 방법:
docker build --no-cache -t my-image .
이렇게 하면 캐시를 사용하지 않고 새로 빌드되어 모든 변경 사항이 반영됩니다.
侍エンジニア塾