proxy reverso nginx com contêineres docker e locais aninhados específicos

proxy reverso nginx com contêineres docker e locais aninhados específicos

Gostaria de configurar o nginx como um proxy reverso com vários aplicativos em contêineres do docker residindo permanentemente em locais específicos, por exemplo:

https://sub.example.com/wiki
https://sub.example.com/app1
https://sub.example.com/app2

Em particular, quero usar oimagem da janela de encaixe mediawikiao lado de outros aplicativos. Este é meu docker-compose.yml:

version: '3.5'
services:

  mediawiki:
    image: mediawiki
    restart: unless-stopped
    hostname: mediawiki
    ports:
      - "8080:80"
    links:
      - database
    volumes:
      - images:/var/www/html/images
      # - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php
    networks:
      - wiki
  
  database:
    image: mariadb
    restart: unless-stopped
    hostname: database
    environment:
      MYSQL_DATABASE: my_wiki
      MYSQL_USER: wikiuser
      MYSQL_PASSWORD: example
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
    volumes:
      - db:/var/lib/mysql
    networks:
      - wiki

  app1:
    # ...
    expose:
      - "4000"
    networks:
      - apps

  nginx:
    image: nginx:1.23-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./certbot/conf:/etc/nginx/ssl
      - ./certbot/data:/usr/share/nginx/html/letsencrypt
    depends_on:
      - app1
      - mediawiki
    networks:
      - apps
      - wiki

  certbot:
    image: certbot/certbot:latest
    # ...
    volumes:
      - ./certbot/conf:/etc/letsencrypt
      - ./certbot/logs:/var/log/letsencrypt
      - ./certbot/data:/usr/share/nginx/html/letsencrypt
    networks:
      - apps
      - wiki

networks:
  apps:
  wiki:

O problema que estou enfrentando é que, com o seguinte default.conf, consigo fazer proxy do contêiner mediawiki, bem como de outros aplicativos, mas certos links e recursos retornam 404.

upstream testwiki {
    server mediawiki:80;
}

server {
    listen 80;
    listen [::]:80;

    server_name sub.example.com;

    location / {
        return 301 https://$server_name$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    
    server_name sub.example.com;

    ssl_certificate /etc/nginx/ssl/live/sub.example.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/live/sub.example.com/privkey.pem;

    location /wiki/ {
        proxy_pass http://testwiki/;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
}

Suspeito que o motivo desse comportamento seja devido a URLs relacionais, como <a href="/mw-config/index.php">complete the installation</a>, direcionando solicitações para o local raiz em vez do aninhado. Eu tentei muitas coisas, como rewrite(incl. regex), sub_filtere proxy_redirectmétodos proxy_set_header, mas o melhor que descobri foi:

location /wiki/ {
    proxy_pass http://mediawiki:80/;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}

location /app1/ {
    proxy_pass http://app1:4000/;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
}


if ($http_referer = "https://sub.example.com/wiki/") {
    set $proxypass http://mediawiki:80;
}
if ($http_referer = "https://sub.example.com/app1/") {
    set $proxypass http://app1:4000;
}
    
location / {
    proxy_pass $proxypass;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Como (ainda) não consigo configurar um baseurl para o mediawiki, tentei fazer proxy das solicitações recebidas no local raiz, dependendo do arquivo http_referer. Isso funciona para todas as solicitações GET iniciais feitas em https://sub.example.com/wiki/e também para o link mencionado acima.

Porém, após clicar em <a href="/mw-config/index.php">..., index.phpfaz novas solicitações - novamente direcionadas para https://sub.example.com/. Como a URL não é reescrita e o referenciador diz https://sub.example.com/mw-config/index.php, essas solicitações retornam 500.

Minha pergunta é: como posso corrigir esse comportamento para que meus aplicativos residam permanentemente em seus respectivos locais? Infelizmente não posso alterar o subdomínio neste momento.

Qualquer ajuda é apreciada!

Editar:


Como desejo usar vários outros aplicativos que possam encontrar problemas semelhantes, gostaria de encontrar uma solução mais geral. Em alguns casos não tenho controle sobre o URL base.

Responder1

Há algumas coisas acontecendo aqui que precisamos colocar na mesma página para que isso funcione:

  1. NGINXconfiguração: roteamento baseado em caminho, proxy reverso
    • Eu tentei sua configuração eAcredito que sua configuração esteja correta
  2. Apache2configuração: mapeie corretamente o URI para caminhos de arquivo e scripts
    • Use uma diretiva AliasMatch "^/wiki(.*)" "/var/www/html/$1"para remover /wikie mapear corretamente os caminhos de arquivos internos
  3. MediaWikiconfigurações: adicione o /wikicaminho para que Nginxsaiba onde reverter o proxy dos links e, em seguida, Apache2possa remover /wikie usar os caminhos de arquivo internos corretos.
    • Defina $wgScriptPath = "/wiki";o LocalSettings.phparquivo criado após executar a configuração do MediaWiki e substitua esse arquivo em seudocker-compose.yml
  4. Composição do Docker: Persista essas mudanças montando nossos arquivos locais modificados no mediawikicontêiner docker

Apache2

Vamos adicionar AliasMatch "^/wiki(.*)" "/var/www/html/$1"à configuração em /etc/apache2/sites-enabled/000-default.conf. Você também precisará substituir o conteúdo deste arquivo em seudocker-compose.yml

#/etc/apache2/sites-enabled/000-default.conf 
<VirtualHost *:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        #ServerName www.example.com

        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html
        AliasMatch "^/wiki(.*)" "/var/www/html/$1"

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
        AllowEncodedSlashes NoDecode
</VirtualHost>

Configurações do MediaWiki:

Este é apenas um trecho do LocalSettings.phparquivo que precisa ser alterado. É um pouco grande incluir todo o padrão aqui. Parece que você já tem uma cópia local LocalSettings.phpque está montando no contêiner do docker usando docker-compose, então apenas modifique a $wgScriptPathvariável e reinicie o contêiner.

## The URL base path to the directory containing the wiki;
## defaults for all runtime URL paths are based off of this.
## For more information on customizing the URLs
## (like /w/index.php/Page_title to /wiki/Page_title) please see:
## https://www.mediawiki.org/wiki/Manual:Short_URL
$wgScriptPath = "/wiki";

Composição do Docker

Agoramodificaremos a seção de volumesda parte MediaWiki do docker-compose.yml parasubstituir a configuração do apache2arquivo para o site MediaWiki.

  mediawiki:
    image: mediawiki
    restart: unless-stopped
    hostname: mediawiki
    ports:
      - "8080:80"
    links:
      - database
    volumes:
      - ./images:/var/www/html/images
      - ./wiki/LocalSettings.php:/var/www/html/LocalSettings.php
      - ./apache2/000-default.conf:/etc/apache2/sites-enabled/000-default.conf
    networks:
      - wiki

Responder2

Definir o URL raiz é a única solução estável para esse problema.

Pesquisei "URL raiz do mediawiki" e o segundo resultado apontou parahttps://www.mediawiki.org/wiki/Topic:Ry90289pdqa86yrd, onde a primeira resposta informa como definir a URL raiz no MediaWiki:

A URL do seu wiki deve ser definida em LocalSettings.php (assim como, por exemplo, $wgLogo, que também está definido nesse arquivo) e você pode alterá-la definindo $wgServer para outro valor. Isso criará URLs de saída do MediaWiki começando com o domínio desejado.

informação relacionada