将vhost分配给Docker端口

nginx proxy dns docker

29570 观看

3回复

1455 作者的声誉

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

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

是否有预先构建的解决方案,最好在Docker主机上运行Nginx代理,或者我应该编写一个node.js代理,可以管理Docker容器(通过Web启动/停止/重新启动) ), 要么...?我有什么选择可以使Docker容器更像是一个自然事件而不是具有无关端口和容器杂耍的东西?

作者: ringmaster 的来源 发布者: 2013 年 8 月 28 日

回应 (3)


42

673 作者的声誉

以下是两个可能的答案:(1)直接使用Docker设置端口并使用Nginx / Apache代理虚拟主机,或者(2)使用Dokku为您管理端口和虚拟机(这是我学习如何做方法1)。

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

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

步骤2:使用“-p”强制Docker中的端口号分配以设置Docker的端口映射,并使用“-e”在Docker中设置自定义环境变量,如下所示:

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环境变量配置,如方法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找出端口)

目前,管理Docker虚拟主机的一个很好的选择是Dokku。即将推出的选项可能是使用Flynn,但截至目前,Flynn刚刚开始并没有做好准备。因此,我们现在使用Dokku:在遵循Dokku安装说明后,对于单个域,通过创建“VHOST”文件启用vhost:

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

现在,当一个应用程序通过SSH推送到Dokku时(请参阅Dokku文档了解如何执行此操作),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然后找出任何随机端口Dokku在VPS端映射到应用程序端的5000。这是圆的(甚至可能在将来改变),但它的工作原理!

引擎盖下的VHOST工作方式是:在通过SSH对应用程序进行git推送时,Dokku将执行生活中的挂钩/var/lib/dokku/plugins/nginx-vhosts。这些钩子也位于Dokku源代码这里,并负责撰写nginx.conf与正确的虚拟主机设置文件。如果您没有此目录/var/lib/dokku,请尝试运行dokku plugins-install

作者: David Baird 发布者: 04.09.2013 07:41

3

2047 作者的声誉

使用docker,您希望内部ips保持正常(例如80)并找出如何连接随机端口。

处理它们的一种方法是使用像hipache这样的反向代理。将您的dns指向它,然后您可以在容器上下移动时重新配置代理。请查看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/

作者: ben schwartz 发布者: 14.12.2013 11:20

76

38971 作者的声誉

这个答案可能有点迟,但你需要的是一个自动反向代理。我用了两个解决方案:

  • jwilder / nginx的代理
  • Traefik

随着时间的推移,我倾向于使用Traefik。主要是因为它有良好的文档和维护,并具有更多功能(负载平衡与不同的策略和优先级,健康检查,断路器,ACME / Let的加密自动SSL证书,......)。


使用jwilder / nginx-proxy

当运行Docker容器Jason Wilder的nginx-proxy Docker映像时,您可以将nginx服务器设置为其他容器的反向代理,而无需维护配置。

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

假设您的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

使用Traefik

运行Traefik容器时,您将获得一个反向代理服务器,该服务器将根据容器上的docker 标签重新配置其转发规则。

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

# start the reverse proxy
docker run --rm -it -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik --docker

# start a first container for http://tutum.test.local
docker run -d -l "traefik.frontend.rule=Host:tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -l "traefik.frontend.rule=Host:deis.test.local" deis/helloworld
作者: Thomasleveil 发布者: 01.06.2014 01:15
32x32