Docker筑基篇-下
Posted Fire king
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker筑基篇-下相关的知识,希望对你有一定的参考价值。
Docker筑基篇-下
1.容器数据卷
回顾docker的理念:将应用和环境打包成一个镜像放到docker中创建容器运行。
既然要容器要运行,那么必然需要数据,倘若数据保存在容器中,那么删除了容器,数据就会丢失了,这对开发来说是不允许的。需求:数据可以持久化。
镜像 容器 容器 删了,镜像 的数据也就没有了。需求:数据可以保存到本地。
容器之间实现数据共享。
容器中中产生的数据,可以同步到本地,反之,亦然。
因此,卷技术产生了。卷技术将容器内的目录挂载到Linux上面。
2.使用数据卷
方式一:直接使用命令来挂在 -v
docker run -it -v 主机目录:容器目录
#测试
[root@localhost home]# docker run -it -v /home/ceshi:/home centos /bin/bash
#启动后另开一个窗口(容器外主机内)通过 docker inspect 容器id
[root@localhost /]# docker inspect 199bf02faedd
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi",#主机内地址
"Destination": "/home",#容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
测试:在容器/home目录下创建test.java,就会同步到主机/home/ceshi,实现数据同步
验证双向同步(实则验证反向同步):
1.停掉容器
2.主机修改test.java
3.启动容器,看/home/test.java是否有内容
4.结果
实验成功,验证将容器目录挂载到主机目录为双向同步
好处:以后修改只需在本地修改即可,容器会自动同步。
3.实战:mysql数据同步
3.1.下载mysql5.7的镜像并挂载运行
#下载mysql5.7的镜像
[root@localhost ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
a076a628af6f: Already exists
f6c208f3f991: Pull complete
88a9455a9165: Pull complete
406c9b8427c6: Pull complete
7c88599c0b25: Pull complete
25b5c6debdaf: Pull complete
43a5816f1617: Pull complete
1831ac1245f4: Pull complete
37677b8c1f79: Pull complete
27e4ac3b0f6e: Pull complete
7227baa8c445: Pull complete
Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
#运行容器,需要数据挂载。 #启动mysql,需要配置密码。
#官方测试:$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#启动并挂载mysql
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
--name 容器名字
[root@localhost ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
dae6f6fa07dd6d97486a22b6c30fdabe806037c828ad8dfd6193b763fbae576c
#启动成功之后,在win10本地使用navicat连接测试
#navicat连接到linux主机的3310 ----linux主机的3310和容器内的3306映射,因此navicat就可以连上容器内的mysql
3.2.连接本地电脑的navicat
3.3.测试映射的路径是否正确
在本地电脑navicat创建一个数据库docker_mysql,查看我们映射的路径是否ok。
创建数据库之前:
创建数据库:
创建数据库之后:
3.4.容器数据持久化功能测试
假设我们将容器删除
[root@localhost ~]# docker rm -f mysql01
mysql01
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
aec63ded193c tomcat "catalina.sh run" 22 hours ago Up 22 hours 0.0.0.0:3355->8080/tcp tomcat01
3cb23d454a26 nginx "/docker-entrypoint.…" 23 hours ago Up 23 hours 0.0.0.0:3344->80/tcp nginx_1
发现,我们连接到本地的数据卷并没有丢失,这就实现了容器数据持久化功能!
[root@localhost data]# ls
auto.cnf docker_test ibtmp1 server-cert.pem
ca-key.pem ib_buffer_pool mysql server-key.pem
ca.pem ibdata1 performance_schema sys
client-cert.pem ib_logfile0 private_key.pem
client-key.pem ib_logfile1 public_key.pem
4.初识Dockerfile
4.1.数据卷之Dockerfile
#创建一个dockerfile文件,名字可以随机,建议dockerfile
[root@localhost docker-test-volume]# vim dockerfile1
#文件中内容 指令(大写)参数
[root@localhost docker-test-volume]# cat dockerfile1
FROM centos #基于centos
VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
#这里的每个命令,就是镜像的一层
#创建镜像
-f 脚本路径(也可写绝对路径)
-t 版本(tag)
[root@localhost docker-test-volume]# docker build -f dockerfile1 -t idvimage/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 fea9e39e9331
Removing intermediate container fea9e39e9331
---> d0f72adf0d7a
Step 3/4 : CMD echo "-----end-----"
---> Running in 94365eb7019c
Removing intermediate container 94365eb7019c
---> c760777cd14c
Step 4/4 : CMD /bin/bash
---> Running in 1e4513c330e5
Removing intermediate container 1e4513c330e5
---> 6fcb0e63fef4
Successfully built 6fcb0e63fef4
Successfully tagged idvimage/centos:1.0
[root@localhost docker-test-volume]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
idvimage/centos 1.0 6fcb0e63fef4 36 seconds ago 209MB
hello-world latest d1165f221234 2 weeks ago 13.3kB
mysql 5.7 a70d36bc331a 2 months ago 449MB
tomcat 9.0 040bdb29ab37 2 months ago 649MB
tomcat latest 040bdb29ab37 2 months ago 649MB
nginx latest f6d0b4767a6c 2 months ago 133MB
centos latest 300e315adb2f 3 months ago 209MB
#进入自制的镜像
[root@localhost docker-test-volume]# docker run -it 125d9f02cefd /bin/bash
#查看长文件
[root@4eef598c3d6f /]# ls -l
total 0
lrwxrwxrwx. 1 root root 7 Nov 3 15:22 bin -> usr/bin
drwxr-xr-x. 5 root root 360 Mar 25 12:56 dev
drwxr-xr-x. 1 root root 66 Mar 25 12:56 etc
drwxr-xr-x. 2 root root 6 Nov 3 15:22 home
lrwxrwxrwx. 1 root root 7 Nov 3 15:22 lib -> usr/lib
lrwxrwxrwx. 1 root root 9 Nov 3 15:22 lib64 -> usr/lib64
drwx------. 2 root root 6 Dec 4 17:37 lost+found
drwxr-xr-x. 2 root root 6 Nov 3 15:22 media
drwxr-xr-x. 2 root root 6 Nov 3 15:22 mnt
drwxr-xr-x. 2 root root 6 Nov 3 15:22 opt
dr-xr-xr-x. 235 root root 0 Mar 25 12:56 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 15:22 sbin -> usr/sbin
drwxr-xr-x. 2 root root 6 Nov 3 15:22 srv
dr-xr-xr-x. 13 root root 0 Mar 24 00:34 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 Mar 25 12:56 volume01
drwxr-xr-x. 2 root root 6 Mar 25 12:56 volume02
这个卷和外部一定有一个同步的目录!
FROM centos #基于centos
VOLUME ["volume01","volume02"] #匿名挂载
CMD echo "-----end-----"
使用docker inspect 6fcb0e63fef4
查看对应的外部目录
发现没有类似如下目录,
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi",#主机内地址
"Destination": "/home",#容器内地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
其实,这是一个对容器概念理解的深度不够,记住,是容器挂载而不是镜像挂载,你应该docker inspect 容器id
而不是docker inspect 镜像id
,而容器id可以通过docker ps
查看正在运行的容器,因此,我得到了我想要的结果:
"Mounts": [
{
"Type": "volume",
"Name": "374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c",
"Source": "/var/lib/docker/volumes/374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c/_data",
"Destination": "volume01",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "12939cecb7b14aafa82b78b85e7b3ac8ee6be82575fef21b3d71b16e869b1d3b",
"Source": "/var/lib/docker/volumes/12939cecb7b14aafa82b78b85e7b3ac8ee6be82575fef21b3d71b16e869b1d3b/_data",
"Destination": "volume02",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
此时,我在容器volume01创建的container.txt文件在虚拟机的/var/lib/docker/volumes/374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c/_data
目录下也找到了:
[root@localhost ~]# ls /var/lib/docker/volumes/374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c/_data
container.txt
至此,特别注意/var/lib/docker/volumes/374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c/_data
中374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c
是随着同镜像新的容器的创建而不断迭代的的,而同镜像不同容器的容器id也是不同的,因此,docker inspect 容器id
中容器id也是变化的。
但删除容器,挂载的目录仍在,数据仍在:
[root@localhost _data]# ls /var/lib/docker/volumes
12939cecb7b14aafa82b78b85e7b3ac8ee6be82575fef21b3d71b16e869b1d3b
374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c
76b4234351ecb3ae40e115990381c1515726289dd6815f4b9d6df62f8486fedd
7c5d5cac7861b295c6b136ebe7cbabf80c02dbffc4db2a64e773f52db2b516a3
9a4610c51743ee098b76393b6e36e838fff6c0c2270e0baed82a86d47e95c6bb
a0d6e258a54d968377a1404e6aa98de01f75a084c3ec7297f72aa4d996c36897
backingFsBlockDev
fbe5a4cb9a0b24e6456d42b61ad37ff28c5b7c6437563ba31c536435bcaa7255
fdec3210278c92adb4ec06455b462c333d18291b426c5398d4217b20216e2f93
metadata.db
[root@localhost _data]# ls /var/lib/docker/volumes/374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c/_data
container.txt
[root@localhost ~]# docker run -it --name docker01 idvimage/centos:1.0
[root@cfcf34b863ed /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
[root@localhost ~]# docker run -it --name docker02 --volumes-from docker01 idvimage/centos:1.0
[root@f1600ab7e96b /]#
#启动docker01容器
[root@localhost ~]# docker run -it --name docker01 idvimage/centos:1.0
[root@cfcf34b863ed /]# ls
bin etc lib lost+found mnt proc run srv tmp var volume02
dev home lib64 media opt root sbin sys usr volume01
#启动docker02容器
[root@localhost ~]# docker run -it --name docker02 --volumes-from docker01 idvimage/centos:1.0
#docker01创建文件
[root@cfcf34b863ed volume01]# touch docker01
#docker02同步
[root@f1600ab7e96b /]# ls volume01
docker01
#创建docker03容器
[root@localhost ~]# docker run -it --name docker03 --volumes-from docker01 idvimage/centos:1.0
#发现也同步了
[root@29b32d69a3b3 /]# ls volume01
docker01
#顺带创建docker03文件
[root@29b32d69a3b3 /]# touch /volume01/docker03
[root@29b32d69a3b3 /]# ls volume01
docker01 docker03
看看docker01和docker02有没有同步到docker03文件
docker01容器:
[root@cfcf34b863ed volume01]# ls
docker01 docker03
docker02容器:
[root@f1600ab7e96b /]# ls volume01
docker01 docker03
结果:实验证明,容器间通过挂载目录可以达到数据共享。
再来,删除docker01容器,看数据还在不在:
删除之前:
[root@localhost ~]# ls /var/lib/docker/volumes
12939cecb7b14aafa82b78b85e7b3ac8ee6be82575fef21b3d71b16e869b1d3b
374a5f63c63d988b0ba766ff95b3a26222b0ca768fbf4b1aa69d83e13a19ed7c
76b4234351ecb3ae40e115990381c1515726289dd6815f4b9d6df62f8486fedd
7c5d5cac7861b295c6b136ebe7cbabf80c02dbffc4db2a64e773f52db2b516a3
9a4610c51743ee098b76393b6e36e838fff6c0c2270e0baed82a86d47e95c6bb
a0d6e258a54d968377a1404e6aa98de01f75a084c3ec7297f72aa4d996c36897
a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d
backingFsBlockDev
be3a4eb4d8d7235582c66eb19e99cc1f0ecf9d3f743da399f7228e084753c5de
fbe5a4cb9a0b24e6456d42b61ad37ff28c5b7c6437563ba31c536435bcaa7255
fdec3210278c92adb4ec06455b462c333d18291b426c5398d4217b20216e2f93
metadata.db
#docker01对应的目录
a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d"
#删除docker01
[root@localhost ~]# docker rm -f cfcf34b863ed
cfcf34b863ed
#docker01数据仍在,其他容器更在
[root@localhost ~]# ls /var/lib/docker/volumes/a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d/_data
docker01 docker03
再来一个测试,docker02创建docker02文件,原来docker01还会同步吗?
[root@f1600ab7e96b /]# touch volume01/docker02
[root@f1600ab7e96b /]# ls volume01
docker01 docker02 docker03
揭晓答案:仍然同步,即使docker01容器被删
[root@localhost ~]# ls /var/lib/docker/volumes/a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d/_data
docker01 docker02 docker03
当然,docker02也会同步
[root@29b32d69a3b3 /]# ls volume01
docker01 docker02 docker03
总结:docker01挂载在Linux主机的/var/lib/docker/volumes/目录下,docker02和docker03通过--volumes-from
实际也是挂载在Linux主机的/var/lib/docker/volumes/目录下,因此即使删了docker01,docker02和docker03也能数据共享,更准确地说docker01、docker02以及docker03也能数据共享,数据共享实质上是/var/lib/docker/volumes/每个容器挂载生成的目录(类似a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d)/_data
之间双向拷贝,即使删除容器,它生成的`每个容器挂载生成的目录(类似a7519deeed55d733f80b92f232e4d24cef1ee76ac718894445addf3f1034723d)/_data``依然存在,仍能数据共享。
以上是关于Docker筑基篇-下的主要内容,如果未能解决你的问题,请参考以下文章