Docker: Nginx and php5-fpm dockers are not talking
Asked Answered
F

3

15

I’d like to make a fully dockerized Drupal install. My first step is to get containers running with Nginx and php5-fpm, both Debian based. I’m on CoreOS alpha channel (using Digital Ocean.)

My Dockerfiles are the following:

Nginx:

FROM debian
MAINTAINER fvhemert
RUN apt-get update && apt-get install -y nginx && echo "\ndaemon off;" >> /etc/nginx/nginx.conf
CMD ["nginx"]
EXPOSE 80

This container build and runs nicely. I see the default Nginx page on my server ip.

Php5-fpm:

FROM debian
MAINTAINER fvhemert
RUN apt-get update && apt-get install -y \
            php5-fpm \
            && sed 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf
CMD ["php5-fpm"]
EXPOSE 9000

This container also builds with no problems and it keeps running when started.

I start the php5-fpm container first with:

docker run -d --name php5-fpm freek/php5-fpm:1

Ad then I start Nginx,, linked to php5-fpm:

docker run -d -p 80:80 --link php5-fpm:phpserver --name nginx freek/nginx-php:1

The linking seems to work, there is an entry in /etc/hosts with name phpserver. Both dockers run:

core@dockertest ~ $ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
fd1a9ae0f1dd        freek/nginx-php:4   "nginx"             38 minutes ago      Up 38 minutes       0.0.0.0:80->80/tcp   nginx
3bd12b3761b9        freek/php5-fpm:2    "php5-fpm"          38 minutes ago      Up 38 minutes       9000/tcp             php5-fpm

I have adjusted some of the config files. For the Nginx container I edited /etc/nginx/sites-enabled/default and changed:

server {
        #listen   80; ## listen for ipv4; this line is default and implied
        #listen   [::]:80 default_server ipv6only=on; ## listen for ipv6

        root /usr/share/nginx/www;
        index index.html index.htm index.php;

(I added the index.php)

And further on:

location ~ \.php$ {
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
        #       # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
        #
        #       # With php5-cgi alone:
                fastcgi_pass phpserver:9000;
        #       # With php5-fpm:
        #       fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_index index.php;
                include fastcgi_params;
        }

In the php5-fpm docker I changed /etc/php5/fpm/php.ini:

cgi.fix_pathinfo=0

php5-fpm runs:

[21-Nov-2014 06:15:29] NOTICE: fpm is running, pid 1
[21-Nov-2014 06:15:29] NOTICE: ready to handle connections

I also changed index.html to index.php, it looks like this (/usr/share/nginx/www/index.php):

<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body bgcolor="white" text="black">
<center><h1>Welcome to nginx!</h1></center>

<?php
phpinfo();
?>

</body>
</html>

I have scanned the 9000 port from the Nginx docker, it appears as closed. Not a good sign of course:

root@fd1a9ae0f1dd:/# nmap -p 9000 phpserver

Starting Nmap 6.00 ( http://nmap.org ) at 2014-11-21 06:49 UTC
Nmap scan report for phpserver (172.17.0.94)
Host is up (0.00022s latency).
PORT     STATE  SERVICE
9000/tcp closed cslistener
MAC Address: 02:42:AC:11:00:5E (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 0.13 seconds

The Nginx logs:

root@fd1a9ae0f1dd:/# vim /var/log/nginx/error.log
2014/11/20 14:43:46 [error] 13#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 194.171.252.110, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "128.199.60.95"
2014/11/21 06:15:51 [error] 9#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 145.15.244.119, server: localhost, request: "GET / HTTP/1.0", upstream: "fastcgi://172.17.0.94:9000", host: "128.199.60.95"

Yes, that goes wrong and I keep getting a 502 bad gateway error when browsing to my Nginx instance.

My question is: What exactly goes wrong? My guess is that I’m missing some setting in the php config files.

EDIT FOR MORE DETAILS: This is the result (from inside the php5-fpm container, after apt-get install net-tools):

root@3bd12b3761b9:/# netstat -tapen
Active Internet connections
(servers and established) Proto Recv-Q Send-Q Local Address
Foreign Address State User Inode PID/Program name

From inside the Nginx container:

root@fd1a9ae0f1dd:/# netstat -tapen
Active Internet connections
(servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:*
LISTEN 0 1875387 -

EDIT2: Progression!

In the php5-fpm container, in the file:

/etc/php5/fpm/pool.d/www.conf

I changed the listen argument from some socket name to:

listen = 9000

Now when I go to my webpage I get the error: "No input file specified."

Probably I have trailing / wrong somewhere. I'll look into it more closely!

EDIT3:

So I have rebuild the dockers with the above mentioned alterations and it seems that they are talking. However, my webpage tells me: "file not found." I'm very sure it has to do with the document that nginx sents to php-fpm but I have no idea how it should look like. I used the defaults when using the socket method which always worked. Now it doesn't work anymore. What should be in /etc/nginx/sites-enabled/default under location ~ .php$ { ?

Fructiferous answered 21/11, 2014 at 6:45 Comment(1)
Did it work for you with separating the volume container?Metaphor
L
15

The reason it doesn't work is, as you have discovered yourself, that nginx only sends the path of the PHP file to PHP-FPM, not the file itself (which would be quite inefficient). The solution is to use a third, data-only VOLUME container to host the files, and then mount it on both docker instances.

FROM debian
VOLUME /var/www
CMD ['true']

Build the above Dockerfile and create an instance (call it for example: storage-www), then run both the nginx and the PHP-FPM containers with the option:

--volumes-from storage-www

That will work if you run both containers on the same physical server. But you still could use different servers, if you put that data-only container on a networked file-system, such as GlusterFS, which is quite efficient and can be distributed over a large-scale network.

Hope that helps.

Update:

As of 2015, the best way to make persistent links between containers is to use docker-compose.

Leede answered 9/2, 2015 at 17:48 Comment(4)
the nginx container tells me that /var/www is forbidden to access do I have to provide something for it?Metaphor
@Metaphor you need to map /var/www to another directory on your docker host when creating your storage-www containerLeede
I did it. I recognized that my nginx.conf uses /var/www on it's own container instead the /var/www that is linked via the volume. Maybe my root /var/www; is the problem?Metaphor
It seems to work now at least with the html But for the .hh instead of .php it returns a 404 connect() failed (111: Connection refused) from logMetaphor
F
2

So, I have tested all settings and none worked between dockers while they did work with the same settings on 1 server (or also in one docker probably). Then I found out that php-fpm is not taking php files from nginx, it is receiving the path, if it can't find the same file in its own container it generates a "file not found". See here for more information: https://code.google.com/p/sna/wiki/NginxWithPHPFPM So that solves the question but not the problem, sadly. This is quite annoying for people that want to do load balancing with multiple php-fpm servers, they'd have to rsync everything or something like that. I hope someday I'll find a better solution. Thanx for the replies.

EDIT: Perhaps I can mount the same volume in both containers and get it to work that way. That won't be a solution when using multiple servers though.

Fructiferous answered 22/11, 2014 at 14:50 Comment(1)
Adding one more container to the stack pushed this sollution into the realm of "too complicated" for what I want and I just started using full servers (digital ocean droplets). I wanted to run a lot of Drupal servers and I found Drush to also fill all my automated-setup needs.Fructiferous
B
1

When you are in your container as

root@fd1a9ae0f1dd:/# , check the ports used with

netstat -tapen | grep ":9000 "

or

netstat -lntpu | grep ":9000 "

or the same commands without the grep

Beaumarchais answered 21/11, 2014 at 7:45 Comment(8)
This is the result (from inside the php5-fpm container, after apt-get isntall net-tools): (Sorry, why is this so poorly formatted and how can I change that?) root@3bd12b3761b9:/# netstat -tapen Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name tcp 0 0 172.17.0.94:58181 46.4.205.44:80 TIME_WAIT 0 0 - tcp 0 0 172.17.0.94:44741 140.112.8.139:80 TIME_WAIT 0 0 -Fructiferous
This looks like the container with the EXPOSE 80 command, not the container with the EXPOSE 9000 Can you check the ports used on both containers?Beaumarchais
See the original post for more details, thanx!Fructiferous
So the php5-fm container has no network connection active. Clearly something has gone wrong when starting your stuff. When inside this container, try launching php5-fpm I guess you will get an error message.Beaumarchais
Strange, there does not seem to be anything there? Is there a PHP setting that should make it listen there instead of via a socket as is the default I think?Fructiferous
Indeed: root@3bd12b3761b9:/# php5-fpm [21-Nov-2014 09:05:30] ERROR: An another FPM instance seems to already listen on /var/run/php5-fpm.sock [21-Nov-2014 09:05:30] ERROR: FPM initialization failed root@3bd12b3761b9:/# It is listening via a socket.. how to change that...Fructiferous
See the main question, at the bottom, there is progress, I found the setting for changing from a socket to listening on a port.Fructiferous
saying docker in plural isn't quite right. you have "docker containers", not "dockers". It's not the pants :)Twentytwo

© 2022 - 2024 — McMap. All rights reserved.