IT & Lập trình

Docker Volume & Network: lưu trữ và kết nối container

📚
Phần 5 trong series
Hướng dẫn Docker từ A đến Z
5/8

Container vốn tạm thời (ephemeral) — xóa container là mất dữ liệu bên trong. Vậy database lưu ở đâu? Các container nói chuyện với nhau thế nào? Bài viết này trả lời hai câu hỏi đó qua volumenetwork.

Vấn đề: dữ liệu biến mất khi container bị xóa

Mặc định, mọi thứ container ghi ra đều nằm trong lớp ghi (writable layer) của container đó. Khi container bị xóa, lớp này biến mất theo:

text
docker run postgres → ghi dữ liệu vào container
docker rm postgres  → DỮ LIỆU MẤT SẠCH

Rõ ràng database, file upload, log… cần tồn tại độc lập với vòng đời container. Đó là lý do có volume.

Phần 1: Lưu trữ dữ liệu

Docker có hai cơ chế lưu trữ chính:

text
        ┌──────────────────────────────────────────┐
        │              Container                     │
        │  /var/lib/postgresql/data ───┐             │
        └──────────────────────────────┼────────────┘
              ┌─────────────────────────┴─────────────────┐
              │                                            │
        ┌─────▼──────┐                          ┌──────────▼─────────┐
        │   VOLUME   │                          │    BIND MOUNT      │
        │ Docker quản│                          │ Thư mục cụ thể trên│
        │  lý, an    │                          │  máy host          │
        │  toàn      │                          │ (vd: ./data)       │
        └────────────┘                          └────────────────────┘

Volume (khuyến nghị cho dữ liệu)

Volume do Docker quản lý, lưu ở khu vực riêng trên host. Đây là cách được khuyến nghị để lưu dữ liệu ứng dụng:

bash
# Tạo volume
docker volume create pgdata

# Gắn volume vào container
docker run -d \
  --name db \
  -v pgdata:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

# Bây giờ xóa container, dữ liệu vẫn còn trong volume pgdata
docker rm -f db

# Chạy lại với cùng volume → dữ liệu cũ vẫn nguyên
docker run -d --name db -v pgdata:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret postgres:16

Bind Mount (khuyến nghị cho code lúc dev)

Bind mount gắn một thư mục cụ thể trên máy host vào container. Rất hữu ích khi dev — sửa code trên host, container thấy ngay:

bash
# Mount thư mục code hiện tại vào container
docker run -d \
  --name web \
  -p 3000:3000 \
  -v $(pwd):/app \
  node:20-alpine \
  npm run dev

Volume vs Bind Mount — chọn cái nào?

VolumeBind Mount
Ai quản lýDockerBạn (đường dẫn host cụ thể)
Vị tríKhu vực riêng của DockerThư mục bạn chỉ định
Dùng choDữ liệu app (DB, upload)Code khi dev, file cấu hình
Tính di độngCaoPhụ thuộc đường dẫn host
Khuyến nghịProduction dataDevelopment

Lệnh quản lý volume

bash
# Liệt kê volume
docker volume ls

# Xem chi tiết một volume
docker volume inspect pgdata

# Xóa volume (mất dữ liệu)
docker volume rm pgdata

# Dọn volume không còn container nào dùng
docker volume prune

Phần 2: Network — kết nối container

Trong ứng dụng thực tế, bạn thường có nhiều container: web app, database, cache… Chúng cần giao tiếp với nhau. Đó là việc của Docker network.

Các loại network

LoạiMô tả
bridgeMặc định; container trên cùng bridge network nói chuyện được với nhau
hostContainer dùng chung network của host (không cô lập cổng)
noneContainer không có network

Phần lớn thời gian bạn làm việc với bridge network tự tạo.

Vì sao cần tự tạo network?

Điểm mấu chốt: trên một user-defined bridge network, các container có thể gọi nhau bằng tên (Docker tự lo phần DNS):

text
┌──────────────── network: myapp-net ────────────────┐
│                                                      │
│   ┌──────────┐                  ┌──────────┐         │
│   │  web     │ ──"db:5432"────▶ │   db     │         │
│   │ (app)    │                  │(postgres)│         │
│   └──────────┘                  └──────────┘         │
│   gọi nhau bằng TÊN container, không cần IP           │
└──────────────────────────────────────────────────────┘

Ví dụ: web app kết nối database

bash
# 1. Tạo network riêng
docker network create myapp-net

# 2. Chạy database trên network đó
docker run -d \
  --name db \
  --network myapp-net \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

# 3. Chạy web app trên cùng network
docker run -d \
  --name web \
  --network myapp-net \
  -p 3000:3000 \
  my-app:1.0

Trong code của web, bạn kết nối tới database bằng hostname là db (đúng bằng tên container), ví dụ:

text
DATABASE_URL=postgres://postgres:secret@db:5432/mydb
                              tên container = hostname

Không cần biết IP — Docker tự phân giải db thành đúng IP của container database.

Lệnh quản lý network

bash
# Liệt kê network
docker network ls

# Xem chi tiết (gồm các container đang nối vào)
docker network inspect myapp-net

# Nối / gỡ container khỏi network
docker network connect myapp-net web
docker network disconnect myapp-net web

# Xóa network
docker network rm myapp-net

Ghép lại: một stack hoàn chỉnh

Kết hợp volume + network để chạy một ứng dụng thực tế:

bash
# Network và volume
docker network create shop-net
docker volume create shop-db

# Database: có network + volume bền vững
docker run -d --name shop-db \
  --network shop-net \
  -v shop-db:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

# Web app: cùng network, expose ra ngoài
docker run -d --name shop-web \
  --network shop-net \
  -p 8080:3000 \
  -e DATABASE_URL=postgres://postgres:secret@shop-db:5432/postgres \
  my-shop:1.0

Bạn sẽ nhận ra việc gõ tay nhiều lệnh thế này khá mệt và dễ sai. Đó chính là lý do Docker Compose ra đời — chủ đề của bài tiếp theo.

Tóm tắt

  • Container là tạm thời; dùng volume để lưu dữ liệu bền vững
  • Volume hợp cho dữ liệu app (DB); bind mount hợp cho code khi dev
  • Tạo user-defined network để container gọi nhau bằng tên thay vì IP
  • Volume + network là nền tảng để chạy ứng dụng nhiều container thực tế

Bài trước: ← Dockerfile: tự đóng gói ứng dụng thành image

Bài tiếp theo: Docker Compose: quản lý ứng dụng multi-container →

Phần trước Dockerfile: tự đóng gói ứng dụng thành image Phần tiếp theo Docker Compose: quản lý ứng dụng multi-container
NC
Nguyễn Chung
Senior Automation Test Engineer

5+ năm kinh nghiệm QA & Automation. Đam mê chia sẻ kiến thức về testing, tiếng Anh và tiếng Trung cho developer Việt.