Servir du contenu statique à l'aide de docker + nginx + php-fpm

10

J'essaie de configurer une webapp php à l'aide de docker. L'idée est d'exécuter l'application à l'aide php-fpmd'un conteneur autonome et d'avoir un autre conteneur qui exécutera nginx. L'idée de cette configuration est d'utiliser ce même conteneur nginx pour proxy des requêtes vers d'autres webapps qui fonctionnent déjà sur la même machine. Le problème est que je ne parviens pas nginxà traiter correctement les fichiers statiques (js, css, etc.), car les demandes à ceux-ci continuent de l'être fpm.

Voici à quoi ressemble le système de fichiers:

/
├── Makefile
├── config
│   └── webapp.config
└── webapp
    └── web
        ├── index.php
        └── static.js

J'exécute le tout en utilisant un Makefilequi ressemble à ceci (cela ne m'intéresse pas 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

Voilà à quoi config/webapp.confressemble mon .

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

Quelle que soit l'action qui doit être traitée à l'aide de ce index.phpfichier, cela fonctionnera. Cependant, les fichiers statiques ne seront pas servis, ce qui entraînera des 404erreurs désagréables (car la webapp php n'a pas vraiment de routes configurées pour celles-ci). Je crois que nginx essaie de charger ceux-ci à partir de son propre système de fichiers de conteneur, lorsqu'ils sont réellement dans le webappconteneur, en échouant @webapp.

Existe-t-il un moyen de configurer nginxpour servir ces fichiers qui résident dans un autre conteneur?

ThisIsErico
la source
3
Utilisez-vous docker pour isoler nginx des applications php tout en exigeant que nginx ait accès aux fichiers dans les applications php?
Stefan Schmiedl
Je ne suis pas sûr de comprendre votre commentaire ... J'utilise docker pour gérer mon infrastructure. Cependant, je ne nginxcrée pas de fichiers de demande dans l'application php, je suis mandataire pour fpmle faire et j'ai besoin nginxd'accéder à des fichiers statiques non php.
ThisIsErico
Les fichiers "résident dans un autre conteneur", c'est-à-dire pas là où nginx peut les voir, non?
Stefan Schmiedl
C'est vrai @Stefan, ils ne sont montés que comme volumes dans le webappconteneur, pas dans celui- nginxci.
ThisIsErico

Réponses:

1

J'ai réussi à résoudre le problème en montant le webappvolume dans le nginxconteneur. Voici à quoi run-nginxressemble le travail maintenant:

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

Et voici le webapp.conffichier, qui tentera de charger les fichiers statiques à partir du conteneur et, si ce n'est pas possible, procurera la demande au fpmtravailleur par proxy :

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

Cependant, j'aimerais savoir s'il existe une meilleure façon de le faire au lieu de partager le même volume deux fois. Merci beaucoup!

ThisIsErico
la source
4
Étant donné la séparation de nginx et de php dans différents conteneurs, je ne pense pas. Vous avez besoin des données à deux endroits différents, vous devez les fournir deux fois. Je suis aussi très curieux de savoir si quelqu'un a une meilleure idée.
Stefan Schmiedl
0

Peut-être que cela pourrait être réalisé en utilisant NFS

Un conteneur de docker exécutant NFS pourrait être créé là où réside le code, qui pourrait être lié aux conteneurs exécutant nginx et php. Les fichiers seraient stockés dans un seul conteneur. Cela pourrait également fournir une autre couche d'isolement.

Magarusu
la source
0

J'ai deux options suggérées: La première consiste à mettre vos actifs statiques dans eg / static et à demander à nginx d'appeler un service backend différent pour ceux-ci. Pas:

1) Mettez à jour vos sites Web pour pointer vers / static / * pour tous les actifs statiques, par exemple /styles.css devient /static/styles.css

2) Mettez vos actifs soit dans un conteneur séparé desservi par peut-être un autre nginx (afin que vous puissiez réutiliser le conteneur pour plusieurs sites)

3) Modifiez nginx.conf pour envoyer toutes les demandes à / static / * vers le nouveau conteneur:

location /static/ {
   proxy_pass http://static-container;
}

La deuxième option consiste à simplement déplacer vos actifs statiques vers un CDN, il vous suffit donc de mettre à jour votre site Web pour charger chaque actif statique à partir d'une URL externe ( https: //cdnwebsite/asdsadasda/styles.css au lieu de /styles.css ou /static/styles.css)

La deuxième option présente plusieurs avantages par rapport aux autres, principalement en termes de performances. Un CDN les servira plus rapidement et vous contournez également la limite de connexion simultanée qu'un navigateur peut établir pour chaque nom de domaine complet, de sorte que votre page peut se charger plus rapidement en raison de davantage de connexions simultanées utilisées pour charger votre site.

Pedro Perez
la source