跪拜 Guibai
← All articles
Artificial Intelligence · Frontend Framework · Full Stack

LangGraph Build Fails Locally? Build the Docker Image on a Server Instead

By 锋行天下 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

This gives Western developers a concrete fallback when LangGraph's local Docker build fails on Macs due to image registry issues, plus a clean nginx recipe for exposing a chat front end to a localhost-only model API.

Summary

A Mac user hit repeated failures with langgraph build because Docker could not download images, and mirror source changes did not fix it. The workaround is to build the Docker image on a remote server, where langgraph itself does not need to be installed.

The official langgraph dockerfile command generates a Dockerfile and docker-compose.yml. Regenerating that Dockerfile is required whenever langgraph.json changes, otherwise the image drifts from the configuration. docker-compose up -d then starts Redis, PostgreSQL, the custom image, and environment variables in one step.

The post then wires a Vite-based chat front end to the server. An nginx config serves the built dist files, proxies /lg/ to a localhost-only model API on port 8123, and includes streaming-friendly settings like proxy_buffering off. It also blocks common scanner paths and returns a custom 429 response for rate limiting.

Takeaways
— LangGraph dev runs locally on a Mac, but langgraph build repeatedly fails because Docker cannot download the required images; changing mirror sources did not help.
— It is possible to build the LangGraph Docker image on a remote server that does not have LangGraph installed.
— Run langgraph dockerfile ./Dockerfile --add-docker-compose to generate a Dockerfile and docker-compose.yml.
— Regenerate the Dockerfile every time langgraph.json changes, or the built image may not match the configuration.
— docker build -t xxx:vxx . builds the image locally from the Dockerfile; docker-compose up -d starts Redis, PostgreSQL, the LangGraph image, and environment variables together.
— A Vite-based chat front end needs only three main files: index.html, main.js, and vite.config.js (for chat UI, JS logic, and cross-origin config).
— The nginx config blocks common scanner paths and returns a custom 429 error for rate limiting.
— The model API listens only on 127.0.0.1:8123, so only the front end served by nginx can reach it.
— Streaming works via proxy_http_version 1.1, proxy_buffering off, and increased proxy timeouts (e.g., 600s).
Conclusions

LangGraph's official CLI assumes Docker can pull images, but on systems with restricted registry access the failure is not easily fixed by changing mirrors, so a server-side build is a pragmatic alternative.

The regeneration requirement for the Dockerfile ties the build closely to langgraph.json, meaning config changes must be remembered to avoid stale images.

Serving a chat UI with nginx and a localhost-only model API is a common pattern for keeping the model endpoint private while still allowing a public front end.

The author's use of AI-generated code for the front end suggests that the main technical friction in this stack is the infrastructure setup, not the chat UI itself.

Concepts & terms
langgraph dockerfile
A CLI command that generates a Dockerfile and optionally a docker-compose.yml from a LangGraph project, so deployment can be containerized.
langgraph build
A CLI command that builds a Docker image for a LangGraph application; it relies on downloading base images and can fail if registry access or mirror settings are problematic.
proxy_pass to 127.0.0.1
An nginx directive that forwards requests to a service listening only on the local loopback address, keeping the underlying API private while exposing a public front end.
proxy_buffering off
An nginx setting that disables response buffering so data streams through to the client as it arrives, which is important for chat and other streaming responses.
From the discussion
Featured comments
booboosui

Let me add three more pitfalls you'll hit later. First, during build, pulling the image is done by your local Docker daemon, and changing pip or npm sources has zero effect on it—what you need to change is Settings → Docker Engine → registry-mirrors in Docker Desktop, and it only takes effect after Apply & Restart. Likewise, the HTTPS_PROXY you export in your shell isn't read by the daemon; you have to fill it in under Resources → Proxies separately. That's probably the real reason 'changing mirrors didn't work.' Second, your nginx buffer parameters are right, but you're missing proxy_http_version 1.1: the default is 1.0, which sends 'Connection: close' upstream and breaks streaming anyway. Also bump proxy_read_timeout from the default 60 seconds to 600 seconds, otherwise a longer graph gets cut off after a minute and the frontend only sees half a sentence, with no error—very hard to debug. Third, the Dockerfile in the directory is a generated artifact; you've already written that it must be regenerated when langgraph.json changes, but conversely don't hand-edit it—the next regeneration will overwrite it. Dependency changes should go into langgraph.json, or be appended after generation.

锋行天下

Wow, all useful stuff, thanks for the guidance 🙏🏻

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗