Sirva contenido estático usando docker + nginx + php-fpm

10

Estoy tratando de configurar una aplicación web php usando docker. La idea es ejecutar la aplicación usando php-fpmun contenedor independiente y tener otro contenedor que ejecute nginx. La idea para esta configuración es usar ese mismo contenedor nginx para enviar solicitudes de proxy a otras aplicaciones web que ya están trabajando en la misma máquina. El problema es que no puedo nginxprocesar correctamente los archivos estáticos (js, css, etc.), ya que las solicitudes a esos continúan fpm.

Así es como se ve el sistema de archivos:

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

Estoy ejecutando todo usando un Makefileaspecto similar a este (no estoy interesado en docker-composeesto):

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

Así es config/webapp.confcomo se ve mi .

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

Cualquier acción que necesite procesarse usando ese index.phparchivo funcionará. Sin embargo, los archivos estáticos no se servirán, lo que provocará 404errores desagradables (ya que la aplicación web php realmente no tiene rutas configuradas para esos). Creo que nginx intenta cargarlos desde su propio sistema de archivos contenedor, cuando realmente están en el webappcontenedor, fallando nuevamente @webapp.

¿Hay alguna forma de configurarlo nginxpara servir esos archivos que residen en otro contenedor?

ThisIsErico
fuente
3
¿Está utilizando Docker para aislar nginx de las aplicaciones php mientras requiere que nginx tenga acceso a los archivos dentro de las aplicaciones php?
Stefan Schmiedl
No estoy seguro de entender su comentario ... Estoy usando Docker para administrar mi infraestructura. Sin embargo, no estoy haciendo nginxarchivos de solicitud dentro de la aplicación php, estoy prox fpmpara hacerlo y necesito nginxacceder a archivos estáticos no php.
ThisIsErico
Los archivos "residen en otro contenedor", es decir, no donde nginx puede verlos, ¿verdad?
Stefan Schmiedl
Así es @Stefan, solo se montan como volúmenes en el webappcontenedor, no en el nginxuno.
ThisIsErico

Respuestas:

1

Logré resolver el problema montando el webappvolumen en el nginxcontenedor. Así es run-nginxcomo se ve el trabajo ahora:

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

Y este es el webapp.confarchivo, que intentará cargar los archivos estáticos del contenedor y, si eso no es posible, enviará la solicitud al fpmtrabajador:

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

Sin embargo, me gustaría saber si hay una mejor manera de hacerlo en lugar de compartir el mismo volumen dos veces. ¡Muchas gracias!

ThisIsErico
fuente
44
Dada su separación de nginx y php en diferentes contenedores, no lo creo. Necesita los datos en dos ubicaciones diferentes, debe proporcionarlos dos veces. También tengo mucha curiosidad si a alguien se le ocurre una idea mejor.
Stefan Schmiedl
0

Quizás esto se pueda lograr usando NFS

Se podría hacer un contenedor de docker que ejecute NFS donde reside el código, que se podría vincular a los contenedores que ejecutan nginx y php. Los archivos se almacenarían en un solo contenedor. Esto también podría proporcionar otra capa de aislamiento.

Magarusu
fuente
0

Tengo dos opciones sugeridas: la primera es poner sus activos estáticos en eg / static e indicar a nginx que llame a un servicio back-end diferente para ellos. Pasos:

1) Actualice sus sitios web para que apunten a / static / * para cualquier activo estático, por ejemplo, /styles.css se convierte en /static/styles.css

2) Coloque sus activos en un contenedor separado servido por quizás otro nginx (para que pueda reutilizar el contenedor para varios sitios)

3) Edite nginx.conf para enviar todas las solicitudes a / static / * al nuevo contenedor:

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

La segunda opción es simplemente mover sus activos estáticos a un CDN, por lo que solo necesita actualizar su sitio web para cargar cada activo estático desde una URL externa ( https: //cdnwebsite/asdsadasda/styles.css en lugar de /styles.css o /static/styles.css)

La segunda opción tiene varias ventajas sobre las demás, principalmente en torno al rendimiento. Un CDN los servirá más rápido y también está trabajando alrededor del límite de conexión simultánea que un navegador puede establecer para cada FQDN, por lo que su página podría cargar más rápido debido a que se utilizan más conexiones simultáneas para cargar su sitio.

Pedro Pérez
fuente