Windows Docker 环境下多项目端口配置问题及解决方案
在 Windows Docker 环境中管理多个项目时,我们经常会遇到端口重复的问题。本文将探讨在使用 Docker Compose 运行 Hyperf 和 Redis 服务时遇到的端口冲突问题,并提供相应的解决方案。
问题描述
假如我们已经有一个 A 项目包含 Hyperf 和 Redis 服务的 Docker 项目中已经使用 6379 端口,我们希望将 B 项目 Redis 的默认端口 6379 映射到主机的 6389 端口,以避免与其他项目冲突
问题复现
在
.env
文件中设置 Redis 端口REDIS_HOST=redis REDIS_PORT=6389
在 docker-compose.yml 中配置 Redis 服务
redis: image: redis ports: - '${REDIS_PORT:-6389}:6379'
启动服务
docker-compose up -d
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 协议》,转载必须注明作者和本文链接