참고 개념

윈도우 환경에서 도커 엔진(Docker Engine)은 컨테이너 기반으로 애플리케이션을 경량화하여 실행하는 반면, VM웨어(VMware)는 완전한 게스트 OS를 포함한 가상 머신(VM)을 구동합니다. 도커는 가볍고 빠르며 호스트 커널을 공유하는 반면, VM웨어는 개별 커널을 가지는 격리된 환경으로 자원을 더 많이 소모하지만 보안성이 높습니다.

핵심 차이점 비교

  • 가상화 방식: 도커는 애플리케이션 단위(컨테이너), VM웨어는 하드웨어 단위(OS 전체) 를 가상화합니다.
  • 애플리케이션 개발 및 배포, 마이크로서비스 아키텍처에는 도커가, 전체 운영 체제를 가상화하거나 격리된 환경이 필요할 때는 VMware가 적합합니다
  • 자원 및 속도: 도커는 호스트 OS의 커널을 공유하여 가볍고 부팅 속도가 수 초 내로 빠르지만, VMware는 게스트 OS를 부팅해야 하므로 무겁고 느립니다.
  • 구조: 도커는 애플리케이션과 종속 항목만 포함하는 반면, VM웨어는 게스트 OS 전체를 가상화하여 훨씬 큰 용량을 차지합니다.
  • 이식성: 도커는 동일한 이미지로 어떤 환경에서든 동일하게 실행되어 이식성이 뛰어나지만, VM웨어는 전체 VM 파일을 이동해야 합니다.

핵심 개념

Docker Engine을 제대로 이해하려면 이 세 가지 요소가 서로 어떻게 상호작용하는지 아는 것이 핵심입니다. 쉽게 비유하자면, 이미지는 '설계도', 컨테이너는 '실제 건물', 볼륨은 '창고'라고 볼 수 있습니다.

💡
비유: 이미지는 붕어빵 틀, 컨테이너는 붕어빵,. 볼륨은 붕어빵을 다 먹어도 남아있는 '접시'
구분 Docker Image Docker Container Docker Volume
성격 실행 파일 / 설계도 실행 중인 프로세스 저장소 (데이터)
가변성 변경 불가능 (Immutable) 변경 가능 (Mutable) 지속적 보존 (Persistent)
생명 주기 삭제 전까지 계속 존재 실행 중 혹은 정지 상태 컨테이너와 독립적으로 존재
주요 역할 환경 배포 및 표준화 애플리케이션 실제 구동 데이터 영속성 관리 및 공유

Docker Image (이미지)

  • 정의: 애플리케이션을 실행하는 데 필요한 모든 것(코드, 런타임, 라이브러리, 설정 등)을 포함한 읽기 전용(Read-Only) 템플릿입니다.
  • 레이어 구조: 이미지는 여러 개의 읽기 전용 레이어가 쌓인 구조입니다. FROM ubuntuRUN apt-get install 등 Dockerfile의 각 명령어가 하나의 레이어를 생성합니다. 레이어는 캐싱되므로 변경된 레이어 이후만 재빌드됩니다.
  • 특징: 상태를 가지지 않으며(Stateless), 한 번 만들어지면 변하지 않습니다.

주요 CLI 명령어:

bash
# 이미지 목록 확인
docker images

# Docker Hub에서 이미지 내려받기
docker pull nginx:latest

# Dockerfile로 이미지 빌드 (현재 디렉토리 기준)
docker build -t my-app:1.0 .

# 이미지 레이어 내역 확인
docker history nginx:latest

# 이미지 삭제
docker rmi nginx:latest

# 사용하지 않는 이미지 전체 삭제
docker image prune -a

Docker Container (컨테이너)

  • 정의: 이미지를 실행한 상태입니다. 이미지라는 설계도를 바탕으로 실제로 메모리 위에 올라가 동작하는 프로세스입니다.
  • 쓰기 레이어(Writable Layer): 컨테이너 실행 시, 읽기 전용 이미지 레이어 위에 얇은 쓰기 가능 레이어가 추가됩니다. 컨테이너 내 파일 변경은 이 레이어에만 기록되며, 컨테이너 삭제 시 함께 사라집니다.
  • 생명 주기: created → running → paused → stopped → removed 단계를 거칩니다.

주요 CLI 명령어:

bash
# 컨테이너 실행 (백그라운드, 포트 매핑, 이름 지정)
docker run -d -p 8080:80 --name my-nginx nginx:latest

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

# 전체 컨테이너 목록 (정지 포함)
docker ps -a

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

# 실행 중인 컨테이너 내부 접속
docker exec -it my-nginx /bin/bash

# 컨테이너 정지 / 재시작 / 삭제
docker stop my-nginx
docker restart my-nginx
docker rm my-nginx

# 정지된 컨테이너 전체 삭제
docker container prune

Docker Volume (볼륨)

  • 정의: 컨테이너의 데이터를 영구적으로 저장하기 위해 사용하는 외부 저장 공간입니다.
  • 특징: 컨테이너가 삭제되어도 데이터가 보존됩니다. DB 데이터, 로그, 업로드 파일 등에 필수적입니다.

스토리지 마운트 3가지 비교:

타입 저장 위치 관리 주체 주요 용도
Volume Docker 관리 영역 (/var/lib/docker/volumes/) Docker DB 데이터, 영속 데이터 (권장)
Bind Mount 호스트 임의 경로 사용자 로컬 개발, 소스코드 실시간 반영
tmpfs Mount 메모리(RAM) OS 민감 정보 임시 저장, 재시작 시 소멸

주요 CLI 명령어:

bash
# 볼륨 생성
docker volume create my-data

# 볼륨 목록 확인
docker volume ls

# 볼륨 상세 정보 확인 (마운트 경로 등)
docker volume inspect my-data

# 볼륨을 마운트하여 컨테이너 실행
docker run -d -v my-docker-volumn:/var/lib/mysql --name my-mariadb mariadb:latest

# Bind Mount 방식 (개발 환경)
docker run -d -v C:/myapp:/usr/share/nginx/html -p 8080:80 nginx

# 미사용 볼륨 삭제
docker volume prune

# 특정 볼륨 삭제
docker volume rm my-docker-volume

이들의 유기적인 관계

flowchart LR A["Dockerfile"] -->|"docker build"| B["Image (Read-Only Layers)"] B -->|"docker run"| C["Container\n(Image + Writable Layer)"] C <-->|"mount"| D["Volume\n(Persistent Data)"] C -->|"container 삭제 시 소멸"| E["Writable Layer 제거"] D -->|"컨테이너 삭제 후에도 보존"| D
  1. 사용자가 Dockerfile을 빌드하여 이미지를 생성합니다.
  2. docker run 명령어로 이미지를 기반으로 하나 이상의 컨테이너를 실행합니다.
  3. 컨테이너 내부에서 생성되는 중요 데이터는 볼륨에 저장하여, 컨테이너를 업데이트하거나 재생성해도 데이터를 유지합니다.

ClassicPress (PHP/MariaDB) 실습부터 완전 삭제까지

실습 환경

  • Windows OS
  • Docker Desktop for Windows (WSL2 백엔드)
  • C 드라이브 잔여 공간: 20GB
⚠️
WSL2 용량 주의: WSL2는 기본적으로 가상 디스크(.vhdx) 파일을 생성하며, 데이터를 삭제해도 이 파일의 크기가 자동으로 줄어들지 않습니다. 실습 후 반드시 아래 3단계(디스크 압축)를 수행해야 용량이 회수됩니다.

1단계: 실습 전 — WSL2/Docker 용량 확보 및 설정

Windows 사전 요구사항: 기능 활성화

Docker Desktop for Windows를 사용하려면 아래 두 가지 중 하나를 활성화해야 합니다.

  • 제어판 → 프로그램 → Windows 기능 켜기/끄기 에서 아래 항목 체크:
  • 설정 후 재부팅 필요

WSL2 활성화 (PowerShell 관리자 권한)

powershell
# WSL2 설치 (미설치 시)
wsl --install

# 기본 버전을 WSL2로 설정
wsl --set-default-version 2

# 설치된 배포판 및 버전 확인
wsl -l -v

WSL2 vs Hyper-V 백엔드 선택

💡
Docker Desktop은 두 백엔드 모두 동일한 기능을 제공하며, 어느 쪽이 더 낫다고 단정하기 어렵습니다. 다만 WSL2 백엔드는 다중 사용자 환경에서 주의가 필요합니다.

가상 디스크 위치 이동 (선택 사항)

C 드라이브 외 다른 드라이브(D:, E: 등)에 여유가 있다면 WSL2 데이터 저장소를 옮기는 것이 가장 효율적입니다. C 드라이브만 사용해야 한다면 아래 .wslconfig 설정을 반드시 적용하세요.

.wslconfig 설정 — 메모리 및 스왑 제한

Windows 사용자 폴더(C:\Users\사용자명)에 .wslconfig 파일을 생성하고 아래 내용을 입력합니다.

plain text
[wsl2]
# WSL2에 할당할 최대 RAM (전체 RAM의 50% 이하 권장)
memory=4GB

# 스왑 파일 크기 (0으로 설정하면 스왑 없음)
swap=2GB

# 프로세서 코어 수 제한
processors=2

# 가상 디스크 최대 크기 (기본값 1TB → 축소)
[wsl2]
localhostForwarding=true

설정 적용: PowerShell에서 wsl --shutdown 후 Docker Desktop 재시작.

2단계: ClassicPress 실습 — Docker Compose 활용

ClassicPress는 WordPress 포크 버전입니다. docker compose를 이용해 PHP와 DB 컨테이너를 묶어 실행하면 나중에 한 번에 정리하기 쉽습니다.

실습 환경 구축 단계

  1. 작업 폴더 생성: C:\test-classicpress
  2. 아래 docker-compose.yml 파일을 작성합니다.
💡
MySQL 대신 MariaDB를 사용하는 이유
yaml
services:
  db:
    image: mariadb:10.11
    container_name: cp_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: classicpress
      MYSQL_USER: cpuser
      MYSQL_PASSWORD: cppassword
    volumes:
      - db_data:/var/lib/mysql
    # MariaDB 메모리 사용량 최소화
    command: --innodb-buffer-pool-size=64M --innodb-log-file-size=16M

  wordpress:
    image: wordpress:php8.2-apache
    container_name: cp_web
    restart: unless-stopped
    depends_on:
      - db
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: classicpress
      WORDPRESS_DB_USER: cpuser
      WORDPRESS_DB_PASSWORD: cppassword
    volumes:
      - wp_data:/var/www/html

volumes:
  db_data:
  wp_data:
  1. 실행:
bash
# 작업 폴더로 이동
cd C:\test-classicpress

# 백그라운드에서 컨테이너 실행
docker compose up -d

# 실행 상태 확인
docker compose ps

# 로그 확인
docker compose logs -f
  1. 브라우저에서 http://localhost:8080 접속 → WordPress 설치 화면에서 ClassicPress Migration Plugin 설치 후 마이그레이션 진행.
💡
ClassicPress 설치 방법: WordPress를 먼저 설치한 뒤, 플러그인 검색에서 "ClassicPress Migration" 플러그인을 설치하고 마이그레이션 버튼을 클릭하면 ClassicPress로 전환됩니다.

3단계: 실습 후 — 흔적 없는 완전 삭제 프로세스

실습이 끝난 후, 단순히 컨테이너를 끄는 것만으로는 디스크 용량이 확보되지 않습니다. 아래 3단계를 순서대로 진행합니다.

① Docker 리소스 정리

bash
# 컨테이너 + 볼륨 + 이미지 한 번에 삭제
docker compose down -v --rmi all
# -v : 볼륨(DB 데이터 등) 삭제
# --rmi all : 사용된 이미지 전부 제거

# 잔여 리소스가 있다면 전체 강제 정리
docker system prune -a --volumes

# 정리 결과 확인 (용량 통계)
docker system df

② WSL2 가상 디스크 용량 회수 (핵심 단계)

Docker 리소스를 삭제해도 WSL2의 .vhdx 파일 크기는 자동으로 줄어들지 않습니다. 아래 절차로 수동 압축이 필요합니다.

powershell
# 1. Docker Desktop 완전 종료 (시스템 트레이 우클릭 → Quit)

# 2. WSL 완전 종료 (PowerShell 관리자 권한)
wsl --shutdown

# 3. diskpart로 가상 디스크 압축
# PowerShell(관리자)에서 diskpart 실행
diskpart

diskpart 프롬프트 진입 후:

javascript
# ext4.vhdx 경로 예시 (사용자명과 Docker 버전에 따라 다름)
# 일반적인 경로: C:\Users\사용자명\AppData\Local\Docker\wsl\data\ext4.vhdx
# 또는: C:\Users\사용자명\AppData\Local\Packages\CanonicalGroupLimited...\LocalState\ext4.vhdx

select vdisk file="C:\Users\사용자명\AppData\Local\Docker\wsl\data\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit
🔍
정확한 경로 확인 방법: PowerShell에서 wsl -l -v로 배포판 이름 확인 후, %LOCALAPPDATA%\Docker\wsl\data\ 또는 %LOCALAPPDATA%\Packages\ 아래에서 ext4.vhdx를 검색합니다.

③ Docker Desktop 데이터 루트 정리 (선택 사항)

Docker Desktop 설정(Settings → Resources → Advanced)에서 Disk image location을 D: 등 다른 드라이브로 변경하면 향후 이미지/볼륨이 C 드라이브를 잠식하는 것을 방지할 수 있습니다.

4단계: 추가 팁

docker-compose.yml 주요 옵션 정리

옵션 설명 예시
restart 컨테이너 재시작 정책 unless-stopped, always, on-failure
depends_on 서비스 시작 순서 제어 depends_on: - db
environment 환경 변수 주입 MYSQL_ROOT_PASSWORD: secret
volumes Named Volume 또는 Bind Mount db_data:/var/lib/mysql
ports 호스트:컨테이너 포트 매핑 "8080:80"
command 컨테이너 기본 명령 오버라이드 --innodb-buffer-pool-size=64M

Windows에서 정확한 ext4.vhdx 경로 찾기

powershell
# 방법 1: 직접 검색
Get-ChildItem -Path $env:LOCALAPPDATA -Recurse -Filter "ext4.vhdx" -ErrorAction SilentlyContinue | Select-Object FullName

# 방법 2: Docker Desktop WSL 데이터 기본 경로
ls "$env:LOCALAPPDATA\Docker\wsl\data\"

임시 파일 정리 (Temporary Files)

powershell
# Docker 관련 임시 파일 경로
$tempPath = "$env:LOCALAPPDATA\Temp"

# 10일 이상 된 파일 삭제
Get-ChildItem -Path $tempPath -Recurse | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-10) } | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue

전체 디스크 사용량 확인 (정리 전후 비교)

bash
# Docker 리소스별 용량 확인
docker system df -v

# 이미지별 크기 상세 확인
docker images --format "table .Repository\t.Tag\t.Size"