如何解决两个Laravel Docker服务间通信失败的问题?
解决Docker中Laravel服务app1与app2互通失败的问题
问题场景
我有两个Laravel应用(app1、app2)部署在Docker环境中,通过docker-compose管理,搭配Nginx作为反向代理。尝试从app1向app2发起HTTP请求时,出现cURL连接失败错误,非Docker环境下两个应用可正常通信。
现有配置
docker-compose.yml
version: '3.8' services: app1: build: context: ./my-laravel-app dockerfile: Dockerfile image: laravel-app container_name: tasks working_dir: /var/www/app1 volumes: - ./my-laravel-app:/var/www/app1 networks: - laravel app2: build: context: ./team_members dockerfile: Dockerfile image: laravel-app2 container_name: team_members working_dir: /var/www/app2 volumes: - ./team_members:/var/www/app2 networks: - laravel nginx: image: nginx:latest container_name: nginx ports: - "8081:81" # app2 - "8090:90" # app1 volumes: - ./my-laravel-app:/var/www/app1 - ./team_members:/var/www/app2 - ./nginx/default.conf:/etc/nginx/conf.d/default.conf networks: - laravel depends_on: - app1 - app2 postgres: image: postgres:13 container_name: postgres environment: POSTGRES_DB: tasks POSTGRES_USER: postgres POSTGRES_PASSWORD: qwerty22 volumes: - pgdata:/var/lib/postgresql/data networks: - laravel networks: laravel: driver: bridge volumes: pgdata: driver: local
Nginx配置(default.conf)
server { listen 80; server_name localhost; root /var/www/app2/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_pass app2:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } } server { listen 90; server_name localhost; root /var/www/app1/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_pass app1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } }
错误请求与提示
发起请求的代码:
$response = $client->get('http://app2:81/team_member/names');
错误信息:
cURL error 7: Failed to connect to app2 port 81 after 1 ms: Couldn't connect to server for http://app2:81/team_member/names
问题分析
核心错误是请求目标错误:
- app2容器本身并未监听81端口,81是Nginx容器的端口(宿主机8081映射到Nginx的81)
- Docker内部容器间通信,不能直接用宿主机的端口映射逻辑,需使用容器内部的服务名与监听端口
- localhost在容器中指向自身,而非宿主机或其他容器
解决方案
方案一:直接通过Nginx服务访问(最简方案)
在app1中发起请求时,目标地址改为Nginx服务的地址加上app2对应的监听端口(Nginx配置中app2的server块监听80端口):
$response = $client->get('http://nginx:80/team_member/names');
说明:
- Docker内部网络中,服务名
nginx可直接解析到Nginx容器的IP - Nginx的80端口对应配置中app2的Web服务,请求会被正确转发到app2处理
方案二:通过自定义域名访问(更规范)
如果希望用类似app2.local的域名访问,可按以下步骤调整:
- 修改Nginx配置,给两个server块添加独立的server_name:
server { listen 80; server_name app2.local; # 新增自定义域名 root /var/www/app2/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_pass app2:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } } server { listen 80; server_name app1.local; # 新增自定义域名 root /var/www/app1/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include fastcgi_params; fastcgi_pass app1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~ /\.ht { deny all; } }
- 修改docker-compose.yml,给app1添加hosts映射,将自定义域名指向Nginx服务:
services: app1: # 原有配置不变 extra_hosts: - "app2.local:nginx"
- 修改请求地址:
$response = $client->get('http://app2.local/team_member/names');
方案三:直接访问PHP-FPM(不推荐)
若跳过Nginx直接访问app2的PHP-FPM服务,需使用FastCGI客户端发起请求,但会跳过Web服务器的路由、中间件等处理,仅适用于特殊场景,不推荐常规使用。
注意事项
- Docker内部容器通信必须使用服务名(如nginx、app1)作为域名,而非localhost或宿主机IP
- 端口映射(如8081:81)仅用于宿主机与容器的外部访问,容器间通信直接使用容器内部监听的端口
- 确保所有服务都加入同一个Docker网络(本配置中已使用laravel网络,无需调整)
内容的提问来源于stack exchange,提问作者rytee
相关产品推荐
相关产品推荐

