跳转至

💾 Docker 数据卷详解

约 1044 个字 123 行代码 1 张图片 预计阅读时间 7 分钟

数据卷是Docker中用于持久化数据的机制。容器中的数据默认是临时的,容器删除后数据也会丢失。数据卷允许我们将数据存储在主机文件系统或其他容器中,实现数据的持久化。

为什么需要数据卷?

容器内的文件系统是临时的,当容器被删除时,其中的所有数据也会丢失。这对于数据库、文件存储等需要持久化的应用来说是不可接受的。数据卷解决了这个问题,它提供了:

  • 数据持久化:即使容器删除,数据仍然保留
  • 数据共享:多个容器可以共享同一个数据卷
  • 性能:直接访问主机文件系统,性能更好
  • 备份和迁移:可以轻松备份和迁移数据

数据卷的类型

1. 命名卷(Named Volumes)

由Docker管理的卷,存储在Docker的存储目录中。

创建命名卷

Bash
$ docker volume create mydata

查看所有卷

Bash
$ docker volume ls

查看卷详细信息

Bash
$ docker volume inspect mydata

使用命名卷

Bash
$ docker run -d -v mydata:/data --name container1 nginx
$ docker run -d -v mydata:/data --name container2 nginx
# 两个容器共享同一个数据卷

2. 绑定挂载(Bind Mounts)

直接挂载主机文件系统上的目录或文件到容器中。

使用绑定挂载

Bash
# 挂载主机目录到容器
$ docker run -d -v /home/user/data:/data --name web nginx

# 挂载单个文件
$ docker run -d -v /home/user/config.conf:/etc/nginx/conf.d/default.conf nginx

注意

  • 主机路径必须是绝对路径
  • 如果主机目录不存在,Docker会自动创建
  • 如果容器路径已存在,挂载会覆盖原有内容

3. 匿名卷(Anonymous Volumes)

在Dockerfile中使用VOLUME指令或运行时使用-v但不指定名称创建的卷。

Bash
# 创建匿名卷
$ docker run -d -v /data --name container nginx

区别

匿名卷在容器删除后可能被清理,而命名卷会一直保留直到手动删除。

数据卷操作

创建卷

Bash
# 创建命名卷
$ docker volume create mydata

# 创建带标签的卷
$ docker volume create --label project=myapp mydata

查看卷列表

Bash
$ docker volume ls

查看卷详细信息

Bash
$ docker volume inspect mydata

输出示例:

JSON
[
    {
        "CreatedAt": "2023-01-01T00:00:00Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
        "Name": "mydata",
        "Options": {},
        "Scope": "local"
    }
]

删除卷

Bash
# 删除单个卷
$ docker volume rm mydata

# 删除未使用的卷
$ docker volume prune

谨慎操作

docker volume prune会删除所有未被容器使用的卷,请确保数据已备份。

使用数据卷

在docker run中使用

Bash
# 使用命名卷
$ docker run -d -v mydata:/data --name myapp nginx

# 使用绑定挂载
$ docker run -d -v /host/path:/container/path --name myapp nginx

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

在Dockerfile中定义

Docker
FROM nginx
# 定义数据卷
VOLUME /data
VOLUME /var/log

在Docker Compose中使用

YAML
version: '3.8'

services:
  web:
    image: nginx
    volumes:
      # 命名卷
      - web-data:/var/www/html
      # 绑定挂载
      - ./config:/etc/nginx/conf.d
      # 只读挂载
      - ./readonly:/readonly:ro

volumes:
  web-data:

数据卷共享

使用--volumes-from

将一个容器的数据卷共享给另一个容器:

Bash
# 创建数据容器
$ docker run -d --name datacontainer -v /data busybox

# 其他容器使用datacontainer的卷
$ docker run -d --volumes-from datacontainer --name app1 nginx
$ docker run -d --volumes-from datacontainer --name app2 nginx

多个容器共享命名卷

Bash
# 创建命名卷
$ docker volume create shared-data

# 多个容器使用同一个卷
$ docker run -d -v shared-data:/data --name container1 nginx
$ docker run -d -v shared-data:/data --name container2 nginx

实战案例

案例1:MySQL数据持久化

Bash
# 创建MySQL数据卷
$ docker volume create mysql-data

# 运行MySQL并挂载数据卷
$ docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=mypassword \
  mysql:8.0

# 即使删除容器,数据仍然保留
$ docker rm mysql
$ docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=mypassword \
  mysql:8.0
# 数据完全恢复

案例2:开发环境代码挂载

Bash
# 在开发时挂载代码目录
$ docker run -d \
  --name dev-app \
  -v $(pwd)/src:/app/src \
  -p 5000:5000 \
  myapp

# 修改代码后,容器内立即生效(需要应用支持热重载)

案例3:配置文件管理

Bash
# 挂载配置文件
$ docker run -d \
  --name web \
  -v /host/config/nginx.conf:/etc/nginx/nginx.conf:ro \
  -p 80:80 \
  nginx

数据备份和恢复

备份数据卷

Bash
# 备份命名卷
$ docker run --rm \
  -v mydata:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/backup.tar.gz -C /data .

# 备份MySQL数据
$ docker run --rm \
  -v mysql-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/mysql-backup.tar.gz -C /data .

恢复数据卷

Bash
# 恢复命名卷
$ docker run --rm \
  -v mydata:/data \
  -v $(pwd):/backup \
  alpine sh -c "cd /data && tar xzf /backup/backup.tar.gz"

最佳实践

  1. 使用命名卷存储数据:对于需要持久化的应用数据,使用命名卷而不是绑定挂载
  2. 使用绑定挂载存储配置:配置文件通常使用绑定挂载,方便修改
  3. 设置只读挂载:对于不需要修改的目录,使用只读挂载提高安全性
  4. 定期备份:建立定期备份数据卷的机制
  5. 清理未使用的卷:定期清理不再使用的数据卷,释放存储空间

常见问题

Q: 容器删除后数据卷还在吗?

A: 命名卷会一直保留,直到手动删除。匿名卷在容器删除后可能会被清理。

Q: 如何查看数据卷的实际存储位置?

A: 使用docker volume inspect <volume_name>查看Mountpoint字段。

Q: 可以在Dockerfile中指定主机路径吗?

A: 不可以。Dockerfile中的VOLUME只能指定容器路径,这是为了可移植性。主机路径只能在运行时通过-v参数指定。

Q: 如何迁移数据卷?

A: 可以使用备份和恢复的方法,或者直接复制Docker管理的卷目录。

总结

数据卷是Docker中实现数据持久化的关键机制。通过合理使用数据卷,你可以:

  • ✅ 实现数据持久化
  • ✅ 在容器间共享数据
  • ✅ 方便地备份和迁移数据
  • ✅ 提高应用性能

掌握数据卷的使用后,你就可以放心地使用Docker部署需要持久化数据的应用了!

评论