Nginx menulis ulang pada mesin buruh pelabuhan ketika port host! = Port kontainer

10

Saya mencoba menjalankan beberapa container docker yang semuanya menjalankan nginx mendengarkan pada port 80, tetapi dengan pemetaan host port yang berbeda ke port container 80.

Sebagian besar ini berfungsi, kecuali ketika nginx melakukan redirect karena tidak ada garis miring.

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

Dengan konfigurasi nginx di atas dan sebuah docker container yang menjalankannya dengan port host 8080 yang dipetakan ke port container 80, saya bisa mendapatkan 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 ...

tetapi jika saya meminta localhost: 8080 / docs saya mendapatkan redirect ke 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 ...

Bagaimana saya bisa mendapatkan nginx untuk mempertahankan port asli saat melakukan pengalihan? Saya sudah mencoba melihat port_in_redirect dan server_name_in_redirect tetapi mereka tidak membantu.


EDIT

Berdasarkan https://forum.nginx.org/read.php?2,261216,261216#msg-261216 ini tidak terlihat mungkin saat ini.

Ibasa
sumber
Lihatlah ke dalam wadah nginx-proxy , jadi Anda tidak perlu melakukan sampah penulisan ulang port yang gila ini.
Michael Hampton
Saya benar-benar tidak ingin keseimbangan apa pun di depan wadah ini. Saya punya file docker-compose yang menetapkan port eksternal berdasarkan env var, dan sebagian besar waktu saya hanya "docker-compose -d" file ini sekali. Namun untuk alasan pengujian dan untuk memungkinkan saya bekerja pada hal-hal lain saya ingin dapat melakukan "PORT = 8080 buruh pelabuhan-menulis -p uji up -d" untuk memutar set baru seluruh wadah (karena nama proyek baru ) yang dipetakan ke port host yang berbeda.
Ibasa
Ack, baru saja mengalami masalah ini juga. Saya kira saya harus pergi vanilla nginx atau memindahkan barang-barang di 8080 ke sesuatu yang lain.
Ken

Jawaban:

2

Solusi paling sederhana adalah dengan menghapus indexarahan dan tidak bergantung pada $uri/pengalihan eksplisit atau implisit . Sebagai contoh:

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

Ini bukan perilaku yang identik karena menghindari pengalihan sama sekali. Jika Anda menginginkan trailing slash redirect seperti yang diberikan oleh modul indeks, maka diperlukan solusi yang lebih kompleks. Sebagai contoh:

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
sumber
Seperti yang saya katakan di pertanyaan saya sudah mencoba ini, saya menambahkan port_in_redirect off; ke blok http, hasil yang sama dari pengalihan ke localhost / docs /, mencoba menambahkan server_name_in_redirect off; demikian juga. Masih dialihkan ke localhost / docs /
Ibasa
@ Ibasa Ya, maaf soal itu. Baca dua kali - tulis sekali. Harus berusaha mengingatnya.
Richard Smith
5

Klien HTTP akan meletakkan porta di header Host. Jika Anda menggunakan nilai asli dari header host saat melakukan pengalihan, itu harus berfungsi seperti yang diharapkan. Saya menguji kode berikut dan terlihat melakukan persis apa yang Anda minta:

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
sumber
Secara teknis ini adalah jawaban yang benar. Ini juga berfungsi dengan IP, misalnya permintaan ke 127.0.0.1:8000 akan memiliki 127.0.0.1:8000 sebagai http_host. Itu karena menurut: tools.ietf.org/html/rfc2616#section-14.23 http_host perlu memenuhi ambiguitas, yang akan ditambahkan port. Jika port ditinggalkan, maka standarnya tersirat (misalnya 80 atau 443). Jadi solusi ini harus menjadi yang paling bersih untuk bekerja dengan ...
lifeofguenter
0

Cukup ikuti perbaikan sederhana ini

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

Menarik ... Saya menemukan persis masalah ini dan dapat memperbaikinya seperti yang disarankan oleh jawaban Richard Smith :

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

Satu-satunya perbedaan adalah bahwa saya tidak menentukan index.html?

Tentukan kode kesalahan untuk menghindari redirect loop.

Masih menunggu umpan balik dari dukungan nginx.

Kevin W Matthews
sumber