wuee
Docker · 容器化

Docker Compose 网络与数据卷管理

2026.07 · 预计阅读 8 分钟

Docker Compose 让多容器应用的编排变得简单,但网络通信和数据持久化是两个最容易踩坑的地方。本文通过实际案例深入讲解自定义网络、命名卷、绑定挂载的适用场景和常见陷阱。

一、Docker 网络模型

Docker 提供多种网络驱动,Compose 中最常用的是 bridge(自定义桥接网络)。

网络类型对比

驱动           | 适用场景                  | 容器间DNS解析
--------------|--------------------------|---------------
bridge        | 单机多容器通信            | ✅ 支持容器名解析
host          | 高性能场景,共享宿主机网络  | ❌ 无隔离
overlay       | Swarm 跨主机通信          | ✅ 支持
none          | 完全隔离                  | —

Compose 自定义网络

version: "3.8"
services:
  web:
    image: nginx
    networks:
      - frontend
      - backend

  api:
    image: myapp:latest
    networks:
      - backend
      - db-net

  mysql:
    image: mysql:8
    networks:
      - db-net

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
  db-net:
    driver: bridge
关键点:Docker Compose 默认会创建一个网络,所有服务都加入其中。显式声明多个网络可以实现更细粒度的隔离——web 容器无法直接访问数据库。

二、容器间通信实践

在自定义网络中,容器可以通过服务名(service name)直接通信,无需知道 IP 地址。

# application.yml (Spring Boot)
spring:
  datasource:
    url: jdbc:mysql://mysql:3306/myapp  # 用服务名 mysql,不是 IP
    username: root
    password: ${DB_PASS}

  redis:
    host: redis                        # 服务名解析
    port: 6379

验证容器间通信:

# 进入 web 容器,测试能否 ping 通 api
docker compose exec web ping api

# 查看网络详情
docker network inspect compose_backend

三、数据持久化策略

1. 命名卷(Named Volume)

适合需要 Docker 管理生命周期的数据,如数据库文件。

services:
  mysql:
    image: mysql:8
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:  # Docker 自动创建并管理

2. 绑定挂载(Bind Mount)

适合开发热重载、配置文件注入、日志输出。

services:
  api:
    image: myapp:dev
    volumes:
      - ./logs:/app/logs           # 日志持久化
      - ./config:/app/config:ro    # 只读配置

  # 代码热重载(开发环境)
  spring-app:
    build: .
    volumes:
      - ./src:/app/src           # 代码修改即时生效

3. tmpfs 挂载

适合临时数据,数据不写入磁盘,容器停止后消失。

services:
  app:
    image: myapp
    tmpfs:
      - /tmp

四、常见坑与解决方案

问题 1:卷残留导致存储膨胀

docker compose down 不会删除命名卷。定期清理:

# 查看所有卷
docker volume ls

# 清理未使用的卷
docker volume prune

# 彻底清理(包括网络和卷)
docker compose down -v   # ⚠️ 会删除数据!

问题 2:绑定挂载的权限问题

容器内进程以非 root 用户运行时,挂载的目录权限可能不对。解决方案:

# 方案一:创建目录时指定用户
mkdir -p data && chown -R 1000:1000 data

# 方案二:Dockerfile 中创建目录并授权
RUN mkdir -p /app/data && chown -R appuser:appuser /app/data

# 方案三:使用初始化容器修复权限
services:
  permission-fix:
    image: busybox
    command: chown -R 1000:1000 /data
    volumes:
      - app-data:/data

问题 3:网络冲突

多个 Compose 项目的网络可能冲突。显式指定子网:

networks:
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 10.10.0.0/16

五、完整的 Java 应用部署示例

version: "3.8"
services:
  mysql:
    image: mysql:8
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS}
      MYSQL_DATABASE: myapp
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - backend
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: always

  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: prod
      DB_PASS: ${DB_PASS}
      REDIS_HOST: redis
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    volumes:
      - app-logs:/app/logs
    networks:
      - backend
    restart: always

volumes:
  mysql-data:
  redis-data:
  app-logs:

networks:
  backend:
    driver: bridge
总结:网络方面,善用自定义网络隔离 + 服务名解析;数据卷方面,按场景选择命名卷(持久数据)、绑定挂载(配置/日志)、tmpfs(临时数据)。记住三条原则:敏感数据用环境变量注入、非 root 用户需要处理权限、定期清理无用卷。

延伸阅读:六服务 Docker Compose 编排实战 · 用 Caddy 让所有服务自动接入 HTTPS
← 返回首页