不同Docker Stack服务通信问题及mysqli_connect报错排查
先给你吃个定心丸:你这套跨Stack通信的配置其实是没问题的!你遇到的Call to undefined function mysqli_connect()错误和网络连通性无关,核心原因是你的PHP容器没有正确安装并启用mysqli扩展。下面一步步帮你解决:
1. 修复PHP mysqli扩展缺失的问题
官方的php:7-fpm镜像默认没有预装mysqli扩展,你提到的“已安装php-mysql扩展”大概率是在宿主机操作的,或者在容器内临时安装后没保存到镜像里(容器重启就会丢失)。推荐两种持久化的解决方式:
方式一:构建自定义PHP镜像(推荐)
在stack1的目录下创建Dockerfile:
FROM php:7-fpm # 安装并启用mysqli扩展 RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
修改stack1的docker-compose.yml中php服务的配置,把image替换为build指令:
php: build: . # 指向当前目录的Dockerfile volumes: - ./code:/code networks: - apps-net - db-net deploy: mode: replicated replicas: 1
重新部署stack1:
docker stack deploy -c docker-compose.yml stack1
方式二:启动时临时安装(适合快速测试)
如果不想构建镜像,可以在php服务的command中加入扩展安装命令,让容器每次启动时自动安装:
php: image: php:7-fpm volumes: - ./code:/code command: > sh -c "docker-php-ext-install mysqli && docker-php-ext-enable mysqli && php-fpm" networks: - apps-net - db-net deploy: mode: replicated replicas: 1
2. 确认跨Stack通信的访问地址
你的网络配置是正确的:swarm作用域的外部网络db-net已经让两个Stack的服务处于同一网络中。需要注意的是,Swarm模式下跨Stack访问服务,要使用<Stack名称>_<服务名称>作为主机名。
比如你部署stack2时用的命令是docker stack deploy -c docker-compose.yml stack2,那么stack2里的db服务在网络中的可访问主机名是stack2_db。你的index.php连接代码应该改成:
<?php $conn = mysqli_connect('stack2_db', 'root', 'password', 'wordpress'); if (!$conn) { die("Connection failed: " . mysqli_connect_error()); } echo "Connected successfully"; ?>
3. 验证网络连通性(可选)
如果想确认两个Stack的服务确实能通信,可以进入stack1的php容器,ping stack2的db服务:
# 找到php容器ID docker ps | grep stack1_php # 进入容器并测试 docker exec -it <容器ID> ping stack2_db
如果能收到响应,说明网络连通完全正常。
内容的提问来源于stack exchange,提问作者Tara Prasad Gurung

