我正在使用 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;
}
}
}
型
3条答案
按热度按时间i2loujxw1#
要解决解析
"b.domain.com"
时容器A被重定向到主机而不是直接查找容器B的问题,可以在Docker Compose文件中为容器B添加别名。修改你的Docker Compose文件以包含以下内容:字符串
通过在
"my-net"
网络中为容器B指定别名"b.domain.com"
,容器A将能够在解析主机名时直接定位容器B。但是,请注意,如果您的容器不是同一网络的一部分,Docker将安装UFW(简单防火墙)规则,该规则可能会阻止容器A和容器B之间的连接。因此,请确保两个容器位于同一网络中,或者如果它们位于不同的网络中,请采取适当的措施允许它们之间的通信。
8aqjt8rx2#
我在过去有过类似的情况,有一个特别让我想起你的情况,因为你有子域的问题,这也是我的情况。如果我的回答对你不起作用,请忽略它,但我会把它留在这里,以防它对其他人有帮助,并避免浪费他们的时间。
我的场景
我正在运行Kubernetes(KIND)部署,它使用Docker网络,与Docker compose设置相同。我需要从容器连接到AWS端点,这些是外部域名:
从部署的容器中,我可以向
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网络不工作。到目前为止,我还没有读到任何可以解释我所接受的行为的东西。
要尝试的事情
当与这些问题作斗争时,我会尝试像这样的快速行动,看看这些是否对你有帮助。
https://assets.example.com
)是否会遇到同样的问题?如果是这样,那么NGINX就不是问题所在。https://assets.example.com
(目前没有)?https://example.com
)发出curl请求吗?ee7vknir3#
更新Docker容器的DNS配置以使用DNS解析器,该解析器应正确解析域名。然后,通过在服务定义下添加dns选项,在
docker-compose.yml
文件中为每个服务指定DNS解析程序。