Docker는 컨테이너 기반 애플리케이션을 개발, 배포, 실행하기 위한 플랫폼으로, 리눅스 커널의 네임스페이스와 cgroups를 활용하여 격리된 환경에서 애플리케이션을 실행하며, 이 가이드에서는 우분투 리눅스에서 Docker를 설치하고 첫 컨테이너를 실행하는 전체 과정을 단계별로 설명한다.

Docker 설치 전 요구사항

Docker 설치 요구사항

Docker Engine은 64비트 리눅스 시스템에서 실행되며, 커널 버전 3.10 이상이 필요하다. 우분투의 경우 20.04 LTS, 22.04 LTS, 24.04 LTS 버전이 공식 지원된다.

지원되는 우분투 버전

우분투 버전코드명지원 상태권장 여부
Ubuntu 24.04 LTSNoble Numbat공식 지원권장
Ubuntu 22.04 LTSJammy Jellyfish공식 지원권장
Ubuntu 20.04 LTSFocal Fossa공식 지원지원
Ubuntu 23.10Mantic Minotaur공식 지원비LTS
Ubuntu 18.04 LTSBionic Beaver지원 종료 예정비권장

시스템 아키텍처 지원

Docker는 다양한 CPU 아키텍처를 지원하며, 각 아키텍처에 따라 설치 방법이 약간 다를 수 있다.

아키텍처설명지원 여부
x86_64 / amd64일반적인 데스크탑/서버 CPU완전 지원
arm64 / aarch64ARM 기반 서버 (AWS Graviton, Apple M 시리즈 등)완전 지원
armhf32비트 ARM (Raspberry Pi 등)제한적 지원
s390xIBM Z 시리즈 메인프레임완전 지원

Docker 설치 과정

Step 1: 기존 Docker 패키지 제거

새로운 Docker 설치 전에 시스템에 설치되어 있을 수 있는 비공식 Docker 패키지나 이전 버전을 제거해야 하며, 이는 패키지 충돌을 방지하고 깨끗한 설치 환경을 보장한다.

# 기존 Docker 관련 패키지 제거
sudo apt-get remove docker docker-engine docker.io containerd runc

# 제거 후에도 /var/lib/docker/ 디렉토리의 이미지, 컨테이너, 볼륨은 유지됨
# 완전 삭제가 필요한 경우:
# sudo rm -rf /var/lib/docker
# sudo rm -rf /var/lib/containerd

Step 2: 필수 패키지 설치

Docker 저장소를 HTTPS로 접근하기 위해 필요한 패키지들을 설치한다.

# 패키지 목록 업데이트
sudo apt-get update

# 필수 패키지 설치
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

각 패키지의 역할은 다음과 같다.

패키지역할
apt-transport-httpsAPT가 HTTPS를 통해 패키지를 다운로드할 수 있게 함
ca-certificatesSSL 인증서 검증을 위한 CA 인증서 번들
curlURL을 통한 데이터 전송 도구
gnupgGPG 키 관리 및 서명 검증
lsb-releaseLinux 배포판 정보 확인 유틸리티

Step 3: Docker 공식 GPG 키 추가

Docker 패키지의 무결성과 신뢰성을 검증하기 위해 Docker의 공식 GPG 키를 시스템에 추가해야 하며, 이 키는 패키지가 Docker에 의해 서명되었음을 확인하는 데 사용된다.

# Docker의 공식 GPG 키 다운로드 및 설치
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Step 4: Docker 저장소 추가

Docker 패키지를 다운로드할 저장소를 APT 소스 목록에 추가한다.

# Docker 저장소 추가
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Step 5: Docker Engine 설치

저장소가 추가되면 Docker Engine과 관련 구성 요소를 설치할 수 있다.

# 패키지 목록 업데이트
sudo apt-get update

# Docker Engine, CLI, containerd, Docker Compose 플러그인 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

설치되는 패키지의 역할은 다음과 같다.

패키지역할
docker-ceDocker Engine (Community Edition)
docker-ce-cliDocker 명령줄 인터페이스
containerd.io컨테이너 런타임
docker-buildx-plugin확장된 빌드 기능 (멀티 플랫폼 빌드 등)
docker-compose-pluginDocker Compose V2 플러그인

Docker 설정

비루트 사용자로 Docker 실행

Docker 그룹 권한

기본적으로 Docker 데몬은 root 권한으로 실행되며, docker 명령어도 sudo가 필요하다. 보안과 편의성을 위해 현재 사용자를 docker 그룹에 추가하면 sudo 없이 Docker 명령어를 실행할 수 있다.

# docker 그룹에 현재 사용자 추가
sudo usermod -aG docker $USER

# 그룹 변경 적용 (로그아웃 없이 적용)
newgrp docker

# 또는 시스템 재시작
# sudo reboot

Docker 서비스 관리

Docker 서비스를 시작하고 시스템 부팅 시 자동으로 시작되도록 설정한다.

# Docker 서비스 시작
sudo systemctl start docker

# 부팅 시 자동 시작 설정
sudo systemctl enable docker

# Docker 서비스 상태 확인
sudo systemctl status docker

출력 예시:

● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2025-01-20 10:00:00 KST; 1min ago
       Docs: https://docs.docker.com
   Main PID: 1234 (dockerd)
      Tasks: 10
     Memory: 100.0M
        CPU: 500ms
     CGroup: /system.slice/docker.service
             └─1234 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

설치 확인

Docker 버전 확인

# Docker 버전 확인
docker --version

# 상세 버전 정보
docker version

상세 버전 정보 출력 예시:

Client: Docker Engine - Community
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10
 Git commit:        afdd53b
 Built:             Thu Oct 26 09:07:41 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:       311b9ff
  Built:            Thu Oct 26 09:07:41 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.24
  GitCommit:        61f9fd88f79f081d64d6fa3bb1a0dc71ec870523
 runc:
  Version:          1.1.9
  GitCommit:        v1.1.9-0-gccaecfc
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

hello-world 컨테이너 실행

Docker가 정상적으로 작동하는지 확인하기 위해 공식 hello-world 이미지를 실행한다.

docker run hello-world

출력 예시:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:4bd78111b6914a99dbc560e6a20eab57ff6655aea4a80c50b0c5491968cbc2e6
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

첫 컨테이너 실행하기

Nginx 웹 서버 실행

실용적인 예제로 Nginx 웹 서버 컨테이너를 실행해 보겠다.

# Nginx 컨테이너 실행
docker run -d -p 8080:80 --name my-nginx nginx:latest

이 명령어의 각 옵션 설명은 다음과 같다.

옵션설명
-d백그라운드(detached) 모드로 실행
-p 8080:80호스트의 8080 포트를 컨테이너의 80 포트에 매핑
–name my-nginx컨테이너에 ‘my-nginx’라는 이름 부여
nginx:latest사용할 이미지와 태그 지정

웹 브라우저에서 http://localhost:8080으로 접속하면 Nginx 기본 페이지가 표시된다.

컨테이너 상태 확인

# 실행 중인 컨테이너 목록
docker ps

# 모든 컨테이너 목록 (중지된 컨테이너 포함)
docker ps -a

출력 예시:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                                   NAMES
a1b2c3d4e5f6   nginx:latest   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   my-nginx

컨테이너 로그 확인

# 컨테이너 로그 확인
docker logs my-nginx

# 실시간 로그 스트리밍 (-f: follow)
docker logs -f my-nginx

# 최근 100줄만 표시
docker logs --tail 100 my-nginx

컨테이너 내부 접속

# 컨테이너 내부에서 bash 셸 실행
docker exec -it my-nginx bash

# 컨테이너 내부에서 명령어 실행
docker exec my-nginx cat /etc/nginx/nginx.conf

필수 Docker 명령어

이미지 관리 명령어

# 로컬 이미지 목록 확인
docker images

# 이미지 다운로드 (pull)
docker pull ubuntu:22.04
docker pull python:3.11-slim

# 이미지 검색
docker search nginx

# 이미지 삭제
docker rmi nginx:latest

# 사용하지 않는 이미지 정리
docker image prune

# 모든 미사용 이미지 삭제
docker image prune -a

컨테이너 관리 명령어

# 컨테이너 생성 및 실행
docker run -d --name myapp nginx

# 컨테이너 중지
docker stop my-nginx

# 컨테이너 시작
docker start my-nginx

# 컨테이너 재시작
docker restart my-nginx

# 컨테이너 삭제 (중지된 컨테이너만)
docker rm my-nginx

# 실행 중인 컨테이너 강제 삭제
docker rm -f my-nginx

# 모든 중지된 컨테이너 삭제
docker container prune

시스템 정보 및 정리

# Docker 시스템 정보
docker info

# 디스크 사용량 확인
docker system df

# 상세 디스크 사용량
docker system df -v

# 사용하지 않는 모든 리소스 정리 (이미지, 컨테이너, 네트워크, 캐시)
docker system prune

# 볼륨까지 포함하여 정리
docker system prune --volumes

Docker 네트워크

Docker 네트워크란?

Docker 네트워크는 컨테이너 간 통신을 관리하는 가상 네트워크 인프라로, 컨테이너를 격리하거나 연결하여 마이크로서비스 아키텍처를 구현할 수 있게 한다.

네트워크 유형

네트워크 드라이버설명사용 사례
bridge기본 네트워크, 동일 호스트 내 컨테이너 통신단일 호스트 애플리케이션
host호스트 네트워크 직접 사용, 격리 없음성능이 중요한 애플리케이션
none네트워크 비활성화완전히 격리된 컨테이너
overlay여러 Docker 호스트 간 네트워크Docker Swarm, 멀티 호스트
macvlan컨테이너에 MAC 주소 할당레거시 애플리케이션

네트워크 생성 및 관리

# 네트워크 목록 확인
docker network ls

# 사용자 정의 브리지 네트워크 생성
docker network create my-network

# 서브넷 지정하여 네트워크 생성
docker network create --subnet=172.20.0.0/16 my-custom-network

# 네트워크에 컨테이너 연결하여 실행
docker run -d --name app --network my-network nginx

# 기존 컨테이너를 네트워크에 연결
docker network connect my-network my-nginx

# 네트워크에서 컨테이너 분리
docker network disconnect my-network my-nginx

# 네트워크 상세 정보
docker network inspect my-network

# 네트워크 삭제
docker network rm my-network

컨테이너 간 통신 예제

# 네트워크 생성
docker network create app-network

# 데이터베이스 컨테이너 실행
docker run -d \
    --name mysql-db \
    --network app-network \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=myapp \
    mysql:8.0

# 애플리케이션 컨테이너 실행 (같은 네트워크)
docker run -d \
    --name web-app \
    --network app-network \
    -e DB_HOST=mysql-db \
    -p 8080:8080 \
    my-web-app:latest

# 같은 네트워크 내에서는 컨테이너 이름으로 통신 가능
# web-app 컨테이너에서 mysql-db:3306으로 접속 가능

Docker 볼륨

Docker 볼륨이란?

Docker 볼륨은 컨테이너의 데이터를 영구적으로 저장하기 위한 메커니즘으로, 컨테이너가 삭제되어도 데이터가 유지되며, 여러 컨테이너 간에 데이터를 공유할 수 있다.

데이터 저장 방식 비교

저장 방식설명사용 사례
볼륨 (volume)Docker가 관리하는 저장소프로덕션 데이터베이스, 영구 데이터
바인드 마운트 (bind mount)호스트 파일 시스템의 특정 경로 마운트개발 환경, 설정 파일
tmpfs 마운트메모리에만 저장 (Linux)민감한 임시 데이터

볼륨 생성 및 관리

# 볼륨 목록 확인
docker volume ls

# 볼륨 생성
docker volume create my-data

# 볼륨 상세 정보
docker volume inspect my-data

# 볼륨을 사용하여 컨테이너 실행
docker run -d \
    --name postgres-db \
    -v my-data:/var/lib/postgresql/data \
    -e POSTGRES_PASSWORD=secret \
    postgres:15

# 바인드 마운트 사용 (호스트 디렉토리 연결)
docker run -d \
    --name dev-nginx \
    -v $(pwd)/html:/usr/share/nginx/html:ro \
    -p 8080:80 \
    nginx

# 볼륨 삭제
docker volume rm my-data

# 사용하지 않는 볼륨 정리
docker volume prune

데이터베이스 데이터 영구 저장 예제

# PostgreSQL 데이터를 볼륨에 저장
docker volume create postgres-data

docker run -d \
    --name postgres \
    -v postgres-data:/var/lib/postgresql/data \
    -e POSTGRES_USER=admin \
    -e POSTGRES_PASSWORD=secret \
    -e POSTGRES_DB=myapp \
    -p 5432:5432 \
    postgres:15

# 컨테이너를 삭제해도 데이터는 유지됨
docker rm -f postgres

# 같은 볼륨으로 새 컨테이너 실행하면 데이터 복원
docker run -d \
    --name postgres-new \
    -v postgres-data:/var/lib/postgresql/data \
    -p 5432:5432 \
    postgres:15

문제 해결

Docker 데몬 문제

# Docker 서비스 상태 확인
sudo systemctl status docker

# Docker 데몬 로그 확인
sudo journalctl -u docker.service -f

# Docker 데몬 재시작
sudo systemctl restart docker

권한 문제

# "permission denied" 오류 발생 시
# 1. docker 그룹에 사용자 추가 확인
groups $USER

# 2. 그룹이 없으면 추가
sudo usermod -aG docker $USER

# 3. 재로그인 또는 newgrp 실행
newgrp docker

디스크 공간 부족

# Docker 디스크 사용량 확인
docker system df

# 사용하지 않는 리소스 정리
docker system prune -a --volumes

# 특정 이미지 삭제
docker rmi $(docker images -q -f "dangling=true")

# 중지된 컨테이너 전체 삭제
docker rm $(docker ps -a -q -f "status=exited")

네트워크 문제

# 네트워크 상태 확인
docker network ls
docker network inspect bridge

# 컨테이너 IP 확인
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx

# DNS 해결 테스트
docker run --rm alpine nslookup google.com

다음 단계

Docker 기본 설치와 사용법을 익힌 후에는 다음 주제들을 학습하면 컨테이너 기술을 더 효과적으로 활용할 수 있다.

다음 단계설명
Dockerfile 작성커스텀 이미지 빌드 방법
Docker Compose멀티 컨테이너 애플리케이션 관리
Docker 이미지 최적화이미지 크기 줄이기, 빌드 캐싱
Docker 보안보안 모범 사례, 취약점 스캔
Kubernetes컨테이너 오케스트레이션 플랫폼

결론

Docker 설치는 컨테이너 기술을 시작하는 첫 단계이며, 공식 저장소를 통한 설치가 가장 안정적이고 최신 버전을 유지할 수 있는 방법이다. 기본적인 컨테이너 실행, 이미지 관리, 네트워크 및 볼륨 구성을 익히면 복잡한 마이크로서비스 아키텍처도 효과적으로 구축할 수 있다.

Docker는 개발 환경의 일관성을 보장하고 배포 프로세스를 단순화하며, 리소스 효율성을 높이는 강력한 도구로서 현대 소프트웨어 개발에서 필수적인 기술이 되었다.