Docker《二:镜像,数据卷,dockerfile及网络基本介绍》

498 阅读27分钟

一:镜像

镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某 个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件

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容器内部发现 image.png 不仅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端口,发现已经正常了 image.png 总结

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 80808080 --name tomcat05 -v tomcat-jinlong:/usr/local/tomcat:ro tomcat
docker run -d -P 80808080 --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账号 image.png

如果直接推送镜像,默认是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,已经推送成功 image.png 方法二: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通的 image.png 我们再启动一个容器,会发现容器之间,容器和主机之间都是可以互相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。 image.png 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容器内部 image.png

这个ba060848ef19就是容器的id 我们已经可以看出centos4之所以能够ping通centos2的原因就是在host文件里多了上图这样的一个配置。-–link 本质就是在hosts配置中添加映射 image.png 官网已经不建议使用--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