其他文章:
----------------------------------------------------------------
六、数据卷
解决容器和系统的资源隔离问题。
什么是数据卷
docker中的数据如何保存?
如果数据都放在容器内部,容器删除后,数据就会丢失了。需求:数据可以持久化。
如果安装了一个mysql容器,容器删除,数据必须还在。需求:容器数据存在的宿主机。
什么是数据卷技术?容器直接可以有一个数据共享技术,docker容器中产生的数据,同步到本地宿主机。这就是数据卷技术。使用目录挂载,将容器内部的目录挂载到linux上即可。
总结:数据卷解决容器数据的持久化和同步操作!容器之间也可以数据共享!
如何使用数据卷
方式一:直接使用命令挂载 -v
[root@localhost ~]#
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]#
[root@localhost ~]# ls /local # 宿主机没有该目录
ls: cannot access /local: No such file or directory
[root@localhost ~]#
# 使用-v挂载,将宿主机的/local目录和容器的/home目录进行映射
[root@localhost ~]# docker run -it -v /local:/home centos /bin/bash
[root@bc9c7875eb78 /]#
[root@bc9c7875eb78 /]# ls /home/ # 查看容器内的/home目录
[root@bc9c7875eb78 /]#
[root@bc9c7875eb78 /]# touch /home/test.java # 在home下面创建文件
[root@bc9c7875eb78 /]#
[root@bc9c7875eb78 /]# ls /home/
test.java
[root@bc9c7875eb78 /]#
# 宿主机查看结果
[root@localhost ~]# ls /local/ # 容器启动后会自动创建该目录
test.java
[root@localhost ~]#
# 容器停止后,依然可以通过宿主机操作该目录。当容器重启后可以看到相关的修改。数据会自动同步。
# 查看容器挂载信息
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5992d9af84d centos "/bin/bash" 31 seconds ago Up 30 seconds sharp_ramanujan
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# docker inspect b5992d9af84d # 查看容器信息
"Mounts": [
{
"Type": "bind",
"Source": "/local", # 宿主机地址
"Destination": "/home", # docker内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
实战:安装mysql
容器中/data目录是存储mysql的数据的,需要将/data目录挂载到宿主机上,防止数据丢失。
注意点:1.将配置文件映射出来;2.将数据映射出来;3.密码处理
[root@localhost ~]# docker run -d -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
即使使用docker rm 容器id
删除了容器,mysql的数据依然存在。
直接挂载分两种:匿名挂载和具名挂载
# -v /宿主机目录:/容器目录 # 这是直接将两个目录进行映射 目录都以/开头
# -v /容器目录 # 这是匿名挂载
# -v 挂载名称:/容器目录 # 这是具名挂载 挂载名称不以/开头
# 查看卷信息 docker volume
[root@localhost docker]# docker volume --help
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
[root@localhost docker]#
[root@localhost docker]#
[root@localhost docker]#
[root@localhost docker]# docker volume ls # 目前不存在卷
DRIVER VOLUME NAME
[root@localhost docker]#
# 匿名挂载
[root@localhost docker]#
[root@localhost docker]# docker run -P -d -v /etc/nginx --name nginx01 nginx # 匿名挂载
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
f7ec5a41d630: Already exists
aa1efa14b3bf: Pull complete
b78b95af9b17: Pull complete
c7d6bca2b8dc: Pull complete
cf16cd8e71e0: Pull complete
0241c68333ef: Pull complete
Digest: sha256:75a55d33ecc73c2a242450a9f1cc858499d468f077ea942867e662c247b5e412
Status: Downloaded newer image for nginx:latest
3d33b05202eeee3f3e60a68f7c9f039ea77dc4981cbf8557b8ec03a9ffbbc934
[root@localhost docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d33b05202ee nginx "/docker-entrypoint.…" 28 seconds ago Up 26 seconds 80/tcp nginx01
[root@localhost docker]#
[root@localhost docker]# docker volume ls # 查看卷信息
DRIVER VOLUME NAME
local 1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3 # 匿名
[root@localhost docker]#
[root@localhost docker]# ls /var/lib/docker/volumes/ # 查看目录中的卷信息
1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3 metadata.db
backingFsBlockDev
[root@localhost docker]#
[root@localhost docker]#
[root@localhost docker]# docker volume inspect 1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3 # 查看挂载的详细信息
[
{
"CreatedAt": "2021-05-07T19:19:29+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3/_data", # 宿主机的目录
"Name": "1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3",
"Options": null,
"Scope": "local"
}
]
[root@localhost docker]#
# 具名挂载(常用)
[root@localhost docker]#
[root@localhost docker]# docker run -P -d -v nginx-Juming:/etc/nginx --name nginx02 nginx
6f4fcf67b2fb40ab2cb81685dd4de7ac2cef38f6c2599e1eec719a79797c2538
[root@localhost docker]#
[root@localhost docker]# docker volume ls
DRIVER VOLUME NAME
local 1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3
local nginx-Juming # 具名
[root@localhost docker]#
[root@localhost docker]# ls /var/lib/docker/volumes/
1f8593b8dd6b2c78764a5710d037156795a644d0f9460e40d4300b0fbdbc04b3 metadata.db
backingFsBlockDev nginx-Juming # 具名
[root@localhost docker]#
[root@localhost docker]# docker volume inspect nginx-Juming # 查看挂载的详细信息
[
{
"CreatedAt": "2021-05-07T19:27:01+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/nginx-Juming/_data", # 宿主机的目录 可以在这里修改配置文件
"Name": "nginx-Juming",
"Options": null,
"Scope": "local"
}
]
[root@localhost docker]#
权限控制
# 数据卷权限控制 -v nginx-Juming:/etc/nginx:ro
[root@localhost docker]# docker run -P -d -v nginx-Juming:/etc/nginx:ro --name nginx02 nginx
# ro: read only 只读。只能在容器外部改变文件,不能在容器内部改变文件
# rw: read write 读写。默认权限。容器内外都能改变文件。
方式二:使用DockerFile
之前我们使用commit构建过镜像。
初识Dockerfile。先体验一下。
Dockerfile就是用来构建docker镜像的构建文件!Dockerfile就是一段命令脚本,通过这个脚本可以生成镜像!镜像是一层一层的,脚本是一个一个命令,可以理解成每个命令就是一层镜像。
[root@localhost ~]# mkdir docker-build-test
[root@localhost ~]# cd docker-build-test/
[root@localhost docker-build-test]#
# 1.生成dockerfile
[root@localhost docker-build-test]# vim DockerFile #名字可以自定义 建议用dockerfile
# dockerfile中的内容每一行是一条命令。 每一条命令有指令(大写)和参数组成。每个命令就是一层镜像。
[root@localhost docker-build-test]# cat DockerFile
FROM centos # 基于centos镜像为基础
VOLUME ["volume01","volume02"] # 自动挂载的数据卷目录
CMD echo "----end----"
CMD /bin/bash
[root@localhost docker-build-test]#
[root@localhost docker-build-test]# docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to
enable unlimited swap
--network string Set the networking mode for the RUN instructions
during build (default "default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful
build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
[root@localhost docker-build-test]#
# 2.通过dockerfile构建镜像
[root@localhost docker-build-test]# docker build -f /root/docker-build-test/DockerFile -t wuxl/centos:1.0 .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM centos
---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
---> Running in 46e3da7ae117
Removing intermediate container 46e3da7ae117
---> 77b04bfac2fa
Step 3/4 : CMD echo "----end----"
---> Running in dd2b6ddfed0b
Removing intermediate container dd2b6ddfed0b
---> 8512e84141d6
Step 4/4 : CMD /bin/bash
---> Running in eab90b2dd126
Removing intermediate container eab90b2dd126
---> d60645df454b
Successfully built d60645df454b
Successfully tagged wuxl/centos:1.0
[root@localhost docker-build-test]#
# 3.查看镜像
[root@localhost docker-build-test]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wuxl/centos 1.0 d60645df454b About a minute ago 209MB # 构建的镜像
tomcat 2.0 c01bd59511a6 7 days ago 672MB
tomcat latest c0e850d7b9bb 2 weeks ago 667MB
mysql 5.7 87eca374c0ed 2 weeks ago 447MB
nginx latest 62d49f9bab67 3 weeks ago 133MB
centos latest 300e315adb2f 5 months ago 209MB
[root@localhost docker-build-test]#
# 4.运行镜像 这里需要注意,如果使用的是容器名称启动,必须加tag: wuxl/centos:1.0
[root@localhost docker-build-test]# docker run -it d60645df454b /bin/bash # 运行
[root@b8d89421ecfd /]#
[root@b8d89421ecfd /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02 # 目录
dev home lib64 media opt root sbin sys usr volume01 # 目录
[root@b8d89421ecfd /]#
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b8d89421ecfd d60645df454b "/bin/bash" About a minute ago Up About a minute funny_banach
# 查看容器的挂载情况(匿名挂载)
[root@localhost ~]# docker inspect b8d89421ecfd
"Mounts": [
{
"Type": "volume",
"Name": "2c728e3c84280bead80b4c39fd016dc87c385e377cea0fc12c4ced893eb7673b",
"Source": "/var/lib/docker/volumes/2c728e3c84280bead80b4c39fd016dc87c385e377cea0fc12c4ced893eb7673b/_data", # 宿主机目录
"Destination": "volume02", # 容器目录
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "1d8c109f6254daada08d5646529b630e8ff4cc9e099c7cb4a5674f9446e05ce1",
"Source": "/var/lib/docker/volumes/1d8c109f6254daada08d5646529b630e8ff4cc9e099c7cb4a5674f9446e05ce1/_data", # 宿主机目录
"Destination": "volume01", # 容器目录
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
这种方式使用的十分多,因为我们通常会构建自己的镜像。
假设构建镜像的时候没有挂载数据卷,要手动挂载镜像 -v 卷名:/容器内目录。
数据卷容器
两个容器相互同步数据。比如多个mysql容器同步数据。
# 使用上面我们通过dockerfile构建的镜像,启动三个容器 测试
# 1.启动第一个容器(作为父容器或数据卷容器)
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wuxl/centos 1.0 d60645df454b 39 minutes ago 209MB
tomcat 2.0 c01bd59511a6 7 days ago 672MB
tomcat latest c0e850d7b9bb 2 weeks ago 667MB
mysql 5.7 87eca374c0ed 2 weeks ago 447MB
nginx latest 62d49f9bab67 3 weeks ago 133MB
centos latest 300e315adb2f 5 months ago 209MB
[root@localhost ~]#
[root@localhost ~]# docker run -it --name wuxlcentos01 wuxl/centos:1.0
[root@81d68891cee7 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 7 12:38 dev
drwxr-xr-x. 1 root root 66 May 7 12:38 etc
drwxr-xr-x. 2 root root 6 Nov 3 2020 home
lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 123 root root 0 May 7 12:38 proc
dr-xr-x---. 2 root root 162 Dec 4 17:37 root
drwxr-xr-x. 11 root root 163 Dec 4 17:37 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 7 09:13 sys
drwxrwxrwt. 7 root root 145 Dec 4 17:37 tmp
drwxr-xr-x. 12 root root 144 Dec 4 17:37 usr
drwxr-xr-x. 20 root root 262 Dec 4 17:37 var
drwxr-xr-x. 2 root root 6 May 7 12:38 volume01 # 数据卷01
drwxr-xr-x. 2 root root 6 May 7 12:38 volume02 # 数据卷02
[root@81d68891cee7 /]#
[root@81d68891cee7 /]# cd volume01
[root@81d68891cee7 volume01]# touch centos01.java # 在数据卷01中创建一个文件
[root@81d68891cee7 volume01]# ls
centos01.java
[root@81d68891cee7 volume01]#
# 启动第二个容器 继承wuxlcentos01容器的数据卷: --volumes-from wuxlcentos01
[root@localhost ~]#
[root@localhost ~]# docker run -it --volumes-from wuxlcentos01 --name wuxlcentos02 wuxl/centos:1.0
[root@be78dfb1ac82 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 7 12:43 dev
drwxr-xr-x. 1 root root 66 May 7 12:43 etc
drwxr-xr-x. 2 root root 6 Nov 3 2020 home
lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 125 root root 0 May 7 12:43 proc
dr-xr-x---. 2 root root 162 Dec 4 17:37 root
drwxr-xr-x. 11 root root 163 Dec 4 17:37 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 7 09:13 sys
drwxrwxrwt. 7 root root 145 Dec 4 17:37 tmp
drwxr-xr-x. 12 root root 144 Dec 4 17:37 usr
drwxr-xr-x. 20 root root 262 Dec 4 17:37 var
drwxr-xr-x. 2 root root 27 May 7 12:39 volume01
drwxr-xr-x. 2 root root 6 May 7 12:38 volume02
[root@be78dfb1ac82 /]# ls /volume01/ # wuxlcentos01创建的数据
centos01.java
[root@be78dfb1ac82 /]# touch /volume01/centos02.java # wuxlcentos02也创建文件
[root@be78dfb1ac82 /]#
[root@be78dfb1ac82 /]# ls /volume01/
centos01.java centos02.java
[root@be78dfb1ac82 /]#
# 启动第三个容器 也继承wuxlcentos01容器的数据卷: --volumes-from wuxlcentos01
[root@localhost ~]# docker run -it --volumes-from wuxlcentos01 --name wuxlcentos03 wuxl/centos:1.0
[root@f6c6b2d2c8e3 /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x. 5 root root 360 May 7 12:46 dev
drwxr-xr-x. 1 root root 66 May 7 12:46 etc
drwxr-xr-x. 2 root root 6 Nov 3 2020 home
lrwxrwxrwx. 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 2020 media
drwxr-xr-x. 2 root root 6 Nov 3 2020 mnt
drwxr-xr-x. 2 root root 6 Nov 3 2020 opt
dr-xr-xr-x. 130 root root 0 May 7 12:46 proc
dr-xr-x---. 2 root root 162 Dec 4 17:37 root
drwxr-xr-x. 11 root root 163 Dec 4 17:37 run
lrwxrwxrwx. 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 2020 srv
dr-xr-xr-x. 13 root root 0 May 7 09:13 sys
drwxrwxrwt. 7 root root 145 Dec 4 17:37 tmp
drwxr-xr-x. 12 root root 144 Dec 4 17:37 usr
drwxr-xr-x. 20 root root 262 Dec 4 17:37 var
drwxr-xr-x. 2 root root 48 May 7 12:44 volume01 # 继承的数据卷
drwxr-xr-x. 2 root root 6 May 7 12:38 volume02 # 继承的数据卷
[root@f6c6b2d2c8e3 /]# ls /volume01/
centos01.java centos02.java
[root@f6c6b2d2c8e3 /]# touch /volume01/centos03.java
[root@f6c6b2d2c8e3 /]#
[root@f6c6b2d2c8e3 /]# ls /volume01/
centos01.java centos02.java centos03.java
[root@f6c6b2d2c8e3 /]#
即使docker rm wuxlcentos01后,wuxlcentos02和wuxlcentos03的数据依然存在。因为数据共享是一个双向拷贝的概率。
两个mysql容器的数据如何实现同步?
[root@localhost ~]# docker run -d -p 3306:3306 -v /etc/mysql/conf.d -v /var/lib/mysql --name mysql01 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
[root@localhost ~]# docker run -d -p 3306:3306 --volumes-from mysql01 --name mysql02 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# mysql02容器启动时使用--volumes-from mysql01 ,就可以使得两个mysql容器的数据同步了。
# mysql01是父容器(数据卷容器),mysql02是mysql01的子容器。
结论
容器之间的配置信息的传递(集群),数据卷容器的生命周期一直持续到没有任何容器使用为止。不会因为某个容器的关闭、删除导致数据的丢失。一旦父容器的数据通过-v持久化到了宿主机,这个数据就不会丢失。
上述知识实际操作基本够用。