将带有 Yii 的 docker 容器连接到带有 MySQL 服务器的非链接 docker 容器
Connect a docker container with Yii to a non-linked docker container with MySQL server
我有一个 docker 化的 Yii 项目和 nginx。我有一个单独的 docker 容器和 mysql 服务器,我将 mysql 转储导入其中。
项目因错误而失败:
2018-08-15 12:34:52 [-][-][-][error][yii\db\Exception] 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.yml
docker 实际上创建一个单独的网络。 ref
Behind the scenes, the Docker Engine creates the necessary Linux
bridges, internal interfaces, iptables rules, and host routes to make
this connectivity possible.
因此,我可以从我的本地计算机自由访问这两个容器,但它们不能相互访问。不修改我现有的 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)
并确保两个容器在同一网络中,以便它们可以相互访问。
如果您不指定特定网络,默认情况下它们将在同一网络中,您不需要 link 一个到另一个。
更新 docker-compose
后进行编辑
由于您的数据库容器和您的应用程序容器不在 运行 同一个 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 script
或docker-compose
。请参阅 docker 网络文档中的 Specify custom networks。
如果您在同一个docker compose 文件中有db
个服务,则无需对外提供任何链接。您可以从 yii
或 app
容器中按名称 db
调用它。确保在 yii
或 app
service/container 的连接字符串中使用 db
作为 mysql 主机名。
('mysql:host=db', 'user', 'pass', NULL)
重新创建容器 -
$ docker-compose build ; docker-compose up -d
如果您的 mysql 存在于主机上,您可以将主机 IP 放入连接字符串或使用 network_mode
(首选) 在你的 docker-compose 中,将下面添加到 docker-compose 的 app/yii
服务中并再次构建容器 -
network_mode: "host"
使用network_mode: "host"
后,需要将连接字符串改为(host=127.0.0.1, port=3306) -
('mysql:host=127.0.0.1....', 'user', 'pass', NULL)
参考 - https://docs.docker.com/compose/compose-file/#network_mode
我有一个 docker 化的 Yii 项目和 nginx。我有一个单独的 docker 容器和 mysql 服务器,我将 mysql 转储导入其中。
项目因错误而失败:
2018-08-15 12:34:52 [-][-][-][error][yii\db\Exception] 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.yml
docker 实际上创建一个单独的网络。 ref
Behind the scenes, the Docker Engine creates the necessary Linux bridges, internal interfaces, iptables rules, and host routes to make this connectivity possible.
因此,我可以从我的本地计算机自由访问这两个容器,但它们不能相互访问。不修改我现有的 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)
并确保两个容器在同一网络中,以便它们可以相互访问。 如果您不指定特定网络,默认情况下它们将在同一网络中,您不需要 link 一个到另一个。
更新 docker-compose
后进行编辑由于您的数据库容器和您的应用程序容器不在 运行 同一个 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 script
或docker-compose
。请参阅 docker 网络文档中的 Specify custom networks。
如果您在同一个docker compose 文件中有db
个服务,则无需对外提供任何链接。您可以从 yii
或 app
容器中按名称 db
调用它。确保在 yii
或 app
service/container 的连接字符串中使用 db
作为 mysql 主机名。
('mysql:host=db', 'user', 'pass', NULL)
重新创建容器 -
$ docker-compose build ; docker-compose up -d
如果您的 mysql 存在于主机上,您可以将主机 IP 放入连接字符串或使用 network_mode
(首选) 在你的 docker-compose 中,将下面添加到 docker-compose 的 app/yii
服务中并再次构建容器 -
network_mode: "host"
使用network_mode: "host"
后,需要将连接字符串改为(host=127.0.0.1, port=3306) -
('mysql:host=127.0.0.1....', 'user', 'pass', NULL)
参考 - https://docs.docker.com/compose/compose-file/#network_mode