03. Docker Volume & Network
컨테이너 데이터 지속성(Volume)과 네트워크 통신
📚 시리즈 네비게이션
| 이전 | 현재 | 다음 |
|---|---|---|
| Dockerfile & Image | Volume & Network | Docker 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/>볼륨 데이터 유지"]
세 가지 방식
| 방식 | 관리 | 경로 | 용도 |
|---|---|---|---|
| Volume | Docker | /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 nginxBind 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 \
nginxVolume vs Bind Mount 구분:
# 볼륨 (이름만)
-v myvolume:/data
# Bind Mount (경로)
-v /host/path:/data
-v ./local:/datatmpfs (메모리)
메모리에 임시 저장. 컨테이너 종료 시 삭제됨.
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