如何在远程Docker堆栈中创建网络连接

35次阅读
没有评论

问题描述

在使用docker stack deploy在远程机器上运行应用程序时遇到了问题。当他在Windows笔记本上使用docker swarm deploy部署应用程序时,一切正常。但是当他在Linux集群上运行时,无法连接到应用程序。在本地运行应用程序时,使用curl localhost:8000可以得到一些输出,但在远程机器上却得到了curl: (7) Failed to connect to localhost port 8000: Connection refused的错误。用户还不明白为什么在本地和远程计算机上会得到不同的结果,即什么配置导致了这种差异。
用户尝试了删除所有网络并从头开始,但问题仍然存在。
用户通过SSH连接到远程服务器,并使用以下命令启动一个Web应用程序:

ssh -qy -L 8000:localhost:8000

用户使用以下简单的yaml文件testapp.yml启动docker stack

version: '3'
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - web_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  web_data: {}

用户使用以下命令部署应用程序:

docker swarm deploy -c testapp.yml testapp

用户使用sudo docker stack services testapp命令得到以下输出:

ID             NAME                MODE         REPLICAS   IMAGE              PORTS
93rj1ialspj2   testapp_db          replicated   1/1        mysql:5.7          *:8000->80/tcp
nl18a7mr4auk   testapp_wordpress   replicated   1/1        wordpress:latest

然而,当用户访问localhost:8000时,显示”该网站无法访问。localhost拒绝连接”的错误。在本地和远程计算机上运行curl localhost:8000命令返回”curl: (7) Failed to connect to localhost port 8000: Connection refused”的错误。
用户在远程计算机上运行的Docker版本为20.10.9,本地计算机上运行的Docker版本为20.10.8。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

首先,感谢您提供了详细的信息,让我能够更好地理解您的问题。
在使用Docker Swarm时,如果您希望在集群内部进行流量转发,您需要在前端使用代理。我个人使用NGINX作为代理层,并创建一个上游(upstream)来连接到Docker Swarm管理节点的IP堆栈,而不是发送到工作节点。
Docker Swarm的工作方式是将流量发送到单个端口号,例如9000,并将此端口9000绑定到堆栈/服务上的端口80或您所需的端口。每个副本现在都在端口9000上运行,以接收来自管理节点的外部流量,并将其发送到集群中。
确保您只将堆栈部署到工作节点,除非需要控制器软件,否则可能会导致不稳定的集群。
如果您的Redis和SQL在集群中运行(我希望不是这样),但如果您需要它们,您可以为这些堆栈设置一个网络,并将该网络添加到其他堆栈中,但我建议将Redis、SQL等保留在独立的服务器上。
因此,根据我的描述,您需要以下内容:
– HTTP/HTTPS代理将流量路由到自定义端口,例如9000,用于Docker Swarm管理节点。
– 将端口(例如9000)暴露给服务端口(例如80)。
– 在服务内部设置连接以使用外部的Redis和SQL。
希望我已经足够清楚地解释了,如果还有问题,请随时提问。

示例 – Docker中的端口暴露

docker run -p 9000:6379 --name redis_cont -d redis

将主机上的端口9000路由到Redis容器上的端口6379。

示例 – docker-compose.yml中的端口暴露

version: "3.7"
services:
  redis:
    image: "redis:alpine"
    ports:
      - "9000:6379"

在Docker Swarm中部署一个Redis堆栈,并允许主机(Docker Swarm集群)上的端口9000路由到Redis堆栈服务上的端口6379。

方案2

请注意以下操作注意版本差异及修改前做好备份。
另一种方法是使用网络代理来管理流量路由。您可以使用docker run命令手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。
以下是一个简单的bash脚本示例,可以在容器A启动后启动容器B:

#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
  sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b

在这个示例中,我们首先使用docker run命令启动容器A,并将其命名为container_a。然后,使用一个循环来等待容器A完全启动(这里是通过在容器内运行echo命令来测试)。一旦容器A就绪,我们再使用docker run命令启动容器B,并将其命名为container_b
请注意,这只是一个示例,您需要根据实际情况进行调整和修改。

正文完