我在我的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持久化数据。谢谢你!
更新2020-07-30:
如果我绑定挂载同一个文件到php和nginx容器中(所以我放弃了命名卷),突然它就工作了:
- /usr/src/app/docker/src/phpinfo.php:/usr/share/nginx/html/phpinfo.php
然而,这一个没有:
- nginx:/usr/share/nginx
为什么命名卷会有不同的行为,为什么它适用于绑定挂载?
我检查了Laradock项目,它几乎在所有地方都使用绑定挂载。看起来我应该只在容器(比如数据库)内创建代码时才使用卷,对吗?如果我想将同一位置公开给多个容器,卷会发生什么?
1条答案
按热度按时间w9apscun1#
构建过程:
1.使用包含php-fpm和apache的基础构建单个镜像(php-fpm-apache)
1.创建一个pod,其中包含两个容器,具有相同的图像,但在前台运行不同的命令。
1.(2.1)Apache的第一个容器(root用户)[root]。
1.(2.2)第二个容器与php-fpm(与continua用户在示例中)[非根]
参考示例:here