我有运行像几个集装箱的码头工人
- Nginx的
- 网络应用1
- 网络应用2
- PostgreSQL的
由于Nginx的需要Web应用程序服务器连接的Web应用程序1和2的内部和Web应用程序需要跟PostgreSQL数据库,所以我有这样的联系
- Nginx的---链接--->的Web应用程序1
- Nginx的---链接--->的Web应用程序2
- 网络应用1 ---链接--->的PostgreSQL
- 网络应用2 ---链接--->的PostgreSQL
这工作得很好的开始,但是,当我开发Web应用程序1和Web应用程序2的新版本,我需要更换。 我要做的就是清除Web应用程序容器,设置新的容器和启动它们。
对于Web应用容器中,在第一个自己的IP地址会是这样的
后,我代替他们,他们现在有新的IP地址
此时,在Nginx的容器那些暴露的环境变量仍然指向旧的IP地址。 这里谈到的问题,如何更换容器,但未其他容器之间打破联动? 同样的问题也发生在PostgreSQL的,如果我想升级PostgreSQL的图像版本,我当然需要将其删除,并运行新的,但后来我需要重建整个容器图形,这不是真正的好主意人生服务器操作。
Answer 1:
The effect of --link
is static, so it will not work for your scenario (there is currently no re-linking, although you can remove links).
We have been using two different approaches at dockerize.it to solve this, without links or ambassadors (although you could add ambassadors too).
1) Use dynamic DNS
The general idea is that you specify a single name for your database (or any other service) and update a short-lived DNS server with the actual IP as you start and stop containers.
We started with SkyDock. It works with two docker containers, the DNS server and a monitor that keeps it updated automatically. Later we moved to something more custom using Consul (also using a dockerized version: docker-consul).
An evolution of this (which we haven't tried) would be to setup etcd or similar and use its custom API to learn the IPs and ports. The software should support dynamic reconfiguration too.
2) Use the docker bridge ip
When exposing the container ports you can just bind them to the docker0
bridge, which has (or can have) a well known address.
When replacing a container with a new version, just make the new container publish the same port on the same IP.
This is simpler but also more limited. You might have port conflicts if you run similar software (for instance, two containers can not listen on the 3306 port on the docker0
bridge), etcétera… so our current favorite is option 1.
Answer 2:
链接是为特定的容器,而不是基于容器的名字。 所以,你删除一个容器的那一刻,链路断开连接,新的容器(即使使用相同的名称)将不会自动取代其位置。
新的网络功能,您可以通过他们的名字连接到容器,所以如果你创建一个新的网络,连接到网络的任何容器,可以通过自己的名字达到其他容器。 例:
1)创建新的网络
$ docker network create <network-name>
2)连接的容器到互联
$ docker run --net=<network-name> ...
要么
$ docker network connect <network-name> <container-name>
3)以名称平容器
docker exec -ti <container-name-A> ping <container-name-B>
64 bytes from c1 (172.18.0.4): icmp_seq=1 ttl=64 time=0.137 ms
64 bytes from c1 (172.18.0.4): icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from c1 (172.18.0.4): icmp_seq=3 ttl=64 time=0.074 ms
64 bytes from c1 (172.18.0.4): icmp_seq=4 ttl=64 time=0.074 ms
请参见本文档的部分;
注:不同于传统的links
的新的网络将不会创建环境变量,也不与其他容器共享的环境变量。
此功能目前不支持别名
Answer 3:
您可以使用大使容器 。 但是,不要大使容器链接到你的客户,因为这将创建与上述相同的问题。 相反,使用大使容器的暴露的端口搬运工主机(典型地172.17.42.1)上。 例:
Postgres的量:
$ docker run --name PGDATA -v /data/pgdata/data:/data -v /data/pgdata/log:/var/log/postgresql phusion/baseimage:0.9.10 true
Postgres的容器:
$ docker run -d --name postgres --volumes-from PGDATA -e USER=postgres -e PASS='postgres' paintedfox/postgresql
Postgres的大使容器:
$ docker run -d --name pg_ambassador --link postgres:postgres -p 5432:5432 ctlc/ambassador
现在,您可以在不连接大使容器和访问PostgreSQL的网关主机(通常为172.17.42.1)上启动一个PostgreSQL客户端容器:
$ docker run --rm -t -i paintedfox/postgresql /bin/bash
root@b94251eac8be:/# PGHOST=$(netstat -nr | grep '^0\.0\.0\.0 ' | awk '{print $2}')
root@b94251eac8be:/# echo $PGHOST
172.17.42.1
root@b94251eac8be:/#
root@b94251eac8be:/# psql -h $PGHOST --user postgres
Password for user postgres:
psql (9.3.4)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
postgres=#
postgres=# select 6*7 as answer;
answer
--------
42
(1 row)
bpostgres=#
现在,您可以重新启动大使容器具有内部消除重新启动客户端。
Answer 4:
如果有人仍然好奇,你必须使用在每个搬运工容器的/ etc / hosts文件中的主机条目和不会自动更新,他们不应该依赖于ENV变量。
将有格式为每个链接的容器的主机文件条目LINKEDCONTAINERNAME_PORT_PORTNUMBER_TCP等。
以下是从码头工人文档
在泊坞窗环境变量的重要注意事项
不像在/ etc主机项/ hosts文件,存储在环境变量的IP地址不会自动在源容器重新启动更新。 我们建议使用在/ etc / hosts中的主机条目,以解决与容器的IP地址。
这些环境变量只设置在容器中的第一个过程。 某些服务,如sshd的,用于连接产卵壳时将擦洗它们。
Answer 5:
这包括在泊坞窗的实验生成3个星期前,引进服务: https://github.com/docker/docker/blob/master/experimental/networking.md
您应该能够通过运行带有泊坞窗容器得到代替动态链接--publish-service <name>
参数。 这个名称将是通过DNS访问。 (为重新启动容器那是当然的相同的服务名称为长)这是容器重新启动持续
Answer 6:
您可以使用dockerlinks用名称来解决这个问题。
最基本的设置将首先创建一个名为数据库容器:
$ sudo docker run -d --name db training/postgres
然后创建一个Web容器连接到数据库:
$ sudo docker run -d -P --name web --link db:db training/webapp python app.py
有了这个,你并不需要手动与他们的IP不会忽略连接容器。
Answer 7:
与OpenSVC方法,您可以通过解决方法:
- 使用自己的IP地址/ DNS名称的服务(一个最终用户将连接到)
- 告诉搬运工暴露的端口这个特定的IP地址(“--ip”泊坞窗选项)
- 配置您的应用程序连接到服务IP地址
每次更换容器时,你确信它会连接到正确的IP地址。
教程这里=> 多克多与OpenSVC集装箱
在政党成员的最后千万不要错过“复杂的业务流程”的一部分,它可以帮助你开始以正确的顺序/停止容器(1个PostgreSQL的子集+ 1级的web应用子集+ 1个nginx的子集)
主要的缺点是,你暴露Web应用程序和PostgreSQL端口的公共地址,实际上只nginx的TCP端口需要在公众场合暴露。
Answer 8:
您也可以尝试有一个中间容器的大使方法只是为了保持完整的链接...(见https://docs.docker.com/articles/ambassador_pattern_linking/ )更多信息
Answer 9:
您可以将图像的连接端口绑定到主机上的固定端口和配置服务,而不是使用它们。
这有它的缺点,以及,但它可能在你的情况下工作。
Answer 10:
另一种方法是使用--net container:$CONTAINER_ID
选项。
第1步:创建“网络”容器
docker run --name db_net ubuntu:14.04 sleep infinity
docker run --name app1_net --link db_net:db ubuntu:14.04 sleep infinity
docker run --name app2_net --link db_net:db ubuntu:14.04 sleep infinity
docker run -p 80 -p 443 --name nginx_net --link app1_net:app1 --link app2_net:app2 ubuntu:14.04 sleep infinity
第2步:中注入服务的“网络”容器
docker run --name db --net container:db_net pgsql
docker run --name app1 --net container:app1_net app1
docker run --name app2 --net container:app1_net app2
docker run --name nginx --net container:app1_net nginx
只要你不碰“网络”容器,您的链接的IP地址不应该改变。
Answer 11:
网络范围的别名是你所需要的就是这种情况。 这是一个比较新的功能,它可以用于“发布”的容器为整个网络提供服务,不像只从一个容器访问链接的别名。
它不添加任何类型的容器之间的依赖关系 - 只要都在运行,他们可以沟通,无论重启和更换和启动顺序。 它使用DNS在内部,我相信不是/ etc / hosts文件,
使用这样的: docker run --net=some_user_definied_nw --net-alias postgres ...
你可以使用别名从任何容器连接到它在同一个网络上。
默认的网络上是不行的,不幸的是,你必须创建一个与docker network create <network>
,然后用用它--net=<network>
每一个容器( 撰写支持它以及 )。
除了容器通过别名下来,因此无法访问多个容器也可以分享在这种情况下不能保证它会被解析到正确的别名。 但在某些情况下,可以用无缝升级帮助,大概。
这一切都没有很好的记录作为然而,很难仅仅通过阅读手册页搞清楚。
文章来源: How to setup linkage between docker containers so that restarting won't break it?