nginx「host not found in upstream」の原因と直し方
host not found in upstream は、転送先の名前を nginx から引けるようにすれば直る。
コンテナなら同じユーザー定義ネットワークに置く。
起動順に左右されたくなければ、resolver と変数で実行時に解決させる。
公開:
要約
nginx: [emerg] host not found in upstream "app" は、proxy_pass や upstream に書いた名前を nginx が引けないと出る。
名前は設定を読み込むときに引かれるので、引けなければ nginx は起動せず、終了コード 1 で止まる。転送先と同じネットワークに nginx を置いて、名前を引ける状態にすれば直る。
nginx: [emerg] host not found in upstream "app" in /etc/nginx/conf.d/default.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed引用符の中身は、名前を書いた場所で少し変わる。
nginx 1.29.8 では次のように出た。
| 書いた場所 | 表示 |
|---|---|
proxy_pass http://app:8000; | host not found in upstream "app" |
upstream の server app:8000; | host not found in upstream "app:8000" |
解決策
1. 同じネットワークに置く
ユーザー定義ネットワークを作り、転送先と nginx の両方を入れる。proxy_pass にはコンテナ名を書く。
docker network create web
docker run -d --name app --network web python:3.14-slim python -m http.server 8000
docker run -d --name nginx --network web -p 8080:80 \
-v "$PWD/default.conf:/etc/nginx/conf.d/default.conf:ro" nginx:1.29起動する前に確かめるなら、同じネットワークで nginx -t を打つ。
docker run --rm --network web \
-v "$PWD/default.conf:/etc/nginx/conf.d/default.conf:ro" nginx:1.29 nginx -t2. Compose では depends_on を書く
同じ compose.yaml のサービスは同じネットワークに入るので、残るのは起動順だけである。depends_on を足すと、3 回とも nginx は起動した。
services:
web:
image: nginx:1.29
depends_on: [app]
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf:ro
app:
image: python:3.14-slim
command: python -m http.server 80003. resolver と変数で実行時に解決する
転送先が止まっていても nginx を起動したいときは、名前を変数に入れて、リクエストのたびに引かせる。127.0.0.11 は Docker の組み込み DNS(新しいタブで開く) のアドレスである。
server {
listen 80;
resolver 127.0.0.11 valid=10s;
set $upstream http://app:8000;
location / {
proxy_pass $upstream;
}
}転送先が無い間、nginx は動いたまま 502 を返し、error.log に app could not be resolved (3: Host not found) と書く。
転送先を起動すると、reload しなくても 200 に変わった。
resolver か変数の片方だけでは足りない。resolver だけ書いて proxy_pass に名前を直接書くと、同じ [emerg] で止まる。
変数だけだと、リクエストのたびに no resolver defined to resolve app で 502 になる。
変数にすると、location のパスの置き換えも変わる。location /b/ に proxy_pass $upstream/; と書くと、/b/x への要求も / へ転送された。
パスを削るなら rewrite を足す。
location /d/ {
set $upstream http://app:8000;
rewrite ^/d/(.*)$ /$1 break;
proxy_pass $upstream;
}4. nginx 1.27.3 以降なら upstream の resolve を使う
upstream の server に resolve を付けると、起動時に名前を引けなくても止まらず、あとから解決される。zone を書かないと、resolving names at run time requires upstream "backend" で止まる。
resolver 127.0.0.11 valid=5s;
upstream backend {
zone backend 64k;
server app:8000 resolve;
}nginx 1.29.8 では、転送先が無い間は 502 を返し、起動すると 200 に変わった。
1.26 と 1.27.2 では invalid parameter "resolve" で止まり、1.27.3 では nginx -t が通った。
よくある原因
- 転送先のコンテナが別のネットワークにいる。
Docker の名前解決は同じネットワークの中でしか効かないので、転送先が動いていてもこのエラーになる。 - 既定の bridge ネットワークでコンテナ名を書いている。
--networkを付けずにdocker runしたコンテナどうしは、同じ bridge にいても名前を引けない(新しいタブで開く)。 - 転送先のコンテナがまだ起動していない。
depends_onの無いcompose.yamlを 3 回docker compose upすると、2 回は nginx がこのエラーを出して終了コード 1 で止まり、1 回は起動できた。 - 名前を打ち間違えている。
appと書くつもりのapqでも同じ文言になる。