Nginx menulis ulang pada mesin docker saat host port != port kontainer

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

Untuk sebagian besar ini berfungsi, kecuali ketika nginx melakukan pengalihan karena kehilangan garis miring.

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

Mengingat konfigurasi nginx di atas dan wadah buruh pelabuhan menjalankannya dengan port host 8080 dipetakan ke port kontainer 80 Saya bisa mendapatkan localhost: 8080 / docs / melalui 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 sepertinya tidak mungkin sekarang.

Klien HTTP akan menempatkan port di header Host. Jika Anda menggunakan nilai asli header host saat melakukan pengalihan, itu akan berfungsi seperti yang diharapkan. Saya menguji kode berikut dan terlihat melakukan 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/

Solusi paling sederhana adalah menghapus index direktif dan tidak bergantung pada eksplisit atau implisit $uri/ pengalihan. Misalnya:

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 pengalihan garis miring seperti yang diberikan modul indeks, maka diperlukan solusi yang lebih kompleks. Misalnya:

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

Cukup ikuti perbaikan sederhana ini

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

Menarik... Saya mengalami masalah ini dengan tepat dan dapat memperbaikinya sebanyak Jawaban Richard Smith menyarankan:

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 loop pengalihan.

Masih menunggu umpan balik dari dukungan nginx.

Saya pikir itu terjadi karena Docker Anda adalah jenis NAT/Proxy ke wadah nginx Anda. Untuk perutean antara informasi penambahan port yang berbeda diperlukan.

Bagi saya ini diselesaikan tambahkan yang berikut ke nginx.conf

http {    ...    proxy_set_header Host $http_host; # required for docker client's sake    proxy_set_header X-Real-IP $remote_addr; # pass on real client's IP    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;    proxy_set_header X-Forwarded-Proto $scheme;    ...}

Ack, baru saja mengalami masalah ini juga. Saya kira saya harus pergi vanilla nginx atau memindahkan barang-barang di 8080 ke sesuatu yang lain.

Melihat ke dalam [nginx-proxy] (GitHub - nginx-proxy/nginx-proxy: Automated nginx proxy for Docker containers using docker-gen) wadah, jadi Anda tidak perlu melakukan salah satu dari sampah penulisan ulang port gila ini.

Saya tidak benar-benar ingin ada yang menyeimbangkan di depan wadah ini. Saya Punya file Docker-compose yang mengatur port eksternal berdasarkan env var, dan sebagian besar waktu saya hanya “docker-compose up-d” file ini sekali. Namun untuk alasan pengujian dan untuk memungkinkan saya mengerjakan hal-hal lain, saya ingin dapat melakukan “PORT=8080 docker-compose-p test up-d” untuk memutar satu set kontainer baru (karena nama proyek baru) yang dipetakan ke port host yang berbeda.