03. Docker Volume & Network

컨테이너 데이터 지속성(Volume)과 네트워크 통신


📚 시리즈 네비게이션

이전현재다음
Dockerfile & ImageVolume & NetworkDocker Compose

시리즈 목차


📦 Volume (볼륨)

왜 필요한가?

컨테이너는 일시적(ephemeral) 임.

flowchart TB
    subgraph Without["볼륨 없이"]
        C1["Container"]
        D1["Data"]
        C1 --- D1
        D1 -.->|"컨테이너 삭제 시<br/>함께 삭제됨!"| X1["❌"]
    end

볼륨 사용 시:

flowchart TB
    subgraph With["볼륨 사용"]
        CA["Container A"]
        CB["Container B"]
        Vol["Volume<br/>(Data)"]
        
        CA --> Vol
        CB --> Vol
    end
    
    Note["컨테이너 삭제해도<br/>볼륨 데이터 유지"]

세 가지 방식

방식관리경로용도
VolumeDocker/var/lib/docker/volumes/운영 환경 권장
Bind Mount사용자호스트 임의 경로개발 환경, 설정 파일
tmpfs메모리메모리임시 데이터, 보안

Volume (Docker 관리)

# 볼륨 생성
docker volume create mydata
 
# 볼륨 목록
docker volume ls
 
# 볼륨 상세 정보
docker volume inspect mydata
 
# 볼륨 삭제
docker volume rm mydata
 
# 미사용 볼륨 정리
docker volume prune

컨테이너에 연결:

# -v 옵션 (볼륨명:컨테이너경로)
docker run -d \
    --name db \
    -v mydata:/var/lib/mysql \
    mysql:8.0
 
# --mount 옵션 (더 명시적)
docker run -d \
    --name db \
    --mount source=mydata,target=/var/lib/mysql \
    mysql:8.0

자동 생성:

# 볼륨이 없으면 자동 생성
docker run -d -v newvolume:/data nginx

Bind Mount (호스트 경로)

호스트의 특정 디렉토리를 컨테이너에 마운트.

# -v 옵션 (호스트경로:컨테이너경로)
docker run -d \
    -v /home/user/html:/usr/share/nginx/html \
    nginx
 
# --mount 옵션
docker run -d \
    --mount type=bind,source=/home/user/html,target=/usr/share/nginx/html \
    nginx
 
# 읽기 전용
docker run -d \
    -v /home/user/html:/usr/share/nginx/html:ro \
    nginx

Volume vs Bind Mount 구분:

# 볼륨 (이름만)
-v myvolume:/data
 
# Bind Mount (경로)
-v /host/path:/data
-v ./local:/data

tmpfs (메모리)

메모리에 임시 저장. 컨테이너 종료 시 삭제됨.

docker run -d \
    --tmpfs /tmp \
    nginx
 
# 또는
docker run -d \
    --mount type=tmpfs,target=/tmp,tmpfs-size=100m \
    nginx

용도:

  • 임시 파일
  • 민감한 데이터 (비밀번호 파일 등)
  • 빠른 I/O 필요

실습: MySQL 데이터 유지

# 볼륨 생성
docker volume create mysql-data
 
# MySQL 실행 (볼륨 연결)
docker run -d \
    --name mysql-test \
    -e MYSQL_ROOT_PASSWORD=secret \
    -v mysql-data:/var/lib/mysql \
    mysql:8.0
 
# 데이터 생성
docker exec -it mysql-test mysql -u root -psecret -e "
  CREATE DATABASE testdb;
  USE testdb;
  CREATE TABLE users (id INT, name VARCHAR(50));
  INSERT INTO users VALUES (1, 'Alice');
"
 
# 컨테이너 삭제
docker rm -f mysql-test
 
# 새 컨테이너로 같은 볼륨 연결
docker run -d \
    --name mysql-test2 \
    -e MYSQL_ROOT_PASSWORD=secret \
    -v mysql-data:/var/lib/mysql \
    mysql:8.0
 
# 데이터 확인 (유지됨!)
docker exec -it mysql-test2 mysql -u root -psecret -e "SELECT * FROM testdb.users;"
# +------+-------+
# | id   | name  |
# +------+-------+
# |    1 | Alice |
# +------+-------+
 
# 정리
docker rm -f mysql-test2
docker volume rm mysql-data

🌐 Network (네트워크)

왜 필요한가?

컨테이너 간 통신, 외부 연결을 위해 필요함.

flowchart TB
    subgraph Network["Docker Network"]
        nginx["nginx<br/>:80"]
        app["app<br/>:3000"]
        mysql["mysql<br/>:3306"]
        
        nginx <--> app
        app <--> mysql
    end

네트워크 드라이버

드라이버설명용도
bridge기본, 독립된 네트워크단일 호스트
host호스트 네트워크 직접 사용성능, 포트 매핑 불필요
none네트워크 없음격리된 컨테이너
overlay다중 호스트 연결Swarm, 클러스터
macvlan물리 네트워크에 직접 연결레거시 앱

Bridge 네트워크

기본 bridge (docker0)

# 기본 네트워크로 실행
docker run -d --name web nginx
 
# IP 확인
docker inspect web | grep IPAddress
# "IPAddress": "172.17.0.2"
 
# 다른 컨테이너에서 접근
docker run --rm alpine ping -c 3 172.17.0.2

⚠️ 기본 bridge에서는 컨테이너 이름으로 통신 불가.

사용자 정의 bridge (권장)

# 네트워크 생성
docker network create mynet
 
# 네트워크 목록
docker network ls
 
# 컨테이너 실행 (네트워크 지정)
docker run -d --name web --network mynet nginx
docker run -d --name app --network mynet alpine sleep 3600
 
# 컨테이너 이름으로 통신 가능!
docker exec app ping -c 3 web
# PING web (172.18.0.2): 56 data bytes
# 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.089 ms
 
# 네트워크 상세
docker network inspect mynet
 
# 정리
docker rm -f web app
docker network rm mynet

사용자 정의 bridge 장점:

  • 컨테이너 이름으로 DNS 해석
  • 더 나은 격리
  • 실행 중 네트워크 연결/분리 가능

Host 네트워크

호스트의 네트워크를 직접 사용함.

docker run -d --network host nginx
 
# 포트 매핑 없이 호스트의 80 포트 사용
curl http://localhost:80

특징:

  • 포트 매핑 불필요 (-p 옵션 무시됨)
  • 네트워크 성능 좋음
  • 포트 충돌 주의
  • Linux에서만 완전 지원

None 네트워크

네트워크 완전 격리.

docker run -d --network none alpine sleep 3600
 
# 네트워크 없음
docker exec <container> ip addr
# lo만 존재

네트워크 명령어

# 네트워크 목록
docker network ls
 
# 네트워크 생성
docker network create mynet
docker network create --driver bridge --subnet 10.10.0.0/16 mynet
 
# 네트워크 상세
docker network inspect mynet
 
# 실행 중인 컨테이너에 네트워크 연결
docker network connect mynet container_name
 
# 네트워크 연결 해제
docker network disconnect mynet container_name
 
# 네트워크 삭제
docker network rm mynet
 
# 미사용 네트워크 정리
docker network prune

실습: 3-Tier 네트워크

# 네트워크 생성
docker network create app-net
 
# MySQL (DB)
docker run -d \
    --name db \
    --network app-net \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=appdb \
    mysql:8.0
 
# App (Backend) - DB 연결
docker run -d \
    --name app \
    --network app-net \
    -e DB_HOST=db \
    -e DB_PORT=3306 \
    node:18-alpine sleep 3600
 
# Nginx (Frontend)
docker run -d \
    --name web \
    --network app-net \
    -p 8080:80 \
    nginx
 
# 연결 테스트
docker exec app ping -c 2 db
docker exec app ping -c 2 web
docker exec web ping -c 2 app
 
# 정리
docker rm -f web app db
docker network rm app-net

🔌 포트 매핑

기본 문법

# -p 호스트포트:컨테이너포트
docker run -d -p 8080:80 nginx
 
# 여러 포트
docker run -d -p 8080:80 -p 8443:443 nginx
 
# 특정 IP
docker run -d -p 127.0.0.1:8080:80 nginx
 
# 랜덤 포트
docker run -d -p 80 nginx
docker port <container>  # 할당된 포트 확인
 
# UDP
docker run -d -p 53:53/udp dns-server

포트 확인

# 컨테이너 포트 매핑 확인
docker port <container>
 
# 또는
docker ps
# PORTS: 0.0.0.0:8080->80/tcp

📋 Volume 명령어 요약

# 볼륨
docker volume create <n>
docker volume ls
docker volume inspect <n>
docker volume rm <n>
docker volume prune
 
# 컨테이너에 연결
-v <volume>:<path>              # 볼륨
-v <host_path>:<path>           # Bind mount
-v <volume>:<path>:ro           # 읽기 전용
--mount source=<vol>,target=<path>

📋 Network 명령어 요약

# 네트워크
docker network create <n>
docker network ls
docker network inspect <n>
docker network rm <n>
docker network prune
 
# 연결
docker network connect <net> <container>
docker network disconnect <net> <container>
 
# 실행 시 지정
--network <n>
--network host
--network none

🔗 시리즈 네비게이션

시리즈 목차로 돌아가기


🔗 참고 자료