You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决两个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的域名访问,可按以下步骤调整:

  1. 修改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;
    }
}
  1. 修改docker-compose.yml,给app1添加hosts映射,将自定义域名指向Nginx服务:
services:
  app1:
    # 原有配置不变
    extra_hosts:
      - "app2.local:nginx"
  1. 修改请求地址:
$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:04:51