I have the following docker-compose in my Vagrant + Ansible local development stack (master for Ansible execution, node-1 for VPS simulation):
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
I want to test PHP-FPM with a simple phpinfo.php file, which is mounted from the host to the following location in the Nginx container: /usr/share/nginx/html/phpinfo.php
Running this file I'm getting the infamous blank page response in my browser. Maybe I have bad Nginx settings, so I executing cgi-fcgi
directly on both PHP and Nginx container also, but /status
and /ping
works just fine:
$ 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
In the next step, I copy with curl
a simple phpinfo
file into /usr/share/nginx/html/phpinfo.php
location in php
container and surprise, it's returning the expected HTML output. So the issue is probably related to file permissions between the containers, volumes and host mounted files.
But this approach creates a new problem on it's own, because now I have two different versions of a file between the php
and nginx
container. One is host mounted, the another one is rewritten by the curl
command, both under the path of the same volume:
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();
?>
I need some advice in the following questions:
- Is there a way to create FastCGI connection between a PHP and Nginx (or Apache) container without exposing a volume to both containers?
- If it's only possible if I install both PHP and Nginx in the same container, in my mind this is defeats the "one process for one thing" paradigm. I don't consider this a solution.
- Maybe a less painful approach would be using a multi-stage build Dockerfile? But again, PHP have it's needed system packages on it's own, so this is probably not gonna work...
- Lot of resources on the internet considering getting your app into containers with
git
as a bad practice, but seems like mounting from the host can create another problem, because if a file modified inside a container, the same mounted volume can have a different file version in another container. - A
COPY
command in aDockerfile
can be a viable solution to not have host mounted problems like in my case (duplicate file versions, if one container modifying the file)?
Please give me some advice how to properly handle persisting data with Docker Volumes between multiple containers, if you consider using CI/CD on the future also. Thank You!
Update 2020-07-30:
If I bind mounting the same file both into php and nginx containers (so I abandone the named volumes), suddanly it works:
- /usr/src/app/docker/src/phpinfo.php:/usr/share/nginx/html/phpinfo.php
However this one doesn't:
- nginx:/usr/share/nginx
Why is this different behavior with named volumes and why it works with bind mounts?
I examined the Laradock project and it also uses bind mounts almost everywhere. Seems like I should only use volumes when my code created inside the containers (like a database), am I right? What's happening with volumes if I want to expose the same location to multiple containers?