绑定挂载 #

什么是绑定挂载? #

绑定挂载(Bind Mount)将主机上的特定目录或文件挂载到容器中。与数据卷不同,绑定挂载直接使用主机文件系统上的路径。

绑定挂载 vs 数据卷 #

text
┌─────────────────────────────────────────────────────┐
│              绑定挂载 vs 数据卷                      │
├─────────────────────────────────────────────────────┤
│                                                     │
│  绑定挂载(Bind Mount):                              │
│  - 使用主机指定路径                                  │
│  - 主机管理文件                                      │
│  - 路径必须存在                                      │
│  - 适合开发环境                                      │
│                                                     │
│  数据卷(Volume):                                    │
│  - Docker管理存储                                    │
│  - 更容易备份和迁移                                  │
│  - 可以使用驱动                                      │
│  - 适合生产环境                                      │
│                                                     │
└─────────────────────────────────────────────────────┘

使用绑定挂载 #

-v 参数 #

bash
# 基本用法
docker run -v /host/path:/container/path nginx

# 相对路径(会自动转换为绝对路径)
docker run -v ./src:/app/src nginx

# 只读挂载
docker run -v /host/path:/container/path:ro nginx

# SELinux标签(Linux)
docker run -v /host/path:/container/path:z nginx    # 共享
docker run -v /host/path:/container/path:Z nginx    # 私有

–mount 参数 #

bash
# 基本用法
docker run --mount type=bind,source=/host/path,target=/container/path nginx

# 只读挂载
docker run --mount type=bind,source=/host/path,target=/container/path,readonly nginx

# 完整示例
docker run --mount \
  type=bind, \
  source=/host/path, \
  target=/container/path, \
  readonly \
  nginx

参数对比 #

bash
# -v 简写
docker run -v /host/path:/container/path:ro nginx

# --mount 完整写法
docker run --mount type=bind,source=/host/path,target=/container/path,readonly nginx

# 区别:
# -v: 如果主机路径不存在,会创建目录
# --mount: 如果主机路径不存在,会报错

开发环境应用 #

代码热更新 #

bash
# Node.js开发环境
docker run -d \
  --name node-dev \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/package.json:/app/package.json \
  -p 3000:3000 \
  node:18 \
  npm run dev

# Python开发环境
docker run -d \
  --name python-dev \
  -v $(pwd)/src:/app \
  -v $(pwd)/requirements.txt:/app/requirements.txt \
  -p 8000:8000 \
  python:3.11 \
  python /app/main.py

前端开发 #

bash
# Vue/React开发
docker run -d \
  --name frontend-dev \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/public:/app/public \
  -v $(pwd)/package.json:/app/package.json \
  -p 8080:8080 \
  node:18 \
  npm run serve

配置文件挂载 #

bash
# Nginx配置
docker run -d \
  --name nginx \
  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v $(pwd)/html:/usr/share/nginx/html:ro \
  -p 80:80 \
  nginx:alpine

# MySQL配置
docker run -d \
  --name mysql \
  -v $(pwd)/my.cnf:/etc/mysql/conf.d/my.cnf:ro \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  mysql:8.0

Docker Compose中使用 #

基本配置 #

yaml
version: '3.8'

services:
  web:
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "80:80"

  app:
    image: node:18
    working_dir: /app
    volumes:
      - ./src:/app/src
      - ./package.json:/app/package.json
    command: npm run dev

开发环境配置 #

yaml
version: '3.8'

services:
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.dev
    volumes:
      - ./frontend/src:/app/src
      - ./frontend/public:/app/public
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.dev
    volumes:
      - ./backend/src:/app/src
      - ./backend/tests:/app/tests
    ports:
      - "8000:8000"
    environment:
      - DEBUG=true

挂载选项 #

只读挂载 #

bash
# 只读挂载
docker run -v /host/path:/container/path:ro nginx
docker run --mount type=bind,source=/host/path,target=/container/path,readonly nginx

SELinux标签 #

bash
# z: 多容器共享
docker run -v /host/path:/container/path:z nginx

# Z: 单容器私有
docker run -v /host/path:/container/path:Z nginx

传播属性 #

bash
# shared: 挂载传播到副本
docker run --mount type=bind,source=/host/path,target=/container/path,bind-propagation=shared nginx

# slave: 接收主挂载的传播
docker run --mount type=bind,source=/host/path,target=/container/path,bind-propagation=slave nginx

# private: 不传播(默认)
docker run --mount type=bind,source=/host/path,target=/container/path,bind-propagation=private nginx

注意事项 #

路径问题 #

bash
# 使用绝对路径(推荐)
docker run -v /home/user/project:/app nginx

# 使用相对路径
docker run -v $(pwd)/project:/app nginx
docker run -v ./project:/app nginx

# Windows路径
docker run -v C:\Users\project:/app nginx
docker run -v /c/Users/project:/app nginx  # Git Bash

权限问题 #

bash
# 容器内用户权限
# 如果容器以非root用户运行,可能需要调整权限

# 方法1: 在Dockerfile中设置用户
FROM node:18
USER node
VOLUME /app/data

# 方法2: 运行时设置用户
docker run --user $(id -u):$(id -g) -v $(pwd)/data:/app/data nginx

# 方法3: 调整主机目录权限
chmod 777 ./data

文件同步问题 #

bash
# 主机文件修改会立即反映到容器
# 容器文件修改会立即反映到主机

# 注意: 删除主机文件会影响容器
# 注意: 容器内删除文件会影响主机

最佳实践 #

1. 开发环境使用绑定挂载 #

yaml
# docker-compose.dev.yml
version: '3.8'

services:
  app:
    build: .
    volumes:
      - ./src:/app/src
      - ./config:/app/config:ro
    environment:
      - NODE_ENV=development

2. 生产环境使用数据卷 #

yaml
# docker-compose.prod.yml
version: '3.8'

services:
  app:
    image: myapp:v1.0
    volumes:
      - app-data:/app/data
    environment:
      - NODE_ENV=production

volumes:
  app-data:

3. 使用.dockerignore #

text
# .dockerignore
node_modules
.git
.env
*.log

4. 避免挂载敏感文件 #

bash
# 不推荐: 挂载.env文件
docker run -v ./.env:/app/.env myapp

# 推荐: 使用环境变量
docker run -e DB_PASSWORD=secret myapp

# 或使用secrets
docker run --secret db_password myapp

小结 #

本节学习了Docker绑定挂载的使用方法:

  • 绑定挂载的概念和特点
  • -v和–mount参数的使用
  • 开发环境中的应用
  • Docker Compose中的配置
  • 注意事项和最佳实践

下一步 #

接下来,让我们学习 数据卷容器,了解容器间数据共享的方法。