Caddy: Caddy + PHP-FPM in different Docker containers

Created on 16 Apr 2016  路  32Comments  路  Source: caddyserver/caddy

First, big thanks for this great piece of software and the amazing spirit in this community.

Running 0.8.2 on alpine:3.2 in ubuntu DO droplet

I'm trying to get caddy to work with PHP-FPM and Docker, having caddy in one container, linked to another one with php.
This is no problem at all, but it gets tricky when trying to combine with vhosts, because the root for PHP-FPM is configured to say /var/www whilst the the vhosts go in /var/www/site-1 etc.

I use one caddyfile:

import /etc/caddy/vhosts/*

:80 {
  root /var/www
  tls false  
  fastcgi / php:9000 php
}

And another one in the vhosts directory:

my-site.com {
  root /var/www/my-site.com
  gzip
  markdown
  tls [email protected] 
  fastcgi / php:9000 php
}

The PHP-FPM container is configured to listen on 0.0.0.0:9000, both containers mount the same volume with the webdirs to the same path and the root for PHP-FPM is configured to this same base path: /var/www.

Also i created the same user/group with equal ids in both containers, use chaperone als per container init system to run both, caddy and php as this user and have chowned the /var/www path correctly.

In a test environment, where i can call the localhost:80 base-vhost, php works, file paths are being resolved correctly. But using the domain from the vhost php doesnt work.

(I even called localhost/my-site.com/test.php which works just fine)

Caddy seems to forward the requests but php always gives me ERROR: Unable to open primary script which apparently means that the fastcgi_param SCRIPT_FILENAME was missing/wrong.

From the logs i saw, that php tried to open /var/www/my-site.com/test.php when being called via https://my-site.com/test.php, which is the correct, but absolute, path.
AFAIK this should just be /my-site.com/test.php.

Please, could anyone point me to a solution, crawling all the php-fpm/fastcgi issues here just didn't help me in the end. Also i did search the net a lot, compared working configurations for nginx etc.
Apparently on nginx i can pass fastcgi_param SCRIPT_FILENAME based on the vhosts root dir, but in the fastcgi documentation for caddy i only found env parameters. These would not help me a lot, as php is running inside another container.

I guess i could just change my docker images to go the combined way and have php and caddy in just one container. But i really wanted to go the one job - one container way, to be able to just rebuild the container whose service got updated.

I hope there is a way.
Thanks a lot.

question

Most helpful comment

All 32 comments

If I get you right, the challenge is from here.

From the logs i saw, that php tried to open /var/www/my-site.com/test.php when being called via https://my-site.com/test.php, which is the correct, but absolute, path.
AFAIK this should just be /my-site.com/test.php.

AFAIK, PHP-FPM needs the absolute path to the file. I may be missing something here but mounting the site directory on same path in both containers should've fixed this.

What do you expect the absolute value to be if /var/www/my-site.com/test.php is the wrong one for that container ?

Actually this absolute path is correct, only that for some reason the variant with the 'top-level vhost' works, while the other doesn't. I just figured, since the path it shows in the error message is the correct absolute path, it should have been relative to the root configured in php-fpms www.conf.
But after more then 30h trying to fix this, i'll try rebuilding the configs and logging everything i can.
Will report my findings.
Is there a known working configuration for this scenario? (multi container caddy + php)

30h is much 馃槼. I personally haven't really used caddy and php in separate containers.

Regarding paths, I am almost sure Caddy passes absolute path to php-fpm and therefore do not think base path in www.conf is used.

I did have some sleep in between :smile:

I also couldn't imagine it being path related. The majority of similar cases where about permissions.

Just tried it again, permissions, ownership and absolute paths are ok, log still says ERROR: Unable to open primary script. But the error generated by caddy is a 404 instead of 5xx: No input file specified. 404 Not Found

Maybe some more sleep will help, i still refuse to give it up. Will retry another day (which probably means tomorrow).
Just a bit bewildered no one else ran into this.

If your docker setup is not complex (e.g. compose), you can share it and I can try to replicate it.

I did rebuild it from scratch, same problem. But since it is a not to complex docker-compose driven project, will just pack it up and send it to you.
Thanks for all your effort, really appreciate it.

You need to the same volumes attached, but you must also take care of which user runs in which container. The error can also be caused by a permission problem.

But @abiosoft knows a lot more about Docker than I do...

@DenBeke i know, its actually 100% identical, i have one base image, which creates users and mount points. the strange thing is, that php works if i use the _base_ caddyfile (the one with root /var/www ) but the imported vhost file where the root is different ( root /var/www/my-site.com ) doesn't.
The connected php container has a doc root at /var/www, but since the cgi passes absolute pathes (/var/www/my-site.com/test.php) it should work all the same.
:cry: But it doesn't.

I did test something new now, i created a second php-fpm container, with adjusted doc root to /var/www/my-site.com/ and connected this one also to the container with caddy. Then in the caddyfile of the vhost i changed the target cgi host to the other one:

my-site.com {
  root /var/www/my-site.com
  gzip
  markdown
  tls [email protected] 
  fastcgi / php2:9000 php
}

This does work. So the problem occurs when the root of caddy and the doc root for php are not identical, even though the caddy root is inside the php doc root.
AFAIK this is no problem when running in the same container, so i guess there is information passed regarding the relative root directory. This is the part where passing to the other container / host makes this fail.
Maybe caddy needs to pass some HEADERS with the request to the php endpoint, the same way as setting env values would be possible.
I think something like

my-site.com {
  root /var/www/my-site.com
  gzip
  markdown
  tls [email protected] 
  fastcgi / php:9000 php
  header SCRIPT_NAME {root}/my-site.com/{path}
}

could do the trick. (But i am not sure if SCRIPT_NAME is the missing one, this was just suggested by some similar issue on an nginx specific article)

@abiosoft Did you get the zip with the compose setup? I sent it to your email address and realized later, that i don't know if this would get to you and be ok. Sorry if it wasn't.

It got to me :) However, I only downloaded it and yet to run it. I will go through the scripts and run the necessary commands. I currently use Docker for Mac and I prefer that over VirtualBox machine that the script is gonna create.

:smile: yep, thats just my laziness there... as my linux is still the linux i want :wink:

@schlypel any luck yet? I have not had time to troubleshoot this 馃槥.

@abiosoft nope, apparently this is not not possible, at least not with the 0.8.x versions. Didn't try with newer yet and solved it for the time being with multiple php-fpm containers for the different purposes.
But will have to rebuild the complete setup anyways during the next days, updating, hardware changes, etc. So i'll try with the newer versions and report back, if i manage to find a solution.

Argh.... missed the green button by 5mm... now its closed, though unsolved :cry:

I haven't read all the posts in this topic, but will write some hints from my tests.

I created a caddy webserver image (0.8.3, also tested with 0.9 beta) and another with caddy webserver. The public html directory is shared by a volume and the same absolute path.

It works fine.

Caddyfile line:
fastcgi / phpfpm:9000 php

You need to link the php container to the caddy one as "phpfpm" in my example.

Important is to change the LISTEN inside the php-fpm configuration! Default is just 127.0.0.1!!!
So change listen 127.0.0.1:9000 to something like listen :9000

@pwFoo This is not the issue, its about having a multi site setup, using imported vhost caddyfiles to set up different roots for different domains.

Apparently on nginx i can pass fastcgi_param SCRIPT_FILENAME based on the vhosts root dir, but in the fastcgi documentation for caddy i only found env parameters.

@schlypel I think those are equivalent. Did you try it?

Also thank you for your kind remark at the beginning of your issue! :blush: Our community really is fantastic.

I did a quick check just right now, but it didn't work.

But i'm in the process of rebuilding the stack, so a thorough test will have to wait a bit. Once tested again, i will comment again.

PS: i tried add every HEADER I thought could be helping :smile:

fastcgi / php:9000 php {
  env DOCUMENT_ROOT "/var/www/my-site.comt"
  env QUERY_STRING {query}
  env REQUEST_METHOD {method}
  env SCRIPT_FILENAME "/var/www/my-site.com/{path}/{file}"
  env SCRIPT_NAME "{file}"
  env REQUEST_URI "{uri}"
  env REMOTE_ADDR {remote}
}

FastCGI Environment variables do not support placeholders.

Now that I have seen the need for it, I will consider implementing it.

Thank you very much :+1:

Maybe that's the whole reason for my problems...

@schlypel may I ask why you want to overwrite those values considering every one of them is set by Caddy ?

@abiosoft Actually I don't _want_ to overwrite them. It just appeared to me, that some information php-fpm needs doesn't get passed over. AFAIK nginx sets specific HEADERS with the

fastcgi_param SCRIPT_NAME my-script.php

and similar ones.
Since @mholt suggested the env parameter for caddy might just do the trick here, i tried it, setting everything that apparently went missing before manually.
I do realize that the php preset of caddy _normally_ does all the required things.
The example above was just a quick test to make sure setting env parameters wasn't the solution to my problem.

@schlypel Whoops, with @abiosoft to the rescue, do you have the ability to build from source and try again?

(Abiola's right, though, that Caddy sets these values automatically. But maybe there's something funky going on with containers so setting the SCRIPT_FILENAME manually will be helpful...)

I guess there's nothing left to do here, so, closing.

I just downloaded caddy and set a path in Caddyfile, php doesn't work out of the box this way. So Caddy can not adjust SCRIPT_FILENAME from path and i have to set this setting myself?

23/Sep/2016:01:27:04 +0200 [ERROR 0 /test.php] Primary script unknown
localhost:8000
root web
fastcgi / /var/run/php/php5.6-fpm.sock php
errors error.log

You appear to be using caddyserver and php on the same host. This ticket was about using caddyserver in one docker container and php in another, so environment and stuff couldnt be passed on.
If you stick to https://caddyserver.com/docs/fastcgi php should work fine.
Maybe you could try to configure php to listen on 127.0.0.1:9000 instead of the socket file, that way i never had any problems.
By the way, @others, with the caddyserver 0.9x and php-fpm pools for each virtual host i finally got it to work as intended :)
Thanks again for having this great community.

Hey schlypel, what is the final config of your setup?
Thank you!

@renegoretzka this gist

Sorry for not answering faster. Had not enough time to finish up my config, its working, but missing a few things to be nice to use.
I hope i麓ll have some time at the end of this year and will definitively post my setup here when ready.
If you try to do this with multiple sites/vhosts, you need to add pools in php-fpm according to your caddyfile. I do this with import. In the php-fpm config you can have all the configs from pools.d loaded, same with caddyfiles import, where i use a folder named sites-enabled for the additonal sites.
Important is, that you麓ll have to use different ports in each php pool.
I numbered my vhosts, so first website uses php-fpm, listening on 9001 and so on.

Hope this helps for now.

Ah, and the most important part, set the root dirs for vhosts and pools accordingly, errors here result in not found answers from php, although the path it says it cant find is absolutely correct.

Perhaps it would be nice for such a config to have a more prominent spot in the Caddy documentation. I wanted to try Caddy but gave up after missing some configuration stuff. Want to try again when a good example is available.

Feel free to put examples in https://github.com/caddyserver/examples :)

Was this page helpful?
0 / 5 - 0 ratings