Servir conteúdo estático usando o docker + nginx + php-fpm

10

Estou tentando configurar um php webapp usando o docker. A ideia é executar o aplicativo usando php-fpmum contêiner autônomo e ter outro contêiner que execute o nginx. A idéia para essa configuração é usar o mesmo contêiner nginx para proxy de solicitações para outros aplicativos da web que já estão trabalhando na mesma máquina. O problema é que não consigo nginxprocessar corretamente os arquivos estáticos (js, css etc.), conforme as solicitações para aqueles continuam fpm.

É assim que o sistema de arquivos se parece:

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

Estou executando a coisa toda usando um Makefileque se parece com isso (não estou interessado docker-composenisso):

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

É assim que a minha config/webapp.confaparência.

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

Qualquer ação que precise ser processada usando esse index.phparquivo funcionará. No entanto, os arquivos estáticos não serão exibidos, resultando em 404erros desagradáveis (como o php webapp realmente não possui rotas configuradas para eles). Eu acredito que o nginx tenta carregar aqueles do seu próprio sistema de arquivos do contêiner, quando eles estão realmente no webappcontêiner, fazendo o failback @webapp.

Existe uma maneira de configurar nginxpara exibir os arquivos que residem em outro contêiner?

ThisIsErico
fonte
3
Você está usando o docker para isolar o nginx dos aplicativos php enquanto exige que o nginx tenha acesso aos arquivos nos aplicativos php?
Stefan Schmiedl
Não sei se entendi seu comentário ... Estou usando o docker para gerenciar minha infraestrutura. No entanto, não estou fazendo nginxarquivos de solicitação no aplicativo php, estou fpmfazendo proxy para fazer isso e preciso nginxacessar arquivos não-php estáticos.
ThisIsErico
Os arquivos "residem em outro contêiner", ou seja, não onde o nginx pode vê-los, certo?
Stefan Schmiedl
É isso mesmo @Stefan, eles só são montados como volumes no webappcontêiner, não no nginxúnico.
ThisIsErico 06/06

Respostas:

1

Consegui resolver o problema montando o webappvolume no nginxcontêiner. É assim que o run-nginxtrabalho se parece agora:

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

E este é o webapp.confarquivo, que tentará carregar os arquivos estáticos do contêiner e, se isso não for possível, fará o proxy da solicitação ao fpmtrabalhador:

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

No entanto, gostaria de saber se existe uma maneira melhor de fazê-lo, em vez de compartilhar o mesmo volume duas vezes. Muito obrigado!

ThisIsErico
fonte
4
Dada a sua separação de nginx e php em diferentes contêineres, acho que não. Você precisa dos dados em dois locais diferentes, precisa fornecê-los duas vezes. Também estou muito curioso, se alguém tiver uma idéia melhor.
Stefan Schmiedl
0

Talvez isso possa ser alcançado usando o NFS

Um contêiner de docker executando o NFS pode ser criado onde o código reside, o qual pode ser vinculado aos contêineres executando o nginx e o php. Os arquivos seriam armazenados em apenas um contêiner. Isso poderia fornecer outra camada de isolamento também.

Magarusu
fonte
0

Eu tenho duas opções sugeridas: A primeira é colocar seus ativos estáticos em eg / static e instruir o nginx a chamar um serviço de back-end diferente para eles. Passos:

1) Atualize seus sites para apontar para / static / * para quaisquer ativos estáticos, por exemplo, /styles.css se torna /static/styles.css

2) Coloque seus ativos em um contêiner separado, servido por talvez outro nginx (para que você possa reutilizar o contêiner em vários sites)

3) Edite o nginx.conf para enviar todas as solicitações para / static / * para o novo contêiner:

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

A segunda opção é apenas mover seus ativos estáticos para uma CDN, portanto, você só precisa atualizar seu site para carregar cada ativo estático de uma URL externa ( https: //cdnwebsite/asdsadasda/styles.css em vez de /styles.css ou /static/styles.css)

A segunda opção tem várias vantagens sobre as outras, principalmente em relação ao desempenho. Uma CDN servirá a eles mais rapidamente e você também estará trabalhando em torno do limite de conexão simultânea que um navegador pode estabelecer para cada FQDN, para que sua página seja carregada mais rapidamente devido ao uso de conexões simultâneas para carregar seu site.

Pedro Perez
fonte