简体   繁体   中英

Docker + Apache + PHP-FPM static content

I am in the process of moving over some sites in PHP using Slim/Twig to docker containers. In the old server a request came in slim routed the request sent back the html and then the browser made the call to get the resources CSS, images, etc. where apache took over.

Moving to Docker the httpd conf is essentially this:

ProxyPassMatch "^/(.*\.php\/(.*)?)$" "fcgi://php:9000/var/www/html/public/index.php/$2"

Still working all that out but this essentially forwards a request like http://192.168.33.20:8080/index.php/admin to fcgi://php:9000/var/www/html/public/index.php/$2 and Slim picks off all the rest of the path so admin and returns the correct view rendered by twig.

Issue I am running into is the resources. I have most of my css and front-end frameworks in the php application via composer. So the browser makes another call to:

/index.php/vendor/twbs/bootstrap/dist/js/bootstrap.bundle.js HTTP/1.1" 404

Getting a 404 because Slim has no idea what this path is and apache is just forwarding.

What I have looked at and the cons:

  1. Placing the resources on Apache but this basically couple Apache and php like the server was.

  2. Creating a container to server these files ie another non-loadbalancer Apache to server these requests. This still couples and also means I need to find a way to potentially store multiple versions in a blue green deployment.

  3. Mount a volume to the Apache lb. Not sure why I abandoned this one. Probably version issues.

  4. Create a route that can search for the resource. So far my favorite idea but added code complexity.

So the question I have is there a standard way of dealing with this in Docker?

My standard practice is to control resource access by framework route. An example implementation (in Lumen):

$router->get('/asset[/{path:.*}]', 'AssetController@load');

An example request and response looks like this:

GET /asset/js/app.js HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: */*
Referer: http://localhost:8080/spa/example
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

HTTP/1.1 200 OK
Server: nginx
Content-Type: application/javascript
Content-Length: 21056410
Connection: keep-alive
Last-Modified: Sun, 31 Jul 63 19:34:21 +0000
Cache-Control: private, must-revalidate
Date: Wed, 31 Jul 2019 19:34:21 GMT
Accept-Ranges: bytes
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src  'self'; connect-src  'self'; img-src  'self'; style-src 'unsafe-inline' fonts.googleapis.com 'self'; font-src fonts.gstatic.com 'self'; script-src 'unsafe-inline'  'self' 'unsafe-eval'

Your controller (eg, AssetController in my earlier example), would take care to translate the URL path to the file system path (watch out for .. and other tricks, use realpath and compare it to your code's installation base path), set the Content-Type and Content-Length headers, any relevant caching headers, and then stream the file.

While that does add complexity and a certain amount of overhead, it provides the flexibility to constrain resources by business logic.

If performance is a concern, you can promote the access to the web server or shield the route behind a CDN and proxy content.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM