我正在从本地迁移到远程Docker,我可以发现守护进程的公共IP吗?

时间:2018-04-08 10:04:35

标签: docker docker-compose

我正在使用Docker Compose来部署我的应用程序。在我的docker-compose.yml我有一个容器my-frontend,它必须知道后端my-backend的公共IP。图像my-frontend是NodeJS应用程序,它在客户端的浏览器中运行。

在我这样做之前:

my-backend:
  image: my-backend:latest
  ports:
    - 81:80
my-frontend:
  image: my-frontend:latest
  ports:
    - 80:80
  environment:
    - BACKEND=http://localhost:81

当我部署到本地Docker守护程序并且客户端在本地运行时,这可以正常工作。

我现在正在迁移到远程Docker守护程序。在这种情况下,客户端不再与Docker守护程序在同一主机上运行。因此,我需要更改BACKEND中的环境变量my-frontend

  environment:
    - BACKEND=http://<ip-of-daemon>:81

当我将<ip-of-daemon>硬编码到Docker守护程序的实际ip时,一切正常。但我想知道是否有办法动态填写此内容?所以我可以对任何远程Docker守护进程使用相同的docker-compose.yml

2 个答案:

答案 0 :(得分:2)

使用Docker Compose,您的Docker容器将全部显示在同一台计算机上。也许您正在使用Swarm或Kubernetes等工具来将容器分发到不同的主机上,这意味着您的后端和前端容器确实可以通过不同的公共IP地址访问。

处理此问题的常用方法是在单个入口点上使用Traefik之类的前端代理。这意味着从浏览器的角度来看,前端和后端的IP地址是相同的。在内部,代理将使用过滤规则将流量定向到正确的LAN名称。通常的方法是使用像/backend/这样的URL路径前缀。

您在评论中正确地提到,假设您的前端容器可以在静态公共IP上访问,您可以使用NginX从内部代理到您的后端。这应该可以正常工作。

这些方法中的任何一种都允许单个IP看起来“共享”端口 - 这解决了想要在多个容器中监听80/443上的相同IP的问题。您需要尝试避免用于后端呼叫的非标准端口,因为某些网络可能会阻止它们(例如移动网络,公司防火墙环境)。

我不确定这些方法会有什么替代方案。如果您可以在主机上运行代码,您当然可以获取计算机的公共IP,但如果您的容器编排正在将容器发送到计算机,那么将运行的唯一代码位于每个容器内,我不相信公开的IP信息会暴露那里。

根据您的用例

进行更新

我最初从你的问题中假设你期望你的容器在Docker服务器场中的任意主机上启动。实际上,您在评论中确认的当前方法是许多未连接的Docker主机,因此无论何时部署,您的容器都可以保证共享公共IP。我现在更了解您的问题背后的目的 - 您想要为后端指定基本URL,包括完全限定的域,非标准端口和URL路径前缀。

正如我在讨论中指出的那样,这可能不是必需的,因为您可以在前端NginX中放置代理URL路径前缀(/backend)。这消除了对非标准端口的需求。

如果您想指定自定义后端前缀(例如/backend/v1以对您的API进行版本控制),那么您可以在Docker Compose配置中的env vars中执行此操作。

如果您需要在JavaScript中引用后端的完全限定地址以便连接到AJAX / WebSocket服务器,您可以从window.location.host派生出来。在你的开发环境中,这将是一个裸IP地址,在你的远程环境中,听起来你有一个域名。

附录

关于这个问题的一些混淆是关于我们指的是什么类型的IP地址。例如:

  

我相信my-backend的公共IP等于docker守护程序的IP

嗯,您的Docker主机有几个IP地址,公共地址只是其中之一。例如,虚拟网络接口docker0是您的Docker主机的LAN IP,如果您要求Docker主机的IP,那确实是一个正确的答案(当然,它无法在公共互联网)。

事实上,我会说,守护进程的LAN地址属于(因为Docker设置了它)而公共IP没有(它是盒子的一个特性,而不是Docker)。

在任何Docker主机中,请尝试以下命令:

ifconfig docker0

这将为您提供有关主机IP的一些信息,如果Docker容器希望与主机联系(例如,如果要连接到未在容器中运行的服务),则非常有用。将此处的IP作为env var传递到容器中非常有用,以便允许进行此连接。

答案 1 :(得分:0)

my-backend:
  image: my-backend:latest
  ports:
    - 81:80
my-frontend:
  image: my-frontend:latest
  ports:
    - 80:80
  environment:
    - BACKEND="${BACKEND_ENV}"

其中BACKEND_ENV和环境变量设置为docker守护程序的ip。

在docker-compose执行的机器中,先设置环境变量。

导出BACKEND_ENV =&#34; http://remoteip..."

或者只是启动指向远程地址的前端

docker run -p 80:80 -e BACKEND='http://remote_backend_ip:81' my-frontend:latest