Réécriture Nginx sur la machine Docker lorsque le port hôte! = Port conteneur

10

J'essaie d'exécuter plusieurs conteneurs Docker exécutant tous l'écoute nginx sur le port 80, mais avec différents ports hôte mappant sur le port 80 des conteneurs.

Pour la plupart, cela fonctionne, sauf lorsque nginx effectue une redirection en raison de l'absence d'une barre oblique de fin.

server {
    listen 80;
    root /var/www;
    index index.html;
    location /docs {}
}

Étant donné la configuration nginx ci-dessus et un conteneur docker l'exécutant avec le port hôte 8080 mappé sur le port conteneur 80, je peux obtenir localhost: 8080 / docs / via curl ok:

> GET /docs/ HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx/1.9.5 is not blacklisted
< Server: nginx/1.9.5
< Date: Sat, 28 Nov 2015 17:27:05 GMT
< Content-Type: text/html
< Content-Length: 6431
< Last-Modified: Sat, 28 Nov 2015 17:17:06 GMT
< Connection: keep-alive
< ETag: "5659e192-191f"
< Accept-Ranges: bytes
<
... html page ...

mais si je demande localhost: 8080 / docs, je reçois une redirection vers localhost / docs /

> GET /docs HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
* Server nginx/1.9.5 is not blacklisted
< Server: nginx/1.9.5
< Date: Sat, 28 Nov 2015 17:29:40 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/docs/
< Connection: keep-alive
<
... html redirect page ...

Comment puis-je obtenir nginx pour conserver le port d'origine lors de la redirection? J'ai essayé de regarder port_in_redirect et server_name_in_redirect mais ils n'ont pas aidé.


ÉDITER

Basé sur https://forum.nginx.org/read.php?2,261216,261216#msg-261216, cela ne semble pas possible pour le moment.

Ibasa
la source
Regardez dans le conteneur nginx-proxy , afin que vous n'ayez à faire aucune de ces ordures de réécriture de ports insensées.
Michael Hampton
Je ne veux vraiment rien d'équilibrer devant ces conteneurs. J'ai un fichier docker-compose qui définit le port externe basé sur une variable env, et la plupart du temps je viens de "docker-composer up -d" ce fichier une fois. Cependant, pour des raisons de test et pour me permettre de travailler sur d'autres choses, je veux pouvoir faire "PORT = 8080 docker-compose -p test up -d" pour faire tourner un tout nouvel ensemble de conteneurs (en raison du nouveau nom du projet ) qui sont mappés sur un autre port hôte.
Ibasa
Ack, vient de rencontrer aussi ce problème. Je suppose que je vais devoir aller vanilla nginx ou déplacer les trucs sur 8080 à autre chose.
Ken

Réponses:

2

La solution la plus simple consiste à supprimer la indexdirective et à ne pas s'appuyer sur des $uri/redirections explicites ou implicites . Par exemple:

server {
  listen 80;
  root /var/www;
  location /docs {
    try_files $uri $uri/index.html =404;
  }
}

Ce comportement n'est pas identique car il évite complètement la redirection. Si vous vouliez une redirection de barre oblique de fin comme le donne le module d'index, alors une solution plus complexe est requise. Par exemple:

server {
  listen 80;
  root /var/www;
  location /docs {
    try_files $uri @redirect;
  }
  location @redirect {
    if ($uri ~* ^(.+)/$) { rewrite ^ $uri/index.html last; }
    if (-d $document_root$uri) { return $scheme://$host:8080$uri/; }
    return 404;
  }
}
Richard Smith
la source
Comme je l'ai dit dans la question que j'ai essayé, j'ai ajouté port_in_redirect off; au bloc http, même résultat d'une redirection vers localhost / docs /, a essayé d'ajouter off server_name_in_redirect off; ainsi que. Redirige toujours vers localhost / docs /
Ibasa
@ Ibasa Oui, désolé pour ça. Lisez deux fois - écrivez une fois. Doit essayer de s'en souvenir.
Richard Smith
5

Les clients HTTP mettront le port dans l'en-tête Host. Si vous utilisez la valeur d'origine de l'en-tête d'hôte lors de la redirection, cela devrait fonctionner comme prévu. J'ai testé le code suivant et semble faire exactement ce que vous avez demandé:

location ~ ^.*[^/]$ {
    try_files $uri @rewrite;
}
location @rewrite {
    return 302 $scheme://$http_host$uri/;
}

> GET /bla HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:8080
> Accept: */*
>
< HTTP/1.1 302 Moved Temporarily
< Server: nginx/1.9.7
< Date: Sun, 29 Nov 2015 06:23:35 GMT
< Content-Type: text/html
< Content-Length: 160
< Connection: keep-alive
< Location: http://localhost:8080/bla/
Florin Asăvoaie
la source
C'est techniquement la bonne réponse. Il fonctionne également avec les adresses IP, par exemple, une demande à 127.0.0.1:8000 aura 127.0.0.1:8000 comme http_host. En effet, selon: tools.ietf.org/html/rfc2616#section-14.23 http_host doit tenir compte de l'ambiguïté, à laquelle un port s'ajoutera. Si les ports sont laissés de côté, les valeurs par défaut sont implicites (par exemple 80 ou 443). Cette solution devrait donc être la plus propre avec laquelle travailler ...
lifeofguenter
0

Suivez simplement cette solution simple

location /app {
    alias /usr/share/nginx/html/folder;
    if (-d $request_filename) {
        rewrite [^/]$ $scheme://$http_host$uri/ permanent;
    }
}
imal hasaranga perera
la source
0

Intéressant ... J'ai rencontré précisément ce problème et j'ai pu le résoudre comme le suggère la réponse de Richard Smith :

root /var/www;
location = /docs {
    try_files $uri $uri/ =404;
}

La seule différence est que je ne précise pas index.html?

Spécifiez le code d'erreur pour éviter une boucle de redirection.

Toujours en attente des commentaires du support de nginx.

Kevin W Matthews
la source