备注:
趁这几天不太忙,试着粗略翻译了docker高级网络配置这篇文章。ipv6方面没有翻译,目前未涉及。在快搞完这个文章时,发现在开发者社区已经被翻译了,地址。所以点对点通信是借过来的,省了些力气。本人英文水平不高,还请包涵。
Configuring DNS
How can Docker supply each container with a hostname and DNS configuration, without having to build a custom image with the hostname written inside? Its trick is to overlay three crucial /etc files inside the container with virtual files where it can write fresh information. You can see this by running mount inside a container:
docker如何给每一个容器配置主机名与dns,而无需创建一个包含主机名的定置的image?它的戏法是用可以写实时信息的虚拟文件来覆盖3个关键的容器内部的/etc/文件。我们可以在一个容器内部运行mount查看:
$$ mount
...
/dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/hosts type ext4 ...
/dev/disk/by-uuid/1fec...ebdf on /etc/resolv.conf type ext4 ...
...
This arrangement allows Docker to do clever things like keep resolv.conf up to date across all containers when the host machine receives new configuration over DHCP later. The exact details of how Docker maintains these files inside the container can change from one Docker version to the next, so you should leave the files themselves alone and use the following Docker options instead.
这个约定允许docker灵活执行任务,比如当主机通过dhcp收到最近的配置后保证所在的容器的resolv.conf实时更新。docker如何维护容器内的文件的精确细节能从一个docker的版本到下一个改变,所以应让它们独自丢弃掉这些文件,并且使用下面的选项来代替:
Four different options affect container domain name services.
4个不同的选项影响容器域名称服务
-h HOSTNAME or --hostname=HOSTNAME — sets the hostname by which the container knows itself. This is written into /etc/hostname, into /etc/hosts as the name of the container's host-facing IP address, and is the name that /bin/bash inside the container will display inside its prompt. But the hostname is not easy to see from outside the container. It will not appear in docker ps nor in the /etc/hosts file of any other container.
-h 设置为由容器自己知道的主机名。这会写入/etc/hostname,/etc/hosts作为容器面向的ip的名称,以及容器内要显示的/bin/bash提示符。但这个主机名不是很容易从容器的外面看到。
--link=CONTAINER_NAME_or_ID:ALIAS — using this option as you run a container gives the new container's /etc/hosts an extra entry named ALIAS that points to the IP address of the container identified by CONTAINER_NAME_or_ID. This lets processes inside the new container connect to the hostname ALIAS without having to know its IP. The --link= option is discussed in more detail below, in the section Communication between containers. Because Docker may assign a different IP address to the linked containers on restart, Docker updates the ALIAS entry in the /etc/hosts file of the recipient containers.
--link=CONTAINER_NAME_or_ID:ALIAS 使用这个选项在你运行一个容器时,将能此容器的/etc/hosts文件中增加一个额外ALIAS主机名,这个名字名为CONTAINER_NAME的容器的IP地址的别名。这使得新容器的内部进程可以访问主机名为ALIAS的容器而不用知道它的IP。--link= 关于这个选项的详细讨论请看:Communication between containers.因为docker可以分配一个不同的ip地址给被链接的容器在重启时,docker在接收容器的/etc/hosts文件更新这个ALIAS名字。
--dns=IP_ADDRESS... — sets the IP addresses added as server lines to the container's /etc/resolv.conf file. Processes in the container, when confronted with a hostname not in /etc/hosts, will connect to these IP addresses on port 53 looking for name resolution services.
--dns 设置这个ip地址做为server写到容器的/etc/hosts文件中。容器中的处理流程,当面对一个主机名没在/etc/hosts中时,会连接这个地址的53端口查找名称解析服务。
--dns-search=DOMAIN... — sets the domain names that are searched when a bare unqualified hostname is used inside of the container, by writing search lines into the container's /etc/resolv.conf. When a container process attempts to access host and the search domain example.com is set, for instance, the DNS logic will not only look up host but also host.example.com. Use --dns-search=. if you don't wish to set the search domain.
--dns-search
--dns-search 当一个未修饰的不合格的主机名被用在容器内时,通过写入search行到容器的/etc/resolv.conf设置domain names。当一个容器流程尝试访问主机并且search domain example.com被设置时,比如,这个dns原理将不仅查找主机而且也会查找host.example.com。
Note that Docker, in the absence of either of the last two options above, will make /etc/resolv.conf inside of each container look like the /etc/resolv.conf of the host machine where the docker daemon is running. You might wonder what happens when the host machine's /etc/resolv.conf file changes. The docker daemon has a file change notifier active which will watch for changes to the host DNS configuration. When the host file changes, all stopped containers which have a matching resolv.conf to the host will be updated immediately to this newest host configuration. Containers which are running when the host configuration changes will need to stop and start to pick up the host changes due to lack of a facility to ensure atomic writes of the resolv.conf file while the container is running. If the container's resolv.conf has been edited since it was started with the default configuration, no replacement will be attempted as it would overwrite the changes performed by the container. If the options (--dns or --dns-search) have been used to modify the default host configuration, then the replacement with an updated host's /etc/resolv.conf will not happen as well.
注意,当上面两个参数不存在时,docker将会在容器内生成与运行docker守护进程的宿主机相类似的/etc/resolv.conf。你可以好奇当宿主机的/etc/resolv.conf生成改变时会发生什么。docker守护进程有一个活动的文件改变通告者,它会监控宿主机的dns配置。当host文件发生改变时,所有被停止的容器将会立刻被更新成最新的host配置。在容器运行期间因为不具备确保/etc/resolv.conf原子写的能力,在运行的容器在宿主机的配置改变时需要stop和start来恢复host的改变。自容器以默认的配置启动后,如果容器的/etc/resolv.conf被编辑过,不会有替换发生,同时它将覆盖由容器执行的改变。如果使用了--dns和--dns-search改变默认的宿主机配置,那么被更新过的宿主机的/etc/resolv.conf也不会发生替换。
Communication between containers and the wider world
容器与公网间的通信
Whether a container can talk to the world is governed by two factors.
一个容器是否能与公网交互由两个因素支配。
Is the host machine willing to forward IP packets? This is governed by the ip_forward system parameter. Packets can only pass between containers if this parameter is 1. Usually you will simply leave the Docker server at its default setting --ip-forward=true and Docker will go set ip_forward to 1 for you when the server starts up. To check the setting or turn it on manually:
宿主机会转发ip包吗?这是由ip_forward系统参数支配的。如果为1,数据包只能在容器间传递。通常你你只是简单的让docker服务保留它默认的配置--ip-forward=true,并且docker会在服务启动时设置ip_forward为1.检查设置或者手动打开它:
$ cat /proc/sys/net/ipv4/ip_forward 0
$ echo 1 > /proc/sys/net/ipv4/ip_forward
$ cat /proc/sys/net/ipv4/ip_forward 1
Many using Docker will want ip_forward to be on, to at least make communication possible between containers and the wider world.
May also be needed for inter-container communication if you are in a multiple bridge setup.
许多使用docker的人想让ip_forward是打开的,至少在容器与公网间的尽可能的通信。如果人然一个多个网桥设置中,内部网桥通信也可能是需要的。
Do your iptables allow this particular connection? Docker will never make changes to your system iptables rules if you set --iptables=false when the daemon starts. Otherwise the Docker server will append forwarding rules to the DOCKER filter chain.
你的iptables允许特别的连接吗?docker不会生成更改你的iptables的规则,当docker守护进程启动时如果你设置--iptables=false。不然docker服务会追加转发规则到DOCKER filter链中。
Docker will not delete or modify any pre-existing rules from the DOCKER filter chain. This allows the user to create in advance any rules required to further restrict access to the containers.
docker不会删除或更改docker filter链中任何预存在的规则。这样允许用户事先创建任何需要求的规则来进一步地限制访问容器。
Docker's forward rules permit all external source IPs by default. To allow only a specific IP or network to access the containers, insert a negated rule at the top of the DOCKER filter chain. For example, to restrict external access such that only source IP 8.8.8.8 can access the containers, the following rule could be added:
docker的forward规则默认准许所有外部的源ip。如果仅允许一个指定的ip或网络访问容器,在DOCKER filter链的顶部插入一个否定的规则。例如,限制外部访问仅允许源IP为8.8.8.8可以访问容器。
$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP
Communication between containers
容器间的通迅
Whether two containers can communicate is governed, at the operating system level, by two factors.
Does the network topology even connect the containers' network interfaces? By default Docker will attach all containers to a single docker0 bridge, providing a path for packets to travel between them. See the later sections of this document for other possible topologies.
网络拓朴连接到容器的网络接口吗?默认的docker会附加所有的容器到一个单独的docker0桥上,为数据包在它们之间经过提供一个路径。
Do your iptables allow this particular connection? Docker will never make changes to your system iptables rules if you set --iptables=false when the daemon starts. Otherwise the Docker server will add a default rule to the FORWARD chain with a blanket ACCEPT policy if you retain the default --icc=true, or else will set the policy to DROP if --icc=false.
你的iptables允许特别的连接吗?docker不会改变你的系统的iptables规则在进程启动时如果你设置--iptables=false。另外docker会增加一个以完全ACCEPT策略的默认的规则到FORWARD链,如果你保留默认的--icc=true,或者也会设置策略为DROP,如果--icc=true.
It is a strategic question whether to leave --icc=true or change it to --icc=false (on Ubuntu, by editing the DOCKER_OPTS variable in /etc/default/docker and restarting the Docker server) so that iptables will protect other containers — and the main host — from having arbitrary ports probed or accessed by a container that gets compromised.
是否保留--icc=true或改变它为--icc=false是一个非常重要的问题,以使iptables保护其它的容器和宿主机从任意端口探测或容器泄露访问。
If you choose the most secure setting of --icc=false, then how can containers communicate in those cases where you want them to provide each other services?
如果你选择了最安全的--icc=false设置,那么怎样能让他们的容器之间相互提供服务的情况下进行沟通?
The answer is the --link=CONTAINER_NAME_or_ID:ALIAS option, which was mentioned in the previous section because of its effect upon name services. If the Docker daemon is running with both --icc=false and --iptables=true then, when it sees docker run invoked with the --link= option, the Docker server will insert a pair of iptables ACCEPT rules so that the new container can connect to the ports exposed by the other container — the ports that it mentioned in the EXPOSE lines of its Dockerfile. Docker has more documentation on this subject — see the linking Docker containers page for further details.
答案是--link=CONTAINER_NAME_or_ID:ALIAS参数,这就是之前提到的基于它们的名称服务之上影响。如果docker守护进程正在以--icc=false和--iptables=true运行,那么,当它看到docker运行调用了--link=参数时,docker server会插入一对iptables ACCEPT规则以让新的容器能访问其它容器的开放端口--这个端口在它们的dockerfile中EXPOSE行提及。
Note: The value CONTAINER_NAME in --link= must either be an auto-assigned Docker name like stupefied_pare or else the name you assigned with --name= when you ran docker run. It cannot be a hostname, which Docker will not recognize in the context of the --link= option.
注意: --link=中CONTAINER_NAME的值必须即可以是docker自动分配的名字,也可以是你使用--name=参数启动时分配的名字。它不能是一个主机名,这样docker将不会识别--link=参数的内容。
Note: Docker is careful that its host-wide iptables rules fully expose containers to each other's raw IP addresses, so connections from one container to another should always appear to be originating from the first container's own IP address.
注意: docker对于宿主机的iptables的规则完全地开放容器间的ip地址是很谨慎的,所以从一个容器连接到另一个应该看起来像是来自第一容器自身的IP地址
Binding container ports to the host
绑定容器端口至宿主机
By default Docker containers can make connections to the outside world, but the outside world cannot connect to containers. Each outgoing connection will appear to originate from one of the host machine's own IP addresses thanks to an iptables masquerading rule on the host machine that the Docker server creates when it starts:
默认的docker容器能连接到公网,但公网不能连接到容器。得益于宿主机上docker在起动时创建的iptables masquerading规则,每个外部连接看到的源地址是宿主机的拥有的地址
But if you want containers to accept incoming connections, you will need to provide special options when invoking docker run. These options are covered in more detail in the Docker User Guide page. There are two approaches.
但是如果你想让容器接受进来的连接,你需要提供一个特别的选项,在调用docker run时。 这有两种方法。
First, you can supply -P or --publish-all=true|false to docker run which is a blanket operation that identifies every port with an EXPOSE line in the image's Dockerfile and maps it to a host port somewhere in the range 49153–65535. This tends to be a bit inconvenient, since you then have to run other docker sub-commands to learn which external port a given service was mapped to.
首先,你能提供-P或--publish-all=true|false来运行docker run操作,一个通用的并标识每个在镜像的dockerfile文件中EXPOSE行指定的端口的吕作,以及映射它到一个宿主机的49153-65535这个范围端口上。
More convenient is the -p SPEC or --publish=SPEC option which lets you be explicit about exactly which external port on the Docker server — which can be any port at all, not just those in the 49153-65535 block — you want mapped to which port in the container.
更实用的是 -p SPEC或--publish=SPEC参数,它让你对待docker server上的外部端口更加精确,这样可以完全的是任意端口,不仅仅是在49153-65535块中-你要映射至容器上的端口。
Either way, you should be able to peek at what Docker has accomplished in your network stack by examining your NAT tables.
另外的方法,通过检查nat表,你应该能偷看在你网络栈中docker已完成的信息。
You can see that Docker has exposed these container ports on 0.0.0.0, the wildcard IP address that will match any possible incoming port on the host machine. If you want to be more restrictive and only allow container services to be contacted through a specific external interface on the host machine, you have two choices. When you invoke docker run you can use either -p IP:host_port:container_port or -p IP::port to specify the external interface for one particular binding.
你能查看docker开放这些容器在0.0.0.0的端口,这个通配的ip地址将匹配宿主机上的任何可能的进来的端口。如果你要做更进一步的限制和只允许容器服务在宿主机上通过特定的外部接口被连接,你有两种选择。当你调用docker run时,你能即可以用 -p IP:host_port::container_port或 -p IP::port来为一个特定的binding指定外部接口.
Or if you always want Docker port forwards to bind to one specific IP address, you can edit your system-wide Docker server settings (on Ubuntu, by editing DOCKER_OPTS in /etc/default/docker) and add the option --ip=IP_ADDRESS. Remember to restart your Docker server after editing this setting.
或者如果你一直想让docker端口转发到一个特定的ip地址上,你能编辑你的系统端docker server设置和增加这个参数 --ip=IP_ADDRESS.记住在编辑完成后重启你的docker server。
Again, this topic is covered without all of these low-level networking details in the Docker User Guide document if you would like to use that as your port redirection reference instead.
再次,这个主题都没有在docker User Guide的低端网络细节涉及,如果你想使用它作为您的端口重定向参考。
Customizing docker0
定置化docker0
By default, the Docker server creates and configures the host system's docker0 interface as an Ethernet bridge inside the Linux kernel that can pass packets back and forth between other physical or virtual network interfaces so that they behave as a single Ethernet network.
默认地,docker server在linux kernel中创建和配置宿主机系统的docker0接口作为以太网桥,这样能来回在物理网络与虚拟网络接口间来回传递数据包,以便他们做为一个独立的以太网络。
Docker configures docker0 with an IP address, netmask and IP allocation range. The host machine can both receive and send packets to containers connected to the bridge, and gives it an MTU — the maximum transmission unit or largest packet length that the interface will allow — of either 1,500 bytes or else a more specific value copied from the Docker host's interface that supports its default route. These options are configurable at server startup:
docker 用一个ip地址,掩码和ip分配范围配置docker0.宿主机能接收和发送包到被连接到桥的容器,并且给它一个MTU--最大传输单元或是接口被允许的最大包长--即可以是1500字节也可以是一个拷贝于docker宿主机上的支持它们的默认路由接口的值。这些选项可以配置在server启动时:
--bip=CIDR — supply a specific IP address and netmask for the docker0 bridge, using standard CIDR notation like 192.168.1.5/24.
--bip=CIDR 使用标准的CIDR标记为docker0网桥提供一个特定的ip address和掩码
--fixed-cidr=CIDR — restrict the IP range from the docker0 subnet, using the standard CIDR notation like 172.167.1.0/28. This range must be and IPv4 range for fixed IPs (ex: 10.20.0.0/16) and must be a subset of the bridge IP range (docker0 or set using --bridge). For example with --fixed-cidr=192.168.1.0/25, IPs for your containers will be chosen from the first half of 192.168.1.0/24 subnet.
--fixed-cidr=CIDR 用于限制docker网段的ip范围。这个范围必须是固化的ipv4范围,并且必须是一个网桥使用的ip子网的范围。
--mtu=BYTES — override the maximum packet length on docker0.
Once you have one or more containers up and running, you can confirm that Docker has properly connected them to the docker0 bridge by running the brctl command on the host machine and looking at the interfaces column of the output. Here is a host with two different containers connected:
一旦你有一个或更多的容器启动和运行,通过在宿主机上运行brctl确认docker可正常连接他们到docker0网桥。
# Display bridge info
$ sudo brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.3a1d7362b4ee no veth65f9
vethdda6
Finally, the docker0 Ethernet bridge settings are used every time you create a new container. Docker selects a free IP address from the range available on the bridge each time you docker run a new container, and configures the container's eth0 interface with that IP address and the bridge's netmask. The Docker host's own IP address on the bridge is used as the default gateway by which each container reaches the rest of the Internet.
最后,每次你创建新容器时docker以太网桥设置会被使用。docker从桥上的可用范围选择一个空闲的ip给新的容器,然后配置ip和桥的掩码到容器的eth0接口上。docker宿主机中网桥的ip地址是被用来做为默认的网关,以这种方式每个容器可到达公网的其它地方。
# The network, as seen from a container
$ sudo docker run -i -t --rm base /bin/bash
$$ ip addr show eth0
24: eth0:
mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 32:6f:e0:35:57:91 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::306f:e0ff:fe35:5791/64 scope link
valid_lft forever preferred_lft forever
$$ ip route
default via 172.17.42.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.3
$$ exit
Building your own bridge
建立自己的网桥
If you want to take Docker out of the business of creating its own Ethernet bridge entirely, you can set up your own bridge before starting Docker and use -b BRIDGE or --bridge=BRIDGE to tell Docker to use your bridge instead. If you already have Docker up and running with its old docker0 still configured, you will probably want to begin by stopping the service and removing the interface:
如果你要把docker完全地创建它自己的以太网桥,在使用-b BRIDGE或--bridge=BRIDGE启动docker前你能建立自己的网桥来告诉docker使用你的网桥来代替。如果你己经用docker0启动和运行docker,你或许要从停止服务和删除这个接口开始。
service docker stop
ip link set dev docker0 down
brctl delbr docker0
iptables -t nat -F POSTROUTING
Then, before starting the Docker service, create your own bridge and give it whatever configuration you want. Here we will create a simple enough bridge that we really could just have used the options in the previous section to customize docker0, but it will be enough to illustrate the technique.
然后,在启动docker之前,创建你自己的网桥并且给它你要的配置。这样我们将创建一个简单的完整的桥
# Create our own bridge
$ sudo brctl addbr bridge0
$ sudo ip addr add 192.168.5.1/24 dev bridge0
$ sudo ip link set dev bridge0 up
# Confirming that our bridge is up and running
$ ip addr show bridge0
4: bridge0: mtu 1500 qdisc noop state UP group default
link/ether 66:38:d0:0d:76:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.5.1/24 scope global bridge0
valid_lft forever preferred_lft forever
# Tell Docker about it and restart (on Ubuntu)
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
$ sudo service docker start
# Confirming new outgoing NAT masquerade is set up
$ sudo iptables -t nat -L -n
...
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 192.168.5.0/24 0.0.0.0/0
The result should be that the Docker server starts successfully and is now prepared to bind containers to the new bridge. After pausing to verify the bridge's configuration, try creating a container — you will see that its IP address is in your new IP address range, which Docker will have auto-detected.
结果应为docker server成功启动,现在准备绑定容器到新的网桥上。稍微停下核实一下配置,然后尝试创建一个容器---你将看到它的ip地址是新的ip地址范围,docker将会自动检测到。
Just as we learned in the previous section, you can use the brctl show command to see Docker add and remove interfaces from the bridge as you start and stop containers, and can run ip addr and ip route inside a container to see that it has been given an address in the bridge's IP address range and has been told to use the Docker host's IP address on the bridge as its default gateway to the rest of the Internet.
正如我们上面学习到的,你能使用brctl查看docker增加和移除桥接口当你启动和停止容器时,并且能运行ip addr和ip route在容器内来查看网桥ip范围内给定的地址,以及被告之使用了docker宿主机中网桥的ip地址做为默认网关到其它公网。
How Docker networks a container
docker如何网络连接容器
While Docker is under active development and continues to tweak and improve its network configuration logic, the shell commands in this section are rough equivalents to the steps that Docker takes when configuring networking for each new container.
docker正在积极发展和不断调整和完善自身的网络配置逻辑,本节中的shell命令是大略等同于docker在为每个新容器配置网络化所采取的步骤。
Let's review a few basics.
让我们回顾一点基本的原理。
To communicate using the Internet Protocol (IP), a machine needs access to at least one network interface at which packets can be sent and received, and a routing table that defines the range of IP addresses reachable through that interface. Network interfaces do not have to be physical devices. In fact, the lo loopback interface available on every Linux machine (and inside each Docker container) is entirely virtual — the Linux kernel simply copies loopback packets directly from the sender's memory into the receiver's memory.
通过IP协议进行通迅,一个主机需要访问至少一个能发送和接收数据包的网络接口,并且需要一个定义经由这个接口ip范围可达的路由表。网络接口不必是物理的。实际上,用在每个linux机器上的lo loopback接口是完全虚拟的---这个kernel简单地直接从发送者内存拷贝到接收者的内存。
Docker uses special virtual interfaces to let containers communicate with the host machine — pairs of virtual interfaces called “peers” that are linked inside of the host machine's kernel so that packets can travel between them. They are simple to create, as we will see in a moment.
docker使用特定的虚拟接口让容器与宿主机通迅---成对的叫做"peers"在宿主机的kenel内链接的虚拟接口以便让数据包能在它们之间传行。他们是很简单的创建,我们将稍后看到。
The steps with which Docker configures a container are:
docker配置容器的步骤:
1. Create a pair of peer virtual interfaces.
创建一对兄弟虚拟接口。
2. Give one of them a unique name like veth65f9, keep it inside of the main Docker host, and bind it to docker0 or whatever bridge Docker is supposed to be using.
给与他们一个唯一的名字,保持它在主要的docker宿主机内,同时绑定它到docker0上或正在被docker使用的网桥。
3. Toss the other interface over the wall into the new container (which will already have been provided with an lo interface) and rename it to the much prettier name eth0 since, inside of the container's separate and unique network interface namespace, there are no physical interfaces with which this name could collide.
把另个一个接口放到新的容器中并且重新命名
4. Set the interface's MAC address according to the --mac-address parameter or generate a random one.
根据--mac-address提供的参数设置mac地址或随机生成。
5. Give the container's eth0 a new IP address from within the bridge's range of network addresses, and set its default route to the IP address that the Docker host owns on the bridge. If available the IP address is generated from the MAC address. This prevents ARP cache invalidation problems, when a new container comes up with an IP used in the past by another container with another MAC.
给eth0从桥的网络地址范围内分配一个新的ip,并且设置它的默认路由为docker宿主机网桥的地址。如果这个ip是从MAC地址生成的,这样防止arp缓存失效的问题,当一个新容器提出使用过去其它容器上的amc.
With these steps complete, the container now possesses an eth0 (virtual) network card and will find itself able to communicate with other containers and the rest of the Internet.
完成这些步骤,这个容器现在就拥有了一个eth0网卡并将能与其它容器和其它公网通信。
You can opt out of the above process for a particular container by giving the --net= option to docker run, which takes four possible values.
为特别的容器,你能不选择以上过程通过--net选项运行docker run,它有4个可用的值。
--net=bridge — The default action, that connects the container to the Docker bridge as described above.
默认动作,如上所述连接容器到docker网桥。
--net=host — Tells Docker to skip placing the container inside of a separate network stack. In essence, this choice tells Docker to not containerize the container's networking! While container processes will still be confined to their own filesystem and process list and resource limits, a quick ip addr command will show you that, network-wise, they live “outside” in the main Docker host and have full access to its network interfaces. Note that this does not let the container reconfigure the host network stack — that would require --privileged=true — but it does let container processes open low-numbered ports like any other root process. It also allows the container to access local network services like D-bus. This can lead to processes in the container being able to do unexpected things like restart your computer. You should use this option with caution.(这块翻译有问题)
告诉docker跳过配置容器到分离的网络栈。本质上,这个选择告诉docker不容器化这个容器的网络。在容器进程会一直局限在他们自己的文件系统、进程和资源限制,ip addr命令会展示你,网络信息,他们存在于主docker宿主机"外部"以及安全访问他们网络接口。注意这样不是让容器重新配置宿主机网络栈--那需要--privileged=true--但它让容器进程打开低端端口类似其它root进行程。它还允许容器访问本地网络服务比如d-bus.这样能导致容器内的进程能做不希望的事情比如重启你的计算机。你应谨慎使用这个选项。
--net=container:NAME_or_ID — Tells Docker to put this container's processes inside of the network stack that has already been created inside of another container. The new container's processes will be confined to their own filesystem and process list and resource limits, but will share the same IP address and port numbers as the first container, and processes on the two containers will be able to connect to each other over the loopback interface.
告诉docker把这个容器进程放到已经被创建的另一个容器的网络协议栈中。这个新容器进程将会限制在他们系统、进程列表和资源限制,但会与每一个容器共享相同的ip和端口,并且两个容器上进程将能通过回环接口彼此连接。
--net=none — Tells Docker to put the container inside of its own network stack but not to take any steps to configure its network, leaving you free to build any of the custom configurations explored in the last few sections of this document.
-
根据文档的实例自己做得测试:
-
先启动一个容器
-
docker run -i -t --rm --net=none centos /bin/bash
-
[root@74e320677d80 /]#
-
[root@74e320677d80 /]# ip ad sh
-
49: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
-
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
-
inet 127.0.0.1/8 scope host lo
-
-
打开另一个终端执行如下命令
-
docker inspect -f '{{.State.Pid}}' 74e320677d80
-
pid=3182
-
-
###创建一个netns网络
-
mkdir -p /var/run/netns
-
ln -s /proc/$pid/ns/net /var/run/netns/$pid
-
ll /var/run/netns/3182
-
-
############根据文档实例总结的命令############
-
ip link add A type veth peer name B #生成一对"peer"的网络接口
-
brctl addif bridge0 A #将接口A绑定到网桥上
-
ip link set A up
-
ip link set B netns $pid #将接口B绑到虚拟接口上
-
ip netns exec $pid ip link set dev B name eth0
-
ip netns exec $pid ip link set eth0 address 12:34:56:78:99:0F
-
ip netns exec $pid ip link set eth0 up
-
ip netns exec $pid ip addr add 192.168.33.5/24 dev eth0
-
ip netns exec $pid ip route add default via 192.168.33.1
At this point your container should be able to perform networking operations as usual.
此时你的容器应该如平常一样执行网络方面的操作。
When you finally exit the shell and Docker cleans up the container, the network namespace is destroyed along with our virtual eth0 — whose destruction in turn destroys interface A out in the Docker host and automatically un-registers it from the docker0 bridge. So everything gets cleaned up without our having to run any extra commands! Well, almost everything:
当你最手中退出shell并且docker清除容器时,网络命名空间随着我们的虚拟eth0一起销除--相应删除掉docker宿主机中的A接口以及自动地从docker0中注消它。大概每件事情都不需我们执行额外的命令得到清除。当然,几乎任可事情:
#清除软链接
# Clean up dangling symlinks in /var/run/netns
find -L /var/run/netns -type l -delete
Also note that while the script above used modern ip command instead of old deprecated wrappers like ipconfig and route, these older commands would also have worked inside of our container. The ip addr command can be typed as ip a if you are in a hurry.
另外注意虽然上面脚本使用现在的ip命令来替代老的不再使用的包装像ipconfig和route,这些较旧的命令也可以在容器的内工作。ip adder能被打成ip a,如果你乐意的话。
Finally, note the importance of the ip netns exec command, which let us reach inside and configure a network namespace as root. The same commands would not have worked if run inside of the container, because part of safe containerization is that Docker strips container processes of the right to configure their own networks. Using ip netns exec is what let us finish up the configuration without having to take the dangerous step of running the container itself with --privileged=true
最后,注意ip netns exec命令的重要性,它让我们到达容器内和作为root来配置网络命名空间。同样的命令如果运行在容器内部不会工作,由于安全集成化的作用就是docker剥去容器进行权限来配置网络。使用ip netns exec是让我们完成配置,而不需要使用危险方法,即让容器以--privileged=true运行。
建立点对点连接
By default, Docker attaches all containers to the virtual subnet implemented by docker0. You can create containers that are each connected to some different virtual subnet by creating your own bridge as shown in Building your own bridge, starting each container with docker run --net=none, and then attaching the containers to your bridge with the shell commands shown in How Docker networks a container.
缺省情况下, Docker通过docker0将所有的容器添加到虚拟子网中。你能够按照Building your own bridge中的方法创建你自己的桥让容器连接到不同的虚拟子网。启动容器时使用命令docker run --net=none,然后使用shell命令添加容器到你自己的桥,方法见How Docker networks a container。
But sometimes you want two particular containers to be able to communicate directly without the added complexity of both being bound to a host-wide Ethernet bridge.
但是有时你想让两个特别的容器能够直接通讯,不用绑定到主机的以太网桥上。
The solution is simple: when you create your pair of peer interfaces, simply throw both of them into containers, and configure them as classic point-to-point links. The two containers will then be able to communicate directly (provided you manage to tell each container the other's IP address, of course). You might adjust the instructions of the previous section to go something like this:
解决方案是简单的。创建一对对等接口,将他们放到容器中,并将其配置为经典的点对点链接。两个容器就能够直接通讯了(当然要告诉每个容器对方的IP地址)。您可能会调整在上一节的指示去这样的事情:
-
#下面实例是根据文中例子进行的,最终结果是容器间可通,但不能ping通网关,暂时未找到问题。
-
# Start up two containers in two terminal windows
-
docker run -i -t --rm --net=none centos /bin/bash
-
root@1f1f4c1f931a:/#
-
-
docker run -i -t --rm --net=none centos /bin/bash
-
root@12e343489d2f:/#
-
-
# Learn the container process IDs
-
# and create their namespace entries
-
-
docker inspect -f '{{.State.Pid}}' 5bac1370cec8
-
1237
-
docker inspect -f '{{.State.Pid}}' c6368911ca8d
-
1166
-
mkdir -p /var/run/netns
-
ln -s /proc/2272/ns/net /var/run/netns/2372
-
ln -s /proc/2365/ns/net /var/run/netns/2365
-
# Create the "peer" interfaces and hand them out
-
ip link add A type veth peer name B
-
###brctl addif bridge0 A
-
ip link set meth0 netns 2272
-
ip netns exec 2272 ip addr add 192.168.33.10/32 dev A
-
ip netns exec 2272 ip link set A up
-
ip netns exec 2272 ip route add 192.168.33.1/32 dev A
-
-
ip link set B netns 2365
-
ip netns exec 2365 ip addr add 192.168.33.11/32 dev B
-
ip netns exec 2365 ip link set B up
-
ip netns exec 2365 ip route add 192.168.33.1/32 dev B
The two containers should now be able to ping each other and make connections successfully. Point-to-point links like this do not depend on a subnet nor a netmask, but on the bare assertion made by ip route that some other single IP address is connected to a particular network interface.
两个容器应该可以相互ping通以确定连接成功。点对点链接不依赖于子网或子网掩码,但是ip route需要确认其他的单一IP地址是否连接到了特定的网络接口。
Note that point-to-point links can be safely combined with other kinds of network connectivity — there is no need to start the containers with --net=none if you want point-to-point links to be an addition to the container's normal networking instead of a replacement.
请注意点对点链接可以安全的和其他类型的网络连接混合使用。如果你想用点对点链接替换容器的正常网络连接,启动的时候,不需要带参数--net=none。
A final permutation of this pattern is to create the point-to-point link between the Docker host and one container, which would allow the host to communicate with that one container on some single IP address and thus communicate “out-of-band” of the bridge that connects the other, more usual containers. But unless you have very specific networking needs that drive you to such a solution, it is probably far preferable to use --icc=false to lock down inter-container communication, as we explored earlier.
在Docker主机和容器之间创建点对点链接是这个模板最终的排列方式,它允许主机和有单一IP地址的容器通讯。除非你有很特别的网络需求,让你尝试使用这样的解决方案,正如我们前面探讨的,使用--icc=false锁定跨容器的通讯是更好的方案。