文章目录

  • 1 Docker镜像原理
    • 1.1 联合文件系统
    • 1.2 镜像加载原理
    • 1.3 镜像分层结构原理剖析
    • 1.4 从容器创建一个镜像
  • 2 容器数据卷
    • 2.1 使用centos测试
    • 2.2 使用mysql测试
    • 2.3 匿名和具名挂载
      • 2.3.1 匿名挂载
      • 2.3.2 具名挂载
      • 2.3.3 查看挂载路径
      • 2.3.4 容器对于宿主机挂载目录的读写权限
  • 3 Dockerfile
    • 3.1 编写Dockerfile
      • 3.1.1 Dockerfile编写规范(语法)
      • 3.1.2 Dockerfile构建容器的流程
      • 3.1.3 小结
    • 3.2 Dockerfile Command
  • 4 Docker网络
    • 4.1 使用nginx测试
    • 4.2 剖析宿主机怎么ping容器原理
    • 4.3 docker0小结
    • 4.4 使用服务名在容器之间互访问
    • 4.5 自定义网络
      • 4.5.1 自定义网卡
      • 4.5.2 网络连通

1 Docker镜像原理

镜像是一种轻量级、可执行的软件包,用于打包开发好的软件程序,镜像包括开发好的软件源代码,代码运行需要的环境变量,类库,配置文件等等,总之,只要有镜像,这个软件就可以被创造成容器,运行在宿主机的docker中。

1.1 联合文件系统

Union File System 简称UnionFS,UnionFS是一种分层、轻量级、高性能的文件系统,UnionFS是Docker镜像的基础,基于基础镜像可以制作各种镜像;UnionFS支持对文件系统进行层层叠加,提交一次增加一层。

Docker从仓库拉取镜像的时候看上去是一个文件,但是实际上是一次加载多个文件系统,联合加载会把各层文件系统叠加到一起,最终的文件系统包含所有层的文件和目录。

1.2 镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标
准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

对于一个正常的CentOS最少要几个G,为什么在Docker中只有200多MB,其实对于一个精简的CentOS,只包含最基本的命令,工具和程序库就可以,底层直接调用宿主机的内核,所有只需要提供rootFS就可以。

对于不同的Linux发行版,bootFS基本一样,rootFS会有差别,不同发行版可以公用bootFS

1.3 镜像分层结构原理剖析

[root@localhost ~]# docker pull redis
Using default tag: latest
Trying to pull repository docker.io/library/redis ...
latest: Pulling from docker.io/library/redis
33847f680f63: Pull complete  第一层
26a746039521: Pull complete  第二层
18d87da94363: Pull complete  第三层
5e118a708802: Pull complete  第四层
ecf0dbe7c357: Pull complete  第五层
46f280ba52da: Pull complete  第六层
Digest: sha256:cd0c68c5479f2db4b9e2c5fbfdb7a8acb77625322dd5b474578515422d3ddb59
Status: Downloaded newer image for docker.io/redis:latest

我在拉取一个nginx镜像

从docker hub拉起redis的镜像发现下载的过程是分层的,分了六个块一层一层的下载,这么做的好处是资源共享,能够减少宿主机资源的消耗,在拉取nginx镜像的时候,第一层提示已经存在,所以docker不会重复拉取,镜像的每一层都可以被共享,查看镜像的详细信息。

[root@localhost ~]# docker image inspect redis:latest
[{"Id": "sha256:aa4d65e670d6518e5da96ca9d1a76370a942970a8802e6d5cc6bcf058ab12ca7","RepoTags": ["docker.io/redis:latest"],"DockerVersion": "20.10.7","Author": "","Architecture": "amd64","Os": "linux","Size": 105408205,"VirtualSize": 105408205,"RootFS": {"Type": "layers","Layers": ["sha256:814bff7343242acfd20a2c841e041dd57c50f0cf844d4abd2329f78b992197f4","sha256:dd1ebb1f5319785e34838c7332a71e5255bda9ccf61d2a0bf3bff3d2c3f4cdb4","sha256:11f99184504048b93dc2bdabf1999d6bc7d9d9ded54d15a5f09e36d8c571c32d","sha256:e461360755916af80821289b1cbc503692cf63e4e93f09b35784d9f7a819f7f2","sha256:45f6df6342536d948b07e9df6ad231bf17a73e5861a84fc3c9ee8a59f73d0f9f","sha256:262de04acb7e0165281132c876c0636c358963aa3e0b99e7fbeb8aba08c06935"]}}
]

所有的Docker镜像都来源于一个基础镜像层,官方的大部分镜像都是基于scrach的,当修改或者增加新内容时,就在当前镜像层上创建新的镜像层。


上图镜像中包含三个镜像层,第一层是一个Ubantu镜像,第二层是一个Python镜像,第三层是一个安全镜像,如果在增加什么功能,会增加新的镜像层,同时镜像也会保持更新,镜像一直是所有镜像层的组合。


每个镜像层有三个文件,对于这个镜像来说就有6个文件,镜像可以用相同的方式访问到这6个文件。


对于这个镜像来说,应该有6个文件,因为第三层的文件7是对第二层文件5的更新,所以文件5就不是必要的。
Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统
一的文件系统。
Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfilter 一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分
层和 CoW。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合并,对外提供统一的视图。

Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像的顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层!

1.4 从容器创建一个镜像

[root@localhost ~]# docker commit --helpUsage:  docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]Create a new image from a container's changesOptions:-a, --author string    Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")-c, --change list      Apply Dockerfile instruction to the created image (default [])-m, --message string   Commit message-p, --pause            Pause container during commit (default true)[root@localhost ~]# docker run -it --name centos01 centos # 创建一个centos容器
[root@58cb1845e985 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@58cb1845e985 /]# mkdir test
[root@58cb1845e985 /]# cd test
[root@58cb1845e985 test]# vim 1.py  # 使用vim创建一个文件
bash: vim: command not found  # 发现没有vim命令
[root@58cb1845e985 test]# yum install vim #安装一下vim
Installed:gpm-libs-1.20.7-17.el8.x86_64       vim-common-2:8.0.1763-15.el8.x86_64       vim-enhanced-2:8.0.1763-15.el8.x86_64       vim-filesystem-2:8.0.1763-15.el8.noarch       which-2.21-12.el8.x86_64
Complete!
[root@localhost ~]docker commit -m "add vim" -a "zhao" centos01 mycentos:0.1
[root@localhost ~]# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mycentos            0.1                 3fbc3342fc64        6 minutes ago       275 MB
[root@localhost ~]# docker run -it mycentos:0.1 /bin/bash
[root@localhost ~]# vim 1.txt # 会打开vim窗口

2 容器数据卷

容器是将应用和运行环境打包形成容器运行,但是数据不能一直在容器中,需要数据持久化,比如有一个Mysql的容器,当容器被删除之后,数据就随着消失了,这肯定是不行的。

卷技术本质上就是一个文件或目录,由Docker挂载到容器上,不属于联合文件系统,卷用于数据持久化和共享数据,卷完全独立于容器的生命周期,即使容器删除数据卷也不会被删除,达到了持久化的目的,数据卷中的更改不会包含在镜像的更新中,卷的生命周期一直持续到没有容器使用为止。

2.1 使用centos测试

[root@localhost home]# docker run -v /home/dockervolumn:/home -it --name centos01 centos  # 创建一个容器并运行
[root@f4bc05336ae9 /]# exit  # 退出正在运行的容器
exit
[root@localhost home]# docker start centos01  # 在启动容器
centos01
[root@localhost home]# docker ps  # 查看正在运行的容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f4bc05336ae9        centos              "/bin/bash"         22 seconds ago      Up 3 seconds                            centos01
[root@localhost home]# docker inspect centos01  # 查看容器的详细信息
"Mounts": [ # 表示卷挂载{"Type": "bind",  "Source": "/home/dockervolumn", # 宿主机目录"Destination": "/home",         # 容器内目录"Mode": "","RW": true,                     # 容器对宿主机内的权限 RW 可读写"Propagation": "rprivate"}],[root@f4bc05336ae9 /]# cd /home                     # 容器内——切换到home
[root@f4bc05336ae9 home]# ls
[root@f4bc05336ae9 home]# touch 1.txt               # 容器内——创建文件1.txt
[root@f4bc05336ae9 home]# echo "hello world">1.txt  # 容器内——写值
[root@f4bc05336ae9 home]# cat 1.txt                 # 容器内——查看
hello world
[root@localhost dockervolumn]# cat 1.txt            # 宿主机——查看内容与镜像内相同
hello world
[root@localhost dockervolumn]# echo "i changed it" > 1.txt # 宿主机——修改内容
[root@localhost dockervolumn]# cat 1.txt                   # 宿主机——检查已经修改
i changed it
[root@f4bc05336ae9 home]# cat 1.txt                        # 容器内——已更新
i changed it

对于centos挂载目录没有操作权限

[root@f4bc05336ae9 home]# ls
ls: cannot open directory '.': Permission denied

解决方案

原因是CentOS7中的安全模块selinux把权限禁掉了,至少有以下三种方式解决挂载的目录没有权限的问题:
1.在运行容器的时候,给容器加特权,及加上 --privileged=true 参数:

docker run -i -t -v /soft:/soft --privileged=true 686672a1d0cc /bin/bash

2.临时关闭selinux:

setenforce 0

3.添加selinux规则,改变要挂载的目录的安全性文本

2.2 使用mysql测试

docker search mysql      # 搜索镜像
docker pull mysql:5.7    # 拉取镜像
docker run -d -p 3310:3306 -v
/home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e
MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7  # 创建&启动镜像

2.3 匿名和具名挂载

2.3.1 匿名挂载

-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护
docker volume ls

2.3.2 具名挂载

-v 卷名:/容器内路径
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx

2.3.3 查看挂载路径

docker volume inspect nginxconfig

对于卷名与宿主机名录名怎么区分?看“/”,如果有就是宿主机目录名,没有就是卷名

2.3.4 容器对于宿主机挂载目录的读写权限

# ro: readonly
# rw: readwrite
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx:rw nginx

3 Dockerfile

Dockerfile是创建docker镜像的文件,文件由命令和参数组成
Dockerfile创建容器的步骤

  • 编写Dockerfile文件
  • docker build 构建容器
  • docker run 创建容器

3.1 编写Dockerfile

3.1.1 Dockerfile编写规范(语法)

  • 指定必须全部大写,后面必须跟至少一个参数
  • 执行从上到小顺序执行
  • 表示注释“#号”
  • 每条指令都会创建一个新的镜像层,并对镜像进行提交

3.1.2 Dockerfile构建容器的流程

  • Docker从基础镜像运行一个容器
  • 执行一条指令并对容器进行修改
  • 执行类似docker commit的操作提交一个新的镜像层
  • Docker基于刚提交的运行一个新容器,等待接收下一条命令
  • 执行Dockerfile后面的命令直到所有指令都完成

3.1.3 小结

  • Dockerfile:类似于软件原材料
    DockerFile定义了进程需要的一切东西。DockerFile涉及的内容
    包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进
    程和内核进程(当引用进行需要和系统服务和内核进程打交道,这时需要考虑如何设计 namespace的权
    限控制)等等
  • Docker镜像:类似于Apk文件,在DockerFile 定义了一个文件之后,Docker build 时会产生一个Docker镜像,当运行Docker 镜像时,会真正开始提供服务;
  • Docker容器:类似于安装到手机上供用户使用的软件,直接提供服务

3.2 Dockerfile Command

FROM              # 基础镜像,当前镜像基于哪个镜像
MAINTAINER        # 镜像维护者
RUN               # 容器构建时需要运行的命令
EXPOSE            # 容器对外开放的端口
WORKDIR           # 创建容器后,终端登录进来的工作目录,容器的初始目录
ENV               # 用来在构建镜像过程中设置环境变量
ADD               # 将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY              # 类似ADD,拷贝文件和目录到镜像中
VOLUME            # 容器数据卷,用于数据保存和持久化工作
CMD               # 指定一个容器启动时要运行的命令,dockerFile中可以有多个CMD指令,但只有最
后一个生效!
ENTRYPOINT        # 指定一个容器启动时要运行的命令!和CMD一样
ONBUILD           # 当构建一个被继承的DockerFile时运行命令,父镜像在被子镜像继承后,父镜像的
ONBUILD被触发

CMD:Dockerfile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数
替换!

ENTRYPOINT: docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!

4 Docker网络

查看宿主机的网络

[root@localhost /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::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 1000link/ether 00:0c:29:7f:13:ba brd ff:ff:ff:ff:ff:ffinet 192.168.8.188/24 brd 192.168.8.255 scope global noprefixroute dynamic ens33valid_lft 62600sec preferred_lft 62600secinet6 fe80::92d6:85a5:dfe7:896d/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:2c:c1:39:cb brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:2cff:fec1:39cb/64 scope link valid_lft forever preferred_lft forever

三个网络如下:

lo        127.0.0.1             # 本机回环地址
ens33     192.168.8.188/24      # 虚拟机虚拟IP地址
docker0   172.17.0.1/16         # docker网桥

4.1 使用nginx测试

[root@localhost /]# docker run -d -P --name nginx01 nginx
7e715d6ff7564d1b59acfcb1da267244e3b10275d7a7531ec47b8f68a4d8bc70
[root@localhost /]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
7e715d6ff756        nginx               "/docker-entrypoin..."   2 seconds ago       Up 1 second         0.0.0.0:32768->80/tcp   nginx01
[root@localhost /]# docker run -it --name centos02 centos
[root@localhost /]# docker exec -it centos02 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
58: eth0@if59: <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 0inet 172.17.0.3/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::42:acff:fe11:3/64 scope link valid_lft forever preferred_lft forever[root@localhost /]# ping 172.17.0.3  # 宿主机ping容器 可以通
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.080 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.097 ms

4.2 剖析宿主机怎么ping容器原理

安装Docker的linux主机都有一个docker0虚拟网卡。这是桥接到宿主机的虚拟网卡,使用了veth-pair技术

[root@localhost /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::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 1000link/ether 00:0c:29:7f:13:ba brd ff:ff:ff:ff:ff:ffinet 192.168.8.188/24 brd 192.168.8.255 scope global noprefixroute dynamic ens33valid_lft 61353sec preferred_lft 61353secinet6 fe80::92d6:85a5:dfe7:896d/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:2c:c1:39:cb brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 scope global docker0valid_lft forever preferred_lft foreverinet6 fe80::42:2cff:fec1:39cb/64 scope link valid_lft forever preferred_lft forever
59: veth7c37353@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 22:b6:12:64:08:10 brd ff:ff:ff:ff:ff:ff link-netnsid 1inet6 fe80::20b6:12ff:fe64:810/64 scope link valid_lft forever preferred_lft forever

比较宿主机和容器的IP地址

  • 宿主机
59: veth7c37353@if58: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 22:b6:12:64:08:10 brd ff:ff:ff:ff:ff:ff link-netnsid 1inet6 fe80::20b6:12ff:fe64:810/64 scope link valid_lft forever preferred_lft forever
  • 容器
58: eth0@if59: <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 0inet 172.17.0.3/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::42:acff:fe11:3/64 scope link valid_lft forever preferred_lft forever

每启动一个容器,Linux就会多一个虚拟网卡

[root@localhost /]# docker run -it --name centos03 centos # 再启动一个centos
[root@9e63aa022a17 /]# ip addr  查看地址
62: eth0@if63: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.4/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::42:acff:fe11:4/64 scope link valid_lft forever preferred_lft forever
[root@localhost /]#ip addr
63: veth1a70833@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 66:5c:8b:90:ef:fd brd ff:ff:ff:ff:ff:ff link-netnsid 2inet6 fe80::645c:8bff:fe90:effd/64 scope link valid_lft forever preferred_lft forever

“找规律”

Linux主机:59: veth7c37353@if58       Centos02容器:58: eth0@if59
Linux主机:63: veth1a70833@if62       Centos03容器:62: eth0@if63只要启动一个容器,就有一对网卡
veth-pair就是一对虚拟设备接口,必须成对出现。一端连着协议,一端彼此相连,就向桥梁一样,广泛应用与链接各种虚拟网络设备

测试centos02 能不能ping通 centos02

[root@localhost /]# docker exec -it centos02 ping 172.17.0.4
PING 172.17.0.4 (172.17.0.4) 56(84) bytes of data.
64 bytes from 172.17.0.4: icmp_seq=1 ttl=64 time=0.093 ms

测试结果能够发现,centos02可以ping通centos03,这两个容器公用一个路由器,这个路由器就是docker0,任何一个容器启动默认都链接到docker0,docker会默认给容器分配一个IP。

4.3 docker0小结

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信
Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。

4.4 使用服务名在容器之间互访问

前面说过了,运行在相同宿主机上面的容器可以通过docker分配的随机IP地址相互访问到,但是有一种情况:如果容器升级停掉了,重新创建并运行一个新容器,这样IP地址就改变了,访问这个容器的所有网络链接都要修改IP地址才能重新链接服务,这样就很麻烦。
不要怕,docker替我们考虑到了这个问题。

测试centos02直接访问centos03

[root@localhost /]# docker exec -it centos02 ping centos03
ping: centos03: Name or service not known

结果一目了然,肯定是行不通的。

测试新建一个centos01在启动时候链接centos02(通)

[root@localhost /]# docker run --name centos01 -it --link centos02 centos
[root@localhost /]# docker exec -it centos01 ping centos02
PING centos02 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.064 ms

测试用centos01pingcentos03(不通)

[root@localhost /]# docker exec -it centos01 ping centos03
ping: centos03: Name or service not known

测试用centos02pingcentos01(不通)

[root@localhost /]# docker exec -it centos02 ping centos01
ping: centos01: Name or service not known

这种现象的原理剖析,看centos01的hosts文件

[root@localhost /]# docker exec -it centos01 cat /etc/hosts
127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3  centos02 6c15298d931e  # centos02 被加到了centos01的hosts文件中
172.17.0.5  60d247715ec6

–link 本质

--link 的本质是把link的域名和IP地址写到了hosts文件中

4.5 自定义网络

–link 这种方式目前已经不推荐使用了,目前比较流行的是自定义网络的方式

[root@localhost /]# docker network --helpUsage: docker network COMMANDManage networksOptions:--help   Print usageCommands: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.

查看所有网络

[root@localhost /]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
238fd640e360        bridge              bridge              local
c77cf97addc4        host                host                local
a04f95a329d7        none                null                local

网络模式

网络模式 配置 说明
bridge –net=bridge 默认值,在docker0上为容器创建新的网络栈
none –net=none 不配置网络,用户可以进入容器,自行配置
container –net=container:name/id 容器和另外一个容器共Networknamespace。kubernetes中的pod就是多个容器共享一个Networknamespace。
host –net=host 容器和宿主机共享Network namespace
用户自定义 –net=自定义网络 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络

查看一个具体网络详细信息

[root@localhost /]# docker network inspect 238fd640e360
[{"Name": "bridge","Id": "238fd640e360bbebb9dc2c5a0b91b6d28063ad55c2b4e55c6b15b7f2d497751b","Created": "2021-08-10T09:28:10.078287651+08:00","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.17.0.0/16", # 容器可以分配的IP范围 255*255 - 0 - 255 = 65534可分配"Gateway": "172.17.0.1"    # docker0的IP地址}]},"Internal": false,"Attachable": false,"Containers": {"60d247715ec6692608250b21dab4a050a4adf90370dbeb37a34e266fc0b3c759": {"Name": "centos01","EndpointID": "82e8f21be1fac13959d38b2a3ae7e83f6e30c70939d882f3b72ac1b5314da357","MacAddress": "02:42:ac:11:00:05","IPv4Address": "172.17.0.5/16","IPv6Address": ""},"6c15298d931ec255d5b1dbc61d51284e28b31ed2c13eaf2f987f5b34066f2430": {"Name": "centos02","EndpointID": "45db8c85c1c015160d71588e11be1ddde77134ec6479bb30c6458c56d0e3c37c","MacAddress": "02:42:ac:11:00:03","IPv4Address": "172.17.0.3/16","IPv6Address": ""},"7e715d6ff7564d1b59acfcb1da267244e3b10275d7a7531ec47b8f68a4d8bc70": {"Name": "nginx01","EndpointID": "6b804ad9ece0fa791fe1421e323035e8cfd972cdd23d18a1ad97cb0275b2fa63","MacAddress": "02:42:ac:11:00:02","IPv4Address": "172.17.0.2/16","IPv6Address": ""},"9e63aa022a174b29835dc68e0808d222ac54fee1fc7bc9055c4c8d590f10ac40": {"Name": "centos03","EndpointID": "94eb7e67694be41f329d8d8f70d073224a1eb39b969b32f5ca3ce1ec13c1be20","MacAddress": "02:42:ac:11:00:04","IPv4Address": "172.17.0.4/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": {}}
]

4.5.1 自定义网卡

默认情况是docker0

# 默认我们不配置网络,也就相当于默认值 --net bridge 使用的docker0
docker run -it -P --name centos01 --net bridge centos# docker0特点:默认的   域名访问不通   --link域名通了,删了又不行

创建一个自定义网络,不用docker0

[root@localhost /]# docker network create --helpUsage:  docker network create [OPTIONS] NETWORKCreate a networkOptions:--attachable             Enable manual container attachment--aux-address map        Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])-d, --driver string          Driver to manage the Network (default "bridge")--gateway stringSlice    IPv4 or IPv6 Gateway for the master subnet--help                   Print usage--internal               Restrict external access to the network--ip-range stringSlice   Allocate container ip from a sub-range--ipam-driver string     IP Address Management Driver (default "default")--ipam-opt map           Set IPAM driver specific options (default map[])--ipv6                   Enable IPv6 networking--label list             Set metadata on a network (default [])-o, --opt map                Set driver specific options (default map[])--subnet stringSlice     Subnet in CIDR format that represents a network segment

创建网络

[root@localhost /]# docker network create --driver bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 mynet
5a9f100be1df1e03bed29c22177b2be01f9d462a8307f28db946c1937f3dcfca
[root@localhost /]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
238fd640e360        bridge              bridge              local
c77cf97addc4        host                host                local
5a9f100be1df        mynet               bridge              local
a04f95a329d7        none                null                local

查看网络详细

[root@localhost /]# docker network inspect mynet
[{"Name": "mynet","Id": "5a9f100be1df1e03bed29c22177b2be01f9d462a8307f28db946c1937f3dcfca","Created": "2021-08-10T17:31:25.554550359+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,"Containers": {},"Options": {},"Labels": {}}
]

使用自定义网络,启动两个centos

[root@localhost /]# docker run -it --name centos-mynet-01 --net mynet centos
[root@faad73a0ed6c /]# exit
exit
[root@localhost /]# docker run -it --name centos-mynet-02 --net mynet centos
[root@8de4ca3b5e36 /]# exit
exit
[root@localhost /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@localhost /]# docker start centos-mynet-01
centos-mynet-01
[root@localhost /]# docker start centos-mynet-02
centos-mynet-02
[root@localhost /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
8de4ca3b5e36        centos              "/bin/bash"         23 seconds ago      Up 2 seconds                            centos-mynet-02
faad73a0ed6c        centos              "/bin/bash"         33 seconds ago      Up 4 seconds                            centos-mynet-01
[root@localhost /]# docker exec -it centos-mynet-01 ip addr
73: eth0@if74: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c0:a8:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.0.2/24 scope global eth0
[root@localhost /]# docker exec -it centos-mynet-02 ip addr
75: eth0@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c0:a8:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.0.3/24 scope global eth0
[root@localhost /]# docker exec -it centos-mynet-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.064 ms
[root@localhost /]# docker exec -it centos-mynet-01 ping centos-mynet-02
PING centos-mynet-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-mynet-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.042 ms
64 bytes from centos-mynet-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.126 ms
[root@localhost /]# docker exec -it centos-mynet-02 ping centos-mynet-01
PING centos-mynet-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-mynet-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.033 ms
[root@localhost /]# ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.078 ms
[root@localhost /]# ping 192.168.0.4
PING 192.168.0.4 (192.168.0.4) 56(84) bytes of data.
From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
[root@localhost /]# docker network inspect mynet
"Containers": {"8de4ca3b5e361b2f7d6897dd4a405c583463c55ed5811e3b0b83528075105d1d": {"Name": "centos-mynet-02","EndpointID": "cc5f706bd243965593600822377d16c26dc474fa3faf5e2da5bfdebad46ac6d9","MacAddress": "02:42:c0:a8:00:03","IPv4Address": "192.168.0.3/24","IPv6Address": ""},"faad73a0ed6cb156688ef16a0279e57b41618e2b8982a253ac8d34217702caab": {"Name": "centos-mynet-01","EndpointID": "9edd313f1149e90ab912934c7fd503df83969b0c18027635e82ea2217d1387b3","MacAddress": "02:42:c0:a8:00:02","IPv4Address": "192.168.0.2/24","IPv6Address": ""}},

自定义网络帮我们维护好了所有域名和IP地址映射

4.5.2 网络连通

在docker0下面再创建两个容器

[root@localhost /]# docker run -it --name centos1 centos
[root@5c155a39d581 /]# exit
exit
[root@localhost /]# docker run -it --name centos2 centos
[root@30594893a7bc /]# exit
exit
[root@localhost /]# docker start centos1
centos1
[root@localhost /]# docker start centos2
centos2
[root@localhost /]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
30594893a7bc        centos              "/bin/bash"         18 seconds ago      Up 3 seconds                            centos2
5c155a39d581        centos              "/bin/bash"         32 seconds ago      Up 5 seconds                            centos1
8de4ca3b5e36        centos              "/bin/bash"         10 minutes ago      Up 10 minutes                           centos-mynet-02
faad73a0ed6c        centos              "/bin/bash"         10 minutes ago      Up 10 minutes                           centos-mynet-01
[root@localhost /]# docker exec -it centos1 ping centos-mynet-01
ping: centos-mynet-01: Name or service not known
[root@localhost /]# docker network connect mynet centos1
[root@localhost /]# docker exec -it centos1 ping centos-mynet-01
PING centos-mynet-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-mynet-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.081 ms
64 bytes from centos-mynet-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.055 ms
[root@localhost /]# docker network inspect mynet
[{"Name": "mynet","Id": "5a9f100be1df1e03bed29c22177b2be01f9d462a8307f28db946c1937f3dcfca","Created": "2021-08-10T17:31:25.554550359+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,"Containers": {"5c155a39d581d952c739518861c0e1426dacdc15d802fe711a073edc12fb6525": {"Name": "centos1","EndpointID": "d5c7e9190d166340a1166ab07a7907d5278ace3bf1dd2da6f4c05a3f7ee70f30","MacAddress": "02:42:c0:a8:00:04","IPv4Address": "192.168.0.4/24","IPv6Address": ""},"8de4ca3b5e361b2f7d6897dd4a405c583463c55ed5811e3b0b83528075105d1d": {"Name": "centos-mynet-02","EndpointID": "cc5f706bd243965593600822377d16c26dc474fa3faf5e2da5bfdebad46ac6d9","MacAddress": "02:42:c0:a8:00:03","IPv4Address": "192.168.0.3/24","IPv6Address": ""},"faad73a0ed6cb156688ef16a0279e57b41618e2b8982a253ac8d34217702caab": {"Name": "centos-mynet-01","EndpointID": "9edd313f1149e90ab912934c7fd503df83969b0c18027635e82ea2217d1387b3","MacAddress": "02:42:c0:a8:00:02","IPv4Address": "192.168.0.2/24","IPv6Address": ""}},"Options": {},"Labels": {}}
]
[root@localhost /]# docker exec -it centos1 ip addr   # centos1 有双网卡
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
81: eth0@if82: <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 0inet 172.17.0.2/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
85: eth1@if86: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c0:a8:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.0.4/24 scope global eth1valid_lft forever preferred_lft foreverinet6 fe80::42:c0ff:fea8:4/64 scope link valid_lft forever preferred_lft forever

不同网段的容器互联使用 docker network connect [OPTIONS] NETWORK CONTAINER

《万字长文》-吃透Docker-进阶篇相关推荐

  1. docker进阶篇(一) ---- Volume(数据卷)

    引言 docker的镜像是由多个只读的文件系统叠加在一起形成的.当我们在我启动一个容器的时候,docker会加载这些只读层并在这些只读层的上面(栈顶)增加一个读写层.这时如果修改正在运行的容器中已有的 ...

  2. 3万字长文记录Docker 最全学习笔记,手把手带你入个门

    前言 以下是我为大家准备的几个精品专栏,喜欢的小伙伴可自行订阅,你的支持就是我不断更新的动力哟! MATLAB-30天带你从入门到精通 MATLAB深入理解高级教程(附源码) tableau可视化数据 ...

  3. Docker进阶篇之DockerFile,教你用DockerFile构建镜像

    文章目录 一.DockerFile介绍 二.DockerFile构建过程 三.DockerFile指令 四.实战测试 4.1 对比原生CentOS 五.CMD 和 ENTRYPOINT 的区别 5.1 ...

  4. 万字长文:用这篇文章聊聊To B运营都做些什么

    正文共:11154字 预计阅读时间:30分钟 文:悠然布衣 (这篇文章会比较泛的聊聊To B运营是做什么的,不会太详细的去聊一个具体的技巧,想要交流具体技巧的朋友可以跟我交流.) (PS:排版好麻烦啊 ...

  5. Docker 进阶篇

    1 Docker 安装MySQL主从复制 1.1 主从复制原理 MySQL 主从复制的核心就是二进制日志,过程如下 如上图所示,过程分为三步 1.master 主库在事务提交时,会把数据变更记录在二进 ...

  6. Docker进阶篇 - (一)Docker Compose

    Docker Compose 简介 能够解决的问题:DockerFile build run 一次只能手动操作一个容器,如果到微服务层次,有100个微服务都有依赖关系的,那么前面的方法就显得很笨重,D ...

  7. 【❤️万字长文总结❤️】一篇学会Redis高可用✔集群✔搭建详细教程

    大家好,我是Lex 喜欢欺负超人那个Lex 擅长领域:python开发.网络安全渗透.Windows域控Exchange架构 今日重点:今天总结一下Redis集群高可用的搭建流程 [惊喜推荐+优质资源 ...

  8. 【狂神说】Docker【进阶篇】

    [狂神说Java]Docker进阶篇超详细版教程通俗易懂_哔哩哔哩_bilibili 官网:https://www.docker.com/ 文档地址: https://docs.docker.com/ ...

  9. 两万字长文总结,梳理 Java 入门进阶那些事

    两万字长文总结,梳理 Java 入门进阶那些事 先给大家看下完整的思维导图,也是这篇文章的主要脉络. Java从入门到进阶学习路线 主导三个项目,让我独当一面 能力提升你要怎么学 全篇总结 Java ...

  10. 两万字长文总结,梳理 Java 入门进阶哪些事(推荐收藏)

    两万字长文总结,梳理 Java 入门进阶哪些事(推荐收藏) 程序员小跃 2021-01-12 13:19:09  23  收藏 分类专栏: Java学习之路 文章标签: java 数据库 redis ...

最新文章

  1. java目录更改当前_Java-MVC:查看目录更改的最佳方法
  2. oracle发送邮件附件,oracle发送邮件存储过程:
  3. mysql 导入8msql文件_MySQL导入大容量SQL文件数据问题
  4. python导入哨兵数据_Python 下载哨兵Sentinel数据(Sentinel-1~3)
  5. python3输入密码显示*_python在控制台输入密码但是不显示
  6. 【收藏】SAP记账码
  7. Servlet课程0425(五) sendRedirect实现不同页面共享数据
  8. 软件开发人员薪资标准 人月_IT从业者培训前后薪资差距近3000块钱
  9. 80386/386/Intel386 架构/流水线及其优化
  10. hdu1141 Factstone Benchmark(利用对数进行大数比较)
  11. flask 自定义错误页面
  12. python网络-多进程(21)
  13. saltstack远程操作WINDOWS的POWERSHELL脚本
  14. day19【前台】支付
  15. storage 主机集群共享卷数据不同步_codis 高可用集群跳过nginx 代理
  16. 〖3D激光点云〗深度学习点云知识!
  17. pyodbc linux 乱码,python-无法在Linux上安装pyodbc
  18. MacBook上内容太大无法拷贝到U盘问题的解决
  19. 百度:一盗功成万网枯
  20. 百度网盘文件管理助手 – 多账号多开浏览器

热门文章

  1. 在OpenFOAM中标记某些区域自适应加密
  2. 等保2.0控制点总结
  3. 线性规划模型详解及实际应用反思
  4. 不断突破道,用道来挣钱才能长稳,才能心安!
  5. 数字三角形的多种解法思路
  6. FC金手指使用方法+大全
  7. 商务通打开对话窗口容错代码
  8. 工作多年想转行,有哪些正确的方法及技巧呢
  9. linux gpu 地址空间,显卡内存和进程的虚拟地址空间
  10. 查找同一网络的计算机,怎么从网络中查询另一台计算机的ip地址