Deployment 如何设置Docker容器之间的链接,以便重新启动won';你不能打破它吗?

Deployment 如何设置Docker容器之间的链接,以便重新启动won';你不能打破它吗?,deployment,docker,Deployment,Docker,我有几个Docker容器运行如下: Nginx Web应用程序1 网络应用程序2 PostgreSQL 由于Nginx需要连接到web应用程序1和2内的web应用程序服务器,并且web应用程序需要与PostgreSQL对话,因此我有如下链接: Nginx---link--->Web应用程序1 Nginx---link--->Web应用2 Web应用程序1---链接--->PostgreSQL Web应用程序2---链接--->PostgreSQL 一开始这很有效。然而,当我开发web a

我有几个Docker容器运行如下:

  • Nginx
  • Web应用程序1
  • 网络应用程序2
  • PostgreSQL
由于Nginx需要连接到web应用程序1和2内的web应用程序服务器,并且web应用程序需要与PostgreSQL对话,因此我有如下链接:

  • Nginx---link--->Web应用程序1
  • Nginx---link--->Web应用2
  • Web应用程序1---链接--->PostgreSQL
  • Web应用程序2---链接--->PostgreSQL
一开始这很有效。然而,当我开发web app 1和web app 2的新版本时,我需要替换它们。我要做的是删除web应用程序容器,设置新容器并启动它们

对于web应用程序容器,它们的IP地址最初类似于:

  • 172.17.0.2
  • 172.17.0.3
在我替换它们之后,它们将拥有新的IP地址:

  • 172.17.0.5
  • 172.17.0.6
现在,Nginx容器中暴露的环境变量仍然指向旧的IP地址。问题来了。如何在不破坏容器之间链接的情况下更换容器?同样的问题也会发生在PostgreSQL上。如果我想升级PostgreSQL映像版本,我当然需要删除它并运行新的版本,但是我需要重建整个容器图,因此这对于实际的服务器操作并不理想。

您可以使用with name来解决此问题

最基本的设置是首先创建命名数据库容器:

$ sudo docker run -d --name db training/postgres
然后创建一个连接到db的web容器:

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

这样,您就不需要手动将容器与其IP地址连接起来。

您可以将映像的连接端口绑定到主机上的固定端口,并将服务配置为使用它们


这也有其缺点,但在您的情况下可能会起作用。

使用OpenSVC方法,您可以通过以下方式解决问题:

  • 使用具有自己的ip地址/dns名称的服务(您的最终用户将连接到的名称)
  • 告诉docker将端口公开到此特定ip地址(“--ip”docker选项)
  • 配置应用程序以连接到服务ip地址
每次更换容器时,都要确保它将连接到正确的ip地址

教程在此=>

不要错过tuto结尾的“复杂编排”部分,它可以帮助您以正确的顺序启动/停止容器(1个postgresql子集+1个webapp子集+1个nginx子集)


主要缺点是您将webapp和PostgreSQL端口公开给公共地址,实际上只有nginx tcp端口需要公开。

您也可以尝试使用ambassador方法,即使用一个中介容器来保持链接完整。。。(请参阅)有关详细信息,您可以使用。但不要将大使容器链接到您的客户,因为这会产生与上述相同的问题。相反,使用docker主机上大使容器的暴露端口(通常为172.17.42.1)。例如:

博士后卷:

$ 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
博士后大使容器:

$ docker run -d --name pg_ambassador --link postgres:postgres -p 5432:5432 ctlc/ambassador
现在,您可以启动postgresql客户端容器,而无需链接大使容器,并在网关主机上访问postgresql(通常为172.17.42.1):

现在,您可以重新启动大使容器,而无需重新启动客户端。

链接--link的效果是静态的,因此它不适用于您的场景(尽管您可以重新链接,但目前没有重新链接)

我们在dockerize.it使用了两种不同的方法来解决这个问题,没有链接或大使(尽管您也可以添加大使)

1)使用动态DNS

一般的想法是为数据库(或任何其他服务)指定一个名称,并在启动和停止容器时使用实际IP更新短期DNS服务器

我们从一开始。它与两个docker容器一起工作,DNS服务器和一个监视器使其自动更新。后来,我们转向了更为自定义的使用(也使用了停靠版本:)

这方面的一个发展(我们还没有尝试过)将是设置etcd或类似的,并使用其自定义API来学习IP和端口。软件也应该支持动态重新配置

2)使用docker网桥ip

公开容器端口时,您可以将它们绑定到
docker0
网桥,该网桥具有(或可能具有)一个众所周知的地址

用新版本替换容器时,只需使新容器在同一IP上发布同一端口即可


这更简单,但也更有限。如果运行类似的软件,可能会出现端口冲突(例如,两个容器无法在
docker0
桥上的3306端口上侦听),等等……因此,我们当前最喜欢的是选项1。

如果有人仍然好奇,您必须使用每个docker容器的/etc/hosts文件中的主机条目,并且不应依赖于ENV变量,因为它们不会自动更新

每个链接容器都有一个主机文件条目,格式为LINKEDCONTAINERNAME\u PORT\u PORTNUMBER\u TCP等

以下是docker的文章

关于Docker环境变量的重要说明

与/etc/hosts文件中的主机条目不同,存储在 如果源 容器重新启动。建议在中使用主机条目 /etc/hosts解析链接容器的IP地址

这些环境变量仅为中的第一个进程设置 容器。某些守护进程(如sshd)在生成时会将其清除 用于连接的外壳


这包括在3周前docker的实验构建中,并引入了以下服务:

你应该可以得到
$ 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=# 
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
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
$ docker network create <network-name>       
$ docker run --net=<network-name> ...
$ docker network connect <network-name> <container-name>
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