Windows Docker 环境下多项目端口配置问题及解决方案

在 Windows Docker 环境中管理多个项目时,我们经常会遇到端口重复的问题。本文将探讨在使用 Docker Compose 运行 Hyperf 和 Redis 服务时遇到的端口冲突问题,并提供相应的解决方案。

问题描述

假如我们已经有一个 A 项目包含 Hyperf 和 Redis 服务的 Docker 项目中已经使用 6379 端口,我们希望将 B 项目 Redis 的默认端口 6379 映射到主机的 6389 端口,以避免与其他项目冲突

问题复现

  1. .env 文件中设置 Redis 端口

    REDIS_HOST=redis
    REDIS_PORT=6389
  2. 在 docker-compose.yml 中配置 Redis 服务

    redis:
    image: redis
    ports:
     - '${REDIS_PORT:-6389}:6379'
  3. 启动服务

    docker-compose up -d
  4. Hyperf 应用无法连接到 Redis。

    RedisException: Connection refused
    │
    ╵ /opt/www/vendor/hyperf/redis/src/RedisConnection.php:268
    ╵ /opt/www/vendor/hyperf/redis/src/RedisConnection.php:117
    ╵ /opt/www/vendor/hyperf/redis/src/RedisConnection.php:71
    ╵ /opt/www/vendor/hyperf/redis/src/Pool/RedisPool.php:58

    问题原理

    这个问题的核心在于 Docker 网络通信和端口映射的工作方式:

  • Docker Compose 创建的服务在默认网络中可以通过服务名互相访问。
  • 容器间通信使用的是容器的内部端口,而不是映射到主机的端口。
  • ports 指令在 docker-compose.yml 中定义的是容器端口到主机端口的映射,主要用于主机访问容器服务。

在我们的案例中,Redis 容器内部仍然使用默认的 6379 端口,而 6389 端口只是映射到主机的端口。Hyperf 容器尝试使用 6389 端口连接 Redis,但在 Docker 网络内部,Redis 实际上监听的是 6379 端口。

解决方案

方案一: 使用 Docker 内部网络通信 (推荐)

修改 Hyperf 的 Redis 配置 (config/autoload/redis.php):

return [
    'default' => [
        'host' => env('REDIS_HOST', 'redis'),
        'port' => 6379,  // 直接使用 Redis 的默认内部端口
    ],
];

保持 docker-compose.yml.env 文件不变。
这种方法利用了 Docker 的内部网络,使得 Hyperf 可以通过服务名和默认端口直接访问 Redis,同时保持了对外的端口映射。

方案二: 使用主机网络

修改 .env 文件

REDIS_HOST=host.docker.internal
REDIS_PORT=6389

docker-compose.yml 中为 Hyperf 服务添加 extra_hosts:

services:
  hyperf:
    # ... 其他配置 ...
    extra_hosts:
      - "host.docker.internal:host-gateway"

这种方法让 Hyperf 通过主机网络连接 Redis,使用映射后的端口。

方案三

首先获取 rdis 容器的IP
修改 .env 文件

REDIS_HOST= redis ip 
REDIS_PORT=6389

最后

通常,使用 Docker 的内部网络通信是最简单有效的方法。但在特殊情况下,当我们有多个项目且端口重复的时候,我们也可以通过主机网络来实现更灵活的端口配置。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!