创建网桥进行通信
[root@rhel1 ~]# vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://7fh8zy6l.mirror.aliyuncs.com"],
"bip":"192.168.1.1/24"
}
[root@rhel1 ~]# systemctl daemon-reload
[root@rhel1 ~]# systemctl restart docker
[root@rhel1 ~]# docker run -itd --name web busybox //创建一个容器
4b0a393beb69cfba0a07183d55879df05902c4c9fe5247572029370e3b7c23dc
[root@rhel1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4b0a393beb69 busybox "sh" 14 seconds ago Up 13 seconds web
[root@rhel1 ~]# docker inspect web | grep IPAddress //查看IP是否已经更改
"SecondaryIPAddresses": null,
"IPAddress": "192.168.1.2",
"IPAddress": "192.168.1.2",
[root@rhel1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
0482f6be6b37 host host local
63b6dd5ecb39 none null local
[root@rhel1 ~]# docker network create -d bridge --subnet "192.168.2.0/24" --gateway "192.168.2.1" rhel1 //自定义一个网桥
[root@rhel1 ~]# docker network ls //可以看到刚才创建的网桥
NETWORK ID NAME DRIVER SCOPE
515eda81c941 rhel1 bridge local
0482f6be6b37 host host local
63b6dd5ecb39 none null local
[root@rhel1 ~]# docker run -it --name rhel1 --network cxr1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:02:02
inet addr:192.168.2.2 Bcast:192.168.2.255 Mask:255.255.255.0 //这里的IP已经发生改变
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:36 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:5124 (5.0 KiB) TX bytes:0 (0.0 B)
[root@rhel1 ~]# docker run -it --name cxr1 busybox
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:01:03
inet addr:192.168.1.3 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:15 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2004 (1.9 KiB) TX bytes:0 (0.0 B)
[root@rhel1 ~]# docker network connect rhel2 c2 //c2这个容器连接到cxr1这个网络
/ # ifconfig //查看c2的网卡状态发现多了一个192.168.2.3的ip
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:26 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2826 (2.7 KiB) TX bytes:532 (532.0 B)
eth1 Link encap:Ethernet HWaddr 02:42:C0:A8:02:03
inet addr:192.168.2.3 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:28 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2942 (2.8 KiB) TX bytes:378 (378.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:504 (504.0 B) TX bytes:504 (504.0 B)
/ # ping 192.168.2.3 // 可以看到已经ping通了
PING 192.168.2.3 (192.168.2.3): 56 data bytes
64 bytes from 192.168.2.3: seq=0 ttl=64 time=0.209 ms
64 bytes from 192.168.2.3: seq=1 ttl=64 time=0.070 ms
64 bytes from 192.168.2.3: seq=2 ttl=64 time=0.075 ms
//在进到c1里面去ping c2
/ # ping 192.168.2.3
PING 192.168.2.3 (192.168.2.3): 56 data bytes
64 bytes from 192.168.2.3: seq=0 ttl=64 time=0.257 ms
64 bytes from 192.168.2.3: seq=1 ttl=64 time=0.135 ms
64 bytes from 192.168.2.3: seq=2 ttl=64 time=0.126 ms
COW机制
Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件的副本所隐藏,这就是“写时复制(COW)”机制。

对于这种方式来说,我们去访问一个文件,修改和删除等一类的操作,其效率会非常的低,因为隔着很多层镜像。
而要想绕过这种限制,我们可以通过使用存储卷的机制来实现。
什么是存储卷
存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。

在宿主机上的这个与容器形成绑定关系的目录被称作存储卷
使用存储卷的好处
如果容器中跑的进程的所有有效数据都保存在存储卷中,从而脱离容器自身文件系统之后,带来的好处是当容器关闭甚至被删除时,只要不删除与此容器绑定的在宿主机上的这个存储目录,我们就不用担心数据丢失了。因此就可以实现数据持久,脱离容器的生命周期而持久。
我们通过这种方式管理容器,容器就可以脱离主机的限制,可以在任意一台部署了docker的主机上跑容器,而其数据则可以置于一个共享存储文件系统上,比如nfs。
Docker的存储卷默认情况下是使用其所在的宿主机上的本地文件系统目录的,也就是说宿主机上有一块属于自己的硬盘,这个硬盘并没有共享给其他的Docker主机,而在这台主机上启动的容器所使用的存储卷是关联到此宿主机硬盘上的某个目录之上。
这就意味着容器在这台主机上停止运行或者被删除了再重建,只要关联到硬盘上的这个目录下,那么其数据还存在。但如果在另一台主机上启动一个新容器,那么数据就没了。而如果在创建容器的时候我们手动的将容器的数据挂载到一台nfs服务器上,那么这个问题就不再是问题了。
总结:当容器删除时 里面的数据因为是存在了外面所以并不会消失 可以用数据创建无数个一样的容器
为什么要用存储卷
关闭并重启容器,其数据不受影响,但删除Docker容器,则其更改将会全部丢失。
因此Docker存在的问题有:
- 存储于联合挂载文件系统中,不易于宿主机访问
- 容器间数据共享不便
- 删除容器其数据会丢失
而要解决这些问题,解决方案就是使用存储卷。
存储卷管理方式
存储卷(Data Volume)于容器初始化时被自动创建,由base image提供的卷中的数据会于此期间完成复制。
Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时既不会删除卷,也不会对未被引用的卷做垃圾回收操作。
存储卷为Docker提供了独立于容器的数据管理机制,我们可以把镜像想象成静态文件,例如“程序”,把卷类比为动态内容,例如“数据”。所以镜像可以重用,而卷则可以共享。
卷实现了“程序(镜像)”和“数据(卷)”的分离,以及“程序(镜像)”和“制作镜像的主机”的分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境。

存储卷的分类
Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同:
Bind mount volume (绑定挂载卷)
a volume that points to a user-specified location on the host file system
Docker-managed volume(docker管理卷)
the Docker daemon creates managed volumes in a portion of the host’s file system that’s owned bye Docker

docker存储卷
存储卷的分类
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 bye Docker
容器中管理数据主要有两种方式:
数据卷(Data Volumes)
数据卷容器(Data Volumes Containers)
Docker-managed volume
[root@rhel1 ~]# docker run -it --name b1 -v /data busybox /bin/sh
/ # ls
bin data dev etc home proc root sys tmp usr var
/ #
[root@rhel1 ~]# docker inspect b1 //查看b1的数据存储的位置
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/4b18b15683bd89181ca89e0cd4745c38cccda997020ceee02ec95f37af52fca5-init/diff:/var/lib/docker/overlay2/b65ed408da5ee16c9432d490934e947c18d98197b991db35b0d72901e4591e92/diff",
"MergedDir": "/var/lib/docker/overlay2/4b18b15683bd89181ca89e0cd4745c38cccda997020ceee02ec95f37af52fca5/merged",
"UpperDir": "/var/lib/docker/overlay2/4b18b15683bd89181ca89e0cd4745c38cccda997020ceee02ec95f37af52fca5/diff",
"WorkDir": "/var/lib/docker/overlay2/4b18b15683bd89181ca89e0cd4745c38cccda997020ceee02ec95f37af52fca5/work"
},
//在虚拟机上容器data存储的位置
[root@rhel1 diff]# cd /var/lib/docker/volumes/a7d16fe6c1cd102558b38945f895290ffe5c10c9c7eb99b0f71f3cce9cd91309/_data
[root@rhel1 _data]# touch 123
[root@rhel1 _data]# ls
123
/data # ls /data/
123
[root@rhel1 _data]# rm -f 123
/data # ls /data/ //在容器中查看也被删除了
Bind mount volume
[root@rhel1 _data]# docker run -it --name b2 -v /web:/data busybox //创建一个容器并把data目录映射到虚拟机上的web
[root@rhel1 ~]# ls /
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr web
[root@rhel1 ~]# cd /web/
[root@rhel1 web]# echo "hello world" > index.html
/ # ls
bin data dev etc home proc root sys tmp usr var
/ # cd /data/
/data # ls
index.html
/data # cat index.html //在容器中也是可以看到的
hello world
-
利用存储卷提供网站类容
[root@rhel1 ~]# unzip chishenme.zip
[root@rhel1 ~]# rm -rf chishenme.zip
[root@rhel1 ~]# cp -r chishenme/ /web/
[root@rhel1 ~]# ls /web/
chishenme index.html
[root@rhel1 web]# rm -f index.html
[root@rhel1 web]# mv chishenme/ index.html
[root@rhel1 web]# ll
总用量 0
drwxr-xr-x. 6 root root 137 5月 4 06:17 index.html
//然后做一个apache的容器
[root@rhel1 _data]# docker run -d --name web -v /web:/usr/local/apache2/htdocs -p 80:80 httpd //把web目录和容器中的/usr/local/apache2/htdocs做一个绑定,把容器里的80端口映射到虚拟机上
c71462d8ed565f03315e7cb3c50adf1fb5de81bfec6c6bfc514f68916609cf36
[root@rhel1 _data]# cd
[root@rhel1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c71462d8ed56 httpd "httpd-foreground" 17 seconds ago Up 15 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp web

浙公网安备 33010602011771号