使用 Yii 将 docker 容器连接到使用 MySQL 服务器的非链接 docker 容器



我有一个dockerized Yii项目和nginx。我有一个带有 mysql 服务器的单独 docker 容器,我将 mysql 转储导入其中。

项目失败并显示错误:

2018-08-15 12:34:52 [-][-][-][error][yiidbException] PDOException: SQLSTATE[HY000] [2002] Connection refused in /app/vendor/yiisoft/yii2/db/Connection.php:687
Stack trace:
#0 /app/vendor/yiisoft/yii2/db/Connection.php(687): PDO->__construct('mysql:host=127....', 'user', 'pass', NULL)
.............

我怀疑该项目的 docker 服务应该在docker-compose.yml中链接。像这样:

version: '2'
services:
app:
image: app
links:
- db
db:
image: mysql:5.7

是否可以在不链接 docker 服务的情况下连接到 mysql 服务器? 如果是,如何做?

更新 1

我目前的 docker-compose.yml:

version: '2'
services:
yiiapp_nginx:
image: nginx
hostname: 'dev.yiiapp.com'
depends_on:
- yiiapp_app
ports:
- "80:80"
volumes_from:
- yiiapp_app
volumes:
- ./docker/nginx/conf:/etc/nginx/
- ./docker/nginx/logs:/var/log/nginx
container_name: "yiiapp_nginx"
yiiapp_app:
build:
./
container_name: yiiapp_app
hostname: 'dev.yiiapp.com'
environment:
MYSQL_DATABASE: yiiapp
MYSQL_USER: yiiapp
MYSQL_PASSWORD: yiiapp
MYSQL_ROOT_PASSWORD: yiiapp

volumes:
- ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro
- ./:/app
- ./docker/container-files/usr/local/etc/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf
expose:
- "9000"

更新 2

这就是我在我的案例中解决它的方式。 对于每个单独的docker-compose.ymldocker 实际上会创建一个单独的网络。裁判

在幕后,Docker引擎创建了必要的Linux。 要创建的网桥、内部接口、iptables 规则和主机路由 这种连接是可能的。

因此,从我的本地机器上,我可以自由访问两个容器,但它们不能相互访问。在不修改现有docker-compose.yml的情况下,我运行了:

docker network create yiiapp_network
docker network connect yiiapp_network mysql_container
docker network connect yiiapp_network yiiapp_app
docker network connect yiiapp_network yiiapp_nginx
docker network inspect yiiapp_network

它创建了一个新网络并将所有容器添加到其中。

此外,我将数据库主机名更改为我的数据库容器名称:

$db_host = 'mysql_container';

它奏效了。

您是否正在尝试从应用程序连接到127.0.0.1?如果是这样,则必须将其更改为运行docker-compose中的数据库的服务的名称,即db。 看到您的错误消息,您应该有类似的东西:

('mysql:host=db', 'user', 'pass', NULL)

并确保两个容器位于同一网络中,以便它们可以相互访问。 如果未指定特定网络,则默认情况下它们将位于同一网络中,并且无需将一个网络链接到另一个网络。

更新码头工人撰写后编辑

由于您的数据库容器和应用程序容器未在同一个 docker-compose 中运行,并且您没有强制它们中的任何一个加入特定网络,因此它们不在同一网络中,无法相互访问。

如果您不想公开主机网络上的数据库端口,则无需公开。您可以简单地创建一个专用于您的应用程序的网络,我们称之为backend

docker network create backend

默认情况下,它将使用网桥驱动程序,只有来自同一主机的容器才能连接到网络。

您无需停止数据库容器即可将其附加到backend网络,只需运行:

docker network connect backend <db_container_name>

最后修改你的docker-compose.yml:

version: '3'
services:
yiiapp_nginx:
image: nginx
hostname: 'dev.yiiapp.com'
depends_on:
- yiiapp_app
ports:
- "80:80"
volumes_from:
- yiiapp_app
volumes:
- ./docker/nginx/conf:/etc/nginx/
- ./docker/nginx/logs:/var/log/nginx
container_name: "yiiapp_nginx"
networks:
- frontend
yiiapp_app:
build: .
container_name: yiiapp_app
hostname: 'dev.yiiapp.com'
environment:
- MYSQL_DATABASE=yiiapp
- MYSQL_USER=yiiapp
- MYSQL_PASSWORD=yiiapp
- MYSQL_ROOT_PASSWORD=yiiapp
volumes:
- ~/.ssh/id_rsa:/root/.ssh/id_rsa:ro
- ./:/app
- ./docker/container-files/usr/local/etc/php-fpm.d/www.conf:/usr/local/etc/php-fpm.d/www.conf
expose:
- "9000"
network:
- backend_network
- frontend
networks:
backend_network:
external:
name: backend
frontend:
name: yiiapp_frontend
driver: bridge

使用docker-compose up --build重新构建您的撰写堆栈,它应该可以正常工作。

您肯定希望您的 mysql 数据库容器始终保留在backend网络中,因此请以相同的方式修改其docker run scriptdocker-compose。请参阅从 docker 网络文档指定自定义网络。

如果在同一 docker 撰写文件中db服务,则无需在外部提供任何链接。可以通过名称dbyiiapp容器调用它。 请确保使用db作为yiiapp服务/容器的连接字符串中的 mysql 主机名。

('mysql:host=db', 'user', 'pass', NULL)

重新创建容器 -

$ docker-compose build ; docker-compose up -d

如果您的 mysql 存在于主机上,您可以将主机 IP 放入连接字符串或在 docker-compose 中使用network_mode(首选(,将以下内容添加到您的 docker-composeapp/yii服务中并再次构建容器 -

network_mode: "host"

使用network_mode: "host"后,需要将连接字符串更改为 (host=127.0.0.1,端口=3306( -

('mysql:host=127.0.0.1....', 'user', 'pass', NULL)

参考 - https://docs.docker.com/compose/compose-file/#network_mode

最新更新