参考:https://www.imooc.com/article/26316
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层
如果运行中的容器修改了一个现有的一个已存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本已隐藏,此即“写时复制”机制。
为什么需要存储卷?
这得从 docker 容器的文件系统说起。出于效率等一系列原因,docker 容器的文件系统在宿主机上存在的方式很复杂,这会带来下面几个问题:
- 无法在多个容器之间共享数据。
- 当容器删除时,容器中产生的数据将丢失。
- 为了解决这些问题,docker 引入了数据卷(volume) 机制。数据卷是存在于一个或多个容器中的特定文件或文件夹,这个文件或文件夹以独立于 docker 文件系统的形式存在于宿主机中。数据卷的最大特定是:其生存周期独立于容器的生存周期。
有状态应用:redis(需要持久存储数据),mysql(需要持久存储数据),tomcat(不用持久存储)
无状态应用:nginx(无持久存储)
有状态应用的数据如果放容器上,会有很大麻烦,容器挂了数据就没了,迁移麻烦。
Why Data Volume?
- 关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失。
- 存在的问题:
- 存储于联合文件系统,不易于宿主机访问;
- 荣期间共享数据不便
- 删除容器其数据全部丢失
解决方案:“卷”
- “卷”是容器上的一个或多个目录,此类目录可绕过联合文件系统,与宿主机上某目录“绑定(关联)”。(一个卷是一个目录)
Data volumes
- Data volumes provide several useful features for persistent or shared data
- Volume于容器初始化之时即会创建,由base image 提供的卷中的数据会于此期间完成复制
- Data volumes can be shared and reused among containers
- Changes to a data volume are made directly
- Changes to a data volume will not be included when you updated an image
- Data volumes persist even if the container itself is deleted
- Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时既不会删除卷,也不会对哪怕未引用的卷做垃圾回收操作。
- 卷为docker提供了独立于容器的数据管理机制
- 可以把镜像想象成静态文件,例如“程序”,把卷类比为动态内容,例如“数据”;于是,镜像可以重用,而卷可以共享。
- 卷实现了“程序(镜像)”和“数据(卷)”分离,以及“程序(镜像)”和“制作镜像的主机”分离,用户制作镜像时无需再考虑镜像运行的容器所在的主句环境;
Volume types
Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同。
- Bind mount volume
- a volume that points to a user-specified location on the host file system
- Docker-managed volume
- the docker daemon creates managed volumes in a portion of the host's file system that's owned by Docker
在容器中使用Volumes
为docker run命令使用-v选项即可使用volume
- docker-managed volume
- [root@docker2 ~]# docker container run --name t1 --rm -it -v /data busybox
- [root@docker2 ~]# docker inspect -f {{.Mounts}} t1
- Bind-mount Volume
- [root@docker2 ~]# docker container run --name t1 --rm -it -v /data/volumes/t1:/data busybox
- [root@docker2 _data]# docker inspect t1
docker管理卷
运行容器t1,-v指定挂载卷
[root@docker2 ~]# docker container run --name t1 --rm -it -v /data busybox
/ # ls /
bin data dev etc home proc root sys tmp usr var
/ #
新开终端,查看容器挂载详情:
[root@docker2 ~]# docker inspect -f {{.Mounts}} t1
[{volume f46554c192d70109c2608ae5101d58739a0d6a2fb6fa64830e171ecc91dcc142 /var/lib/docker/volumes/f46554c192d70109c2608ae5101d58739a0d6a2fb6fa64830e171ecc91dcc142/_data /data local true }]
到此目录下面创建文件
[root@docker2 ~]# cd /var/lib/docker/volumes/f46554c192d70109c2608ae5101d58739a0d6a2fb6fa64830e171ecc91dcc142/_data
[root@docker2 _data]# echo hehe>hehe.txt
[root@docker2 _data]# cat hehe.txt
hehe
在容器中查看,有了
/ # ls /data/
hehe.txt
/ # cat /data/hehe.txt
hehe
Bind-mount volumes
创建容器,指定将容器的/data目录挂载到宿主机的/data/volumes/t1
[root@docker2 ~]# docker container run --name t1 --rm -it -v /data/volumes/t1:/data busybox
/ # ls /
bin data dev etc home proc root sys tmp usr var
/ # echo hello > /data/hello.txt
宿主机会自动创建该目录,当容器删除时该目录的文件从仍然存在,不会丢失
[root@docker2 ~]# docker inspect -f {{.Mounts}} t1
[{bind /data/volumes/t1 /data true rprivate}]
[root@docker2 ~]# ls /data/volumes/t1
hello.txt
[root@docker2 ~]# cat /data/volumes/t1/hello.txt
hello
docker inspect的选项:
帮助信息:
[root@docker2 ~]# docker inspect --help
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
-f, --format string Format the output using the given Go template
-s, --size Display total file sizes if the type is container
--type string Return JSON for specified type
使用:
[root@docker2 ~]# docker inspect -f {{.NetworkSettings}} t1
{{ 4d5c3e3e315c80afce68befbbff1045c8638334a543062c5093326546b7dba7b false 0 map[] /var/run/docker/netns/4d5c3e3e315c [] []} {c050ae065505a6fc02657274a3972897729f74553bc6e33997dd6f446986afad 172.17.0.1 0 172.17.0.4 16 02:42:ac:11:00:04} map[bridge:0xc420150000]}
[root@docker2 ~]# docker inspect -f {{.NetworkSettings.IPAddress}} t1
172.17.0.4
两个容器共享宿主机的卷
t1容器已经在运行,现在创建t2容器,共享一个卷
[root@docker2 ~]# docker container run --name t2 --rm -it -v /data/volumes/t1:/data busybox
/ # ls /data
hello.txt
/ # echo t2 container >> /data/hello.txt
....
[root@docker2 ~]# docker container run --name t1 --rm -it -v /data/volumes/t1:/data busybox
/ # cat /data/hello.txt
hello
t2 container
共享卷的两种使用方式
多个容器的卷使用同一个主机目录
• [root@docker1 ~]# docker run --name b1 -it -v /data/docker_volumes/v1:/data --rm busybox
• [root@docker1 ~]# docker run --name b2 -it -v /data/docker_volumes/v1:/data --rm busybox
复制其他容器的卷,为docker run 命令使用--volumes-from选项
• [root@docker1 ~]# docker run --name b1 -it -v /data/docker_volumes/v1:/data busybox
• [root@docker1 ~]# docker run --name b2 -it --volumes-from b1 --rm busybox
如下图
创建基础支撑容器:
• [root@docker1 ~]# docker container run --name infra -it -v /data/infra/volume:/data/web/html busybox
创建nginx容器:
• [root@docker1 ~]# docker container run --name nginx --network container:infra --volumes-from infra -it --rm busybox
创建tomcat:
• [root@docker1 ~]# docker container run --name tomcat --network container:infra --volumes-from infra -it busybox
......
docker compose
docker容器单机编排工具
......