Docker 数据卷:容器删了,数据去哪了
昨天用 Compose 一组命令跑起多容器服务时,有个问题没展开:容器里的数据库、上传文件、日志,容器一删还在不在?答案取决于数据放在哪里。先做一个最直观的实验。
1. 先看默认情况:数据跟着容器走
docker run -d --name mydb -e MYSQL_ROOT_PASSWORD=123456 mysql:8
docker exec mydb sh -c "echo hello > /tmp/test.txt"
docker rm -f mydb
容器删了,/tmp/test.txt 也没了。容器层本身就是临时的:写进容器可写层的数据,容器删除即丢,重启也不一定保得住。这就是为什么生产里不能把数据库直接装在容器里裸跑。
2. 数据卷:把数据放到容器外面
docker volume create mydata
docker run -d --name mydb -v mydata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8
这时 /var/lib/mysql 实际落在宿主机的卷目录里(可用 docker volume inspect mydata 看到 Mountpoint)。再删容器试一次:
docker rm -f mydb
docker volume ls # mydata 还在
docker run -d --name mydb2 -v mydata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:8
新容器挂同一个卷,数据还在。结论很简单:容器是临时的,卷是持久的;删容器不删卷,除非你显式 docker volume rm。
3. 三种挂载,别混着用
| 方式 | 写法 | 适合放什么 |
|---|---|---|
| 数据卷 volume | -v mydata:/var/lib/mysql |
数据库、需要持久化又不想管路径的数据 |
| 绑定挂载 bind | -v /home/sven/app:/app |
开发时改代码即生效、配置文件 |
| 临时挂载 tmpfs | --tmpfs /run |
敏感临时数据,容器停了就消失 |
新手最常见的坑有两个:一是把代码目录用 volume 挂了,结果宿主机改了代码容器里看不到(因为卷第一次挂载会把容器里的内容拷出来,之后以卷为准);二是备份时只备份了容器,忘了卷——docker ps 看不到卷,docker volume ls 才能看到。
4. 备份卷,一条命令就够
docker run --rm -v mydata:/data -v $(pwd):/backup busybox tar czf /backup/mydata.tar.gz -C /data .
恢复时反向解压回同一个卷即可。记住顺序:先停掉正在写这个卷的容器,再备份,否则可能拷到写一半的文件。
5. Compose 里的写法
services:
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: "123456"
volumes:
- mydata:/var/lib/mysql
volumes:
mydata:
顶层 volumes: 声明一次,服务里引用即可;docker compose down 默认不删卷,docker compose down -v 才会连卷一起删——这就是很多人“down 一下数据全没了”的原因,-v 要慎用。
一句话总结
容器负责跑,卷负责存:要删容器随便删,要删数据必须显式删卷;分清这两层,Docker 的数据问题就少了一大半。
- 点赞
- 收藏
- 关注作者
评论(0)