前面有一篇关于docker 通过DNAT将container的端口映射出来的效率问题.
本文将讲一下container之间的通讯方法, 除了使用-p或-P将端口映射出来, 还可以使用--link, 连接多个container.
(--link 其实也是通过IP通讯的(通过虚拟网桥管理, 或者使用openvswitch), 只是docker会自动维护一些变量和主机名, 方便使用者使用)
以一个例子来讲解 :
首先启动一个container, 注意我们这里没有使用--name指定名字. 也没有使用-p或-P做DNAT映射.
查看这个container的网络 :
在宿主机通过网络可以连接到container.
接下来启动另一个container, 使用--link来建立链接. 格式 :
在建立完连接后, 在当前的container可以看到两个变化,
2. 另外会自动创建环境变量 :
例如 :
其实--link主要的好处是维护了一个unique alias, 在container中连其他container, 使用alias即可, 而不需要知道IP是多少.
查看当前宿主机的iptables条目.
网桥信息 :
3. http://blog.163.com/digoal@126/blog/static/163877040201492315242694/
[root@db-172-16-3-221 ~]# docker run -d postgres:9.3.5
64366c42153653adf595242b1f36dca189ea671aed24a3d642bf104a49b7359d
[root@db-172-16-3-221 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
64366c421536 postgres:9 /docker-entrypoint.s 2 seconds ago Up 1 seconds 5432/tcp dreamy_ptolemy
查看这个container的网络 :
[root@db-172-16-3-221 ~]# docker inspect 64366c421536
[{
"Args": [
"postgres"
],
"Config": {
"AttachStderr": false,
"AttachStdin": false,
"AttachStdout": false,
"Cmd": [
"postgres"
],
"CpuShares": 0,
"Cpuset": "",
"Domainname": "",
"Entrypoint": [
"/docker-entrypoint.sh"
],
"Env": [
"PATH=/usr/lib/postgresql/9.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=en_US.utf8",
"PG_MAJOR=9.3",
"PG_VERSION=9.3.5-1.pgdg70+1",
"PGDATA=/var/lib/postgresql/data"
],
"ExposedPorts": {
"5432/tcp": {}
},
"Hostname": "64366c421536",
"Image": "postgres:9.3.5",
"Memory": 0,
"MemorySwap": 0,
"NetworkDisabled": false,
"OnBuild": null,
"OpenStdin": false,
"PortSpecs": null,
"StdinOnce": false,
"Tty": false,
"User": "",
"Volumes": {
"/var/lib/postgresql/data": {}
},
"WorkingDir": ""
},
"Created": "2014-10-27T02:26:37.738875408Z",
"Driver": "devicemapper",
"ExecDriver": "native-0.2",
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"Dns": null,
"DnsSearch": null,
"Links": null,
"LxcConf": [],
"NetworkMode": "bridge",
"PortBindings": {},
"Privileged": false,
"PublishAllPorts": false,
"VolumesFrom": null
},
"HostnamePath": "/var/lib/docker/containers/64366c42153653adf595242b1f36dca189ea671aed24a3d642bf104a49b7359d/hostname",
"HostsPath": "/var/lib/docker/containers/64366c42153653adf595242b1f36dca189ea671aed24a3d642bf104a49b7359d/hosts",
"Id": "64366c42153653adf595242b1f36dca189ea671aed24a3d642bf104a49b7359d",
"Image": "935836384c524aafc0ac1c05246002c9c93343f0b4283a34e77a5f92f97f9a7c",
"MountLabel": "",
"Name": "/dreamy_ptolemy",
"NetworkSettings": {
"Bridge": "docker0",
"Gateway": "172.17.42.1",
"IPAddress": "172.17.0.13",
"IPPrefixLen": 16,
"PortMapping": null,
"Ports": {
"5432/tcp": null
}
},
"Path": "/docker-entrypoint.sh",
"ProcessLabel": "",
"ResolvConfPath": "/etc/resolv.conf",
"State": {
"ExitCode": 0,
"FinishedAt": "0001-01-01T00:00:00Z",
"Paused": false,
"Pid": 8584,
"Running": true,
"StartedAt": "2014-10-27T02:26:38.525831218Z"
},
"Volumes": {
"/var/lib/postgresql/data": "/var/lib/docker/vfs/dir/52a3cbd99e3462e1fd8593d086d82bd86afa94c435ec0bc141872f7f5507144a"
},
"VolumesRW": {
"/var/lib/postgresql/data": true
}
}
在宿主机通过网络可以连接到container.
[root@db-172-16-3-221 ~]# ping 172.17.0.13
PING 172.17.0.13 (172.17.0.13) 56(84) bytes of data.
64 bytes from 172.17.0.13: icmp_seq=1 ttl=64 time=1.10 ms
[root@db-172-16-3-221 ~]# telnet 172.17.0.13 5432
Trying 172.17.0.13...
Connected to 172.17.0.13.
Escape character is '^]'.
quit
Connection closed by foreign host.
接下来启动另一个container, 使用--link来建立链接. 格式 :
--link 源container_name:源container_alias
[root@db-172-16-3-221 ~]# docker run -t -i --link dreamy_ptolemy:db1 postgres:9.3.5 /bin/bash
root@3e76ddd8025c:/# ping 172.17.0.13
PING 172.17.0.13 (172.17.0.13): 48 data bytes
56 bytes from 172.17.0.13: icmp_seq=0 ttl=64 time=1.428 ms
在建立完连接后, 在当前的container可以看到两个变化,
1. /etc/hosts
2. env
1. 自动在/etc/hosts中建立源container的条目, 主机名即alias.
172.17.0.13 db1
root@3e76ddd8025c:/# cat /etc/hosts
172.17.0.14 3e76ddd8025c
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.13 db1
2. 另外会自动创建环境变量 :
以alias_开头的一些环境变量 :
<name>_PORT_<port>_<protocol> will contain a URL reference to the port. Where <name> is the alias name specified in the --link parameter (e.g. webdb), <port> is the port number being exposed, and <protocol> is either TCP or UDP. The format of the URL will be: <protocol>://<container_ip_address>:<port> (e.g. tcp://172.17.0.82:8080). This URL will then be split into the following 3 environment variables for convinience:
<name>_PORT_<port>_<protocol>_ADDR will contain just the IP address from the URL (e.g. WEBDB_PORT_8080_TCP_ADDR=172.17.0.82).
<name>_PORT_<port>_<protocol>_PORT will contain just the port number from the URL (e.g. WEBDB_PORT_8080_TCP_PORT=8080).
<name>_PORT_<port>_<protocol>_PROTO will contain just the protocol from the URL (e.g. WEBDB_PORT_8080_TCP_PROTO=tcp).
例如 :
DB1_NAME=/nostalgic_mclean/db1
DB1_PORT=tcp://172.17.0.13:5432
DB1_PORT_5432_TCP=tcp://172.17.0.13:5432
DB1_PORT_5432_TCP_PROTO=tcp
DB1_PORT_5432_TCP_ADDR=172.17.0.13
DB1_PORT_5432_TCP_PORT=5432
DB1_ENV_PGDATA=/var/lib/postgresql/data
DB1_ENV_LANG=en_US.utf8
DB1_ENV_PG_VERSION=9.3.5-1.pgdg70+1
DB1_ENV_PG_MAJOR=9.3
root@3e76ddd8025c:/# env
HOSTNAME=3e76ddd8025c
DB1_ENV_PG_VERSION=9.3.5-1.pgdg70+1
TERM=xterm
DB1_ENV_PG_MAJOR=9.3
DB1_PORT_5432_TCP_PORT=5432
PG_MAJOR=9.3
DB1_PORT_5432_TCP=tcp://172.17.0.13:5432
DB1_PORT_5432_TCP_ADDR=172.17.0.13
PATH=/usr/lib/postgresql/9.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DB1_ENV_PGDATA=/var/lib/postgresql/data
DB1_ENV_LANG=en_US.utf8
PWD=/
LANG=en_US.utf8
HOME=/
SHLVL=1
PG_VERSION=9.3.5-1.pgdg70+1
DB1_PORT=tcp://172.17.0.13:5432
PGDATA=/var/lib/postgresql/data
DB1_PORT_5432_TCP_PROTO=tcp
DB1_NAME=/nostalgic_mclean/db1
_=/usr/bin/env
其实--link主要的好处是维护了一个unique alias, 在container中连其他container, 使用alias即可, 而不需要知道IP是多少.
例如 : ping --link指定的alias即可.
root@3e76ddd8025c:/# ping db1
PING db1 (172.17.0.13): 48 data bytes
56 bytes from 172.17.0.13: icmp_seq=0 ttl=64 time=0.069 ms
56 bytes from 172.17.0.13: icmp_seq=1 ttl=64 time=0.076 ms
root@3e76ddd8025c:/# psql -h db1 -p 5432 -U postgres postgres
psql (9.3.5)
Type "help" for help.
postgres=# \q
测试一下在一个container中使用pgbench测试另一个container的数据库.
和在宿主机测试效率差不多.
root@3e76ddd8025c:/# echo "select 1;" >./test.sql
root@3e76ddd8025c:/# pgbench -M prepared -n -r -f ./test.sql -h db1 -p 5432 -U postgres -c 16 -j 4 -T 30 postgres
transaction type: Custom query
scaling factor: 1
query mode: prepared
number of clients: 16
number of threads: 4
duration: 30 s
number of transactions actually processed: 4528033
tps = 150932.697607 (including connections establishing)
tps = 151004.884662 (excluding connections establishing)
statement latencies in milliseconds:
0.104734 select 1;
查看当前宿主机的iptables条目.
[root@db-172-16-3-221 ~]# iptables-save
# Generated by iptables-save v1.4.7 on Mon Oct 27 10:45:13 2014
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1683:453100]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s 192.168.0.0/16 -j ACCEPT
-A INPUT -s 10.0.0.0/8 -j ACCEPT
-A INPUT -s 172.16.0.0/16 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -s 172.17.0.13/32 -d 172.17.0.14/32 -i docker0 -o docker0 -p tcp -m tcp --sport 5432 -j ACCEPT
-A FORWARD -s 172.17.0.14/32 -d 172.17.0.13/32 -i docker0 -o docker0 -p tcp -m tcp --dport 5432 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Mon Oct 27 10:45:13 2014
# Generated by iptables-save v1.4.7 on Mon Oct 27 10:45:13 2014
*nat
:PREROUTING ACCEPT [543:173998]
:POSTROUTING ACCEPT [472:24624]
:OUTPUT ACCEPT [276:14384]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -d 172.17.0.0/16 -j MASQUERADE
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
COMMIT
# Completed on Mon Oct 27 10:45:13 2014
网桥信息 :
[root@db-172-16-3-221 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.12551bd59cad no veth6cb1
vetha6e7
[参考]
2. man docker-run
-P, -publish-all=true|false When set to true publish all exposed ports to the host interfaces. The default is
false. If the operator uses -P (or -p) then Docker will make the exposed port accessible on the host and the
ports will be available to any client that can reach the host. To find the map between the host ports and the
exposed ports, use docker port.
-p, -publish=[] Publish a container's port to the host (format: ip:hostPort:containerPort | ip::containerPort |
hostPort:containerPort) (use docker port to see the actual mapping)
3. http://blog.163.com/digoal@126/blog/static/163877040201492315242694/