长安的Docker教程长安的Docker教程
首页
快速开始
编程指南
首页
快速开始
编程指南
  • 🎯 Docker入门篇

    • 快速开始
    • Docker是什么?
    • 为什么要用Docker?
    • 安装Docker
    • 第一个容器
  • 📦 Docker基础篇

    • Docker镜像详解
    • 容器操作详解
    • 编写Dockerfile
    • 数据卷(Volumes)
    • Docker网络
  • ⚡ Docker进阶篇

    • Docker Compose
    • 多阶段构建
    • Docker性能优化
    • Docker最佳实践
  • 🚀 实战项目

    • 实战:部署Node.js应用
    • 实战:搭建数据库环境
    • 实战:微服务架构
  • 💡 常见问题

    • 常见问题排查
    • 实用技巧

数据卷(Volumes)

嘿!长安来了!今天咱们聊聊Docker的数据持久化——数据卷!这个很重要,不然你的数据容器一删就没了😱

🤔 为什么需要数据卷?

问题场景

# 运行一个MySQL容器
docker run -d --name mysql mysql:8.0

# 使用了一段时间,存了很多数据...

# 不小心删除容器
docker rm -f mysql

# 💥 完蛋!数据全没了!

容器本来就是临时的,删了就没了。但数据不能丢啊!

解决方案:数据卷

# 使用数据卷
docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# 删除容器
docker rm -f mysql

# 数据还在!重新运行
docker run -d \
  --name mysql \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# ✅ 数据完好无损!

📦 数据卷的三种类型

Docker有三种数据持久化方式:

1. Volume(数据卷)- 推荐!

docker run -v volume-name:/path/in/container my-image

特点:

  • 由Docker管理,存储在/var/lib/docker/volumes/
  • 最安全,最推荐
  • 可以在多个容器间共享
  • 可以用Docker命令管理

2. Bind Mount(绑定挂载)

docker run -v /path/on/host:/path/in/container my-image

特点:

  • 直接挂载宿主机目录
  • 路径必须是绝对路径
  • 宿主机和容器都可以修改文件
  • 适合开发环境

3. tmpfs Mount(临时文件系统)

docker run --tmpfs /path/in/container my-image

特点:

  • 存储在内存中
  • 容器停止后数据消失
  • 适合存储敏感临时数据

三种方式对比

特性VolumeBind Mounttmpfs
数据位置Docker管理宿主机任意位置内存
性能高一般最高
持久化✅✅❌
易用性高一般高
推荐场景生产环境开发环境临时数据

💡 长安建议:生产环境用Volume,开发环境用Bind Mount

📚 Volume(数据卷)详解

创建数据卷

# 创建数据卷
docker volume create my-volume

# 查看所有数据卷
docker volume ls

# 查看数据卷详情
docker volume inspect my-volume

输出:

[
    {
        "CreatedAt": "2024-12-01T10:00:00Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
        "Name": "my-volume",
        "Options": {},
        "Scope": "local"
    }
]

使用数据卷

# 使用已存在的数据卷
docker run -d \
  --name web \
  -v my-volume:/data \
  nginx

# 自动创建数据卷(如果不存在)
docker run -d \
  --name web \
  -v new-volume:/data \
  nginx

删除数据卷

# 删除指定数据卷
docker volume rm my-volume

# 删除所有未使用的数据卷
docker volume prune

# 强制删除
docker volume rm -f my-volume

🔗 Bind Mount(绑定挂载)详解

基本用法

# 挂载目录
docker run -v /path/on/host:/path/in/container my-image

# 只读挂载
docker run -v /path/on/host:/path/in/container:ro my-image

# 使用$(pwd)挂载当前目录
docker run -v $(pwd):/app my-image

实战案例:开发环境

# 挂载代码目录,修改代码立即生效
docker run -d \
  --name dev-web \
  -p 8080:80 \
  -v $(pwd)/html:/usr/share/nginx/html \
  nginx

# 修改本地文件
echo "Hello from 长安!" > html/index.html

# 刷新浏览器,立即看到变化!

太方便了! 适合开发调试。

🎯 实战案例

案例1:MySQL数据持久化

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

# 运行MySQL
docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.0

# 创建数据库和表
docker exec -it mysql mysql -uroot -p123456 -e "
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, '长安');
"

# 删除容器
docker rm -f mysql

# 重新运行(使用同一个数据卷)
docker run -d \
  --name mysql-new \
  -e MYSQL_ROOT_PASSWORD=123456 \
  -v mysql-data:/var/lib/mysql \
  -p 3306:3306 \
  mysql:8.0

# 验证数据还在
docker exec -it mysql-new mysql -uroot -p123456 -e "
USE testdb;
SELECT * FROM users;
"

# 输出:
# +------+--------+
# | id   | name   |
# +------+--------+
# |    1 | 长安   |
# +------+--------+

# ✅ 数据完好!

案例2:Nginx配置和日志

# 创建数据卷
docker volume create nginx-conf
docker volume create nginx-logs

# 运行nginx
docker run -d \
  --name web \
  -p 80:80 \
  -v nginx-conf:/etc/nginx \
  -v nginx-logs:/var/log/nginx \
  nginx

# 查看配置
docker exec web cat /etc/nginx/nginx.conf

# 查看访问日志
docker exec web tail -f /var/log/nginx/access.log

案例3:多容器共享数据

# 创建共享数据卷
docker volume create shared-data

# 容器1:写数据
docker run --rm \
  -v shared-data:/data \
  alpine \
  sh -c "echo '长安在此' > /data/message.txt"

# 容器2:读数据
docker run --rm \
  -v shared-data:/data \
  alpine \
  cat /data/message.txt

# 输出:长安在此

案例4:备份和恢复

备份数据卷:

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

# 生成文件:mysql-backup.tar.gz

恢复数据卷:

# 创建新数据卷
docker volume create mysql-data-restored

# 恢复数据
docker run --rm \
  -v mysql-data-restored:/data \
  -v $(pwd):/backup \
  alpine \
  sh -c "cd /data && tar -xzf /backup/mysql-backup.tar.gz"

# 使用恢复的数据卷
docker run -d \
  --name mysql-restored \
  -v mysql-data-restored:/var/lib/mysql \
  mysql:8.0

🎨 Dockerfile中的VOLUME

在Dockerfile中声明数据卷

FROM nginx
VOLUME /var/log/nginx
VOLUME /usr/share/nginx/html

效果:

docker run -d --name web nginx
docker inspect web | grep -A 10 Mounts

会看到自动创建了匿名数据卷。

匿名数据卷

# 不指定名字,Docker会自动生成
docker run -d -v /data nginx

# 查看
docker volume ls

# 输出类似:
# DRIVER    VOLUME NAME
# local     abc123def456...

问题:名字不友好,难以管理

💡 长安建议:总是使用命名数据卷!

💡 数据卷最佳实践

1. 使用命名数据卷

# ✅ 好
docker run -v mysql-data:/var/lib/mysql mysql

# ❌ 不好(匿名数据卷)
docker run -v /var/lib/mysql mysql

2. 数据卷命名规范

# 项目名-服务-data
myapp-mysql-data
myapp-redis-data
myapp-nginx-logs

# 清晰明了!

3. 定期备份

# 写个备份脚本
#!/bin/bash
DATE=$(date +%Y%m%d)
docker run --rm \
  -v mysql-data:/data \
  -v /backup:/backup \
  alpine \
  tar -czf /backup/mysql-$DATE.tar.gz -C /data .

4. 不要在数据卷中存储代码

# ❌ 不好
-v myapp-code:/app

# ✅ 好(代码应该打包在镜像里)
COPY . /app

数据卷是存数据的,不是存代码的!

5. 使用只读挂载(当适用时)

# 配置文件只读
docker run -v $(pwd)/config.json:/app/config.json:ro nginx

6. 清理未使用的数据卷

# 查看占用空间
docker system df -v

# 清理
docker volume prune

🔍 数据卷位置

Linux

/var/lib/docker/volumes/

查看:

sudo ls /var/lib/docker/volumes/
sudo ls /var/lib/docker/volumes/mysql-data/_data

Mac/Windows(Docker Desktop)

数据卷在虚拟机里,不能直接访问。

查看内容:

# 方法1:通过容器访问
docker run --rm -v mysql-data:/data alpine ls /data

# 方法2:进入Docker Desktop的虚拟机
docker run --rm -it --privileged --pid=host alpine \
  nsenter -t 1 -m -u -n -i sh

# 然后
cd /var/lib/docker/volumes

📊 常用命令速查

# 数据卷管理
docker volume create <name>        # 创建数据卷
docker volume ls                   # 列出数据卷
docker volume inspect <name>       # 查看详情
docker volume rm <name>            # 删除数据卷
docker volume prune                # 清理未使用的数据卷

# 使用数据卷
docker run -v volume:/path         # 命名数据卷
docker run -v /host:/container     # 绑定挂载
docker run -v /host:/container:ro  # 只读挂载

# 查看容器的数据卷
docker inspect <container> | grep -A 10 Mounts

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

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

💡 小结

今天长安教你搞定数据持久化:

核心概念

  1. 为什么需要:容器数据不持久
  2. 三种方式:Volume、Bind Mount、tmpfs
  3. 推荐用法:生产用Volume,开发用Bind Mount
  4. 命名规范:项目名-服务-用途

重要命令

docker volume create      # 创建
docker volume ls          # 列出
docker volume rm          # 删除
docker volume prune       # 清理

docker run -v             # 使用数据卷

最佳实践

  1. 总是使用命名数据卷
  2. 定期备份重要数据
  3. 不要在数据卷中存储代码
  4. 适当使用只读挂载
  5. 定期清理未使用的数据卷

🚀 下一步

数据持久化搞定了!但容器之间怎么通信?下一章长安教你 Docker网络!


💬 长安的血泪教训:

有一次,我没用数据卷,直接在容器里跑了一个月的MySQL。

然后不小心执行了docker rm -f mysql...

一个月的数据,瞬间没了😭

老板问我数据呢?我说...容器删了...

那天我差点被开除。

从那以后,我发誓:重要数据一定用数据卷!

你们可千万别学我,记住了吗?💪

在 GitHub 上编辑此页
Prev
编写Dockerfile
Next
Docker网络