Docker Container Linking

前面有一篇关于docker 通过DNAT将container的端口映射出来的效率问题.

http://blog.163.com/digoal@126/blog/static/163877040201492315242694/

本文将讲一下container之间的通讯方法, 除了使用-p或-P将端口映射出来, 还可以使用--link, 连接多个container.

(--link 其实也是通过IP通讯的(通过虚拟网桥管理, 或者使用openvswitch), 只是docker会自动维护一些变量和主机名, 方便使用者使用)

以一个例子来讲解 : 

首先启动一个container, 注意我们这里没有使用--name指定名字. 也没有使用-p或-P做DNAT映射.

[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

[参考]

1. https://docs.docker.com/userguide/dockerlinks/

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/

时间: 2024-08-03 17:10:16

Docker Container Linking的相关文章

mesos slave failed to create a docker container

问题描述 mesos slave failed to create a docker container when i start a docker containner on mesos-slave the mesos-slave log shows that: I1223 15:38:40.822557 258486272 docker.cpp:761] Starting container 'ea1ed2fa-c2e3-469a-bcc4-142e0a6c624d' for task '2

docker-一台服务器跑同一个App的多个Docker Container,性能会怎样?

问题描述 一台服务器跑同一个App的多个Docker Container,性能会怎样? Container是用namespace 来做隔离的,那么问题来了 如果我在一台服务器上, 使用同一个应用的image (比如 WordPress)起了 n个 container 那么这个服务器满载的时候性能 和 同样一台服务器只用一个 Container 处理时满载的性能有什么区别? 按照Container的说法,runtime overhead 很低,是不是这两个场景性能差不了太多 ? 求高手解答 解决方

Docker Container同时启动多服务

Docker Container同时启动多服务 转载请注明来自:http://blog.csdn.net/wsscy2004 昨天踩了个天坑,我有一个基本的镜像centos6.5+ssh,是通过Dockerfile build的,利用CMD命令启动ssh. 通过centos6.5+ssh镜像,我想build一个rabbitmq镜像,Dockerfile中CMD启动rabbitmq服务.虽然我知道Dockerfile中的CMD只能有一个,但没想到创建另一个image,也会继承FROM image的

pipework let&#039;s assign static IP to docker container simple.

pipework是Docker工程师写的一个脚本, 主要用来管理container的网络.  用法参考 https://github.com/jpetazzo/pipework/blob/master/pipework 网友总结的5种定制docker网络的途径, pipework是其中之一 :  http://www.infoworld.com/article/2835222/application-virtualization/5-ways-docker-is-fixing-its-netwo

add network card|interface to docker container online

本文将讲解一下如何对一个正在运行的container添加网卡.  其实就是用的netns, 使用--net=none或--net=bridge都无所谓. 启动一个容器, 默认使用bridge. 所以会自动创建一个网卡. [root@localhost ~]# docker run --name=test -t -i --rm centos:centos6 /bin/bash [root@878894e4216d /]# ip link 1: lo: <LOOPBACK,UP,LOWER_UP>

docker container 设置编码为utf8

以Ubuntu 14.04 为例创建编码为utf8的container 1.创建dockerfile文件 FROM ubuntu:14.04 RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-

docker container mount根分区为NFS

问题描述 我想把dockercontainer的根分区mount为一个NFS挂载点,不知道是不是可行比如有个MFS的挂载点:test:/home/user/3243想类似:dockerrun-it-v"test:/home/user/3243":/centos7/bin/bash这样如果不行的话,可以先挂载到host,再绑定到container,类似:mount-tnfstest:/home/user/3243/mnt/nfs/3243dockerrun-it-v/mnt/nfs/32

Docker 中如何连接多个 Container 协同工作 【已翻译100%】

在Docker使用部分我们接触到了通过网络端口来连接运行在Docker容器内的服务.这是同Docker容器内服务和应用互动的方法之一.在这一节中,我们将带你复习一下通过网络端口连接到Docker容器并给你介绍容器连接的概念. 网络端口映射刷新 在Docker的使用部分中,我们创建了一个运行Python Flask应用的容器. $ sudo docker run -d -P training/webapp python app.py 注意:容器有一个内部网络和IP地址(还记得在使用Docker部分

Docker实践者不能错过2014 Container技术大会的九大理由!

摘要:2014年10月18日,CSDN&<程序员>主办的2014 Container技术大会将在北京召开,目前议题已经基本确定.为帮助更多同学进一步了解本次大会,主办方总结了技术团队不应错过2014 Container技术大会的九大理由. Container技术已经出现了十几年,但直到2013年Docker项目的出现,才逐渐火热起来,广为人知.如今,Docker拥有超过500个代码贡献者,20个核心Maintainer,超过8000个创建在GitHub上的Docker相关项目,30多个