万字长文深入理解Docker镜像分层原理、容器数据卷、网络通信架构(Docker系列第2章,共3章)

镜像分层的简单直观体现

在执行docker pull时,会发现多个Pull complete 字样,就能体现分层,如果是一个文件,只会有一个Pull complete 。

docker pull redis
Using default tag: latest
latest: Pulling from library/redis
a2abf6c4d29d: Already exists 
c7a4e4382001: Pull complete 
4044b9ba67c9: Pull complete 
c8388a79482f: Pull complete 
413c8bb60be2: Pull complete 
1abfd3011519: Pull complete 
Digest: sha256:db485f2e245b5b3329fdc7eff4eb00f913e09d8feb9ca720788059fdc2ed8339
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest

文件系统

  • 概念:文件系统是计算机系统中用于组织和管理数据存储的一种方式。它定义了数据如何存储、命名、访问和修改的方式。
  • 举例:如Windows自带的NTFS、FAT32、EXFAT,和Linux中的EXT3、EXT4这种的。
  • FAT32:有着很好的兼容性,但是不支持单个大于4GB的文件,U盘空间充足却放不下大文件,就是这个原因。可以格式化后换一个文件系统解决。
  • NTFS:NTFS是Windows操作系统中最常用的文件系统之一,它支持大容量硬盘和大文件,提供了较好的安全性、稳定性和恢复能力。
  • EXFAT:为了解决FAT32不支持单个大于4GB的文件而诞生。

操作系统的引导

  • 概括:操作系统的引导(Bootstrapping)是指在计算机启动时,通过加载操作系统的核心组件和必要的驱动程序,使得计算机能够进入操作系统的运行状态。引导过程通常包括以下几个步骤:
  1. 加电自检(Power-On Self-Test,POST):计算机启动时,会执行自检程序,检查硬件是否正常。如果自检过程中发现硬件故障,计算机可能会发出警报或者停止启动。
  2. BIOS/UEFI初始化:计算机启动后,会加载基本输入/输出系统(Basic Input/Output System,BIOS)或统一可扩展固件接口(Unified Extensible Firmware Interface,UEFI),进行硬件初始化和系统设置。
  3. 引导加载程序(Bootloader)启动:BIOS/UEFI会寻找引导加载程序,一般位于硬盘的引导扇区(Boot Sector)或其他可引导的介质(如USB闪存驱动器)。引导加载程序的主要任务是加载操作系统的内核镜像到内存中,并执行操作系统的初始化。
  4. 内核初始化:一旦操作系统的内核镜像被加载到内存中,引导加载程序将控制权转交给操作系统内核。内核开始初始化系统的各个部分,包括设备驱动程序、文件系统等。
  5. 用户空间初始化:内核完成初始化后,操作系统开始启动用户空间的进程,包括系统服务和用户登录界面。

联合文件系统UnionFileSystem

联合文件系统(UFS),是一种分层的高性能文件系统,支持对文件系统的修改作为一次提交来层层叠加。
docker用它作为镜像的存储方式,使得容器在运行时只需存储修改过的部分,而不是整个文件系统,从而节省存储空间并提高效率。

为什么docker用UFS

  • 共享和复用:UFS 允许多个容器共享相同的基础镜像层,这样可以节省存储空间,并减少容器的创建和启动时间。当多个容器共享相同的文件系统层时,这些层中的文件和资源只需存储一次,而不是每个容器都存储一份。这和代码是一样的,封装的方法拆分的越小,可复用性就会更好。
  • 写时复制(Copy-on-Write):UFS 允许容器在运行时进行读写操作,同时保留了镜像的不可变性。当容器对文件系统进行修改时,UFS 会将修改的内容写入新的层中,而不会直接修改原始镜像层,这样可以确保容器之间的隔离性,并且不会影响其他容器或原始镜像。
  • 快速启动和部署:由于 UFS 允许容器共享文件系统层并利用写时复制机制,因此容器的创建和启动速度非常快。Docker 可以快速地在现有镜像的基础上创建新的容器实例,并立即启动运行,这对于实现快速部署和横向扩展至关重要。
  • 轻量级:UFS 提供了一种轻量级的文件系统封装方式,它不需要完整地复制整个文件系统,而是在需要修改文件时才进行复制和修改,这样可以节省存储空间并减少资源消耗,下文会讲。

深入理解Docker镜像分层加载原理

  • 简易概括:在BootFS(宿主机提供)的基础上,利用UFS封装RootFS,使用镜像层的数据,叠加出一个可写的容器层。
    所以说,docker pull下来的CentOS、Ubuntu发行版,才很小,一个原因是省掉了BootFS,另一个原因是抛弃了很多非核心的组件,如vim等。


  • BootFS:引导文件系统(boot filesystem)是指用于引导操作系统的文件系统。这个文件系统通常包含了引导加载程序(boot loader)所需的文件,例如引导配置文件、内核以及其他引导所需的文件,docker用宿主机的内核,出处就是这里。

  • RootFS:在 Linux 中,rootfs(root file system)是指操作系统启动后的根文件系统,它包含了整个文件系统的目录结构和文件,提供了用户空间程序运行所需的基本文件和资源,例如根目录下的几个目录。

  • 镜像层:只读的,包含了应用程序运行所需的所有文件和依赖项。

  • 容器层:可写的,当容器启动时,一个新的容器层被加载到容器的顶部,用来支撑数据变化的存储。

上下层级关系是这样的:
docker的UFS管理了最上面的3层,利用写时复制(Copy-on-Write)的机制,当容器需要修改文件时,UFS 会在容器层中进行写操作,而不会直接修改镜像层中的文件。这样可以保证镜像的不可变性,同时允许容器进行灵活的读写操作。
新的容器又可以commit成一个新的镜像,这个新的镜像基础上,又可以堆叠更多的容器,层层累加。

              --容器层--
           -----镜像层------
      ----------RootFS----------
----------------BootFS----------------

容器数据卷

  • 极简概括:容器数据卷,容器卷、数据卷、一个概念,将宿主机中的目录或文件挂载到容器中,从而让容器和宿主机共同读写这块的数据。并且在容器销毁时,容器卷的数据不会丢失。
  • 用法:docker run --name name1 [-it/-d] -v /宿主机绝对路径:/容器内绝对路径 --privileged=true 镜像id [/bin/bash]
  • 备注:-v是volume的首字母,挂载目录默认是读写权限,但是目录本身容器内部删不掉(极少需要删除),如果宿主机没有这个目录,只要权限充足,它会自动创建。
  • 适用场景:
    • 数据备份:当容器被误删,或者容器内的组件因故障无法运行时,容器卷的数据保留的好好的,这算是一种容灾。
    • 数据互通:容器内的组件,和容器外的系统,可以共享这块数据的读写,实时的,这对开发者、运维人员很友好。
    • 同步日志和数据:很多组件,应用、日志、数据是可以分开的,所以就可以把日志,数据,放进多个数据卷。
  • 优点:
    • 上文的适用场景,就是两个优点。
    • 易于备份:通过使用容器卷,可以轻松地备份和恢复数据,而不需要备份整个容器。
  • 缺点:
    • 复杂化:对于新手,或者刚接触新服务器的运维人员,多容器下的容器卷管理,使得运维工作错综复杂。
    • 高可用问题:MySQL不推荐在docker中,其中一个就是数据的高可用问题,MySQL减少保障故障时数据丢失问题和维护高可用带来的性能问题,使用了3种不同的redo log刷盘机制作为保障,但是又加了一个容器卷环节,多了一个环节,就有可能在这上面出故障,尤其是MySQL这种需要环境极度稳定的组件。

使用容器卷记得添加–privileged=true

使容器具有完全可控的权限,防止出现Permission denied的错误。
注意是等号,不是空格,有个d。

容器数据卷实操

对数据同步的测试

docker run --name=zs_ubuntu --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
进入ubuntu容器后
cd /test
touch a
开启另一个宿主机终端
touch b
容器和宿主机互相ls,发现都有a、b两个文件

使用inspect命令查看挂载相关配置

docker inspect 容器id
找到Mounts段,
"Mounts": [
    {
        "Type": "bind",
        "Source": "/test",
        "Destination": "/test",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],


Type: 指定了数据卷的类型,这里是bind,表示这是一个绑定挂载,即将宿主机上的一个目录挂载到容器内部。
Source: 指定了数据卷的来源,这里是/test,表示宿主机上的目录路径。
Destination: 指定了数据卷在容器内的挂载目标路径,这里也是/test,表示容器内部的路径。
Mode: 这个字段可以用来指定挂载的权限模式,但在这个配置中为空,表示使用默认权限。
RW: 表示是否以读写模式挂载,这里是true,表示挂载为读写模式。
Propagation: 指定了挂载点的传播属性,这里是rprivate,表示挂载点将会被私有化传播,即只会影响到当前容器的进程,不会传播到其他容器。

故障情况下,容器卷内容的情况

停止容器
docker stop ea03c5ef1025
在宿主机内,创建文件
touch /test/c
开启
docker start ea03c5ef1025
进入容器
docker exec -it ea03c5ef1025 /bin/bash
此时发现c依旧存在
ls /test


宿主机误删容器(强制)
docker rm -f ea03c5ef1025
发现a、b、c3个文件都在。
ls /
重新创建新的容器
docker run --name=zs_ubuntu --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
进入容器后,发现a、b、c 3个文件都在。
ls /

容器数据卷的rw与ro两种读写权限

rw:默认值,双方各有读写权限。

执-v命令时,默认是读写权限,以下两个命令是相等的。
docker run --name=zs_ubuntu --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
docker run --name=zs_ubuntu --privileged=true -it -v /test:/test:rw b3797fa08f5b /bin/bash

ro:宿主机的文件可以同步给容器,但容器无法更改。

某些情况下,需要将宿主机映射的目录,让容器只有只读权限,read only,可以这样做:
docker run --name=zs_ubuntu --privileged=true -it -v /test:/test:ro b3797fa08f5b /bin/bash

进入容器,测试容器内写入
touch /test/d
touch: cannot touch 'd': Read-only file system

进入宿主机终端,测试文件写入:
touch /test/d
宿主机成功写入

进入容器,查看容器是否同步,发现已经同步
ls /test/d
a  b  c  d

容器数据卷的继承

卷的继承需要“–volumes-from 父容器卷” 来声明,具有父子关系的容器卷还是互相共享关系,父子间并没有强关联,意味着父容器停了或被删除,不影响子容器。

请空容器,方便测试。
docker rm -f 4432fa5f2d07
并删除/test下所有文件
rm -f /test/*
启动一个父容器
docker run --name parent --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
启动一个子容器
docker run --name son --privileged=true -it --volumes-from parent b3797fa08f5b /bin/bash
宿主机查看正在运行的容器实例
docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS         PORTS     NAMES
5ff477d6b3ec   b3797fa08f5b   "/bin/bash"   5 minutes ago   Up 4 minutes             son
a4da63aca520   b3797fa08f5b   "/bin/bash"   6 minutes ago   Up 6 minutes             parent

宿主机创建a文件
touch /test/a
两个容器上查看,发现a文件都存在。
touch /test

父级故障模拟,测试父子关联性,结果得出父子间没有强关联性。

在宿主机上停止父级容器
docker stop a4da63aca520
在宿主机上创建文件
touch /test/b
在son容器上执行ls,发现有a、b两个文件
ls /test
a b


在宿主机上删除父级容器
docker rm a4da63aca520
在宿主机上创建文件
touch /test/c
在son容器上执行ls,发现有a、b、c两个文件
ls /test
a b c

容器卷的多样化共享

多容用一卷:

强制删除所有容器,能不用则不用。
docker rm -f $(docker ps -aq)
删除宿主机下,容器卷目录所有文件
rm -f /test/*

开3个终端,创建3个容器
docker run --name one --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
docker run --name two --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash
docker run --name three --privileged=true -it -v /test:/test b3797fa08f5b /bin/bash

查看是否开启成功
docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED          STATUS          PORTS     NAMES
8ed7a2356d5c   b3797fa08f5b   "/bin/bash"   17 seconds ago   Up 10 seconds             three
ff2b2a92d984   b3797fa08f5b   "/bin/bash"   26 seconds ago   Up 25 seconds             two
220539fdf650   b3797fa08f5b   "/bin/bash"   54 seconds ago   Up 53 seconds             one

宿主机创建a文件
touch /test/a

三个容器分别执行ls /test,发现都有a
ls /teset
a

一容用多卷:

强制删除所有容器,能不用则不用。
docker rm -f $(docker ps -aq)
删除宿主机下,容器卷目录所有文件
rm -f /test/*
并额外创建2个目录
touch /test2 /test3
如下
ll / | grep test
drwxr-xr-x.   2 root root    6 412 03:07 test
drwxr-xr-x    2 root root    6 412 03:07 test2
drwxr-xr-x    2 root root    6 412 03:07 test3

创建一个容器,并映射3个目录
docker run --name test --privileged=true -it -v /test:/test -v /test2:/test2 -v /test3:/test3 b3797fa08f5b /bin/bash
发现容器内也有3个目录
ll / | grep test
drwxr-xr-x.   2 root root    6 Apr 11 19:07 test/
drwxr-xr-x    2 root root    6 Apr 11 19:07 test2/
drwxr-xr-x    2 root root    6 Apr 11 19:07 test3/

容器内执行
touch /test/a /test2/a /test3/a
宿主机查看,发现文件依然共享
ls /test /test2 /test3
/test:
a

/test2:
a

/test3:
a

网卡相关

安装docker后,执行ifconfig,会看到以下内容:

  • ens33(老版本的叫eth0)是配置宿主机网络用的。
  • lo是本地回环地址,用于本地主机内部通信的虚拟网络接口。
  • docker就是安装docker时虚拟出来的网卡,用于docker容器间和宿主机的通信:
    • flags=4099<UP,BROADCAST,MULTICAST> mtu 1500: 这部分显示了网络接口的名称(docker0)、标志和 MTU(最大传输单元)值(1500)。
    • inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255: 这部分显示了网络接口的 IPv4 地址(172.17.0.1)、子网掩码(255.255.0.0)和广播地址(172.17.255.255)。这个地址范围是 Docker 桥接网络的默认范围。
    • inet6 fe80::42:37ff:fef9:25d7 prefixlen 64 scopeid 0x20: 这部分显示了网络接口的 IPv6 地址。
    • ether 02:42:37:f9:25:d7 txqueuelen 0 (Ethernet): 这部分显示了网络接口的 MAC 地址和一些其他信息。
    • RX packets 4197 bytes 250537 (244.6 KiB): 这部分显示了接收到的数据包和字节数。
    • TX packets 4317 bytes 14144344 (13.4 MiB): 这部分显示了发送的数据包和字节数。。
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:37ff:fef9:25d7  prefixlen 64  scopeid 0x20<link>
        ether 02:42:37:f9:25:d7  txqueuelen 0  (Ethernet)
        RX packets 4197  bytes 250537 (244.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4317  bytes 14144344 (13.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.180  netmask 255.255.255.0  broadcast 192.168.0.255
        inet6 fe80::2545:6607:f0f7:64cb  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:39:be:95  txqueuelen 1000  (Ethernet)
        RX packets 20615  bytes 15431772 (14.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10726  bytes 954390 (932.0 KiB)
        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 32  bytes 2592 (2.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 32  bytes 2592 (2.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

执行ip a,也会看到类似的内容:

  • <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default: 这部分显示了网络接口的名称(docker0)、状态(DOWN)、标志(NO-CARRIER、BROADCAST、MULTICAST、UP)、MTU(最大传输单元)值(1500)以及队列规则(qdisc)等信息。
  • link/ether 02:42:37:f9:25:d7 brd ff:ff:ff:ff:ff:ff: 这部分显示了网络接口的 MAC 地址和广播地址。
  • inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever: 这部分显示了网络接口的 IPv4 地址(172.17.0.1)、子网掩码(/16),以及广播地址。valid_lft和 `preferred_lft 分别表示地址的有效生存时间和首选生存时间,设置为 forever 表示永久有效。
  • inet6 fe80::42:37ff:fef9:25d7/64 scope link valid_lft forever preferred_lft forever: 这部分显示了网络接口的 IPv6 地址和范围。
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 fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:39:be:95 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.180/24 brd 192.168.0.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::2545:6607:f0f7:64cb/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:37:f9:25:d7 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:37ff:fef9:25d7/64 scope link 
       valid_lft forever preferred_lft forever

Docker网络

docker网络顾名思义,为什么要去研究它?

  • 控制容器间通信:只有容器不通信,好比买了个手机不联网,技能无法充分发挥。
  • 降低对网络的运维成本:容器IP变动时(增加、减少容器数量等因素),可以通过服务名进行通信,保证通信不受影响。

Docker网络相关命令

在docker run时,可以使用docker run --network bridge …去指定驱动程序。

docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
f4481eb7078e   bridge    bridge    local
c10b6f388063   host      host      local
21c306a93cbb   none      null      local
  • NETWORK ID:网络唯一标识。
  • NAME:起个名。
  • DRIVER:Docker 网络所使用的驱动程序,一些常见的网络驱动程序包括:
    • bridge(桥接 默认值): 默认的 Docker 网络驱动程序,使用docker0网卡连接容器到宿主机的网络。
    • host(主机): 让容器直接使用宿主机的网络命名空间,与宿主机共享网络栈,使用这个,docker run -p就没有意义了。
    • overlay(覆盖): 允许在多个 Docker 宿主机上创建连接的容器网络,用于容器在不同宿主机间通信。
    • macvlan(MACVLAN): 允许容器拥有自己的 MAC 地址,并直接与物理网络相连。
    • none(无): 禁用容器的网络,使容器无法进行网络通信,很少用。
    • container(容器):新创建的容器不会创建自己的网卡,而是和一个指定容器共享IP和端口,很少用,容易端口冲突,且对容器有依赖性。
  • SCOPE:定义网络范围的作用域
    • local(本地 默认值): 这表示网络只在当前 Docker 宿主机上可见和可用,不会跨越宿主机边界。
    • global(全局): 这表示网络在所有 Docker 宿主机上都可见和可用,可以跨越宿主机边界。
    • swarm(集群): 这表示网络是 Docker Swarm 集群中的一部分,可以在整个 Swarm 集群中使用。

Docker对网络配置的增删改查操作:

执行网络联机的命令行帮助,会得到以下内容,无外乎就是增删改查
docker network --help
Usage:  docker network COMMAND

Manage networks

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  prune       Remove all unused networks
  rm          Remove one or more networks

Run 'docker network COMMAND --help' for more information on a command.


增:
docker network create test_net
7b7c0cbc15c65a5ef4a0e1ad5e7d997ec04afb322afc9e67845c8735ccf1fb06
docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
f4481eb7078e   bridge     bridge    local
c10b6f388063   host       host      local
21c306a93cbb   none       null      local
7b7c0cbc15c6   test_net   bridge    local

删:
docker network rm test_net
^[[Atest_net
docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f4481eb7078e   bridge    bridge    local
c10b6f388063   host      host      local
21c306a93cbb   none      null      local

改:极少操作。

查:
docker inspect f4481eb7078e
返回一个json。

Docker网络通信架构

  • docker0:虚拟出来一块网卡,让容器之间、宿主机、进行通信。docker0是虚拟出来的硬件,bridge是通信的方式。
  • veth:veth(Virtual Ethernet)是Linux系统中一种虚拟网络设备,常用于 Docker 容器之间和容器与宿主机之间的通信,当创建一个Docker容器时,Docker会为容器分配一个唯一的网络命名空间,并为该容器创建一个veth pair设备。容器内的veth设备称为 eth0(或其他指定的网络接口名),而与之配对的宿主机端的veth设备可以在宿主机上看到,通常以 vethXXX 这样的形式命名。通过这种方式,容器可以通过自己的网络接口与宿主机上的其他容器或外部网络进行通信。Docker 使用 Linux 的网络命名空间和 veth 设备来隔离容器的网络栈,同时通过网络桥接(如 docker0)实现容器与宿主机网络的连接和通信。
  • eth0:这是每个容器实例或宿主机自身的内部网卡。
  • 注意:容器内的eth0和veth总是成双成对的出现。
  • 通信方式:无论是容器与容器之间,容器与宿主机之间,都需要通过docker0的bridge方式通信。

上一张经典的图:
在这里插入图片描述

开两个Nginx证明一下是否是多出来两个veth:

关闭宿主机nginx服务,nginx设置开启了服务
service nginx stop
起两个nginx容器
docker run -d -p 80:80 nginx
docker run -d -p 8080:80 nginx
确定容器是否真的跑起来
docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS         PORTS                                   NAMES
bf6321d659c4   nginx     "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   funny_williams
859b85ccf760   nginx     "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp       brave_vaughan

确定配置是否成功,或用curl访问也行
netstat -nlp | grep 80
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      22982/docker-proxy  
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      22838/docker-proxy  
tcp6       0      0 :::8080                 :::*                    LISTEN      22988/docker-proxy  
tcp6       0      0 :::80                   :::*                    LISTEN      22844/docker-proxy  
unix  2      [ ACC ]     STREAM     LISTENING     50191    6480/abrtd           /var/run/abrt/abrt.socket


重点来了,然后再执行ifconfig,会发现多出来两个veth开头的网卡:
ifconfig

veth7c2861b: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::e881:5aff:fe82:55ca  prefixlen 64  scopeid 0x20<link>
        ether ea:81:5a:82:55:ca  txqueuelen 0  (Ethernet)
        RX packets 35  bytes 4797 (4.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 52  bytes 7096 (6.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth8ed54b8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::1cb3:6eff:fe84:1563  prefixlen 64  scopeid 0x20<link>
        ether 1e:b3:6e:84:15:63  txqueuelen 0  (Ethernet)
        RX packets 31  bytes 4017 (3.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 37  bytes 4395 (4.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

同理,可以使用ip a命令
ip addr

14: veth7c2861b@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether ea:81:5a:82:55:ca brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e881:5aff:fe82:55ca/64 scope link 
       valid_lft forever preferred_lft forever
18: veth8ed54b8@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 1e:b3:6e:84:15:63 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::1cb3:6eff:fe84:1563/64 scope link 
       valid_lft forever preferred_lft forever

想要验证,与eth0是否是成对出现的,但是nginx镜像缺少ip 或者ifconfig命令,apt-get update命令报错,导致无法验证。
实际上宿主机上看的veth7c2861b@if13和veth8ed54b8@if17中的if13与if17,都是与容器当中的网卡编号对应的。

当使用docker inspect 容器id时,就能看到该容器网络相关的信息。

docker inspect 6dc7f1d29a17 | tail -n 21
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "MacAddress": "",
                    "NetworkID": "f4481eb7078ebf9be90119f8a99f5869354ed14d9b093924da43bf1ba19b36a0",
                    "EndpointID": "",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "DriverOpts": null,
                    "DNSNames": null
                }
            }

对于这个json,做个介绍:

  • “IPAMConfig”: 这是用于管理IP地址的配置,通常在Docker网络模式为bridge时使用。
  • “Links”: 这里是容器与其他容器之间链接的信息,但在这个例子中为null,表示没有其他容器链接到这个容器。
  • “Aliases”: 这是容器的网络别名,也是null,表示没有设置别名。
  • “MacAddress”: 这是容器的MAC地址,通常由Docker自动生成。
  • “NetworkID”: 这是网络的唯一标识符,用于区分不同的Docker网络。
  • “EndpointID”: 这是容器端点的唯一标识符,用于标识容器在网络中的位置。
  • “Gateway”: 这是网络的网关地址,通常由Docker提供。
  • “IPAddress”: 这是容器分配的IP地址。
  • “IPPrefixLen”: 这是容器IP地址的前缀长度,通常是一个整数。
  • “IPv6Gateway”: 这是IPv6网络的网关地址。
  • “GlobalIPv6Address”: 这是容器的全局IPv6地址。
  • “GlobalIPv6PrefixLen”: 这是容器的全局IPv6地址的前缀长度。
  • “DriverOpts”: 这是网络驱动的选项配置,通常在特定网络驱动中使用。
  • “DNSNames”: 这是容器的DNS名称列表,用于解析容器内部的 DNS 查询。

不同容器配置不同的Docker网络

  • 为了分门别类,方便管理。
  • 有了它,可以避免IP变动引起的故障,为docker容器编排做准备。
创建网络
docker network create zs_test
ee465a9eccd7d758e3b4a4281539352d8169364f860091928f3296129c6ac384

并查看
docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
f4481eb7078e   bridge    bridge    local
c10b6f388063   host      host      local
21c306a93cbb   none      null      local
ee465a9eccd7   zs_test   bridge    local

开两个终端分别执行
docker run --name centos01 --network zs_test -it 5d0da3dc9764 /bin/bash
docker run --name centos02 --network zs_test -it 5d0da3dc9764 /bin/bash

然后再任意终端上ping另一个容器的name参数
ping centos02
PING centos02 (172.23.0.3) 56(84) bytes of data.
64 bytes from centos02.zs_test (172.23.0.3): icmp_seq=1 ttl=64 time=0.082 ms
64 bytes from centos02.zs_test (172.23.0.3): icmp_seq=2 ttl=64 time=0.095 ms
64 bytes from centos02.zs_test (172.23.0.3): icmp_seq=3 ttl=64 time=0.090 ms

使用name参数,可以避免IP变动情况的发生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/542169.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据治理专家岗位的能力模型

数据治理专家的角色要求其具备全方位的专业素养与技能&#xff0c;不仅要有深厚的业务理解与数据技术功底&#xff0c;还需展现出卓越的领导力、团队协作与沟通能力&#xff0c;以驱动组织内部数据治理工作的高效运行与持续优化。以下是对数据治理专家各项能力的深入解读&#…

STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978(5)

接前一篇文章&#xff1a;STM32H743VIT6使用STM32CubeMX通过I2S驱动WM8978&#xff08;4&#xff09; 本文参考以下文章及视频&#xff1a; STM32CbueIDE Audio播放音频 WM8978 I2S_stm32 cube配置i2s录音和播放-CSDN博客 STM32第二十二课&#xff08;I2S&#xff0c;HAL&am…

C++学习进阶:哈希思想的进一步体现

目录 前言 1.位图 1.1.位图的实现与原理 1.2.如何使用位图处理海量数据 2.布隆过滤器 2.1.知识引入 2.2.布隆过滤器的实现 2.3.布隆过滤器的应用 3.哈希切割 前言 我们在之前对哈希表的学习&#xff0c;明白了哈希的本质就是一种映射&#xff01;&#xff01;&#xf…

安达发|APS智能优化排产软件之模具约束

在制造业中&#xff0c;模具是生产过程中不可或缺的重要工具。然而&#xff0c;由于模具的制造周期长、成本高以及生产过程中的复杂性&#xff0c;如何合理安排模具的使用和生产计划成为了一个关键问题。为了解决这个问题&#xff0c;许多企业开始采用APS&#xff08;高级计划与…

主干网络篇 | YOLOv8更换主干网络之VanillaNet | 华为方舟实验室提出全新轻量级骨干架构

前言:Hello大家好,我是小哥谈。华为方舟实验室所提出的VanillaNet架构克服了固有复杂性的挑战,使其成为资源受限环境的理想选择。其易于理解和高度简化的架构为高效部署开辟了新的可能性。广泛的实验表明,VanillaNet提供的性能与著名的深度神经网络和vision transformers相…

深度剖析Java中的String类

目录 引言 String类的特性 String类的部分实现代码&#xff1a; 不可变性&#xff1a; 补充&#xff1a; 常量池&#xff1a; 不可变性的好处 创建String对象 创建String对象的常用的三种方法如下&#xff1a; 使用常量串构造&#xff08;最常用&#xff09;&#xf…

帝国cms仿《鳄鱼下载站》网站源码

仿《鳄鱼下载站》网站源码手机安卓软件网站模版 PHP网站源码 帝国cms内核 采用帝国cms7.5 环境PHPmysql 恢复数据库后如何修改密码: 双击表&#xff0c;进入对应的详细数据表&#xff0c;然后找到&#xff1a;www_96kaifa_com_enewsuser这个表&#xff0c;双击打开修改&…

SAP SD学习笔记06 - 受注的据否,受注的理由,简易变更(一括处理)

上文讲了一括处理和Block&#xff08;冻结&#xff09;处理。 SAP SD学习笔记05 - SD中的一括处理&#xff08;集中处理&#xff09;&#xff0c;出荷和请求的冻结&#xff08;替代实现承认功能&#xff09;-CSDN博客 本章继续讲SAP的流程中一些常用的操作。 1&#xff0c;受注…

【算法】分治-快排

个人主页 &#xff1a; zxctscl 如有转载请先通知 题目 前言1. 75. 颜色分类1.1 分析1.2 代码 2. 912. 排序数组2.1 分析2.2 代码 3. 215. 数组中的第K个最大元素3.1 分析3.2 代码 4. LCR 159. 库存管理 III4.1 分析4.2 代码 前言 分治就是分而治之 1. 75. 颜色分类 1.1 分析…

基于java+springboot+vue实现的网上购物系统(文末源码+Lw+ppt)23-42

摘 要 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决生活上的问题&#xff0c;网上购物系统展现了其蓬勃生命力和广阔的前景。与此同时&#xff0c;为…

Linux【实战篇】—— NFS服务搭建与配置

目录 一、介绍 1.1什么是NFS&#xff1f; 1.2客户端与服务端之间的NFS如何进行数据传输&#xff1f; 1.3RPC和NFS的启动顺序 1.4NFS服务 系统守护进程 二、安装NFS服务端 2.1安装NFS服务 2.2 创建共享目录 2.3创建共享目录首页文件 2.4关闭防火墙 2.5启动NFS服务 2.…

Java 语言程序设计(基础篇)原书第10版 梁勇著 PDF 文字版电子书

简介 Java 语言程序设计&#xff08;基础篇&#xff09;原书第 10 版 是 Java 语言的经典教材&#xff0c;中文版分为基础篇和进阶篇&#xff0c;主要介绍程序设计基础、面向对象程序设计、GUI 程序设计、数据结构和算法、高级 Java 程序设计等内容。本书通过示例讲解问题求解…

抖音滑块验证码加密的盐的位置

最近更新后之前很容易找到盐的位置的方法变了&#xff0c;抖音特意把盐隐藏起来了 {"reply": "RJC","models": "yAd8rl","in_modal": "DTn0nD2","in_slide": "ou7H0Ngda","move": …

C++算法题 - 双指针

目录 125. 验证回文串392. 判断子序列167. 两数之和 Ⅱ - 输入有序数组11. 盛最多的水15. 三数之和 125. 验证回文串 LeetCode_link 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 …

arm工作模式、arm9通用寄存器、异常向量表中irq的异常向量、cpsr中的哪几位是用来设置工作模式以及r13,r14,15别名是什么?有什么作用?

ARM 首先先介绍一下ARM公司。 ARM成立于1990年11月&#xff0c;前身为Acorn计算机公司 主要设计ARM系列RISC处理器内核 授权ARM内核给生产和销售半导体的合作伙伴ARM公司不生产芯片 提供基于ARM架构的开发设计技术软件工具评估版调试工具应用软件总线架构外围设备单元等等CPU中…

一起学习python——基础篇(20)

前言&#xff0c;之前经常从网上找一些免费的接口来测试&#xff0c;有点受制于人的感觉。想了想还不如直接写一个接口&#xff0c;这样方便自己测试。自己想返回什么格式就返回什么样子&#xff0c;不用担心服务报错&#xff0c;因为自己就可以完全掌控。然后宿舍二哥告诉我py…

spring boot集成logback到mysql 8

spring boot集成logback到mysql 8 依赖数据库准备创建log日志用户&#xff0c;并创建数据库执行建表sql 配置文件bugbug 1&#xff1a;Failed to instantiate type ch.qos.logback.classic.db.DBAppenderbug信息&#xff1a;解决&#xff1a; bug2: DBAppender cannot function…

windows SDK编程 --- 第一个程序

一、基础知识 1.Unicode 和 ANSI 在 Windows 编程中&#xff0c;Unicode 和 ANSI 是两种不同的字符编码方法&#xff0c;它们用于定义如何在计算机中表示和存储字符数据。 ANSI ANSI&#xff08;American National Standards Institute&#xff09;编码是一种基于单字节的字符…

最新视频理解大模型之MiniGPT4-video

前言 随着大模型的爆火&#xff0c;多模态大模型也随之卷了起来&#xff0c;基本每隔一小段时间就会冒出一个新模型。 今天给大家带来一个最新发现的关于视频理解的多模态大模型。 它的名字是MiniGPT4-video&#xff0c;可以看的出来其是MiniGPT4的一个分支&#xff1b;Mini…

vue3实现时钟效果

鼬鼬鼬鼬鼬被提需求了&#xff01;&#xff01;&#xff01; 产品&#xff1a;你学什么的&#xff1f; 我&#xff1a;跟CV有点关系 产品&#xff1a;control C加control V是吧 我&#xff1a;对对对 效果 时间实时变化&#xff1a; 页面部分 <template><div clas…