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$ { ?

Freek
  • 1,097
  • 2
  • 12
  • 30

3 Answers3

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.

niieani
  • 4,101
  • 1
  • 31
  • 22
  • the nginx container tells me that `/var/www` is forbidden to access do I have to provide something for it? – bdart Oct 08 '15 at 10:45
  • 1
    @bdart you need to map /var/www to another directory on your docker host when creating your ```storage-www``` container – niieani Oct 08 '15 at 11:41
  • 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? – bdart Oct 08 '15 at 12:25
  • 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 log – bdart Oct 08 '15 at 14:00
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.

Freek
  • 1,097
  • 2
  • 12
  • 30
  • 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. – Freek Oct 12 '15 at 05:33
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

user2915097
  • 30,758
  • 6
  • 57
  • 59
  • 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 -` – Freek Nov 21 '14 at 08:45
  • 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? – user2915097 Nov 21 '14 at 08:49
  • See the original post for more details, thanx! – Freek Nov 21 '14 at 08:57
  • 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. – user2915097 Nov 21 '14 at 09:03
  • 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? – Freek Nov 21 '14 at 09:05
  • 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... – Freek Nov 21 '14 at 09:06
  • See the main question, at the bottom, there is progress, I found the setting for changing from a socket to listening on a port. – Freek Nov 21 '14 at 14:43
  • saying docker in plural isn't quite right. you have "docker containers", not "dockers". It's not the pants :) – programmerq Jan 30 '17 at 19:16