分配虚拟机到Docker端口

我设置了通配符DNS,以便所有到自定义域(* .foo)的Web请求都映射到Docker主机的IP地址。 如果我有多个运行Apache(或Nginx)实例的容器,则每个容器都将Apache端口(80)映射到某个外部入站端口。

我想要做的是向container-1.foo发出一个请求,它已经通过我的自定义DNS服务器映射到了正确的(Docker主机的)IP地址,但是把默认的80端口请求代理到正确的Docker外部端口,以便来自指定容器的正确Apache实例能够基于自定义域进行响应。 同样,container-2.foo会代理第二个容器的apache,依此类推。

是否有预先构build的解决scheme,是我最好在Docker主机上运行一个Nginx代理,还是应该写一个node.js代理,以便pipe理Docker容器(通过Web启动/停止/重新创build), 要么…? 我有什么select可以使Docker容器更像自然事件,而不是无关的端口和容器的杂耍?

这个答案可能有点晚了,但看看Jason Wilder的nginx代理Docker镜像 。 当运行这个镜像的Docker容器时,你会得到一个nginx服务器,作为你的其他容器的反向代理,不需要configuration维护。

只需使用VIRTUAL_HOST环境variables运行其他容器,nginx-proxy将发现它们的ip:port并为您更新nginxconfiguration。

假设您的DNS设置为*.test.local映射到您的Docker主机的IP地址,则只需启动以下容器即可运行快速演示:

 # start the reverse proxy docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy # start a first container for http://tutum.test.local docker run -d -e "VIRTUAL_HOST=tutum.test.local" tutum/hello-world # start a second container for http://deis.test.local docker run -d -e "VIRTUAL_HOST=deis.test.local" deis/helloworld 

这里有两个可能的答案:(1)直接使用Docker设置端口,使用Nginx / Apache来代理虚拟主机,或者(2)使用Dokku为你pipe理端口和虚拟主机(这是我学会做的方法1)。

方法1a(直接分配端口与docker)

第1步:在主机上设置nginx.conf或Apache,并指定所需的端口号。 运行在主机上的这个Web服务器将执行虚拟主机代理。 Docker方面没有什么特别之处 – 这是正常的虚拟主机托pipe。 接下来的特殊部分,在步骤2中,使Docker使用正确的主机端口号。

第2步:在Docker中用“-p”强制端口号分配来设置Docker的端口映射,“-e”在Docker中设置自定义的环境variables,如下所示:

 port=12345 # <-- the vhost port setting used in nginx/apache IMAGE=myapps/container-1 id=$(docker run -d -p :$port -e PORT=$port $IMAGE) # -p :$port will establish a mapping of 12345->12345 from outside docker to # inside of docker. # Then, the application must observe the PORT environment variable # to launch itself on that port; This is set by -e PORT=$port. # Additional goodies: echo $id # <-- the running id of your container echo $id > /app/files/CONTAINER # <-- remember Docker id for this instance docker ps # <-- check that the app is running docker logs $id # <-- look at the output of the running instance docker kill $id # <-- to kill the app 

方法1b硬编码的应用程序端口

…如果您的应用程序使用硬编码端口,例如端口5000(即不能通过PORT环境variablesconfiguration,如方法1a中所示),那么可以通过Docker对其进行硬编码:

 publicPort=12345 id=$(docker run -d -p $publicPort:5000 $IMAGE) # -p $publicPort:5000 will map port 12345 outside of Docker to port 5000 inside # of Docker. Therefore, nginx/apache must be configured to vhost proxy to 12345, # and the application within Docker must be listening on 5000. 

方法2(让Dokku找出端口)

目前,pipe理Docker虚拟主机的一个很好的select是Dokku 。 即将到来的select可能是使用Flynn ,但是现在,Flynn刚刚起步并没有做好准备。 因此,我们现在去Dokku:按照Dokku安装说明,对于单个域,通过创build“VHOST”文件启用虚拟主机:

 echo yourdomain.com > /home/git/VHOST # in your case: echo foo > /home/git/VHOST 

现在,当一个应用程序通过SSH推送到Dokku(请参阅Dokku docs如何做到这一点),Dokku会看VHOST文件和特定的应用程序推(假设你推“container-1”),它会产生以下文件:

 /home/git/container-1/nginx.conf 

它会有以下内容:

 upstream container-1 { server 127.0.0.1:49162; } server { listen 80; server_name container-1.yourdomain.com; location / { proxy_pass http://container-1; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $remote_addr; } } 

当服务器重新启动时,Dokku将确保Docker启动应用程序,将端口映射到其初始部署的端口(此处为49162),而不是随机分配另一个端口。 为了实现这个确定性的分配,Dokku将最初分配的端口保存到/home/git/container-1/PORT并在下次启动时将PORT环境设置为此值,并且将Docker的端口分配映射为主机端和应用程序端。 这与第一次发射相反,当Dokku将设置PORT=5000 ,然后找出在VPS端的随机端口Dokku地图5000应用程序端。 这是围绕(甚至可能在将来会改变),但它的工作原理!

VHOST的工作方式是:在通过SSH进行应用程序的git推动时,Dokku将执行位于/var/lib/dokku/plugins/nginx-vhosts钩子。 这些钩子也位于Dokku源代码中,负责用正确的vhost设置写入nginx.conf文件。 如果你在/var/lib/dokku目录下没有这个目录,请尝试运行dokku plugins-install

使用docker工具,你需要内部ips保持正常(如80),并找出如何连接随机端口。

处理这些问题的一种方法是使用像hipache这样的反向代理。 把你的DNS指向它,然后你可以重新configuration代理,因为你的容器上下。 看看http://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/看看这可以如何工作。;

如果你正在寻找更强大的东西,你可能想看看“服务发现”。 (使用docker查看服务发现: http : //txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/ )