Problem
I’m attempting to connect two distinct containers:
The issue is that php scripts do not function. It’s possible that your php-fpm settings is incorrect. The source code is available on my repository. Here’s the docker-compose.yml file:
nginx:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www/test/
links:
- fpm
fpm:
image: php:fpm
ports:
- "9000:9000"
I used the following Dockerfile to create a custom image based on the nginx one:
FROM nginx
# Change Nginx config here...
RUN rm /etc/nginx/conf.d/default.conf
ADD ./default.conf /etc/nginx/conf.d/
Finally, here is my Nginx virtual host configuration:
server {
listen 80;
server_name localhost;
root /var/www/test;
error_log /var/log/nginx/localhost.error.log;
access_log /var/log/nginx/localhost.access.log;
location / {
# try to serve file directly, fallback to app.php
try_files $uri /index.php$is_args$args;
}
location ~ ^/.+\.php(/|$) {
fastcgi_pass 192.168.59.103:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
Could someone perhaps assist me in properly configuring these containers to run PHP scripts?
P.S. I use docker-composer to run containers like this:
docker-compose up
from the root directory of the project
Asked by Victor Bocharsky
Solution #1
I realize this is an old post, but I was having the same issue and couldn’t figure out why your code didn’t work. I’ve figured out why after a slew of experiments.
It appears that fpm receives the complete path from nginx and attempts to locate the files in the fpm container, implying that it must be same to server. Even if root does not exist in the nginx container, it must be specified in the nginx config.
To demonstrate:
docker-compose.yml
nginx:
build: .
ports:
- "80:80"
links:
- fpm
fpm:
image: php:fpm
ports:
- ":9000"
# seems like fpm receives the full path from nginx
# and tries to find the files in this dock, so it must
# be the same as nginx.root
volumes:
- ./:/complex/path/to/files/
/etc/nginx/conf.d/default.conf
server {
listen 80;
# this path MUST be exactly as docker-compose.fpm.volumes,
# even if it doesn't exist in this dock.
root /complex/path/to/files;
location / {
try_files $uri /index.php$is_args$args;
}
location ~ ^/.+\.php(/|$) {
fastcgi_pass fpm:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
Dockerfile
FROM nginx:latest
COPY ./default.conf /etc/nginx/conf.d/
Answered by Rafael Quintela
Solution #2
Don’t hardcode ip of containers in nginx config, docker link adds the hostname of the linked machine to the hosts file of the container and you should be able to ping by hostname.
EDIT: Docker 1.9 Networking does not require you to link containers; instead, when many containers are connected to the same network, their hosts files are changed so they can communicate by hostname.
When a docker container is created from an image (or even when an existing container is stopped/started), the docker host assigns new IP addresses to the containers. These IP addresses do not belong to the same subnet as your physical machines.
https://docs.docker.com/docs/docs/docs/docs (this is what compose uses in the background)
but the docker-compose documentation on links & expose explain it better.
Links automatically set a bunch of system variables if you set up your project to acquire the ports + other credentials through environment variables:
Answered by Vincent De Smet
Solution #3
The issue, as previously stated, was that the files were not visible to the fpm container. The preferred pattern for sharing data among containers is to use data-only containers (as explained in this article).
To summarize, construct a container that only houses your data, share it with a volume, then link this volume to volumes from in your apps.
The docker-compose.yml file might look like this when using compose (1.6.2 on my machine):
version: "2"
services:
nginx:
build:
context: .
dockerfile: nginx/Dockerfile
ports:
- "80:80"
links:
- fpm
volumes_from:
- data
fpm:
image: php:fpm
volumes_from:
- data
data:
build:
context: .
dockerfile: data/Dockerfile
volumes:
- /var/www/html
Data publishes a volume that is associated with the nginx and fpm services. Then there’s the data service Dockerfile, which contains your source code:
FROM busybox
# content
ADD path/to/source /var/www/html
The nginx Dockerfile just replaces the default configuration:
FROM nginx
# config
ADD config/default.conf /etc/nginx/conf.d
For the purpose of completeness, here is the configuration file needed to make the example work:
server {
listen 0.0.0.0:80;
root /var/www/html;
location / {
index index.php index.html;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
}
}
It just instructs nginx to utilize the shared disk as document root and configures nginx to communicate with the fpm container (i.e., the correct HOST:PORT, which is fpm:9000 thanks to compose’s hostnames, and the SCRIPT FILENAME).
Answered by iKanor
Solution #4
The version of Docker Compose has been upgraded. They currently have a file format known as version 2.
They now support Docker’s networking feature, which creates a default network called myapp default when it is run.
According to their documentation, your file should look like this:
version: '2'
services:
web:
build: .
ports:
- "8000:8000"
fpm:
image: phpfpm
nginx
image: nginx
These containers would be able to communicate with each other because they are immediately added to the default myapp default network. In the Nginx configuration, you’d have:
fastcgi_pass fpm:9000;
Also, as @treeface stated in the comments, make sure PHP-FPM is listening on port 9000. You can do this by modifying /etc/php5/fpm/pool.d/www.conf and adding listen = 9000.
I’ve kept the information below for anyone who are using an older version of Docker/Docker compose and need it.
When I was seeking for an answer to this query on Google, I kept coming across this question, but it wasn’t precisely what I was looking for because the Q/A focused on docker-compose (which at the time of writing only has experimental support for docker networking features). So, here’s my take on what I’ve discovered.
Docker’s link feature has recently been deprecated in favor of its networks feature.
As a result, you can link containers using the Docker Networks feature by following these steps. Read the documentation mentioned above for a complete description of the options.
Create your network first.
docker network create --driver bridge mynetwork
After that, start your PHP-FPM container, making sure to open port 9000 and assign it to your new network (mynetwork).
docker run -d -p 9000 --net mynetwork --name php-fpm php:fpm
The —name php-fpm at the end of the command, which is the name, is crucial; we’ll need it later.
After that, restart your Nginx container and attach it to the network you just built.
docker run --net mynetwork --name nginx -d -p 80:80 nginx:latest
You can also add —volumes-from commands, etc. to the PHP and Nginx containers as needed.
Now it’s time to set up Nginx. Which should appear something like this:
server {
listen 80;
server_name localhost;
root /path/to/my/webroot;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
In the location block, look for fastcgi pass php-fpm:9000;. That means you should contact the php-fpm container on port 9000. When you add containers to a Docker bridge network, their hosts files are automatically updated to match their container name to their IP address. Nginx will know to contact the PHP-FPM container you called php-fpm previously and allocated to your mynetwork Docker network when it sees that.
You can add that Nginx config either during the build process of your Docker container or afterwards its up to you.
Answered by DavidT
Solution #5
I think we also need to give the fpm container the volume, dont we? Consequently,
fpm:
image: php:fpm
volumes:
- ./:/var/www/test/
If I don’t do this, I get the following error when I try to fire a request: fpm cannot find the requested file:
Answered by leberknecht
Post is based on https://stackoverflow.com/questions/29905953/how-to-correctly-link-php-fpm-and-nginx-docker-containers