Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP-FPM + nginx version #54

Closed
schmunk42 opened this issue Dec 4, 2014 · 37 comments
Closed

PHP-FPM + nginx version #54

schmunk42 opened this issue Dec 4, 2014 · 37 comments

Comments

@schmunk42
Copy link

Since there's an Apache flavour available of the PHP Docker image, what's about a similar solution for PHP -FPM + nginx?

PS: I found no instructions for fpm at all - I can start the image, but I didn't manage it to get anything out of port 9000, not even an error.

@yosifkit
Copy link
Member

yosifkit commented Dec 4, 2014

We can't really do an FPM with Nginx image since it would be two separate processes in the image, which would require something like supervisord and that is not the direction we currently want for official images. We are working on documentation to run Nginx and FPM together.

@schmunk42
Copy link
Author

We can't really do an FPM with Nginx image since it would be two separate processes in the image.

I understand what you mean and support that view also, but having two containers just for a simple web-application looks also a bit too much to me - anyway - looking forward to the docs and your solution.

@atmoz
Copy link

atmoz commented Dec 21, 2014

I also had this thought today, and I'm looking forward to the docs!

@dz0ny
Copy link

dz0ny commented Jan 21, 2015

I've just wanted to share my take on it https://github.com/wtool/nginx (control of PHP version trought env variable) and https://github.com/wtool/php (builds all php versions{latest 5.3+} with php-build).

@schmunk42
Copy link
Author

Here's my approach https://github.com/phundament/docker - tailored for our app and with composer pre-installed, but you'll get the idea.
PHP is running as a service but exposes no ports, nginx is triggered via /root/run.sh and should be "the running process" in the container.

@bennibu
Copy link

bennibu commented Jan 29, 2015

I also tried to use the fpm only version (php:5.6.5-fpm, docker 4.1) but can't get the fpm process to successfully bind to 9000. The fpm process outputs "ready for incoming connections" and thats it. Further investigations with netstat show now LISTEN statement at all. So I guess, the php-fpm manager doesn't start properly.

As we currently deploy out php apps with chef scripted nginx + php-fpm I don't want to include apache as a new depency. So I am very interested in having a solid solution for php-fpm and I want to avoid maintaining out own php-fpm Dockerfiles. I appreciate any help.

@md5
Copy link
Contributor

md5 commented Jan 29, 2015

Where did you run netstat? How is the nginx container finding out how to
connect to the fpm container?

@bennibu
Copy link

bennibu commented Jan 30, 2015

O.k. I have to confess. There were no problem in the fpm server. fpm binds sucessfully to 9000, I have used the wrong commands. Nevertheless, I will also have to include an nginx for myself, because for deploying wordpress we also need to serve some static content, which we can't deliver with the php-fpm server, as I understand for now.

So I don't see a solution to not violate the docker best practive of having only one running process in a container at the time. Maybe we can mount the wordpress sources in both containers, but that would require running them on the same host.

Or stick to the provided mode-php-apache concept. But this will introduce another dependency, and we haven't used apache for a long time.

Any suggestions?

@schmunk42
Copy link
Author

@bennibu I had the same thoughts. Could somebody elaborate more on the difference between the php-fpm "service" for nginx and the apapche mod_php - I know that the module is in a child fork of apache and therefore not counted as a separate service. What unexpected things could happen when using only one container with a running nginx and a PHP in the same container?

It looks to me like, if we'd use the PHP cli (theoretically speaking) with nginx we'd not violate the container principle. But that setup makes no sense.

@tianon
Copy link
Member

tianon commented Jan 30, 2015

As one example, the nginx process could die, and you wouldn't notice right
away and be confused why your site is down when your container is up.

@md5
Copy link
Contributor

md5 commented Jan 30, 2015

@bennibu I'd look at making an analogous image to wordpress, except based on php:fpm instead of php:apache. To do this, I'd copy as much of the entrypoint of the existing wordpress image as possible as well as the logic for downloading Wordpress into /usr/src/wordpress and the exposure of /var/www/html as a volume. I'd then craft a custom image based on nginx that serves static assets from a shared /var/www/html/wp-content/whatever and share the volume with the Wordpress container. That same nginx would be configured to talk to FPM on port 9000 for non-static requests.

@tianon Do you think it would be reasonable to have a wordpress:fpm variant in the official images based on php:fpm?

@tianon
Copy link
Member

tianon commented Jan 30, 2015

@md5 that sounds divine :)

@md5
Copy link
Contributor

md5 commented Jan 30, 2015

I have a quick POC for the Wordpress part here: https://github.com/md5/wordpress/commit/c299bbb20d8021ec144a72fdcc79d8b959aa447a

I tried to whip up a quick nginx config to work with it and got it to proxy to the FPM container, but I hit a redirect loop on the install and don't have time today to work on it anymore.

The only thing I had to do besides copying the Dockerfile and entrypoint was to switch the base image to php:fpm, change the CMD to php-fpm, and remove Apache-related stuff that needs to be handled outside the wordpress:fpm image (i.e. the .htaccess stuff).

I also switched the rsync in the entrypoint to tar (after a helpful suggestion someone made in the synctree/mediawiki image) and removed the rsync install from the Dockerfile. This could probably be done in the main wordpress variant as well.

I'm not ready to open a PR for that wordpress:fpm work until I get it working with an example Nginx conf, but if someone wants to run with it I won't stop them.

@tianon
Copy link
Member

tianon commented Jan 30, 2015

Ooh, using "tar" as an "rsync" replacement is clever.

This definitely needs some love (as you outlined), but it looks like some
good progress! 👍

@thaJeztah
Copy link
Contributor

Apache-related stuff that needs to be handled outside the wordpress:fpm image (i.e. the .htaccess stuff)

Might be useful to warn people that .htaccess only applies to Apache and running WordPress on NGINX may need extra configuration. IIRC, some plugins (and WordPress itself) modify the .htaccess to add rewrite-rules etc. and I'm not sure those properly detect NGINX. Sure, this is something the user should research, but there's a lot of non-too experienced users using WordPress that may need the extra pointers.

Looks like this page collects issues/hints for running WordPress on NGINX; http://codex.wordpress.org/Nginx

@md5
Copy link
Contributor

md5 commented Jan 30, 2015

Since Nginx would be running in a different container and the nginx/php-fpm
integration would not work out of the box with a stock Nginx container, I
think this concern could be easily handled in the docs that describe how to
front the wordpress:fpm image with Nginx. This could be done either in the
form of an example configuration or in the form of a preconfigured image
derived from the official nginx image.

On Fri, Jan 30, 2015 at 3:03 PM, Sebastiaan van Stijn <
notifications@github.com> wrote:

Apache-related stuff that needs to be handled outside the wordpress:fpm
image (i.e. the .htaccess stuff)

Might be useful to warn people that .htaccess only applies to Apache and
running WordPress on NGINX may need extra configuration. IIRC, some plugins
(and WordPress itself) modify the .htaccess to add rewrite-rules etc. and
I'm not sure those properly detect NGINX. Sure, this is something the user
should research, but there's a lot of non-too experienced users using
WordPress that may need the extra pointers.

Looks like this page collects issues/hints for running WordPress on NGINX;
http://codex.wordpress.org/Nginx


Reply to this email directly or view it on GitHub
#54 (comment).

@thaJeztah
Copy link
Contributor

Yes, the image should be accompanied with some example(s) and
docs. If only to prevent loads of support questions.

Nice work on the image, though, having an official WordPress NGINX
image would be great.

@md5
Copy link
Contributor

md5 commented Jan 31, 2015

I just had some time to play around and get a working Nginx config to front the wordpress:fpm image I created earlier today: https://gist.github.com/md5/d9206eacb5a0ff5d6be0

I started from the config in the Codex, but it seemed be having issues due to not passing through PATH_INFO or something. The working config added a few lines I found over here to set some additional fastcgi_param values: http://superuser.com/questions/717863/nginxphp-fpm-setup-why-is-this-configuration-workaround-needed-to-properly-set

@bennibu
Copy link

bennibu commented Jan 31, 2015

@md5 Thanks for your work so far. I like this approach and I will give it a try later. Although we haven't used wordpress with apache in our deployments a long time ago, I will give this combination another chance. Especially when the wordpress world still sticks to apache-php as default deployment stack. Beside this I also think, that with an nginx in front of apache-php we maybe can profit of both worlds. Simplicity in setup and deployment and fast delivery of static contents via nginx (or varnish as the better proxy cache). I am not sure yet, we have to evaluate both strategies.

Beside the decision about the webserver the biggest problem is still wordpress requirements for a writable filesystem for uploads/themes so you can't scale your deployments over multiple hosts without a distributed filesystem. I opened an issue in the wordpress docker repo.

@mikehaertl
Copy link

I've built a working php-fpm + nginx setup now for my yii2-dockerized project. It was actually pretty simple. I build a small nginx image with a dedicated configuration for a yii2 application. And fire up the two (or 3 with db) machines with a simple docker-compose.yml. The core part there is:

app:
    build: ./
    expose:
        - "9000"
nginx:
    build: ./nginx
    ports:
        - "8080:80"
    links:
        - app
    volumes_from:
        - app

So I don't think there's a much better way to use php-fpm. If we don't want to break the one-process-per-container principle, this is the way to go.

EDIT: Oh, and of course it's crucial, that the file paths to the app code on both machines are exactly the same. So I've created a volume for this in the app container, that is shared with the nginx container.

@stucki
Copy link

stucki commented Mar 13, 2015

See also my approach which contains nothing else as needed: https://github.com/stucki/docker-lemp

@mikehaertl
Copy link

So IMO what is really the issue, is only the lack of documentation. A fpm+nginx image is not really in the spirit of docker as was mentioned before. Maybe the README could contain a note on the php-fpm tags?

Something along the lines of:

To bring up an application with php-fpm you have to:

  • create a Dockerfile for a simple nginx container (FROM nginx) and add a custom /etc/nginx/nginx.conf
  • create a php-fpm container from php:fpm and mount your source code as a volume e.g. to /var/www/html
  • link the php-fpm container to the nginx container
  • link the volumes from php-fpm to your nginx

In the nginx.conf it's important that

  • the web root points to the volume that is linked from php-fpm and
  • you use the php-fpm container name as PHP proxy hostname

Example:

Dockerfile:

FROM nginx:1.7.10
COPY nginx.conf /etc/nginx/nginx.conf

nginx.conf:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen 80;
        root /var/www/html;
        index index.html index.php;
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
            fastcgi_pass   php-fpm:9000;
            try_files $uri =404;
        }
    }
}
docker build -t mynginx .
docker run -d -v /path/to/app:/var/www/html --name php-fpm php:5.6.6-fpm
docker run -p 8080:80 --volumes-from php-fpm --link php-fpm:php-fpm mynginx

@md5
Copy link
Contributor

md5 commented Mar 14, 2015

@mikehaertl agreed 👍

I did a very similar config to yours as a gist a while back for the wordpress:fpm image: https://gist.github.com/md5/d9206eacb5a0ff5d6be0

I'm sure nobody would object to having this better documented, it's just a matter of someone having the time and inclination to do so.

@mikehaertl
Copy link

I did a very similar config to yours as a gist a while back for the wordpress:fpm image:

@md5 Oh, indeed. Must have missed that :).

@IbnSaeed
Copy link

@mikehaertl Thanks for the above commands. I tried your example and it worked flawlessly

Thanks alot

@intellent
Copy link

Thanks for this interesting discussion.

To me, as well, it makes totally sense to run run FPM and nginx in two separate containers.

But: How does this scale? E.g. in AWS Elastic Beanstalk with a load balancer in front of it? If you use php-apache, you’ve got one image per app and AWS may spawn/kill as many containers as needed.

In the FPM scenario this doesn’t work anymore. You would need two containers (nginx+fpm) per instance …

UPDATE: Ah, well. This is how Amazon proposes doing it, two containers per instance: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_ecstutorial.html

@md5
Copy link
Contributor

md5 commented Aug 23, 2015

@intellent I got confused by your comment because "EBS" usually means Elastic Block Store. At first I thought you actually meant ECS (i.e. EC2 Container Service), but I see now that you're actually talking about Elastic Beanstalk (which uses ECS under the hood for container deployments).

Looks like the docs you found are the right ones for what you're trying to do. 👍

@intellent
Copy link

@md5 Oh, one should never make acronyms up on the fly. Sorry for the confusion. Updated. :-)

@schmunk42
Copy link
Author

@intellent From our tests I can say that the nginx container usually needs much less resources than the fpm container. Which means that you can, i.e. insert a haproxy container in between nginx and fpm and just scale the fpm process.
We scaled from 1:1 to 1:30 (nginx:fpm) for load testing without having nginx as the limiting factor.

@intellent
Copy link

@schmunk42 Very interesting. How do you manage the deployment? Self-managed infrastructure? It should also be possible to use nginx as load balancer for the fpm instances, right?

@schmunk42
Copy link
Author

Yes, nginx should also be able to do that.
We're using https://github.com/tutumcloud/haproxy on the tutum infrastructure. In this setup the haproxy takes also care about connecting containers on different physical nodes.

@jamiehannaford
Copy link

@schmunk42 How can I get a 1:30 relationship between nginx and php-fpm? The only solution I can think of is to have haproxy load balancing multiple nginx/php-fpm container pairs. Could you share how you balance multiple php-fpm backends with a single nginx frontend?

@schmunk42
Copy link
Author

@jamiehannaford To be honest, I haven't fully tested it, but the idea would be something like this: http://nginx.org/en/docs/http/ngx_http_upstream_module.html

upstream websbite {
    server PHPFPM_1_PORT_9000_TCP;
    server PHPFPM_2_PORT_9000_TCP;
    server PHPFPM_3_PORT_9000_TCP;
}

The tricky part is scaling up and down and changing the config dynamically, that's a feature haproxy is doing for you.

@J0WI
Copy link
Contributor

J0WI commented Dec 18, 2015

Would be great to have this documented!
May be also giving a hint in the nginx docs about linking, because there are a lot of nginx-php, nginx-hhvm, nginx-memcached nginx-whatever containers out there.

@knvpk
Copy link

knvpk commented Dec 20, 2015

Hi @mikehaertl , Im using what you have suggested, all are running fine but in web browser im not getting any response. in nginx logs response code is 200 but no matter in the web browser.

@strarsis
Copy link

strarsis commented Jan 7, 2016

I solved it by using xdrum/nginx-extras image for perl/lua support in nginx config
to use system environment variables so I can link nginx-fpm + php-fpm together.

@tianon
Copy link
Member

tianon commented Aug 22, 2016

This really should be handled by using two containers linked together somehow (either with linking, Docker Networks, or some other method). To that end, I'm closing this issue in favor of docker-library/docs#238. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests