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 --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 (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 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:7f:13:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.8.188/24 brd 192.168.8.255 scope global noprefixroute dynamic ens33
valid_lft 62600sec preferred_lft 62600sec
inet6 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:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 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 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
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 0
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 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 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:7f:13:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.8.188/24 brd 192.168.8.255 scope global noprefixroute dynamic ens33
valid_lft 61353sec preferred_lft 61353sec
inet6 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:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 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 1
inet6 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 1
inet6 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 0
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 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 0
inet 172.17.0.4/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 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 2
inet6 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 --help
Usage: docker network COMMAND
Manage networks
Options:
--help Print usage
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.
查看所有网络
[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 --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--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 0
inet 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 0
inet 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 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
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 0
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 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 0
inet 192.168.0.4/24 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::42:c0ff:fea8:4/64 scope link
valid_lft forever preferred_lft forever
不同网段的容器互联使用 docker network connect [OPTIONS] NETWORK CONTAINER
本文深入解析Docker镜像的分层结构,讲解了联合文件系统、镜像加载过程以及如何从容器创建镜像。重点介绍了数据卷的使用方法,包括匿名和具名挂载,以及容器间的网络连接,包括自定义网络和服务名访问。
2006

被折叠的 条评论
为什么被折叠?



