localhost:5173 / vite-docker
Running the Vite dev server in a container
Inside a container localhost means the container, so the dev server has to listen on 0.0.0.0 and the port has to be published — mapping the port alone is not enough.
Bind inside the container
Without this Vite listens on the container’s own loopback address. The port mapping then forwards to an address nothing is listening on, and the browser gets an empty response.
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]
Publish it outside
Both halves are required. Either one alone gives you the same empty page.
services:
web:
build: .
ports:
- "5173:5173"
volumes:
- .:/app
- /app/node_modulesWhy node_modules gets its own volume
The anonymous volume keeps the container’s node_modules from being shadowed by the one on your host. Without it, a host directory built for macOS or Windows lands inside a Linux container, and native dependencies fail in ways that have nothing to do with Vite.
Hot reload does not survive the mount
File change events usually do not cross a bind mount, so the watcher never hears about your edits. Polling asks instead of listening. It works, and it costs CPU — enable it here, not globally.
server: {
host: '0.0.0.0',
watch: { usePolling: true },
}A hostname that is not localhost
If you reach the container through a service name, a Traefik host or a tunnel, expect "Blocked request. This host is not allowed" next. That is the separate host allowlist, and it needs the exact hostname the browser uses.
WSL2 is the same problem with different plumbing
Reaching the dev server from Windows itself normally works. Reaching it from another machine on your LAN does not, because WSL2 has its own network stack — that needs Windows port forwarding or mirrored networking mode, not a Vite setting.
# faq
Questions
Why is localhost:5173 empty when Vite runs in Docker?
Vite is listening on the container’s loopback address. Start it with --host 0.0.0.0.
Is publishing the port enough?
No. The server also has to listen on 0.0.0.0 inside the container.
Why does hot reload not work in a container?
File change events do not reach the watcher across a bind mount. server.watch.usePolling is the usual workaround.
Should usePolling always be on?
No. It keeps a CPU core busy on larger projects. Enable it only where events genuinely do not arrive.
# next