1、项目5 容器相关技术通过本章了解Docker容器相关技术,底层技术,Docker 内部以及容器之间管理数据,网络功能,Docker API,安全。目录任务任务5.1 Docker底层技术底层技术任务任务5.2 存储存储任务任务5.3 网络网络任务任务5.4 Docker API任务任务5.5.安全安全任务5.1 Docker底层技术 Docker 底层使用的核心技术包括 Linux 上的命名空间(Namespaces)控制组(Control groups)联合文件系统(Union file systems)和容器格式(Container format)。图5.1 虚拟机技术与容器技术的对比5.
2、1.1 命名空间nameSpace 命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。Linux内核提供了六种namespace隔离的系统调用,如下表所示。Namespace系统调用参数隔离内容UTSCLONE_NEWUTS主机名与域名IPCCLONE_NEWIPC信号量、消息队列和共享内存PIDCLONE_NEWPID进程编号NetworkCLONE_NEWNET网络设备、网络栈、端口等等MountCLONE_NEWNS挂载点(文件系统)UserCLONE_NEWUSER用户和用户组表
3、5.1 namespace六项隔离5.1.2控制组cgroupcgroups是Linux内核提供的一种机制,cgroup可以根据特定的行为,把一系列系统任务及其子任务整合或分隔到不同的资源等级分组中,从而为系统资源管理提供一个统一的框架。主要的功能包括:资源限制(Resource Limitation):cgroups可以对进程组使用的资源总额进行限制。如设定应用运行时使用内存的上限,一旦超过这个配额就发出OOM(Out of Memory)。优先级分配(Prioritization):通过分配的CPU时间片数量及硬盘IO带宽大小,实际上就相当于控制了进程运行的优先级。资源统计(Account
4、ing):cgroups可以统计系统的资源使用量,如CPU使用时长、内存用量等等,这个功能非常适用于计费。进程控制(Control):cgroups可以对进程组执行挂起、恢复等操作。通俗的来说,cgroups可以限制、记录、隔离进程组所使用的物理资源(包括:CPU、memory、IO等),为容器实现虚拟化提供了基本保证,是构建Docker等一系列虚拟化管理工具的基础。Cgroup功能实现特点:(1)cgroups的API以一个伪文件系统的方式实现,即用户可以通过文件操作实现cgroups的组织管理。(2)cgroups的组织管理操作单元可以细粒度到线程级别,用户态代码也可以针对系统分配的资源创
5、建和销毁cgroups,从而实现资源再分配和管理。(3)所有资源管理的功能都以subsystem(子系统)的方式实现,接口统一。(4)子进程创建之初与其父进程处于同一个cgroups的控制组。5.1.3联合文件系统UnionFS联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改按层(Layer)叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像,可以制作各种具体的应用镜像。Aufs是Docker最初采用的文件系统,由于Aufs未能加入到Linux内核,考虑到兼容性问题,
6、加入了Devicemapper的支持。Docker 目前支持的联合文件系统种类包括 Aufs、btrfs、vfs和DeviceMapper。典型的Linux文件系统由bootfs和rootfs两部分组成,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,当kernel被加载到内存中后bootfs就被umount了。rootfs(root file system)包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件。Docker镜像的典型结构如右图。传统的Linux加
7、载bootfs时会先将rootfs设为read-only,然后在系统自检之后将rootfs从read-only改为read-write,然后就可以在rootfs上进行写和读的操作了。为了形象化Docker的镜像结构,docker pull一个ubuntu:14.04的镜像,使用docker images-tree查看结果如下:rootqingze qingze#docker images-treeWarning:-tree is deprecated,it will be removed soon.See usage.511136ea3c5a Virtual Size:0 B 3b363fd9
8、d7da Virtual Size:192.5 MB 607c5d1cca71 Virtual Size:192.7 MB f62feddc05dc Virtual Size:192.7 MB 8eaa4ff06b53 Virtual Size:192.7 MB Tags:ubuntu:14.04因为如果高Docker版本,docker image不再使用,可以使用“docker history 镜像ID”来查看。可以看到Ubuntu的镜像中有多个长ID的layer,且以一种树状结构继承下来,如下图。其中,第n+1层继承了第n层,并在此基础上有了自己的内容,直观上的表现就是第n+1层占用磁盘空
9、间增大。并且,不同的镜像可能会有相同的父镜像。例如,图中Tomcat和Nginx 继承于同一个Vim 镜像,这种组织方式起到共享的作用,节约了镜像在物理机上占用的空间。使用docker save命令保存镜像tar,查询其结构。rootqingze qingze#docker save-o ubuntu.tar ubuntu:14.04rootqingze qingze#tar-tf ubuntu.tar 3b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a/3b363fd9d7dab4db9591058a3f43e80
10、6f6fa6f7e2744b63b2df4b84eadb0685a/VERSION3b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a/json3b363fd9d7dab4db9591058a3f43e806f6fa6f7e2744b63b2df4b84eadb0685a/layer.tar511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d
11、4d2698e22c158/VERSION511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tar607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa/607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa/VERSIO
12、N607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa/json607c5d1cca71dd3b6c04327c3903363079b72ab3e5e4289d74fb00a9ac7ec2aa/layer.tar8eaa4ff06b53ff7730c4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a/8eaa4ff06b53ff7730c4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a/VERSION8eaa4ff06b53ff7730c
13、4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a/json8eaa4ff06b53ff7730c4d7a7e21b4426a4b46dee064ca2d5d90d757dc7ea040a/layer.tarf62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73/f62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73/VERSIONf62feddc05dc67da9b725361f97d7ae72a32e35
14、5ce1585f9a60d090289120f73/jsonf62feddc05dc67da9b725361f97d7ae72a32e355ce1585f9a60d090289120f73/layer.tarrepositories5.1.4 容器管理 1)Libcontainer在2013年Docker刚发布的时候,它是一款基于LXC的开源容器管理引擎。随着Docker的不断发展,它开始有了更为远大的目标,将底层实现都抽象化到Libcontainer的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用namespace、cgroups技术或是使用systemd等其他方案,只
15、要实现了Libcontainer定义的一组接口,Docker都可以运行。这也为Docker实现全面的跨平台带来了可能。Libcontainer功能实现上涵盖了包括namespaces使用、cgroups管理、Rootfs的配置启动、默认的Linux capability权限集、以及进程运行的环境变量配置。本身主要分为三大块工作内容,一是容器的创建及初始化,二是容器生命周期管理,三则是进程管理,调用方为Docker的execdriver。容器的监控主要通过cgroups的状态统计信息,未来会加入进程追踪等更丰富的功能。另一方面,Libcontainer在安全支持方面也为用户尽可能多的提供了支持和
16、选择。2)runCLinux基金会于2015年6月成立OCI(Open Container Initiative)组织,旨在围绕容器格式和运行时制定一个开放的工业化标准。OCI的目标是为了避免容器的生态分裂为“小生态王国”,确保一个引擎上构建的容器可以运行在其他引擎之上。这是实现容器可移植性至关重要的部分。该组织一成立便得到了包括谷歌、微软、亚马逊、华为等一系列云计算厂商的支持。3)containerd2016年12月Docker 将Docker Engine 中的核心元件Containerd 开源,作为一个独立的开源项目独立发展,目标是提供一个更加开放、稳定的容器运行基础设施。Contain
17、erd可以说是Docker 引擎的引擎(Runtime)。和包含在Docker Engine里containerd相比,独立的containerd将具有更多的功能,可以涵盖整个容器运行时管理的所有需求。Containerd面向运维人员而构建,目的构建工业级规模的Docker系统,在性能上进行了优化,Containerd利用runC来提供高级功能,比如热迁移(checkpoint&restore)seccomp以及用户命名空间支持,这将为Docker引入这些功能敞开大门。containerd的功能和架构如下:Containerd分三层,最上层为API,包括GRPC API(Go RPC)和Met
18、rics API。中间层为内部子系统,包括三个:(1)Distribution:和Docker Registry打交道,拉取镜像(2)Bundle:管理本地磁盘上面镜像的子系统。(3)Runtime:创建容器、管理容器的子系统。最下面为功能组件包括内容、元数据、快照、执行器和监控器。任务5.2 存储下面介绍Docker 内部以及容器之间管理数据。在容器中管理数据主要有两种方式。(1)数据卷(2)数据卷容器5.2.1 数据卷1)数据卷(Data volumes)。数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性:(1)数据卷可以在容器之间共享和重用。(2)对数据
19、卷的修改会立马生效。(3)对数据卷的更新,不会影响镜像(4)数据卷默认会一直存在,即使容器被删除。数据卷的使用,类似于Linux下对目录或文件进行mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看到的是挂载的数据卷。2)创建一个数据卷在用 docker run 命令的时候,使用-v 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。下面创建一个名为 web 的容器,并加载一个数据卷到容器的/webapp 目录。$sudo docker run-d-P-name web-v/webapp training/webapp python app.py可
20、以在Dockerfile中使用 VOLUME 来添加一个或者多个新的卷到由该镜像创建的任意容器。3)删除数据卷数据卷是被设计用来持久化数据的,它的生命周期独立于容器,Docker不会在容器被删除后自动删除数据卷,并且也不存在垃圾回收这样的机制来处理没有任何容器引用的数据卷。如果需要在删除容器的同时移除数据卷。可以在删除容器的时候使用 docker rm-v 这个命令。4)挂载一个主机目录作为数据卷使用-v 标记也可以指定挂载一个本地主机的目录到容器中去。$sudo docker run-d-P-name web-v/src/webapp:/opt/webapp training/webapp
21、python app.py上面的命令加载主机的/src/webapp 目录到容器的/opt/webapp 目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在Docker 会自动为你创建它。Docker 挂载数据卷的默认权限是读写,用户也可以通过:ro 指定为只读。$sudo docker run-d-P-name web-v/src/webapp:/opt/webapp:ro training/webapp python app.py5)查看数据卷的具体信息在主机里使用以下命令可以查看指定容器的信息
22、,在输出的内容中找到其中和数据卷相关的部分,可以看到所有的数据卷都是创建在主机的/var/lib/docker/volumes/下面的$docker inspect web.Volumes:/webapp:/var/lib/docker/volumes/fac362.80535,VolumesRW:/webapp:true.6)挂载一个本地主机文件作为数据卷-v 标记也可以从主机挂载单个文件到容器中$sudo docker run-rm-it-v/.bash_history:/.bash_history ubuntu/bin/bash这样就可以记录在容器输入过的命令了。如果直接挂载一个文件,很
23、多文件编辑工具,包括 vi 或者 sed-in-place,可能会造成文件 inode 的改变,所以最简单的办法就直接挂载文件的父目录。5.2.2 数据卷容器数据卷容器(Data volume containers)涉及容器间共享的持久化、序列化的数据持久性的数据,最好创建数据卷容器。1)创建数据卷容器。(1)首先,创建一个名为 dbdata 的数据卷容器:$sudo docker run-d-v/dbdata-name dbdata training/postgres echo Data-only container for postgres(2)然后,在其他容器中使用-volumes-fr
24、om 来挂载 dbdata 容器中的数据卷。$sudo docker run-d-volumes-from dbdata-name db1 training/postgres$sudo docker run-d-volumes-from dbdata-name db2 training/postgres(3)可以使用超过一个的-volumes-from 参数来指定从多个容器挂载不同的数据卷。也可以从其他已经挂载了数据卷的容器来级联挂载数据卷。$sudo docker run-d-name db3-volumes-from db1 training/postgres2)利用数据卷容器来备份、恢复
25、、迁移数据卷。可以利用数据卷对其中的数据进行进行备份、恢复和迁移。(1)备份:首先使用-volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从主机挂载当前目录到容器的/backup 目录。命令如下:$sudo docker run-volumes-from dbdata-v$(pwd):/backup ubuntu tar cvf/backup/backup.tar/dbdata容器启动后,使用了tar 命令来将dbdata 卷备份为容器中/backup/backup.tar 文件,也就是主机当前目录下的名为 backup.tar 的文件。(2)恢复:如果要恢复数据到一
26、个容器,首先创建一个带有空数据卷的容器dbdata2。$sudo docker run-v/dbdata-name dbdata2 ubuntu/bin/bash然后创建另一个容器,挂载 dbdata2 容器卷中的数据卷,并使用untar 解压备份文件到挂载的容器卷中。$sudo docker run-volumes-from dbdata2-v$(pwd):/backup busybox tar xvf/backup/backup.tar为了查看/验证恢复的数据,可以再启动一个容器挂载同样的容器卷来查看$sudo docker run-volumes-from dbdata2 busybox
27、/bin/ls/dbdata5.3.1 Docker网络功能介绍1)容器网络Docker 的网络实现其实就是利用了 Linux 上的网络命名空间、网桥和虚拟网络设备(VETH)等实现。默认Docker安装完成后会创建一个网桥docker0。Docker中的网络接口默认都是虚拟的网络接口。Docker 容器网络在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通。Docker 创建一个容器执行如下操作:(1)创建一对虚拟接口,分别放到本地主机和新容器中;(2)本地主机一端桥接到默认的docker0或指定网桥上,并具有一个唯一的名字,如veth65f9;(3)容器一端放到新容器中,并修改名字作
28、为eth0,这个接口只在容器的命名空间可见;(4)从网桥可用地址段中获取一个空闲地址IP分配给容器的 eth0,并配置默认路由到桥接网卡veth65f9。(5)完成这些之后,容器就可以使用eth0虚拟网卡来连接其他容器和其他网络。另外,可以在docker run的时候通过-net参数来指定容器的网络配置,有4个可选值:-net=bridge 这个是默认值,连接到默认的网桥。-net=host 告诉 Docker 不要将容器网络放到隔离的命名空间中,使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它root进程一样可以打开低范围的端口机。因此使用这个选项的时候要非常小心
29、。如果进一步的使用-privileged=true,容器会被允许直接配置主机的网络堆栈。-net=container:NAME_or_ID 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 lo 环回接口通信。-net=none 让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。当容器结束后,Docker 会清空容器,容器内的 eth0 会随网络命名空间一起被清除,A 接口也被自动从 docker0 卸载。图5.7
30、Docker 容器网络示意图2)网络配置细节用户使用-net=none 后,可以自行配置网络,让容器达到跟平常一样具有访问网络的权限。通过这个过程,可以了解 Docker 配置网络的细节。(1)首先,启动一个/bin/bash 容器,指定-net=none 参数。$sudo docker run-i-t-rm-net=none base/bin/bashroot63f36fc01b5f:/#(2)在本地主机查找容器的进程 id,并为它创建网络命名空间。$sudo docker inspect-f.State.Pid 63f36fc01b5f2778$pid=2778$sudo mkdir-p/
31、var/run/netns$sudo ln-s/proc/$pid/ns/net/var/run/netns/$pid(3)检查桥接网卡的 IP 和子网掩码信息。$ip addr show docker021:docker0:.inet 172.17.42.1/16 scope global docker0.(4)创建一对“veth pair”接口 A 和 B,绑定 A 到网桥 docker0,并启用它$sudo ip link add A type veth peer name B$sudo brctl addif docker0 A$sudo ip link set A up(5)将B放到
32、容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。$sudo ip link set B netns$pid$sudo ip netns exec$pid ip link set dev B name eth0$sudo ip netns exec$pid ip link set eth0 up$sudo ip netns exec$pid ip addr add 172.17.42.99/16 dev eth0$sudo ip netns exec$pid ip route add default via 172.17.42.1以上,就是 Docker
33、配置网络的具体过程。3)外部访问容器,端口映射容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过-P 或-p 参数来指定端口映射。(1)查看端口信息当使用-P 标记时,Docker 会随机映射一个 4900049900 的端口到内部容器开放的网络端口。使用 docker ps 可以看到,本地主机的 49155 被映射到了容器的 5000 端口。此时访问本机的 49155 端口即可访问容器内 web 应用提供的界面。$sudo docker run-d-P training/webapp python app.py$sudo docker ps-lCONTAINER ID IMAG
34、E COMMAND CREATED STATUS PORTS NAMESbc533791f3f5 training/webapp:latest python app.py 5 seconds ago Up 2 seconds 0.0.0.0:49155-5000/tcp nostalgic_morse同样的,可以通过 docker logs 命令来查看应用的信息。$sudo docker logs-f nostalgic_morse*Running on http:/0.0.0.0:5000/10.0.2.2-23/May/2014 20:16:31 GET/HTTP/1.1 200-10.0
35、.2.2-23/May/2014 20:16:31 GET/favicon.ico HTTP/1.1 404-p(小写的)则可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。支持的格式有ip:hostPort:containerPort|ip:containerPort|hostPort:containerPort。(2)映射所有接口地址使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行$sudo docker run-d-p 5000:5000 training/webapp python app.py此时默认会
36、绑定本地所有接口上的所有地址。(3)映射到指定地址的指定端口可以使用 ip:hostPort:containerPort 格式指定映射使用一个特定地址,比如 localhost 地址 127.0.0.1$sudo docker run-d-p 127.0.0.1:5000:5000 training/webapp python app.py(4)映射到指定地址的任意端口使用 ip:containerPort 绑定 localhost 的任意端口到容器的 5000 端口,本地主机会自动分配一个端口。$sudo docker run-d-p 127.0.0.1:5000 training/weba
37、pp python app.py还可以使用 udp 标记来指定 udp 端口$sudo docker run-d-p 127.0.0.1:5000:5000/udp training/webapp python app.py(5)查看映射端口配置使用 docker port 来查看当前映射的端口配置,也可以查看到绑定的地址$docker port nostalgic_morse 5000127.0.0.1:49155.容器有自己的内部网络和 ip 地址,-p 标记可以多次使用来绑定多个端口,例如:$sudo docker run-d-p 5000:5000 -p 3000:80 trainin
38、g/webapp python app.py5.3.2 容器互联容器的连接(linking)系统是除了端口映射外,另一种跟容器中应用交互的方式。该系统会在源和接收容器之间创建一个隧道,接收容器可以看到源容器指定的信息。1)自定义容器命名连接系统依据容器的名称来执行。因此,首先需要自定义一个好记的容器命名。使用-name 标记可以为容器自定义命名。$sudo docker run-d-P-name web training/webapp python app.py使用 docker ps 来验证设定的命名。$sudo docker ps-lCONTAINER ID IMAGE COMMAND C
39、REATED STATUS PORTS NAMESaed84ee21bde training/webapp:latest python app.py 12 hours ago Up 2 seconds 0.0.0.0:49154-5000/tcp web也可以使用 docker inspect 来查看容器的名字。$sudo docker inspect-f .Name aed84ee21bde/web注意:容器的名称是唯一的。如果已经命名了一个叫 web 的容器,当你要再次使用 web 这个名称的时候,需要先用docker rm 来删除之前创建的同名容器。在执行 docker run 的时候如
40、果添加-rm 标记,则容器在终止后会立刻删除。注意,-rm 和-d 参数不能同时使用。2)容器互联使用-link 参数可以让容器之间安全的进行交互。下面先创建一个新的数据库容器。$sudo docker run-d-name db training/postgres删除之前创建的 web 容器$docker rm-f web然后创建一个新的 web 容器,并将它连接到 db 容器$sudo docker run-d-P-name web-link db:db training/webapp python app.py此时,db 容器和 web 容器建立互联关系。-link 参数的格式为-lin
41、k name:alias,其中 name 是要链接的容器的名称,alias 是这个连接的别名。使用 docker ps 来查看容器的连接$docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES349169744e49 training/postgres:latest su postgres-c/usr About a minute ago Up About a minute 5432/tcp db,web/dbaed84ee21bde training/webapp:latest python app.py 16 hours
42、 ago Up 2 minutes 0.0.0.0:49154-5000/tcp web可以看到自定义命名的容器db 和 web,db 容器的 names 列有 db 也有 web/db。这表示 web 容器链接到 db 容器,web 容器将被允许访问 db 容器的信息。Docker 在两个互联的容器之间创建了一个安全隧道,而且不用映射它们的端口到宿主主机上。在启动 db 容器的时候并没有使用-p 和-P标记,从而避免了暴露数据库端口到外部网络上。Docker 通过 2 种方式为容器公开连接信息:(1)环境变量使用 env 命令来查看 web 容器的环境变量$sudo docker run-r
43、m-name web2-link db:db training/webapp env.DB_NAME=/web2/dbDB_PORT=tcp:/172.17.0.5:5432DB_PORT_5000_TCP=tcp:/172.17.0.5:5432DB_PORT_5000_TCP_PROTO=tcpDB_PORT_5000_TCP_PORT=5432DB_PORT_5000_TCP_ADDR=172.17.0.5.其中 DB_ 开头的环境变量是供 web 容器连接 db 容器使用,前缀采用大写的连接别名。(1)除了环境变量,Docker 还添加 host 信息到父容器的/etc/hosts 的
44、文件。下面是父容器 web 的 hosts 文件这里有 2 个 hosts,第一个是 web 容器,web 容器用 id 作为他的主机名,第二个是 db 容器的 ip 和主机名。可以在 web 容器中安装 ping 命令来测试跟db容器的连通。$sudo docker run-t-i-rm-link db:db training/webapp/bin/bashrootaed84ee21bde:/opt/webapp#cat/etc/hosts172.17.0.7 aed84ee21bde.172.17.0.5 dbrootaed84ee21bde:/opt/webapp#apt-get ins
45、tall-yqq inetutils-pingrootaed84ee21bde:/opt/webapp#ping dbPING db(172.17.0.5):48 data bytes56 bytes from 172.17.0.5:icmp_seq=0 ttl=64 time=0.267 ms56 bytes from 172.17.0.5:icmp_seq=1 ttl=64 time=0.250 ms56 bytes from 172.17.0.5:icmp_seq=2 ttl=64 time=0.256 ms用 ping 来测试db容器,它会解析成 172.17.0.5。注意:官方的 u
46、buntu 镜像默认没有安装 ping,需要自行安装。用户可以链接多个父容器到子容器,比如可以链接多个 web 到 db 容器上。5.3.3 高级网络配置本章将介绍 Docker 的一些高级网络配置和选项。当 Docker 启动时,会自动在主机上创建一个 docker0 虚拟网桥,实际上是 Linux 的一个 bridge,可以理解为一个软件交换机。它会在挂载到它的网口之间进行转发。同时,Docker 随机分配一个本地未占用的私有网段(在 RFC1918 中定义)中的一个地址给 docker0 接口。比如典型的 172.17.42.1,掩码为 255.255.0.0。此后启动的容器内的网口也会
47、自动分配一个同一网段(172.17.0.0/16)的地址。当创建一个 Docker 容器的时候,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。接下来的部分将介绍在一些场景中,Docker 所有的网络定制配置。以及通过 Linux 命令来调整、补充、甚至替换 Docker 默认的网络配
48、置。1)快速配置指南)快速配置指南下面是一个跟 Docker 网络相关的命令列表。其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。-b BRIDGE or-bridge=BRIDGE-指定容器挂载的网桥-bip=CIDR-定制 docker0 的掩码-H SOCKET.or-host=SOCKET.-Docker 服务端接收命令的通道-icc=true|false-是否支持容器之间进行通信-ip-forward=true|false-请看下文容器之间的通信-iptables=true|false-是否允许 Docker 添加 iptables 规则-mtu=BY
49、TES-容器网络中的 MTU下面2个命令选项既可以在启动服务时指定,也可以 Docker 容器启动(docker run)时候指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值。-dns=IP _ADDRESS.-使用指定的DNS服务器-dns-search=DOMAIN.-指定DNS搜索域最后这些选项只有在 docker run 执行时使用,因为它是针对容器的特性内容。-h HOSTNAME or-hostname=HOSTNAME-配置容器主机名-link=CONTAINER_NAME:ALIAS-添加到另一个容器的连接-net
50、=bridge|none|container:NAME_or_ID|host-配置容器的桥接模式-p SPEC or-publish=SPEC-映射容器端口到宿主主机-P or-publish-all=true|false-映射容器所有端口到宿主主机2)配置 DNSDocker 没有为每个容器专门定制镜像,那么怎么自定义配置容器的主机名和 DNS 配置呢?秘诀就是它利用虚拟文件来挂载到来容器的3个相关配置文件。在容器中使用 mount 命令可以看到挂载信息:$mount./dev/disk/by-uuid/1fec.ebdf on/etc/hostname type ext4./dev/dis