
This assumes you have two containers running on the same Docker network, where one container was built from the nginx image and the other container was built from the php:fpm image.
The docker container ls command can be used to ensure the containers are running.
~]# docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e894ff6f352 php:fpm "docker-php-entrypoint" 29 hours ago Up 29 hours 0.0.0.0:9000->9000/tcp php-fpm
24bcf99fc7bc nginx "/docker-entrypoint.sh" 29 hours ago Up 29 hours 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
Let's say the server block in the /etc/nginx/conf.d/default.conf file in the nginx container contains the following. Notice that the document root directory is /var/www/html.
AVOID TROUBLE
Ensure the root directive is not defined inside of a location block.
Ensure DNS is able to resolve server_name to the Docker system that contains the PHP container otherwise the PHP file will be downloaded instead of being presented in the browser.
server {
listen 80;
server_name stage.example.com;
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php;
}
}
In this example, both the nginx and PHP FPM containers will need the same exact files located at /var/www/html in each container, thus you'll almost always want the files to reside somewhere on your Docker system, and then to use the --volume option to mount the files on your Docker system to /var/www/html in the Nginx container.
docker run
--publish 80:80
--volume /path/to/html/files:/var/www/html
nginx
And also in the PHP FPM container.
docker run
--publish 9000:9000
--volume /path/to/html/files:/var/www/html
php:fpm
In this scenario, requests for a PHP file from Nginx will look like this.
The iptables command with the --list and --numeric options can be used to validate that connections are allowed to the PHP FPM container on port 9000. Almost always, the IP address will be an IP address in the 172.17.x.x/16 subnet.
~]# iptables --list --numeric
Chain INPUT (policy ACCEPT 110 packets, 9880 bytes)
target prot opt source destination
ACCEPT all -- 0.0.0.0./0 172.17.0.3 tcp dpt:9000
The ip address command should show that the docker0 interface is bound to the 172.17.x.x/16 subnet.
~]$ ip a
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:18:77:d1:b3 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:18ff:fe77:d1b3/64 scope link
valid_lft forever preferred_lft forever
And the docker inspect command should show the PHP container is bound to the IP address.
~]$ sudo docker inspect container php | grep IPAddress
"IPAddress": "172.17.0.3",
"IPAddress": "172.17.0.3",
You may also need to reload or restart the firewalld service.
systemctl restart firewalld
And the netstat command should show that Docker is listening for connections on port 9000.
~]# netstat -anp | grep 9000
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9000 0.0.0.0:* LISTEN 3515057/docker-prox
Ensure /usr/local/etc/php-fpm.d/www.conf in the PHP container has the following.
listen = 127.0.0.1:9000
You will need to append a location block to the default.conf file for PHP.
- Notice the fastcgi_param directive contains $document_root$fastcgi_script_name. In this example, $document_root is /var/www/html. This means that both the nginx and PHP FPM containers will need the same exact files mounted to /var/www/html. $fastcgi_script_name will be the name of the PHP file that is being requested. For example, if requesting www.example.com/phpinfo.php, then $fastcgi_script_name will be phpinfo.php.
server {
listen 80;
server_name stage.example.com;
root /var/www/html;
index index.html index.php;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass 10.5.14.3:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Notice in this example that fastcgi_pass directive has 10.5.14.3:9000. In this example, 10.5.14.3 is the IP address that is used for the request to reach the Docker system, not the Nginx or PHP containers. This would typically be the IP address of the Docker system or the IP address of the load balancer that forwards requests onto the Docker cluster. The ip address command should show that the network interface is bound to the 10.5.x.x/16 subnet.
~]$ ip address
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:3a:39:61 brd ff:ff:ff:ff:ff:ff
altname enp11s0
inet 10.5.14.3/16 brd 10.5.255.255 scope global noprefixroute ens192
valid_lft forever preferred_lft forever
OpenSSL can be used to determine if the nginx container is able to connect to the PHP container on port 9000.
~]$ sudo docker exec nginx openssl s_client -connect 172.31.29.217:9000
write:errno=0
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 283 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
Did you find this article helpful?
If so, consider buying me a coffee over at