使用docker + nginx + php-fpm服务静态内容


10

我正在尝试使用docker配置php webapp。这个想法是php-fpm在一个独立的容器中运行应用程序,并让另一个容器运行nginx。此设置的想法是使用相同的nginx容器将请求代理到已经在同一台机器上运行的其他Web应用程序。问题是我无法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服务于驻留在另一个容器中的那些文件?


3
您是否正在使用docker隔离nginx与php应用程序,同时要求nginx可以访问php应用程序中的文件?
Stefan Schmiedl

我不确定我是否理解您的评论...我正在使用docker管理我的基础架构。但是,我不是nginx在php应用程序中创建请求文件,而是代理fpm这样做,并且确实需要nginx访问静态非php文件。
ThisIsErico

文件“位于另一个容器中”,即不是在nginx可以看到它们的地方,对吗?
Stefan Schmiedl

没错,@ Stefan,它们仅作为卷安装在webapp容器中,而不是作为nginx一个容器安装。
ThisIsErico

Answers:


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;
    }
}

但是,我想知道是否有更好的方法来代替两次共享相同的卷。非常感谢!


4
考虑到您将nginx和php分为不同的容器,我不这么认为。您需要将数据放在两个不同的位置,必须提供两次。如果有人想出一个更好的主意,我也很好奇。
Stefan Schmiedl

0

也许可以使用NFS来实现

可以在代码所在的位置创建一个运行NFS的docker容器,该容器可以链接到运行nginx和php的容器。文件只能存储在一个容器中。这也可以提供另一层隔离。


0

我有两个建议的选项:第一个选项是将您的静态资产放在/ 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进行的同时连接限制的问题,因此,由于使用了更多同时连接来加载网站,因此页面的加载速度可能会更快。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.