Служите статическому контенту, используя docker + nginx + php-fpm

10

Я пытаюсь настроить php webapp, используя docker. Идея состоит в том, чтобы запустить приложение php-fpmв автономном контейнере и иметь другой контейнер для запуска nginx. Идея этой настройки заключается в том, чтобы использовать тот же контейнер nginx для прокси-запросов к другим веб-приложениям, которые уже работают на той же машине. Проблема в том, что я не могу 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 для них не настроены маршруты). Я полагаю, что nginx пытается загрузить их из собственной файловой системы контейнера, когда они на самом деле находятся в webappконтейнере, возвращаясь обратно @webapp.

Есть ли способ, который я могу настроить nginxдля обслуживания тех файлов, которые находятся в другом контейнере?

ThisIsErico
источник
3
Используете ли вы docker для изоляции nginx от php-приложений, когда требуется, чтобы nginx имел доступ к файлам в php-приложениях?
Стефан Шмидл
Я не уверен, что понимаю ваш комментарий ... Я использую докер для управления своей инфраструктурой. Однако я не делаю nginxфайлы запросов в приложении php, я использую прокси fpmдля этого, и мне нужен nginxдоступ к статическим файлам не-php.
ThisIsErico
Файлы «находятся в другом контейнере», то есть не там, где их видит nginx, верно?
Стефан Шмидль
Правильно @Stefan, они монтируются только как тома в webappконтейнере, а не в nginxодном.
ThisIsErico

Ответы:

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

Тем не менее, я хотел бы знать, есть ли лучший способ сделать это вместо того, чтобы делить один и тот же том дважды. Большое спасибо!

ThisIsErico
источник
4
Учитывая ваше разделение nginx и php на разные контейнеры, я так не думаю. Вам нужны данные в двух разных местах, вы должны предоставить их дважды. Мне тоже очень любопытно, если кто-нибудь придумает лучшую идею.
Стефан Шмидл
0

Может быть, это может быть достигнуто с помощью NFS

Один док-контейнер с NFS может быть создан там, где находится код, который может быть связан с контейнерами с nginx и php. Файлы будут храниться только в одном контейнере. Это может обеспечить еще один уровень изоляции.

Magarusu
источник
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 будет обслуживать их быстрее, и вы также работаете над лимитом одновременных подключений, который браузер может установить для каждого полного доменного имени, поэтому ваша страница может загружаться быстрее из-за того, что для загрузки сайта используется больше одновременных подключений.

Педро Перес
источник