Mamy kilka aplikacji railsowych w ramach wspólnej domeny w Dockerze i używamy nginx do kierowania żądań do określonych aplikacji.
our_dev_server.com/foo # proxies to foo app
our_dev_server.com/bar # proxies to bar
Konfiguracja wygląda tak:
upstream foo {
server foo:3000;
}
upstream bar {
server bar:3000;
}
# and about 10 more...
server {
listen *:80 default_server;
server_name our_dev_server.com;
location /foo {
# this is specific to asset management in rails dev
rewrite ^/foo/assets(/.*)$ /assets/$1 break;
rewrite ^/foo(/.*)$ /foo/$1 break;
proxy_pass http://foo;
}
location /bar {
rewrite ^/bar/assets(/.*)$ /assets/$1 break;
rewrite ^/bar(/.*)$ /bar/$1 break;
proxy_pass http://bar;
}
# and about 10 more...
}
Jeśli jedna z tych aplikacji nie zostanie uruchomiona, nginx zawiedzie i zatrzyma się:
host not found in upstream "bar:3000" in /etc/nginx/conf.d/nginx.conf:6
Nie potrzebujemy ich wszystkich, ale w przeciwnym razie nginx zawodzi. Jak sprawić, by Nginx ignorował nieudane upstreams?
nginx
url-rewriting
proxypass
Morozov
źródło
źródło
upstream
bloku nie zostanie rozwiązany, w czasie działania Nginx zakończy działanie z powyższym błędem ...resolver
( nginx.org/en/docs/http/ngx_http_core_module.html#resolver ) zadziała w Twoim przypadku?proxy.sh
skrypt, który czyta zmienne środowiskowe i dynamicznie dodajeupstream
wpisy dla każdego, a następnie uruchamia Nginx. Działa to świetnie, ponieważ kiedy uruchamiamy nasz kontener proxy, możemy przekazać potrzebne upstremy w czasie wykonywania. Możesz zrobić coś podobnego, aby włączyć / wyłączyć niektóre upstreams podczas uruchamiania (lub, tak jak moja konfiguracja, po prostu dodać te potrzebne w czasie wykonywania)Odpowiedzi:
Jeśli możesz użyć statycznego adresu IP, po prostu użyj go, uruchomi się i po prostu zwróci
503
, jeśli nie odpowie.Użyj
resolver
dyrektywy, aby wskazać coś, co może rozwiązać hosta, niezależnie od tego, czy obecnie działa, czy nie.Rozwiąż to na
location
poziomie, jeśli nie możesz zrobić powyższego (pozwoli to Nginx na uruchomienie / uruchomienie) :źródło
location ~ ^/foo/(.*)$ { proxy_pass http://foo/$1; }
U mnie opcja 3 odpowiedzi od @ Justin / @ duskwuff rozwiązała problem, ale musiałem zmienić adres IP resolwera na 127.0.0.11 (serwer DNS Dockera ):
Ale jak wspomniał @ Justin / @ duskwuff, możesz użyć dowolnego innego zewnętrznego serwera DNS.
źródło
Główną zaletą korzystania z programu
upstream
jest zdefiniowanie grupy serwerów, które mogą nasłuchiwać na różnych portach i skonfigurować równoważenie obciążenia i przełączanie awaryjne między nimi .W twoim przypadku definiujesz tylko 1 serwer główny na serwer nadrzędny, więc musi on działać .
Zamiast tego użyj zmiennych dla swoich
proxy_pass
i pamiętaj, aby obsłużyć możliwe błędy (404, 503), które mogą wystąpić, gdy serwer docelowy nie działa.źródło
set $variable http://foo
iproxy_pass $variable
zachowam foo "upstream" (aby zachować wspomniane zalety), to nadal napotykam problem wspomniany przez OP.set $variable foo
iproxy_pass http://$variable
Miałem to samo „Host not found” problem, ponieważ część mojego hosta był odwzorowany za pomocą
$uri
zamiast$request_uri
:A kiedy żądanie zmieniło się w żądanie autoryzacji,
$uri
utrata wartości początkowej. Zmiana mapowania na użycie$request_uri
zamiast$uri
rozwiązania mojego problemu:źródło
Nie możesz użyć
--link
opcji, zamiast tego możesz użyć mapowania portów i powiązać nginx z adresem hosta.Przykład: Uruchom pierwszy kontener docker z
-p 180:80
opcją, drugi kontener z-p 280:80
opcją.Uruchom nginx i ustaw te adresy dla serwera proxy:
źródło