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

2024-04-04

我在用着docker-compose.yml对于背后的几个服务nginx https://en.wikipedia.org/wiki/NginxUbuntu 上的代理VPS https://en.wikipedia.org/wiki/Virtual_private_server.

我遇到的问题是我的 Docker 容器无法使用公开可用的代理 URL 相互访问。他们只能使用 Docker 服务名称相互联系。

最简单的演示方法如下。我可以通过以下方式从任何地方连接到我的 PostgreSQL 实例:

psql -Atx postgres://username:[email protected] /cdn-cgi/l/email-protection/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

附加信息

我在代理中设置了一个 /test 端点assets.mysite.com服务器名称。

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;
      }
   }
}

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

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

通过指定别名"b.domain.com"对于容器 B 内"my-net"通过网络,容器A在解析主机名时将能够直接找到容器B。

但是,请注意,如果您的容器不属于同一网络,Docker 将安装一个UFW(简单防火墙)规则可能会阻止容器 A 和容器 B 之间的连接。因此,请确保两个容器位于同一网络中,或者如果它们位于不同网络上,请采取适当的措施允许它们之间的通信。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Docker 容器无法通过反向代理访问其他容器 的相关文章

随机推荐