Docker容器无法通过反向代理访问其他容器

fnatzsnv  于 2023-08-03  发布在  Docker
关注(0)|答案(3)|浏览(193)

我正在使用 docker-compose.yml 作为Ubuntu VPS上的nginx代理后面的几个服务。
我遇到了一个问题,我的Docker容器无法使用其公开可用的代理URL相互访问。它们只能使用各自的Docker服务名称相互联系。
最简单的演示方法如下。我可以通过以下命令从任何地方连接到我的PostgreSQL示例:

psql -Atx postgres://username:pw@postgres.mysite.com/database

字符串
但是如果我输入一个正在运行的容器:

docker compose exec backend sh


然后尝试使用相同的连接字符串连接,**它只是挂起...**没有任何日志,即使在代理端。但是,我可以通过使用Docker服务名称来使其工作:

psql -Atx postgres://username:pw@postgres:5432/database


我应该能够从任何地方使用postgres.mysite.com,无论是容器外部还是内部。但由于某种原因,我只能在容器外使用它。下面是nginx配置部分:

upstream docker-postgres {
      server postgres:5432;
   }

   server {
      listen 443 ssl;
      server_name postgres.mysite.com;

      location / {
         proxy_pass http://docker-postgres;
      }
   }


但这与PostgreSQL无关。这种情况似乎与服务无关。每当容器A(应用代码)尝试使用容器C中运行的代理的公开可用URL连接到容器B(服务)时。
例如,对于我的MinIO服务,上传到https://assets.mysite.com时会挂起,但上传到http://minio:9001时不会挂起。
Partial docker-compose.yml file:

proxy:
    image: nginx:alpine
    ports:
      - '80:80'
      - '443:443'
    networks:
      - myNetwork
backend:
    ports:
      - '3000:3000'
    volumes:
      - ./:/app
      - /app/node_modules
    networks:
      - myNetwork
postgres:
    image: postgres:10.4
    ports:
      - "5432:5432"
    networks:
      - myNetwork
minio:
    image: minio/minio
    command: server --console-address ":9090" --address ":9001" ./minio_data
    ports:
      - '9090:9090'
      - '9001:9001'
    networks:
      - myNetwork

networks:
  myNetwork:
    external: true

其他信息

我在assets.mysite.com server_name下的代理中设置了一个/test端点。

location /test { return 200 'success!!'; }


我可以从服务器(Docker容器外部)访问这个端点:
curl https://assets.mysite.com/test →成功
但是,我不能从任何容器中击中它:
docker compose exec backend curl https://assets.mysite.com/test →挂起!
尽管如此,我还是可以成功ping通assets.mysite.com,甚至是从容器中:

docker compose exec backend ping assets.mysite.com


这里是我几乎所有的nginx配置(只是省略了SSL证书)

http {
   server {
      listen 80 default_server;
      listen [::]:80 default_server;
      server_name _;

      location / {
         return 301 https://$host$request_uri;
      }
   }

   upstream docker-backend {
      server backend:9000;
      keepalive 100;
   }

   upstream docker-postgres {
      server postgres:5432;
   }

   upstream docker-redis {
      server redis:6379;
   }

   upstream docker-minio-assets {
      server minio:9001;
   }

   server {
      listen 443 ssl;
      server_name mysite.com;
      root /var/www/frontend;
      index index.html;

      location /test {
         return 200 'success!!';
      }

      location /backend {
         rewrite ^/backend(/.*)$ $1 break;
         proxy_pass http://docker-backend;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Proto $scheme;
         proxy_pass_request_headers on;
         client_max_body_size 3m;
      }

      location / {
         include /etc/nginx/mime.types;
         try_files $uri $uri/ /index.html =404;
      }
   }

   server {
      listen 443 ssl;
      server_name shopadmin.mysite.com;
      root /var/www/admin;
      index index.html;

      location /a/ {
         try_files $uri /index.html;
      }

      location / {
         include /etc/nginx/mime.types;
         try_files $uri /index.html =404;
      }
   }

   server {
      listen 443 ssl;
      server_name assets.mysite.com;
      client_max_body_size 20m; # Allow bigger file uploads.

      location /test {
         return 200 'success!!';
      }

      location / {
         proxy_pass http://docker-minio-assets;
      }
   }

   server {
      listen 443 ssl;
      server_name redis.mysite.com;

      location / {
         proxy_pass http://docker-redis;
      }
   }

   server {
      listen 443 ssl;
      server_name postgres.mysite.com;

      location / {
         proxy_pass http://docker-postgres;
      }
   }
}

i2loujxw

i2loujxw1#

要解决解析"b.domain.com"时容器A被重定向到主机而不是直接查找容器B的问题,可以在Docker Compose文件中为容器B添加别名。修改你的Docker Compose文件以包含以下内容:

networks:
  my-net:
    aliases:
      - b.domain.com

字符串
通过在"my-net"网络中为容器B指定别名"b.domain.com",容器A将能够在解析主机名时直接定位容器B。
但是,请注意,如果您的容器不是同一网络的一部分,Docker将安装UFW(简单防火墙)规则,该规则可能会阻止容器A和容器B之间的连接。因此,请确保两个容器位于同一网络中,或者如果它们位于不同的网络中,请采取适当的措施允许它们之间的通信。

8aqjt8rx

8aqjt8rx2#

我在过去有过类似的情况,有一个特别让我想起你的情况,因为你有子域的问题,这也是我的情况。如果我的回答对你不起作用,请忽略它,但我会把它留在这里,以防它对其他人有帮助,并避免浪费他们的时间。

我的场景

我正在运行Kubernetes(KIND)部署,它使用Docker网络,与Docker compose设置相同。我需要从容器连接到AWS端点,这些是外部域名:

  • authsamples.com(AWS Cloudfront)
  • login.authsamples.com(AWS Cognito)
  • web.authsamples.com(AWS Cloudfront)
  • api.authsamples.com(AWS API Gateway)

从部署的容器中,我可以向https://authsamples.com的基本域以及https://google.com等一般互联网URL发出curl请求,但在调用https://login.authsamples.com等AWS子域时,我收到了挂起。所有URL都可以从主机计算机解析。

决议

我在KIND工作节点和容器上尝试了很多DNS and resolv.conf settings的更新。奇怪的行为是,从容器的一般互联网访问是好的,这个问题是特定于我的基于子域的URL。
我的设置没有什么特别的,比如防火墙。问题原来出在主机网络级别。对我有效的是确保Google的2个主名称服务器在主机上使用,反对TCP/IP连接,而不是使用自动选项。
x1c 0d1x的数据

操作系统

我只在Windows和macOS上遇到过这种类型的问题,尽管这些天我把Ubuntu作为我的主要桌面运行。如果没有这些DNS域名服务器,我有时也会遇到移动的开发问题,例如模拟器上的Android WiFi网络不工作。到目前为止,我还没有读到任何可以解释我所接受的行为的东西。

要尝试的事情

当与这些问题作斗争时,我会尝试像这样的快速行动,看看这些是否对你有帮助。

  • 从NGINX容器调用到子域(例如https://assets.example.com)是否会遇到同样的问题?如果是这样,那么NGINX就不是问题所在。
  • 你可以从NGINX背后的服务向子域发出curl请求吗,例如https://assets.example.com(目前没有)?
  • 你可以从NGINX背后的服务向一般的互联网URL发出curl请求吗?
  • 你可以从NGINX背后的服务向基础域(例如https://example.com)发出curl请求吗?
  • 将主机网络更改为显式使用Google名称服务器是否会改变行为?
ee7vknir

ee7vknir3#

更新Docker容器的DNS配置以使用DNS解析器,该解析器应正确解析域名。然后,通过在服务定义下添加dns选项,在docker-compose.yml文件中为每个服务指定DNS解析程序。

相关问题