![使用 docker + nginx + php-fpm 提供静态内容](https://linux22.com/image/684151/%E4%BD%BF%E7%94%A8%20docker%20%2B%20nginx%20%2B%20php-fpm%20%E6%8F%90%E4%BE%9B%E9%9D%99%E6%80%81%E5%86%85%E5%AE%B9.png)
我正在尝试使用 docker 配置一个 php webapp。这个想法是在独立容器中运行应用程序php-fpm
,并让另一个容器运行 nginx。此设置的想法是使用相同的 nginx 容器将请求代理到已在同一台机器上运行的其他 webapp。问题是我无法nginx
正确处理静态文件(js、css 等),因为对这些文件的请求会继续fpm
。
文件系统如下所示:
/
├── Makefile
├── config
│ └── webapp.config
└── webapp
└── web
├── index.php
└── static.js
我正在使用看起来像这样的东西来运行整个过程(对此Makefile
不感兴趣):docker-compose
PWD:=$(shell pwd)
CONFIG:='/config'
WEBAPP:='/webapp'
run: | run-network run-webapp run-nginx
run-network:
docker network create internal-net
run-webapp:
docker run --rm \
--name=webapp \
--net=internal-net \
--volume=$(PWD)$(WEBAPP):/var/www/webapp:ro \
-p 9000:9000 \
php:5.6.22-fpm-alpine
run-nginx:
docker run --rm \
--name=nginx \
--net=internal-net \
--volume=$(PWD)$(CONFIG)/webapp.conf:/etc/nginx/conf.d/webapp.domain.com.conf:ro \
-p 80:80 \
nginx:1.11.0-alpine
这就是我的config/webapp.conf
样子。
server {
listen 80;
server_name webapp.domain.com;
# This is where the index.php file is located in the webapp container
# This folder will contain an index.php file and some static files that should be accessed directly
root /var/www/webapp/web;
location / {
try_files $uri $uri/ @webapp;
}
location @webapp {
rewrite ^(.*)$ /index.php$1 last;
}
location ~ ^/index\.php(/|$) {
include fastcgi_params;
fastcgi_pass webapp:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
使用该文件需要处理的任何操作index.php
都可以。但是,静态文件将无法使用,从而导致严重404
错误(因为 php webapp 实际上没有为这些文件配置路由)。我相信 nginx 会尝试从其自己的容器文件系统加载这些文件,而实际上它们在容器中webapp
,从而导致故障恢复@webapp
。
有什么方法可以配置nginx
来为驻留在另一个容器中的文件提供服务吗?
答案1
webapp
我设法通过在容器中安装卷解决了该问题nginx
。run-nginx
现在的工作是这样的:
run-nginx:
docker run --rm \
--name=nginx \
--net=internal-net \
--volume=$(PWD)$(CONFIG)/webapp.conf:/etc/nginx/conf.d/webapp.domain.com.conf:ro \
--volume=$(PWD)$(WEBAPP)/web:/var/www/webapp/web:ro \
-p 80:80 \
nginx:1.11.0-alpine
这个webapp.conf
文件会尝试从容器中加载静态文件,如果不可能的话,会将请求代理给工作fpm
进程:
server {
listen 80;
server_name webapp.domain.com;
root /var/www/webapp/web;
location ~ \.(js|css|png) {
try_files $uri $uri/;
}
location / {
rewrite ^(.*)$ /index.php$1 last;
}
location ~ ^/index\.php(/|$) {
include fastcgi_params;
fastcgi_pass webapp:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS off;
}
}
但是,我想知道是否有更好的方法可以做到这一点,而不是两次共享同一个卷。非常感谢!
答案2
也许可以使用NFS
可以在代码所在的位置创建一个运行 NFS 的 docker 容器,该容器可以链接到运行 nginx 和 php 的容器。文件将仅存储在一个容器中。这也可以提供另一层隔离。
答案3
我有两个建议选项:第一个是将静态资产放入例如 /static 中,并指示 nginx 为这些资产调用不同的后端服务。步骤:
1)更新您的网站,使所有静态资产指向 /static/*,例如 /styles.css 变为 /static/styles.css
2)将您的资产放在由另一个 nginx 提供服务的单独容器中(这样您就可以在多个站点上重复使用该容器)
3)编辑nginx.conf,将所有对/static/*的请求发送到新容器:
location /static/ {
proxy_pass http://static-container;
}
第二种选择是将静态资产移至 CDN,因此您只需更新网站以从外部 URL 加载每个静态资产(https://cdnwebsite/asdsadasda/styles.css而不是 /styles.css 或 /static/styles.css)
第二种选择比其他选择有几个优势,主要是在性能方面。CDN 可以更快地为这些内容提供服务,而且你还可以解决同时连接限制浏览器可以对每个 FQDN 进行操作,因此由于使用更多同时连接来加载您的网站,您的页面加载速度可能会更快。