ChatGPT解决这个技术问题 Extra ChatGPT

将虚拟主机分配给 Docker 端口

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

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

是否有为此预先构建的解决方案,我最好的选择是在 Docker 主机上运行 Nginx 代理,或者我应该编写一个具有管理 Docker 容器潜力的 node.js 代理(通过网络启动/停止/reuild ), 或者...?我有哪些选择可以让使用 Docker 容器更像是一种自然事件,而不是使用无关端口和容器杂耍?

我也有这个问题 - 据我所知,在 Docker 容器中运行每个应用程序,然后使用 nginx 服务器(可能在它自己的容器中)在主机上进行路由是这样做的方法。我想知道我是否应该独立运行应用程序服务器(即公开一个 php-fpm、puma 等服务器)或包含一个(毫无意义?)nginx 实例。
看看 github.com/dotcloud/hipache,它是一个通过 redis 配置的反向代理。

T
Thomasleveil

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

jwilder/nginx-代理

特拉菲克

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

使用 jwilder/nginx-proxy

运行 Docker 容器 Jason Wilder's nginx-proxy Docker image 时,您将 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:1.7 --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

-v /var/run/docker.sock:/tmp/docker.sock 这是危险的解决方案吗?容器这个 nginx 代理可以访问 docker 主机守护进程吗?这可能是安全漏洞吗?
可能。另请注意,不共享 /var/run/docker.sock 也不能保证不能从容器中利用 docker 主机。 Docker 安全本身就是一个主题。
是否存在任何已知的安全问题?当您可以从容器访问 docker 主机时。
过去存在漏洞,现在问题已修复,但未来可能会发现新的漏洞。 Docker 不是为了增加安全性,而是为了易于部署
您也可以分别运行 nginx-proxy 和 docker-gen,这样 docker 套接字就不会挂载到 nginx 容器上。
D
David Baird

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

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

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

第二步:在 Docker 中强制端口号分配,“-p”设置 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”文件启用虚拟主机:

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 push 时,Dokku 将执行存在于 /var/lib/dokku/plugins/nginx-vhosts 中的钩子。这些挂钩也位于 Dokku 源代码 here 中,负责编写具有正确 vhost 设置的 nginx.conf 文件。如果 /var/lib/dokku 下没有此目录,请尝试运行 dokku plugins-install


b
ben schwartz

使用 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/