Instruction file imported from videohead/langgraph-copilottoolkit (
.github/instructions/docker-lando.instructions.md). Copyright stays with the author.
Modifying Docker / Lando Service Definitions
Service map
| Service | Definition | Build context | Internal port |
|---|---|---|---|
postgres |
Lando + Compose | prebuilt image | 5432 |
redis |
Lando + Compose | prebuilt image | 6379 |
mcp-filesystem |
Lando + Compose | repo root . |
8765 |
mcp-shell |
Lando + Compose | repo root . |
8770 |
ollama |
Lando + Compose | prebuilt image | 11434 |
appserver / langgraph |
Lando + Compose | repo root . |
8000 |
django |
Lando + Compose | repo root . |
8080 |
frontend |
Lando + Compose | ./frontend |
3000 |
charts |
Lando + Compose | prebuilt image | 80 |
Required sync updates when adding a service
When adding or renaming any service in docker-compose.yml or .lando.yml, also update all of the following in the same change:
- Runtime stack config:
docker-compose.ymlservice definition, healthcheck/dependencies, volumes, and env wiring..lando.ymlservice definition, proxy URL, and tooling commands.
- User-facing docs:
readme.mdarchitecture diagram and the "Additional services" table.
- User-facing services map API:
frontend/app/api/services/data.mjsin all three places:DEFAULT_ENDPOINTSPUBLIC_LOCATIONSservicesarray inbuildServicesDashboardData()
Minimum expected entries include both durable and coordination stores (postgres and redis) so they appear in docs and in the services dashboard.
MCP services should also stay represented in docs and dashboard (mcp-filesystem, mcp-shell).
MCP shell allowlist management
mcp-shell enforces command execution policy via environment variables:
MCP_SHELL_ALLOWLIST— comma-separated executable names.MCP_SHELL_ROOT— command working-directory sandbox root.MCP_SHELL_TIMEOUT_SECONDS— command timeout.MCP_SHELL_MAX_OUTPUT_BYTES— stdout/stderr truncation bound.
When editing allowlist values, update both docker-compose.yml and .lando.yml in the same change.
The allowlist is loaded at process startup, so changes are not hot-reloaded. Restart/recreate mcp-shell after updates.
Build context rules
Django — build context MUST be repo root
django/Dockerfile COPYs from both django/ and src/:
COPY django/requirements.txt ./requirements.txt
COPY src/ ./src/
COPY django/ .
In docker-compose.yml:
django:
build:
context: . # repo root
dockerfile: django/Dockerfile
In .lando.yml:
django:
services:
build:
context: . # repo root
dockerfile: django/Dockerfile
Never set context: ./django — the Dockerfile will fail to find src/.
Frontend — build context is ./frontend
frontend/Dockerfile only needs files inside frontend/:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
Volume mount patterns
Hot-reload: override image files with host source
volumes:
- ./django:/app # Django source
- ./src:/app/src:ro # shared graphs (read-only)
volumes:
- ./frontend:/app # Next.js source
- /app/node_modules # anonymous volume — preserves image's node_modules
The anonymous /app/node_modules volume is essential for the frontend. Without it, the host mount would shadow the container's installed packages with an empty host directory.
src/ is always :ro inside Django
Never mount src/ read-write into the Django container. The graphs are Python library code; Django should not write to them.
Environment variables
Internal service URLs use Docker/Lando DNS — not localhost:
# Correct (Compose)
OLLAMA_BASE_URL: http://ollama:11434
DJANGO_INTERNAL_URL: http://django:8080
# Correct (Lando — service names resolve as <name>.<appname>.internal)
OLLAMA_BASE_URL: http://ollama.langgraph.internal:11434
DJANGO_INTERNAL_URL: http://django.langgraph.internal:8080
OLLAMA_MODEL and OLLAMA_BASE_URL must be set on both langgraph/appserver and django — both services run graphs against Ollama.
Lando service format (API 3)
All services use api: 3 with type: lando. The services: block is a standard Docker Compose service definition:
myservice:
api: 3
type: lando
app_mount: false # disable Lando's default app volume mount
services:
build:
context: .
dockerfile: myservice/Dockerfile
command: my-start-command
environment:
MY_VAR: value
ports:
- "8090" # expose to Lando's internal network (no host binding needed)
volumes:
- ./myservice:/app
moreHttpPorts:
- 8090 # tell Lando to proxy this port
Add a proxy entry to expose it via .lndo.site:
proxy:
myservice:
- myservice.langgraph.lndo.site:8090
Add tooling to run commands in the container:
tooling:
myservice-cmd:
service: myservice
cmd: my-binary
description: "Run my-binary in the myservice container"
Adding a Python dependency (Django)
- Add to
django/requirements.txt lando rebuild -yordocker compose build django
Do not pip install in a running container — it won't persist.
Adding a Node.js dependency (frontend)
lando npm install <pkg> --save(updatespackage.jsonin the volume-mounted source)lando rebuild -yordocker compose build frontend(bakes it into the image layer)
Healthchecks
ollama has a healthcheck; django has one too. The frontend service uses depends_on: django: condition: service_healthy. If you change the Django port, update the healthcheck URL accordingly:
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8080/api/health/ || exit 1"]
Ports exposed to the host
| Host port | Service | Notes |
|---|---|---|
| 3000 | frontend | Next.js dev server |
| 5432 | postgres | Durable checkpoint storage |
| 6379 | redis | Orchestration/state coordination cache |
| 8080 | django | Django/uvicorn |
| 8765 | mcp-filesystem | MCP filesystem server |
| 8770 | mcp-shell | MCP shell server |
| 8123 | langgraph | LangGraph dev server (maps container :8000) |
| 8124 | charts | nginx static |
| 11434 | ollama | Ollama API |
When using Lando, host ports are assigned dynamically — use lando info to find them. The .lndo.site proxy URLs are stable.
Shell mapping (agent + user safety)
Do not run project runtime commands in the host shell. Use a service shell.
| Area | Lando shell | Docker shell |
|---|---|---|
| Frontend | lando ssh -s frontend |
docker exec -it langgraph-frontend sh |
| Django | lando ssh -s django |
docker exec -it langgraph-django sh |
| LangGraph appserver | lando ssh -s appserver |
docker exec -it langgraph-dev sh |
| Postgres | lando ssh -s postgres |
docker exec -it langgraph-postgres sh |
| Redis | lando ssh -s redis |
docker exec -it langgraph-redis sh |
| Ollama | lando ssh -s ollama |
docker exec -it ollama sh |
| MCP filesystem | lando ssh -s mcp-filesystem |
docker exec -it langgraph-mcp-filesystem sh |
| MCP shell | lando ssh -s mcp-shell |
docker exec -it langgraph-mcp-shell sh |
| Charts | lando ssh -s charts |
docker exec -it langgraph-charts sh |
Use lando ssh -s <service> -c "<cmd>" (or docker exec -it <container> sh -lc "<cmd>") for one-off commands.