# Cara Mengatasi 502 Bad Gateway Nginx di Docker dan Cloudflare

> Cara mengatasi 502 Bad Gateway nginx di Docker: baca error log, bedakan 502, 503, dan 504, cek penyebab yang paling sering, dan pahami kode 5xx Cloudflare.

URL: https://www.matthewswong.com/id/learn/devops-from-zero/nginx-502-bad-gateway-docker/

DevOps dari nol · Pelajaran 25 dari 25 · Ditinjau pada 18 Oktober 2026 · Oleh Matthews Wong (https://www.matthewswong.com/id/about/)

> 502 Bad Gateway dari nginx berarti nginx-nya berjalan, tetapi tidak mendapat jawaban yang valid dari aplikasi yang di-proxy: koneksinya ditolak, di-reset, atau ditutup sebelum menjawab, atau balasannya tidak bisa dipakai. Di Docker, penyebab yang paling sering adalah container yang mati atau sedang restart, port yang salah, dan aplikasi yang hanya listen di loopback-nya sendiri. Error log nginx menyebutkan yang mana.

## Setelah pelajaran ini, Anda bisa

- Membedakan 502, 503, dan 504, dan menyebutkan komponen mana yang menghasilkan masing-masing, termasuk kode 52x milik Cloudflare.
- Membaca satu baris error log nginx dan mencocokkan pesan, klausa while, dan field upstream-nya dengan sebuah penyebab.
- Mereproduksi dan memperbaiki penyebab umum di Docker: container yang mati, port yang salah, aplikasi yang hanya listen di loopback, dan upstream yang lambat.

## Di mana request berhenti, dan apa yang dicatat nginx

Satu request melewati Cloudflare, nginx, dan container yang di-publish di 127.0.0.1:3002, ditampilkan saat sehat lalu gagal dengan empat cara: container mati, aplikasi yang tidak listen, aplikasi yang lambat, dan nginx sendiri mati. Setiap kegagalan menghasilkan status code dan baris error log yang berbeda.

1. **Kenali bagiannya.** Sebuah kunjungan melewati Cloudflare, lalu nginx di server Anda, yang meneruskannya ke port container yang di-publish di 127.0.0.1:3002. Setiap kegagalan yang dilihat nginx masuk ke error log-nya.
2. **Request yang sehat.** nginx terhubung ke 127.0.0.1:3002, Docker meneruskan koneksinya ke aplikasi di port 3000, dan jawabannya kembali lewat jalur yang sama. Browser mendapat 200 dan error log tetap sepi.

   ```
   proxy_pass http://127.0.0.1:3002;
   ```

   *Tebak:* Sekarang container-nya dihentikan, lalu request yang sama datang. Apa yang didapat browser? (502 Bad Gateway / 503 Service Unavailable / 504 Gateway Timeout)
3. **Container mati: 502.** Saat container dihentikan, tidak ada yang listen di 3002, jadi koneksinya langsung ditolak. nginx menjawab 502 Bad Gateway dan menulis alasannya ke error log.

   ```
   connect() failed (111: Connection refused) while connecting to upstream
   ```
4. **Jalan, tapi tidak listen.** Sekarang container-nya jalan, tetapi aplikasinya hanya listen di 127.0.0.1 miliknya sendiri, atau masih start. Docker menerima di 3002, lalu koneksinya di-reset: 502 lagi, baris log berbeda.

   ```
   recv() failed (104: Connection reset by peer) while reading response header from upstream
   ```

   *Tebak:* Aplikasinya sudah diperbaiki, tetapi satu halaman butuh 90 detik untuk menjawab, dan nginx memakai proxy_read_timeout default. Apa yang didapat browser? (502 Bad Gateway / 504 Gateway Timeout / 200, setelah 90 detik)
5. **Terlalu lambat: 504.** Aplikasi menerima request, tetapi tidak mengirim apa pun selama 60 detik, batas proxy_read_timeout default nginx. nginx menyerah dengan 504 Gateway Time-out: kehabisan waktu, bukan koneksi yang putus.

   ```
   upstream timed out (110: Operation timed out) while reading response header from upstream
   ```
6. **Cloudflare di depan.** Di balik Cloudflare, 502 atau 504 dari nginx tampil di halaman bermerek Cloudflare. Kalau nginx sendiri mati, Cloudflare menjawab 521; kalau origin tidak pernah menjawab koneksinya, 522.

   ```
   521: web server is down
   522: connection timed out
   ```

## Apa arti 502 Bad Gateway di nginx?

502 Bad Gateway berarti server yang menjawab Anda adalah gateway atau proxy, dan server di belakangnya yang bermasalah. RFC 9110 mendefinisikannya sebagai proxy yang menerima response tidak valid dari server di belakangnya saat mencoba memenuhi request. Kalau nginx berada di depan aplikasi Docker, nginx adalah proxy itu dan container Anda adalah server di belakangnya, yang oleh nginx disebut upstream.

Jadi halaman 502 bertuliskan nginx sebenarnya kabar baik dalam satu hal: nginx hidup, menerima request, dan membuat halaman itu sendiri. Masalahnya ada di antara nginx dan aplikasi. Koneksinya ditolak atau di-reset, aplikasi menutupnya sebelum menjawab, atau balasannya tidak bisa dipakai nginx. Error log memberi tahu mana yang terjadi, dan itulah yang menentukan perbaikannya.

## Apa beda 502, 503, dan 504?

Ketiganya dikirim oleh server, tetapi yang disalahkan berbeda. 502 Bad Gateway: proxy menerima response tidak valid dari server di belakangnya. 504 Gateway Timeout: proxy tidak mendapat response tepat waktu dari server itu. 503 Service Unavailable: server yang menjawab sendiri sedang kelebihan beban atau sedang maintenance, dan boleh mengirim header Retry-After yang menyarankan kapan mencoba lagi.

Di nginx, 504 berarti ada timer yang habis. proxy_connect_timeout membatasi berapa lama nginx menunggu koneksi terbuka, dan proxy_read_timeout berapa lama nginx menunggu di antara dua kali membaca jawaban; keduanya default 60 detik. Timer baca berjalan di antara dua pembacaan, bukan untuk seluruh response, jadi jawaban lambat yang terus mengirim data tidak akan memicunya. Halaman bawaan nginx menuliskannya 504 Gateway Time-out.

503 biasanya sama sekali bukan soal koneksi. Bisa jadi aplikasinya sendiri yang menjawab 503 lalu nginx meneruskannya, atau ada aturan nginx yang menolak request: limit_req menjawab request yang ditolak dengan 503, kecuali limit_req_status mengaturnya lain. Jadi 503 mengarahkan Anda ke log aplikasi atau rate limit, sedangkan 502 atau 504 mengarahkan Anda ke error log nginx lebih dulu.

## Di mana error log nginx, dan bagaimana membaca satu barisnya?

Directive error_log menentukan ke mana error ditulis dan mulai dari level apa; level default-nya, error, mencatat error, crit, alert, dan emerg. Image resmi nginx dan paket nginx di Alpine sama-sama menulis ke /var/log/nginx/error.log, dan nginx -T menguji sekaligus mencetak file konfigurasi Anda, sehingga Anda bisa menemukan baris error_log yang berlaku. Di image Docker resmi, file itu adalah link ke standard error container, jadi docker logs menampilkannya.

Setiap baris punya bentuk yang sama. Ini satu baris dari uji coba setup pelajaran ini, nginx di host dan container dalam keadaan mati: 2026/10/18 02:14:40 [error] 405#405: *3 connect() failed (111: Connection refused) while connecting to upstream, client: 127.0.0.1, server: , request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3002/", host: "127.0.0.1:8080".

Baca tiga bagian. Pesannya menyebutkan apa yang gagal, lengkap dengan nomor error sistem dan teksnya. Klausa while menyebutkan di tahap mana: while connecting to upstream berarti nginx tidak pernah mendapat koneksi, sedangkan while reading response header from upstream berarti nginx sudah terhubung, tetapi awal jawabannya tidak pernah datang, datang rusak, atau datang terlambat. Field upstream menyebutkan persis ke mana nginx mencoba terhubung, sehingga port yang salah ketahuan dalam hitungan detik.

## Apa penyebab 502 di Docker, dari yang paling sering?

Container-nya mati, sedang restart, atau masih start. Kalau nginx di host meneruskan ke port loopback, seperti di situs ini, container yang mati membuat port itu kosong: connect() failed (111: Connection refused). Container yang sudah jalan tetapi aplikasinya belum listen akan melewati port, lalu koneksinya diputus: recv() failed (104: Connection reset by peer) while reading response header from upstream. Cek docker ps dan log aplikasinya lebih dulu; crash loop akan terlihat di sana.

Port-nya salah. Kalau proxy_pass menyebut port yang tidak di-publish siapa pun, koneksinya ditolak, dan field upstream menunjukkan port yang dipakai nginx. Kalau entri ports mengarah ke port container yang tidak dipakai aplikasi, port yang di-publish menerima koneksi lalu me-reset-nya, persis seperti aplikasi yang tidak listen. Bandingkan tiga angka: port di proxy_pass, dua angka di entri ports, dan port yang dicetak aplikasi saat start.

Aplikasinya hanya listen di 127.0.0.1 milik container. Trafik lewat port yang di-publish tiba di alamat network container, bukan di loopback-nya, seperti yang ditunjukkan pelajaran 16, jadi aplikasi tidak pernah melihatnya dan nginx mencatat reset yang sama. Jalankan netstat -tln di dalam container lewat docker exec, kalau image-nya punya: 127.0.0.1:3000 adalah bug-nya, 0.0.0.0:3000 yang benar. Dockerfile situs ini mencegahnya dengan HOSTNAME=0.0.0.0.

Kalau nginx dan aplikasi sama-sama container di satu network, ketiga penyebab yang sama terbaca berbeda, karena tidak ada port publish di antaranya. Dalam uji coba, aplikasi di port yang salah maupun di loopback sama-sama menghasilkan connect() failed (111: Connection refused), sedangkan aplikasi yang dihentikan menghasilkan connect() failed (113: Host is unreachable) setelah jeda beberapa detik.

## Pesan nginx apa lagi yang berakhir dengan 502?

nginx juga berjalan di container, dan proxy_pass menulis localhost. Di dalam container nginx, localhost adalah container nginx itu sendiri. Dalam uji coba, nginx mencoba kedua alamat hasil resolve localhost, [::1] lalu 127.0.0.1, dan mencatat koneksi ditolak untuk masing-masing. Taruh kedua container di satu user-defined network, lalu proxy ke nama service dan port container, misalnya http://web:3000; DNS bawaan Docker yang me-resolve nama itu.

localhost di-resolve ke dua alamat, bahkan saat semuanya berjalan. Referensi proxy_pass menyebutkan bahwa kalau sebuah nama di-resolve ke beberapa alamat, nginx memakai semuanya bergiliran. Dalam uji coba dengan aplikasi yang hanya listen di 127.0.0.1, setiap request tetap dijawab 200, tetapi masing-masing mencatat koneksi ditolak ke [::1] lebih dulu. Menulis proxy_pass http://127.0.0.1:3002 menghilangkan tebak-tebakan sekaligus noise di log.

nginx menyimpan alamat yang sudah di-lookup. Nama seperti web di-resolve saat nginx memuat konfigurasinya, itulah sebabnya nama yang tidak bisa di-resolve membuat nginx gagal start dengan host not found in upstream. Dokumentasi Compose menyebutkan bahwa container yang dibuat ulang mendapat alamat IP baru. Dalam uji coba, nginx tetap mengirim ke alamat lama sampai nginx -s reload membuatnya me-lookup ulang. Parameter resolve di modul upstream, yang ada di nginx open source sejak 1.27.3, mengikuti perubahan itu tanpa reload; parameter ini butuh directive resolver dan zone di shared memory.

Ada dua pesan lagi yang muncul while reading response header from upstream. upstream prematurely closed connection: aplikasi menerima request lalu menutup koneksi tanpa menjawab, seperti yang terjadi kalau aplikasi crash di tengah request. upstream sent too big header: header response, termasuk cookie, tidak muat di proxy_buffer_size, yang default-nya satu memory page, 4K atau 8K tergantung platform. Keduanya tetap 502 meskipun aplikasinya bisa dijangkau.

## Ada Cloudflare di depan: 502 ini milik siapa?

Cloudflare menambah satu hop dan kode-kodenya sendiri. Untuk 502 dan 504, dokumentasinya memberi aturan sederhana: halaman error bermerek Cloudflare berarti 502 atau 504 itu berasal dari web server origin Anda, jadi tempat mencarinya adalah error log nginx. Halaman kosong tanpa merek Cloudflare berarti Cloudflare sendiri yang membuatnya, misalnya karena masalah kompresi di origin.

Kode 52x hanya milik Cloudflare dan menggambarkan koneksinya ke origin Anda. 520: origin mengembalikan response yang kosong, tidak dikenal, atau tidak terduga. 521: origin menolak koneksi, biasanya karena web server-nya mati atau memblokir Cloudflare. 522: tidak ada SYN+ACK dalam 19 detik, atau tidak ada ACK atas request dalam 90 detik. 523: tidak ada rute ke origin. 524: sudah terhubung, tetapi tidak ada response HTTP dalam batas Proxy Read Timeout, yang default-nya 125 detik.

Angka-angka itu punya konsekuensi. proxy_read_timeout nginx default-nya 60 detik, jauh di bawah 125 detik milik Cloudflare, jadi aplikasi yang lambat biasanya menghasilkan 504 dari nginx di halaman bermerek Cloudflare, bukan 524. Di setup ini, Anda baru melihat 524 kalau nginx diatur untuk menunggu lebih lama daripada Cloudflare. Untuk mengeluarkan edge dari persoalan, jalankan curl di server ke nginx, lalu ke port aplikasinya sendiri, dan lihat di titik mana error mulai muncul.

## Konfigurasi nyata di balik pelajaran ini

`docker-compose.yml:24-26`

```yaml
    ports:
      # Bind to loopback only — nginx terminates TLS and proxies to this port.
      - "127.0.0.1:${APP_PORT:-3002}:3000"
```

Inilah upstream yang dituju nginx: port host 3002 di loopback host, diteruskan ke port 3000 milik aplikasi. Saat container dihentikan, tidak ada yang listen di 3002 dan nginx mencatat koneksi ditolak. Saat container jalan tetapi tidak ada yang menjawab di port 3000 di dalamnya, port yang di-publish menerima koneksi lalu me-reset-nya, dan nginx mencatat reset. Dua pesan itu memberi tahu sisi mana dari baris ini yang perlu diperbaiki.

`Dockerfile:45-46`

```dockerfile
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
```

Dua baris ini menutup kemungkinan penyebab loopback. Server standalone Next.js membaca PORT dan HOSTNAME saat start, dan 0.0.0.0 membuatnya listen di semua alamat container, sehingga trafik yang diteruskan dari port publish mendapat jawaban. Dengan HOSTNAME=127.0.0.1, container tetap jalan dan health check-nya tetap lolos, tetapi nginx mencatat reset di setiap request.

`docker-compose.yml:29-42`

```yaml
    healthcheck:
      test:
        [
          "CMD",
          "wget",
          "--no-verbose",
          "--tries=1",
          "--spider",
          "http://127.0.0.1:3000/robots.txt",
        ]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
```

Docker menjalankan pemeriksaan ini di dalam container, jadi yang diuji adalah aplikasi di loopback-nya sendiri, bukan jalur yang dilewati nginx. Ini cara memilah yang berguna: kalau docker ps menampilkan container unhealthy, mulai dari aplikasinya; kalau tampil healthy sementara nginx mencatat 502, periksa bagian di antara nginx dan container, yaitu port dan alamat listen. start_period memberi container baru waktu 20 detik sebelum pemeriksaan yang gagal dihitung; nginx tidak memberi kelonggaran seperti itu.

## Yang sering rusak

- **502 beberapa detik di setiap deploy.** Membuat ulang container meninggalkan celah: container lama sudah hilang dan aplikasi baru belum listen, jadi nginx mencatat koneksi ditolak, lalu reset, lalu berhenti. Kalau baris 502 berhenti tepat saat docker ps menampilkan container baru sebagai healthy, celah itulah seluruh ceritanya. Menutupnya butuh salinan kedua aplikasi sebagai tujuan peralihan, dan itulah yang dilakukan deploy blue-green.
- **Masih 502 setelah container aplikasi hidup lagi.** Kalau nginx berjalan di container dalam network yang sama, nginx me-resolve nama aplikasi saat memuat konfigurasinya. Container yang dibuat ulang mendapat alamat baru, dan nginx tetap mengirim ke alamat lama: connect() failed dengan Connection refused atau Host is unreachable. Jalankan nginx -s reload di container nginx agar nama itu di-lookup ulang, atau pakai parameter resolve di upstream agar nginx mengikuti perubahannya sendiri.
- **nginx tidak mau start: host not found in upstream.** nginx me-resolve setiap nama di proxy_pass saat memuat konfigurasinya, dan langsung berhenti dengan [emerg] host not found in upstream kalau ada yang tidak bisa di-resolve, jadi docker logs menampilkan baris itu dan container-nya berhenti. Cocokkan nama itu dengan nama service di Compose, dan pastikan nginx dan aplikasi berada di network yang sama.
- **upstream sent too big header, dan menaikkan satu buffer gagal.** Response yang header-nya melebihi proxy_buffer_size mendapat 502 meskipun aplikasinya menjawab. Dalam uji coba, menaikkan proxy_buffer_size ke 16k saja membuat nginx -t gagal dengan pesan "proxy_busy_buffers_size" must be less than the size of all "proxy_buffers" minus one buffer. Menambahkan proxy_buffers 8 16k membuatnya lolos dan 502-nya hilang. Memangkas cookie atau header yang kebesaran tetap perbaikan yang lebih baik.

### Kode 5xx yang Anda temui saat nginx berada di balik Cloudflare: siapa yang menghasilkannya, artinya, dan tempat pertama untuk dicek. Sesuai dokumentasi RFC 9110, nginx, dan Cloudflare.

| Kode | Dihasilkan oleh | Artinya | Cek dulu |
| --- | --- | --- | --- |
| 502 Bad Gateway | nginx (di halaman bermerek Cloudflare jika di balik Cloudflare) | Response tidak valid atau tidak ada dari upstream | Error log nginx, lalu docker ps |
| 503 Service Unavailable | Biasanya aplikasi, atau limit_req di nginx | Sedang kelebihan beban atau maintenance | Log aplikasi dan rate limit Anda |
| 504 Gateway Timeout | nginx (di halaman bermerek Cloudflare jika di balik Cloudflare) | Tidak ada response tepat waktu dari upstream | Endpoint yang lambat, lalu proxy_read_timeout |
| 520 | Cloudflare | Response kosong, tidak dikenal, atau tidak terduga dari origin | Crash di origin dan error log nginx |
| 521 | Cloudflare | Origin menolak koneksi | Apakah nginx jalan, dan apakah firewall mengizinkan Cloudflare? |
| 522 | Cloudflare | Timeout saat menghubungi origin | Firewall, alamat origin di DNS, beban server |
| 524 | Cloudflare | Terhubung, tetapi tidak ada response dalam 125 detik | Request yang berjalan lama di origin |

## Coba sendiri

Anda hanya butuh Docker di laptop dan satu terminal. Anda akan menjalankan nginx dan aplikasi kecil di satu network, merusak aplikasinya dengan tiga cara, membaca error log nginx setiap kali, lalu membuatnya cukup lambat untuk memicu 504. Beri setiap container baru waktu sedetik untuk start. Satu-satunya port yang di-publish ada di 127.0.0.1, dan langkah terakhir membersihkan semuanya.

1. Buat network dan aplikasi kecil yang listen di HOST dan PORT yang Anda berikan, port 3000 secara default. /slow baru menjawab setelah 10 detik. Variabel APP menyimpan kodenya untuk langkah-langkah yang membuat ulang aplikasi ini.

   ```bash
   docker network create demo502-net
   APP="require('http').createServer((req, res) => setTimeout(() => res.end('hello\n'), req.url === '/slow' ? 10000 : 0)).listen(process.env.PORT || 3000, process.env.HOST)"
   docker run -d --name demo502-app --network demo502-net -e HOST=0.0.0.0 node:22-alpine node -e "$APP"
   ```
2. Tulis konfigurasi nginx yang meneruskan request ke aplikasi lewat namanya, dengan read timeout 5 detik supaya 504 cepat muncul, lalu jalankan nginx di network yang sama. curl mencetak hello.

   ```bash
   printf 'server {\n  listen 80;\n  location / {\n    proxy_pass http://demo502-app:3000;\n    proxy_read_timeout 5s;\n  }\n}\n' > demo502.conf
   docker run -d --name demo502-nginx --network demo502-net -p 127.0.0.1:8090:80 \
     -v "$PWD/demo502.conf:/etc/nginx/conf.d/default.conf:ro" nginx:alpine
   curl http://127.0.0.1:8090
   ```
3. Rusak pertama: hentikan aplikasinya. Setelah jeda beberapa detik, curl mendapat halaman 502 bawaan nginx, dan log-nya berbunyi connect() failed (113: Host is unreachable) while connecting to upstream. nginx masih memakai alamat yang di-lookup saat start, dan sekarang tidak ada yang menjawab di sana.

   ```bash
   docker stop demo502-app
   curl -i http://127.0.0.1:8090
   docker logs demo502-nginx 2>&1 | grep '\[error\]' | tail -1
   ```
4. Rusak kedua: jalankan aplikasi di port 3001 sementara nginx tetap meneruskan ke 3000, lalu reload nginx agar nama aplikasinya di-lookup ulang. Sekarang log-nya berbunyi connect() failed (111: Connection refused), dan netstat di dalam aplikasi menunjukkan 0.0.0.0:3001.

   ```bash
   docker rm -f demo502-app
   docker run -d --name demo502-app --network demo502-net -e HOST=0.0.0.0 -e PORT=3001 node:22-alpine node -e "$APP"
   docker exec demo502-nginx nginx -s reload
   curl -i http://127.0.0.1:8090
   docker logs demo502-nginx 2>&1 | grep '\[error\]' | tail -1
   docker exec demo502-app netstat -tln | grep 300
   ```
5. Rusak ketiga: port-nya benar, tetapi aplikasi hanya listen di 127.0.0.1 milik container. Log-nya menunjukkan koneksi ditolak yang sama, dan netstat menunjukkan sebabnya: 127.0.0.1:3000, bukan 0.0.0.0:3000.

   ```bash
   docker rm -f demo502-app
   docker run -d --name demo502-app --network demo502-net -e HOST=127.0.0.1 node:22-alpine node -e "$APP"
   docker exec demo502-nginx nginx -s reload
   curl -i http://127.0.0.1:8090
   docker logs demo502-nginx 2>&1 | grep '\[error\]' | tail -1
   docker exec demo502-app netstat -tln | grep 300
   ```
6. Perbaiki dengan HOST=0.0.0.0, dan curl kembali mencetak hello. Lalu minta /slow: setelah 5 detik nginx menyerah dengan 504 Gateway Time-out, yang tercatat sebagai upstream timed out (110: Operation timed out) while reading response header from upstream.

   ```bash
   docker rm -f demo502-app
   docker run -d --name demo502-app --network demo502-net -e HOST=0.0.0.0 node:22-alpine node -e "$APP"
   docker exec demo502-nginx nginx -s reload
   curl http://127.0.0.1:8090
   curl -i http://127.0.0.1:8090/slow
   docker logs demo502-nginx 2>&1 | grep '\[error\]' | tail -1
   ```
7. Bersihkan container, network, dan file konfigurasinya.

   ```bash
   docker rm -f demo502-nginx demo502-app
   docker network rm demo502-net
   rm demo502.conf
   ```

## Kuis singkat

1. **nginx di host mencatat connect() failed (111: Connection refused) while connecting to upstream, upstream: "http://127.0.0.1:3002/". Apa penyebab yang paling mungkin?**
   A. Aplikasinya terlalu lama menjawab
   B. Tidak ada yang listen di 3002: container-nya mati atau port-nya salah
   C. Header response aplikasinya terlalu besar
   Jawaban: B. while connecting to upstream berarti nginx tidak pernah mendapat koneksi, dan Connection refused berarti tidak ada yang listen di alamat dan port itu. Aplikasi yang lambat menghasilkan timeout, dan header yang kebesaran menghasilkan upstream sent too big header setelah terhubung.

2. **Satu endpoint butuh 90 detik. nginx memakai proxy_read_timeout default dan berada di balik Cloudflare. Apa yang dilihat pengunjung?**
   A. 504 bermerek Cloudflare yang dihasilkan nginx
   B. 524 milik Cloudflare
   C. 502 dari nginx
   Jawaban: A. Read timeout 60 detik milik nginx habis lebih dulu dan nginx menjawab 504. Cloudflare menampilkan 504 dari origin di halaman bermerek. 524 baru muncul kalau origin diam melewati batas 125 detik milik Cloudflare.

3. **Di dalam container aplikasi, netstat -tln menunjukkan 127.0.0.1:3000. nginx meneruskan ke port yang di-publish dan mencatat Connection reset by peer. Apa perbaikannya?**
   A. Naikkan proxy_read_timeout
   B. Publish port di 0.0.0.0, bukan di 127.0.0.1
   C. Buat aplikasi listen di 0.0.0.0 di dalam container
   Jawaban: C. Trafik lewat port publish tiba di alamat network container, dan aplikasi yang listen di loopback milik container tidak pernah melihatnya. Membuka port host ke semua alamat tidak mengubah apa pun di dalam container dan malah mengekspos port-nya.

## Pikirkan dulu

- **Browser Anda menampilkan 502 Bad Gateway dengan tulisan nginx di bawah halaman. Komponen mana yang gagal?** Bukan nginx: nginx menerima request dan membuat halaman itu. Upstream-nya, yaitu aplikasi di belakangnya, menolak, me-reset, atau menutup koneksi, atau mengirim sesuatu yang tidak bisa dipakai nginx. Baris di error log menyebutkan yang mana.
- **Apa beda while connecting to upstream dan while reading response header from upstream?** Yang pertama berarti nginx tidak pernah mendapat koneksi: tidak ada yang listen, port salah, atau alamat yang sudah usang. Yang kedua berarti nginx sudah terhubung, tetapi awal jawabannya tidak pernah datang, datang rusak, atau datang terlambat.
- **Halaman 502 memakai merek Cloudflare. Di mana Anda mencari lebih dulu?** Di origin Anda. Dokumentasi Cloudflare menyebutkan bahwa 502 atau 504 bermerek berasal dari web server origin, jadi baca error log nginx. 502 yang kosong tanpa merek adalah milik Cloudflare sendiri.

## Pelajari lebih dalam

- [Cara Setting Nginx Reverse Proxy untuk Docker di Cloudflare](https://www.matthewswong.com/id/blog/cara-setting-nginx-reverse-proxy-docker-cloudflare/)
- [Load Balancer Nginx di Produksi: Konfigurasi, Health Check, dan Failover](https://www.matthewswong.com/id/blog/load-balancer-production-config/)
- [Cara Melihat Docker Logs: Tail, Follow, dan Compose](https://www.matthewswong.com/id/blog/cara-melihat-docker-logs-untuk-pemula/)

## Sumber

- [RFC 9110, HTTP Semantics: 502, 503, dan 504](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.6.3)
- [Dokumentasi nginx: ngx_http_proxy_module (proxy_pass, timeout, buffer)](https://nginx.org/en/docs/http/ngx_http_proxy_module.html)
- [Dokumentasi nginx: directive error_log](https://nginx.org/en/docs/ngx_core_module.html#error_log)
- [Dokumentasi nginx: ngx_http_upstream_module (parameter resolve)](https://nginx.org/en/docs/http/ngx_http_upstream_module.html)
- [Dokumentasi nginx: ngx_http_limit_req_module (limit_req_status)](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html)
- [Dokumentasi nginx: parameter command-line (-T, -s reload)](https://nginx.org/en/docs/switches.html)
- [Dokumentasi Cloudflare: error 5xx Cloudflare](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/)
- [Dokumentasi Cloudflare: Error 502 atau 504](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-502-504/)
- [Dokumentasi Cloudflare: Error 520](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-520/)
- [Dokumentasi Cloudflare: Error 521](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-521/)
- [Dokumentasi Cloudflare: Error 522](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-522/)
- [Dokumentasi Cloudflare: Error 523](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-523/)
- [Dokumentasi Cloudflare: Error 524](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/)
- [Dokumentasi Docker: networking di Compose (nama service, IP baru saat dibuat ulang)](https://docs.docker.com/compose/how-tos/networking/)
- [Dokumentasi Docker: ikhtisar networking (DNS bawaan)](https://docs.docker.com/engine/network/)
- [Dokumentasi Docker: publish dan mapping port](https://docs.docker.com/engine/network/port-publishing/)
- [Dokumentasi Docker: referensi Dockerfile, HEALTHCHECK](https://docs.docker.com/reference/dockerfile/#healthcheck)
- [Dokumentasi Next.js: output standalone (PORT dan HOSTNAME)](https://nextjs.org/docs/app/api-reference/config/next-config-js/output)

---

- HTML version: https://www.matthewswong.com/id/learn/devops-from-zero/nginx-502-bad-gateway-docker/
- English: https://www.matthewswong.com/en/learn/devops-from-zero/nginx-502-bad-gateway-docker/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
