一:镜像
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某 个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
1.1 UnionFs (联合文件系统)
UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支 持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应 用镜像。
1.2 Docker镜像加载原理
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。 boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加 kernel, Linux刚启动时会加bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的 Linux/Unix系统是一样的,包含boot加載器和内核。当boot加载完成之后整个内核就都在内存中了,此时 内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。 rootfs(root file system),在 bootfs之上。包含的就是典型 Linux系统中 的/dev,/proc,/bin,/etc等标准目录和文件。 rootfs就是各种不同的操作系统发行版,比如 Ubuntu, Centos等等。
1.3 commit镜像
docker commit 提交容器成为一个新的副本
[root@localhost ~]# docker commit --help
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
示例: 先启动一个tomcat容器
docker run -d -p 8081:8080 --name tomcat1 tomcat
访问8081发现报404
[root@localhost ~]# curl localhost:8081
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/10.0.10</h3></body></html>[root@localhost ~]#
原因是因为我们pull来的tomcat镜像是阉割版的,我们进去tomcat容器内部发现
不仅webapp里面是空的,连ll等基本命令都无法使用
解决办法:
root@18872572b8ee:/usr/local/tomcat# cp -r webapps.dist/* webapps/
root@18872572b8ee:/usr/local/tomcat# ls
BUILDING.txt CONTRIBUTING.md LICENSE NOTICE README.md RELEASE-NOTES RUNNING.txt bin conf lib logs native-jni-lib temp webapps webapps.dist work
root@18872572b8ee:/usr/local/tomcat# cd webapps
root@18872572b8ee:/usr/local/tomcat/webapps# ls
ROOT docs examples host-manager manager
root@18872572b8ee:/usr/local/tomcat/webapps#
重新访问8081端口,发现已经正常了
总结:
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG]
[root@localhost ~]# docker commit -a "jinlong" -m "完善tomcat" 18872572b8ee tomcat2:1.0
sha256:4687a14cd587d9516c1a44691da0e727b88d6ab91f15b721f96fa02631435c62
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat2 1.0 4687a14cd587 4 seconds ago 684MB
tomcat latest ab1f0e1bb1a1 8 days ago 680MB
mysql 5.7 1d7aba917169 9 days ago 448MB
mysql latest 0716d6ebcc1a 9 days ago 514MB
portainer/portainer latest 580c0e4e98b0 5 months ago 79.1MB
mysql 5.6.48 8de95e6026c3 15 months ago 302MB
我们可以看到我们修改后的容器,commit后,images里面已经多了一个tomcat2的镜像了。
二:容器数据卷
Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume)。数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享。数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用Docker的数据卷,类似在系统中使用 mount 挂载一个文件系统
2.1 直接使用命令挂载 -v
[root@localhost ~]# sudo docker run -p 3306:3306 --name mysql \
> -v /mydata/mysql/log:/var/log/mysql \
> -v /mydata/mysql/data:/var/lib/mysql \
> -v /mydata/mysql/conf:/etc/mysql \
> -e MYSQL_ROOT_PASSWORD=root \
> -d mysql:5.7
6e7871d4c0b16124541fc4253f7827e841ecda1065bc7a04b95082cde50089c8
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e7871d4c0b1 mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
18872572b8ee tomcat "catalina.sh run" 35 minutes ago Up 35 minutes 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat1
b5b6882ff043 portainer/portainer "/portainer" 3 hours ago Up 3 hours 0.0.0.0:8080->9000/tcp, :::8080->9000/tcp quirky_lehmann
[root@localhost ~]# cd /mydata/mysql/
[root@localhost mysql]# ls
conf data log
[root@localhost mysql]# cd ..
使用inspect命令查看挂载卷相关信息
docker inspect 容器id
查询得到mount相关信息
"Mounts": [
{
"Type": "bind",
"Source": "/mydata/mysql/conf",
"Destination": "/etc/mysql",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/mydata/mysql/log",
"Destination": "/var/log/mysql",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/mydata/mysql/data",
"Destination": "/var/lib/mysql",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
2.2 三种挂载方式
2.2.1 匿名挂载
docker run --name tomcat2 -p 8082:8080 -d -v /usr/local/tomcat tomcat2:1.0
[root@localhost /]# docker run --name tomcat2 -p 8082:8080 -d -v /usr/local/tomcat tomcat2:1.0
55465620a5de78a85d3d1665a876d1a262df8b5d16aa651d890f1a26cd8abefb
[root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55465620a5de tomcat2:1.0 "catalina.sh run" 4 seconds ago Up 3 seconds 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp tomcat2
6e7871d4c0b1 mysql:5.7 "docker-entrypoint.s…" 28 minutes ago Up 28 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
18872572b8ee tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat1
b5b6882ff043 portainer/portainer "/portainer" 3 hours ago Up 3 hours 0.0.0.0:8080->9000/tcp, :::8080->9000/tcp quirky_lehmann
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local 5cdce0e2766c9b8a858dea6a78164c10611ff6457b1107c337be107e709c47d5
local d3c9c93978bd7f87782cd03590f17f5e34cc102b087c01ea625da09c6a6c2a29
[root@localhost /]#
匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径
2.2.2 具名挂载
docker run --name tomcat3 -d -p 8083:8080 -v tomcat-jinlong:/usr/local/tomcat tomcat2:1.0
[root@localhost /]# docker run --name tomcat3 -d -p 8083:8080 -v tomcat-jinlong:/usr/local/tomcat tomcat2:1.0
1f3d069f71d7e6ea6d2b3b929ec5f2a3d9bcf02a7e49c01aac7d9f78f59b6eab
[root@localhost /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1f3d069f71d7 tomcat2:1.0 "catalina.sh run" 4 seconds ago Up 2 seconds 0.0.0.0:8083->8080/tcp, :::8083->8080/tcp tomcat3
55465620a5de tomcat2:1.0 "catalina.sh run" 3 minutes ago Up 3 minutes 0.0.0.0:8082->8080/tcp, :::8082->8080/tcp tomcat2
6e7871d4c0b1 mysql:5.7 "docker-entrypoint.s…" 31 minutes ago Up 31 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
18872572b8ee tomcat "catalina.sh run" About an hour ago Up About an hour 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp tomcat1
b5b6882ff043 portainer/portainer "/portainer" 3 hours ago Up 3 hours 0.0.0.0:8080->9000/tcp, :::8080->9000/tcp quirky_lehmann
[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local 5cdce0e2766c9b8a858dea6a78164c10611ff6457b1107c337be107e709c47d5
local d3c9c93978bd7f87782cd03590f17f5e34cc102b087c01ea625da09c6a6c2a29
local tomcat-jinlong
通过inspect查看volume信息
匿名挂载
[root@localhost _data]# docker volume inspect 5cdce0e2766c9b8a858dea6a78164c10611ff6457b1107c337be107e709c47d5
[
{
"CreatedAt": "2021-09-13T11:10:14+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/5cdce0e2766c9b8a858dea6a78164c10611ff6457b1107c337be107e709c47d5/_data",
"Name": "5cdce0e2766c9b8a858dea6a78164c10611ff6457b1107c337be107e709c47d5",
"Options": null,
"Scope": "local"
}
]
具名挂载:
[root@localhost _data]# docker volume inspect tomcat-jinlong
[
{
"CreatedAt": "2021-09-13T14:23:26+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/tomcat-jinlong/_data",
"Name": "tomcat-jinlong",
"Options": null,
"Scope": "local"
}
]
[root@localhost _data]# cd /var/lib/docker/volumes/tomcat-jinlong/_data
[root@localhost _data]# ls
bin BUILDING.txt conf CONTRIBUTING.md lib LICENSE logs native-jni-lib NOTICE README.md RELEASE-NOTES RUNNING.txt temp webapps webapps.dist work
[root@localhost _data]#
2.2.3 指定路径挂载
所有的docker容器内的卷,没有指定目录的情况下都是在 /var/lib/docker/volumes/xxxx/_data下, 如果指定了目录,docker volume ls 是查看不到的 指定路径挂载就是-v 容器外路径:容器内路径
2.3 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
docker run -d -P 8080:8080 --name tomcat05 -v tomcat-jinlong:/usr/local/tomcat:ro tomcat
docker run -d -P 8080:8080 --name tomcat05 -v tomcat-jinlong:/usr/local/tomcat:rw tomcat
- ro: 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
- rw: readwrite 可读可写
三:dockerfile
概念: Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明
3.1 构建步骤
1、 编写一个dockerfile文件
2、 docker build 构建成为一个镜像
3、 docker run运行镜像
4、 docker push发布镜像(DockerHub 、阿里云仓库等)
3.2 DockerFile常用指令
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的, 姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容 添加同目录
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承 DockerFile 这个时候就会运行ONBUILD的指令,触发指令。
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
3.3 示例
- 编写dockerFile文件
FROM centos
MAINTAINER long<18989814@163.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "-----end----"
CMD /bin/bash
- build镜像()
docker build -f myDockerFile_centos -t jinlong_centos:1.0 .
注意: 指令最后一个 . 是上下文路径:上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。 如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。 上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。
- 查看镜像
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jinlong_centos 1.0 f4c447274bc7 9 seconds ago 309MB
tomcat2 1.0 4687a14cd587 4 hours ago 684MB
nginx latest ad4c705f24d3 3 days ago 133MB
tomcat latest ab1f0e1bb1a1 8 days ago 680MB
portainer/portainer latest 580c0e4e98b0 5 months ago 79.1MB
centos latest 300e315adb2f 9 months ago 209MB
可以看到我们自己build的镜像已经生成了!
- run我们自己构建的镜像
[root@localhost ~]# docker exec -it centos3 /bin/bash
[root@d54f380d7c8a local]# pwd
/usr/local
[root@d54f380d7c8a local]# ll
bash: ll: command not found
[root@d54f380d7c8a local]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.4 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:04 txqueuelen 0 (Ethernet)
RX packets 8 bytes 656 (656.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到ifconfig,以及工作路径都生效了!
备注:
CMD # 指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代。
ENTRYPOINT # 指定这个容器启动的时候要运行的命令,可以追加命令
3.4: 推送镜像到仓库
登陆dockhub账号
如果直接推送镜像,默认是push到官方的library,会报denied
[root@localhost ~]# docker push jinlong_centos:1.0
The push refers to repository [docker.io/library/jinlong_centos]
8ccdb8d2ea27: Preparing
cb978c509ffd: Preparing
2653d992f4ef: Preparing
denied: requested access to the resource is denied
如果要推到自己的仓库,有两种办法
方法一:使用docker tag
[root@localhost ~]# docker tag f4c447274bc7 xiaolong123456789/jinlong_centos
[root@localhost ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jinlong_centos 1.0 f4c447274bc7 17 hours ago 309MB
xiaolong123456789/jinlong_centos latest f4c447274bc7 17 hours ago 309MB
tomcat2 1.0 4687a14cd587 21 hours ago 684MB
nginx latest ad4c705f24d3 4 days ago 133MB
tomcat latest ab1f0e1bb1a1 9 days ago 680MB
mysql 5.7 1d7aba917169 10 days ago 448MB
mysql latest 0716d6ebcc1a 10 days ago 514MB
portainer/portainer latest 580c0e4e98b0 5 months ago 79.1MB
centos latest 300e315adb2f 9 months ago 209MB
mysql 5.6.48 8de95e6026c3 15 months ago 302MB
[root@localhost ~]# docker push xiaolong123456789/jinlong_centos:latest
The push refers to repository [docker.io/xiaolong123456789/jinlong_centos]
8ccdb8d2ea27: Pushed
cb978c509ffd: Pushed
2653d992f4ef: Pushed
latest: digest: sha256:9a1e696b9f5b0c4d0d3cefd875f75efb07f76bf75ccff323622f92d417cdd2d6 size: 953
[root@localhost ~]#
查看我们的dockerhub,已经推送成功
方法二:build的时候添加dockerhub用户名
方法三:可以先启动容器,然后通过commit指令重新提交一个待用户名前缀的镜像
总结:无论采取哪种方法,核心思想还是指定镜像前缀为自己的dockerhub用户名
四:网络
4.1:Linux网卡简介
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:7fff:fefd:4eda prefixlen 64 scopeid 0x20<link>
ether 02:42:7f:fd:4e:da txqueuelen 0 (Ethernet)
RX packets 6633 bytes 5750300 (5.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 11444 bytes 26197019 (24.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.188.129 netmask 255.255.255.0 broadcast 192.168.188.255
inet6 fe80::df2a:9946:311b:9441 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:8b:cb:94 txqueuelen 1000 (Ethernet)
RX packets 1544279 bytes 620900259 (592.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1692721 bytes 463228125 (441.7 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 1182 bytes 127205 (124.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1182 bytes 127205 (124.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- lo:全称loopback,是回环地址,经常被分配到127.0.0.1地址上,用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。
- ens33:网卡名,如果有多块网卡,会有多个eth 或其它名称。link/ether:这个是MAC地址,唯一的,一块网卡一个MAC。inet:网卡上绑定的IP地址,通常所说的IPV4,一块网卡可以绑定多个IP地址。在绑定IP地址时注意:windows主机会提示IP地址冲突,而linux主机无任何提示,在添加新的IP地址时务必检测一下新地址是否和原有地址冲突,避免造成访问不可用。常用检测命令:ping或arping IP;inet6:IPV6地址
- docker0:Docker启动的时候会在主机上自动创建一个docker0网桥,实际上是一个Linux网桥,所有容器的启动如果在docker run的时候没有指定网络模式的情况下都会挂载到docker0网桥上。这样容器就可以和主机甚至是其他容器之间通讯了 备注:网络设备状态标识:<BROADCAST,MULTICAST,UP,LOWER_UP>
1.UP:网卡处于启动状态。
2.BROADCAST:网卡有广播地址,可以发生广播包。
3.MULTICAST:网卡可以发生多播包。
4.LOWER_UP:L1是启动的,即网线是插着的。
4.2:docker如何处理容器网络访问
我们启动一个容器,然后看主机ip addr信息
[root@localhost ~]# docker start centos3
centos3
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d54f380d7c8a jinlong_centos:1.0 "/bin/bash" 21 hours ago Up 2 seconds 80/tcp centos3
[root@localhost ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:8b:cb:94 brd ff:ff:ff:ff:ff:ff
inet 192.168.188.129/24 brd 192.168.188.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::df2a:9946:311b:9441/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:7f:fd:4e:da brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:7fff:fefd:4eda/64 scope link
valid_lft forever preferred_lft forever
33: vethee6d3d9@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 32:f9:da:f0:f0:61 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::30f9:daff:fef0:f061/64 scope link
valid_lft forever preferred_lft forever
会发现比没有启动容器前多了一个信息
33: vethee6d3d9@if32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 32:f9:da:f0:f0:61 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::30f9:daff:fef0:f061/64 scope link valid_lft forever preferred_lft forever
进入到该容器中,执行ip addr命令 查看容器内部网络地址 发现容器启动的时候会得到一个 eth0@if33 ip地址,由docker默认分配!
[root@localhost ~]# docker exec -it centos3 /bin/bash
[root@d54f380d7c8a local]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
32: eth0@if33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
我们分别在容器里面ping主机地址,以及在主机ping容器地址,发现都是可以ping通的
我们再启动一个容器,会发现容器之间,容器和主机之间都是可以互相ping通的
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d54f380d7c8a jinlong_centos:1.0 "/bin/bash" 21 hours ago Up 34 minutes 80/tcp centos3
ba060848ef19 centos "/bin/bash" 22 hours ago Up 3 minutes centos2
[root@localhost ~]# docker exec -it centos2 /bin/bash
[root@ba060848ef19 /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
44: eth0@if45: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@ba060848ef19 /]# ping 192.168.188.129
PING 192.168.188.129 (192.168.188.129) 56(84) bytes of data.
64 bytes from 192.168.188.129: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 192.168.188.129: icmp_seq=2 ttl=64 time=0.038 ms
64 bytes from 192.168.188.129: icmp_seq=3 ttl=64 time=0.053 ms
^C
--- 192.168.188.129 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.038/0.046/0.053/0.008 ms
[root@ba060848ef19 /]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.053 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.088 ms
^C
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.053/0.069/0.088/0.017 ms
4.3:veth-pair技术
每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要按照了docker,就会有一个docker0桥接模式,使用的技术是veth-pair技术!现这个容器带来网卡,都是一对对的.veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连,正因为有这个特性 veth-pair 充当一个桥梁,连接各种虚拟网络设备的,OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术,所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用ip。
Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件),只要容器删除,对应的网桥对就没了!
4.4:--link指定容器名
未使用link之前,两个容器ping,会提示Name or service not known
[root@localhost ~]# docker exec -it centos4 ping centos3
ping: centos3: Name or service not known
[root@localhost ~]#
使用link之后,会发现centos4可以ping通centos2了
[root@localhost ~]# docker run -dit --name centos4 --link centos2 xiaolong123456789/jinlong_centos:2.0 /bin/bash
87bae66deb0bcac9d5a8c6cd49486edaeccf90d975ce36f33531b039cb0719a2
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
87bae66deb0b xiaolong123456789/jinlong_centos:2.0 "/bin/bash" 3 seconds ago Up 2 seconds 80/tcp centos4
d54f380d7c8a jinlong_centos:1.0 "/bin/bash" 22 hours ago Up About an hour 80/tcp centos3
ba060848ef19 centos "/bin/bash" 22 hours ago Up 31 minutes centos2
[root@localhost ~]# docker exec -it centos4 ping centos2
PING centos2 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos2 (172.17.0.3): icmp_seq=1 ttl=64 time=0.156 ms
64 bytes from centos2 (172.17.0.3): icmp_seq=2 ttl=64 time=0.122 ms
64 bytes from centos2 (172.17.0.3): icmp_seq=3 ttl=64 time=0.064 ms
^C
--- centos2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
我们分别查看centos4和centos2的inspect元数据,其中最显著的区别就是Links字段
#centos4:
"Links": [
"/centos2:/centos4/centos2"
],
#centos2:
"Links": null
分别进入centos4和centos2容器内部
这个ba060848ef19就是容器的id
我们已经可以看出centos4之所以能够ping通centos2的原因就是在host文件里多了上图这样的一个配置。-–link 本质就是在hosts配置中添加映射
官网已经不建议使用--link来解决容器名之间的连接了,那么我们还能怎么办呢,官网建议我们使用自定义网络来解决两个容器间的通信
4.5:自定义网络
4.5.1:查看所有的docker网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
bd5db71947df bridge bridge local
3bd63bc72994 host host local
589662779a43 none null local
[root@localhost ~]#
网络模式
- bridge :桥接 docker(默认,自己创建也是用bridge模式)
- none :不配置网络,一般不用
- host :和所主机共享网络
- container :容器网络连通(用得少!局限很大)
4.5.2:创建一个新网络
[root@izhp3h1obuue4kllkg92o4z data]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynetwork
d4b5b5dac1bdcc158f34425a3adc22f2f85300d79443438af5473d931f047b33
[root@izhp3h1obuue4kllkg92o4z data]# docker network ls
NETWORK ID NAME DRIVER SCOPE
2174eebb0497 bridge bridge local
6a84a3fdc736 host host local
d4b5b5dac1bd mynetwork bridge local
db6e9be945cd none null local
其中subnet是子网掩码,gateway是网关,mynetwork是自己创建的网络名称,driver是网络模式,如果不指定,默认就是bridge
4.5.3:查看mynetwork元数据
[root@izhp3h1obuue4kllkg92o4z data]# docker inspect mynetwork
[
{
"Name": "mynetwork",
"Id": "d4b5b5dac1bdcc158f34425a3adc22f2f85300d79443438af5473d931f047b33",
"Created": "2021-09-14T16:27:12.72231007+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
4.5.6:使用自定义网络联通容器
分别创建两个使用自定义网络的容器
docker run -it -d --name centos1 --network mynetwork jinlong_centos:1.0 /bin/bash
docker run -it -d --name centos2 --network mynetwork jinlong_centos:1.0 /bin/bash
再次查看mynetwork信息
[root@localhost ~]# docker inspect mynetwork
[
{
"Name": "mynetwork",
"Id": "a8d82a2f082090c960be1db83bd622d8869919570d0a140f7d6cee0cbd83f2b4",
"Created": "2021-09-14T16:45:36.51672375+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/24",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3549f0e705a15377d624602465dd86a8a816bd0359934331cb1d50ea22767719": {
"Name": "centos2",
"EndpointID": "ed1eae182aaa2396de5b5e8711bae7e38bc6a2ef3f0e0ca8ad72413a92e07ad6",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/24",
"IPv6Address": ""
},
"6ad254c947d5f16c021e41ce2b70b101b13a64d4b2ef6fb931140e9b03ea565c": {
"Name": "centos1",
"EndpointID": "0ca0c8b83b61968986483d3c3247b21a6fcfaacd3631b77327c826db99963048",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
主要看Containers模块,会发现我们刚刚创建的这两个容器的网络信息,再次测试一下是否可以ping通
[root@localhost ~]# docker exec -it centos1 ping centos2
PING centos2 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=1 ttl=64 time=0.144 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=2 ttl=64 time=0.094 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=3 ttl=64 time=0.055 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=4 ttl=64 time=0.075 ms
^C
--- centos2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 6ms
rtt min/avg/max/mdev = 0.055/0.092/0.144/0.033 ms
[root@localhost ~]# docker exec -it centos2 ping centos1
PING centos1 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos1.mynetwork (192.168.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from centos1.mynetwork (192.168.0.2): icmp_seq=2 ttl=64 time=0.115 ms
64 bytes from centos1.mynetwork (192.168.0.2): icmp_seq=3 ttl=64 time=0.054 ms
^C
--- centos1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 0.050/0.073/0.115/0.029 ms
我们发现两个容器之间已经可以ping通了
4.5.7不同网络之间容器互通的办法
使用默认网络创建一个centos3容器
[root@localhost ~]# docker run -d -it --name centos3 jinlong_centos:1.0 /bin/bash
9816233bc41633c2c8bf79a59215af1d598339590b13edd8bb47bd7beb13085c
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9816233bc416 jinlong_centos:1.0 "/bin/bash" 3 seconds ago Up 3 seconds 80/tcp centos3
3549f0e705a1 jinlong_centos:1.0 "/bin/bash" 7 minutes ago Up 7 minutes 80/tcp centos2
6ad254c947d5 jinlong_centos:1.0 "/bin/bash" 8 minutes ago Up 8 minutes 80/tcp centos1
查看bridge信息
[root@localhost ~]# docker inspect bridge
[
{
"Name": "bridge",
"Id": "bd5db71947df7629fd5db0708279f34c8abfe20b44b53a82b43fbac78282073e",
"Created": "2021-09-14T13:27:24.057737418+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"9816233bc41633c2c8bf79a59215af1d598339590b13edd8bb47bd7beb13085c": {
"Name": "centos3",
"EndpointID": "b3306c91c460ec1c4e9ee64913129fd9cdc3034b6129303692a08d19d150d450",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
测试使用不同网络的容器之间是否可以互通
[root@localhost ~]# docker exec -it centos1 ping centos2
PING centos2 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=2 ttl=64 time=0.116 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=3 ttl=64 time=0.133 ms
^C
--- centos2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 0.089/0.112/0.133/0.021 ms
[root@localhost ~]# docker exec -it centos1 ping centos3
ping: centos3: Name or service not known
[root@localhost ~]#
我们发现使用mynetwork和默认docker0两个容器之间是不通的,有没有什么办法也能联通这两个使用不同网络之间的容器呢?
4.5.8:docker network connect
其实不同网段之间的容器是无法互通的,要想让centos3也能和centos1和2互通,解决办法就是将centos3加入到我们创建的mynetwork中,也就是和centos1和2网络一致
docker network connect mynetwork centos3
再次查看mynetwork元数据,会发现centos3也在里面了,而且自动分配了IP地址
[root@localhost ~]# docker inspect mynetwork
[
{
"Name": "mynetwork",
"Id": "a8d82a2f082090c960be1db83bd622d8869919570d0a140f7d6cee0cbd83f2b4",
"Created": "2021-09-14T16:45:36.51672375+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/24",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3549f0e705a15377d624602465dd86a8a816bd0359934331cb1d50ea22767719": {
"Name": "centos2",
"EndpointID": "ed1eae182aaa2396de5b5e8711bae7e38bc6a2ef3f0e0ca8ad72413a92e07ad6",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/24",
"IPv6Address": ""
},
"6ad254c947d5f16c021e41ce2b70b101b13a64d4b2ef6fb931140e9b03ea565c": {
"Name": "centos1",
"EndpointID": "0ca0c8b83b61968986483d3c3247b21a6fcfaacd3631b77327c826db99963048",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/24",
"IPv6Address": ""
},
"9816233bc41633c2c8bf79a59215af1d598339590b13edd8bb47bd7beb13085c": {
"Name": "centos3",
"EndpointID": "5155989861c370926b7bbdb10eb7847f6c4cc43c34768aba36d43f0391ec3c21",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/24",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
再次测试容器联通性,我们发现已经可以两两互通了
[root@localhost ~]# docker exec -it centos1 ping centos3
PING centos3 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos3.mynetwork (192.168.0.4): icmp_seq=1 ttl=64 time=0.138 ms
64 bytes from centos3.mynetwork (192.168.0.4): icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from centos3.mynetwork (192.168.0.4): icmp_seq=3 ttl=64 time=0.121 ms
64 bytes from centos3.mynetwork (192.168.0.4): icmp_seq=4 ttl=64 time=0.116 ms
64 bytes from centos3.mynetwork (192.168.0.4): icmp_seq=5 ttl=64 time=0.044 ms
^C
--- centos3 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 0.044/0.096/0.138/0.037 ms
[root@localhost ~]# docker exec -it centos3 ping centos2
PING centos2 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=1 ttl=64 time=0.186 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=2 ttl=64 time=0.065 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=3 ttl=64 time=0.058 ms
64 bytes from centos2.mynetwork (192.168.0.3): icmp_seq=4 ttl=64 time=0.082 ms
^C
--- centos2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 4ms
rtt min/avg/max/mdev = 0.058/0.097/0.186/0.053 ms