【发布时间】:2020-07-30 16:20:45
【问题描述】:
我的 Vagrant + Ansible 本地开发堆栈中有以下 docker-compose(Ansible 执行的 master,VPS 模拟的 node-1):
version: "3.8"
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
nginx:
driver: local
services:
### PHP ########################################################################
php:
image: php:7.4.8-fpm-buster
expose:
- "9000"
networks:
- backend
volumes:
- /usr/src/app/docker/php/php.ini:/usr/local/etc/php/php.ini:ro
- /usr/src/app/docker/php/zzz.ini:/usr/local/etc/php/conf.d/zzz.ini:ro
- /usr/src/app/docker/php/zzz.conf:/usr/local/etc/php-fpm.d/zzz.conf:ro
- nginx:/usr/share/nginx
### Nginx ######################################################################
nginx:
image: nginx:1.19.1
ports:
- "80:80"
- "443:443"
depends_on:
- php
networks:
- frontend
- backend
environment:
- NGINX_HOST=app.test
- NGINX_PORT=80
volumes:
- /usr/src/app/docker/nginx/templates:/etc/nginx/templates
- /usr/src/app/docker/src/phpinfo.php:/usr/share/nginx/html/phpinfo.php
- nginx:/usr/share/nginx
我想用一个简单的 phpinfo.php 文件来测试 PHP-FPM,该文件从主机挂载到 Nginx 容器中的以下位置:/usr/share/nginx/html/phpinfo.php
运行此文件时,我的浏览器中出现了臭名昭著的空白页面响应。也许我的 Nginx 设置不好,所以我也直接在 PHP 和 Nginx 容器上执行 cgi-fcgi,但 /status 和 /ping 工作得很好:
$ ansible node-1 -b -a "docker exec -it app_php_1 /bin/bash -c 'SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping QUERY_STRING=full REQUEST_METHOD=GET cgi-fcgi -bind -connect 127.0.0.1:9000'"
node-1 | CHANGED | rc=0 >>
X-Powered-By: PHP/7.4.8
Content-type: text/plain;charset=UTF-8
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
pong
$ ansible node-1 -b -a "docker exec -it app_nginx_1 /bin/bash -c 'SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping QUERY_STRING=full REQUEST_METHOD=GET cgi-fcgi -bind -connect php:9000'"
node-1 | CHANGED | rc=0 >>
X-Powered-By: PHP/7.4.8
Content-type: text/plain;charset=UTF-8
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
pong
下一步,我使用curl 将一个简单的phpinfo 文件复制到php 容器中的/usr/share/nginx/html/phpinfo.php 位置,令人惊讶的是,它返回了预期的HTML 输出。所以这个问题可能与容器、卷和主机挂载文件之间的文件权限有关。
但是这种方法本身会产生一个新问题,因为现在我在 php 和 nginx 容器之间有两个不同版本的文件。一个是主机挂载的,另一个是通过curl命令重写的,都在同一个卷的路径下:
vagrant@master:~$ ansible node-1 -b -a "docker exec -it app_php_1 cat /usr/share/nginx/html/phpinfo.php"
node-1 | CHANGED | rc=0 >>
<?php
phpinfo();
vagrant@master:~$ ansible node-1 -b -a "docker exec -it app_nginx_1 'cat /usr/share/nginx/html/phpinfo.php"
node-1 | CHANGED | rc=0 >>
<?php
phpinfo();
?>
我需要一些关于以下问题的建议:
- 有没有一种方法可以在 PHP 和 Nginx(或 Apache)容器之间创建 FastCGI 连接,而不会将卷暴露给两个容器?
- 如果只有将 PHP 和 Nginx 都安装在同一个容器中才可能,那么在我看来,这违背了“一个过程做一件事”的范式。我不认为这是一个解决方案。
- 也许使用多阶段构建 Dockerfile 是一种不那么痛苦的方法?但同样,PHP 有它自己需要的系统包,所以这可能行不通...
- 互联网上有很多资源考虑将您的应用程序放入带有
git的容器中作为一种不好的做法,但似乎从主机安装可能会产生另一个问题,因为如果在容器内修改文件,相同的安装卷可以在另一个容器中有不同的文件版本。 -
Dockerfile中的COPY命令可能是一种可行的解决方案,可以避免像我的情况那样出现主机挂载问题(重复文件版本,如果一个容器修改文件)?
如果您考虑在未来也使用 CI/CD,请给我一些建议,如何在多个容器之间使用 Docker Volumes 正确处理持久数据。谢谢!
2020 年 7 月 30 日更新:
如果我将相同的文件同时绑定到 php 和 nginx 容器中(所以我放弃了命名卷),它会突然起作用:
- /usr/src/app/docker/src/phpinfo.php:/usr/share/nginx/html/phpinfo.php
但是这个没有:
- nginx:/usr/share/nginx
为什么命名卷会有这种不同的行为,为什么它适用于绑定挂载?
我检查了Laradock 项目,它几乎在任何地方都使用绑定挂载。似乎我应该只在我的代码在容器(如数据库)内创建时才使用卷,对吗?如果我想将同一个位置暴露给多个容器,卷会发生什么情况?
【问题讨论】:
标签: php docker nginx docker-compose laradock