502 Bad Gateway After Deploying? 8 Causes and How to Fix Each
Build succeeded but the URL shows 502 Bad Gateway? The 8 real causes (wrong port, localhost binding, crashes, memory, env vars) and how to fix each one.
- Published
- Reading time
- 4 min
On this page
Key takeaways
- A 502 after a successful build almost always means the proxy can't reach your app: it isn't listening, or crashed.
- The two most common causes: not reading the PORT environment variable, and binding to 127.0.0.1 instead of 0.0.0.0.
- Run dock logs first: the crash message or the missing variable is usually in the last 20 lines.
The build is green and the deploy says live, but opening the URL gives you 502 Bad Gateway (or it spins until it times out). This is the most common "it worked on my machine" moment in web hosting, and it nearly always comes down to one of eight causes.
What a 502 actually means
Every hosting platform puts a reverse proxy in front of your app. It terminates HTTPS and forwards each request to your container. A 502 means the proxy forwarded the request and got nothing usable back. Your code may be fine: the proxy just can't reach it.
So start with one question: is my process running and listening where the proxy expects it?
dock logs # build + application logs, live1. Not listening on PORT
The platform assigns a port and passes it in the PORT environment variable. If you hard-code 3000 or 8000, the proxy knocks on a door nobody answers.
// Node.js
app.listen(process.env.PORT || 3000);# Python (FastAPI / Uvicorn)
uvicorn main:app --host 0.0.0.0 --port $PORT2. Listening on localhost only
127.0.0.1 (localhost) is only reachable from inside the container. The proxy connects from outside, so bind to 0.0.0.0.
| Framework | Wrong | Right |
|---|---|---|
| Express / Fastify | listen(port, "127.0.0.1") | listen(port, "0.0.0.0") or omit the host |
| Flask dev server | app.run() | Run under Gunicorn: gunicorn app:app |
| Uvicorn | --host 127.0.0.1 | --host 0.0.0.0 |
| Next.js standalone | default host | HOSTNAME=0.0.0.0 |
3. The app crashes on startup
The deploy succeeded, then the process exited. Look at the last lines of dock logs for an exception. The usual suspects:
Cannot find module→ a runtime dependency is indevDependencies, orstartpoints to a file the build doesn't create.ModuleNotFoundError→ the package is missing fromrequirements.txt/pyproject.toml.KeyError: 'SECRET_KEY'→ see cause 4.
On DockHosting, the App output tab on a deploy shows what your app printed while starting, with the failing line.
4. A missing environment variable
Your .env file isn't deployed (and shouldn't be). Every variable your app reads at startup, such as API keys, SECRET_KEY or NODE_ENV, must be set in the project's environment variables. Then restart:
dock restart5. The database points at localhost
postgres://localhost:5432/... works on your laptop and nowhere else. Read the connection string from DATABASE_URL, which is injected when you attach a managed database. See connecting to managed PostgreSQL.
6. Out of memory
If the process gets killed without an error, it probably ran out of memory. On the Free plan an app and its database share 512 MB. Common culprits are a large build step at runtime, an unbounded cache, or too many worker processes.
- Build at build time (
npm run build), and only start at runtime. - Lower worker counts (Gunicorn
--workers 2). - Paid plans give more room: 1 GB on Hobby, 3 GB on Pro and up to 4 GB per app on Team.
7. Slow startup
Apps that need a long time before they listen (for example JVM apps such as Spring Boot, or apps that run migrations first) can look dead while they start. DockHosting gives apps up to 5 minutes to start listening before it marks a start as failed. If yours takes longer, move heavy work out of startup.
8. The app was asleep
On the Free plan, an app sleeps after 1 hour without visits. The first request wakes it, and DockHosting shows a Waking up page instead of an error while it starts. That's expected behavior, not a bug. Hobby and higher plans are always on.
A 60-second checklist
dock logs: is there a stack trace?- Does the app read
PORT? - Is it bound to
0.0.0.0? - Are all environment variables set in the dashboard?
- Does the database URL come from
DATABASE_URL? - Is memory within the plan's limit?
Still stuck? Open a ticket from Support in the dashboard (a failed deploy has a button for it), or ask on Discord.
Frequently asked questions
What does 502 Bad Gateway mean?
The server in front of your app (a reverse proxy or load balancer) received your request but got no valid response from your app. Your app is down, crashed, still starting or listening on the wrong address or port.
Why does my app work locally but return 502 in production?
Locally you open the port you chose, on localhost. In production, the platform tells your app which port to use through the PORT environment variable and connects from outside the container, so the app must listen on process.env.PORT and on 0.0.0.0.
How do I see why my app crashed?
Run dock logs to tail build and application logs, or open the App output tab on the deploy in the dashboard, which shows what your app printed while starting.
- Troubleshooting
- 502
- Deployment
- Node.js
- Python
Written by Doughmi ILYAS
Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.
