Skip to content

PlanExe uses Docker

Docker is the supported way to run PlanExe locally and in most deployments. This page covers common Docker workflows and troubleshooting.

Basic lifecycle

  • Stop everything: docker compose down
  • Build fresh (no cache) after code moves: docker compose build --no-cache database_postgres worker_plan frontend_multi_user
  • Start services: docker compose up
  • Stop services (leave images): docker compose down
  • Build fresh and start services: docker compose build --no-cache database_postgres worker_plan frontend_multi_user && docker compose up

While developing

Simons typical workflow.

While making code changes, I use ./rebuild.sh, that does this:

docker compose down --remove-orphans
docker compose build --no-cache
docker compose up

Frequently I do docker system prune -a to free disk space.

  • Live rebuild/restart on changes: docker compose watch (requires Docker Desktop 4.28+).
    If watch misses changes after file moves, rerun the no-cache build above.
  • View logs:
  • docker compose logs -f worker_plan
  • docker compose logs -f frontend_multi_user

Run individual files

  • Rebuild the worker image when code or data files change: docker compose build --no-cache worker_plan.
  • Run a one-off module inside the worker image (same deps/env as the API):
    docker compose run --rm worker_plan python -m worker_plan_internal.fiction.fiction_writer (swap the module path as needed). If containers are already up, use docker compose exec worker_plan python -m ... instead.
  • For host Ollama access, set base_url in llm_config/<profile>.json to http://host.docker.internal:11434 (default Ollama port). On Linux, add extra_hosts: ["host.docker.internal:host-gateway"] under worker_plan if that hostname is missing, or use your bridge IP.
  • Ensure required env vars (e.g., DEFAULT_LLM) are available via .env or your shell before running the command.

Troubleshooting

  • If the pipeline stops immediately with missing module errors, rebuild with --no-cache so new files are inside the images.
  • If you change environment variables (e.g., PLANEXE_WORKER_RELAY_PROCESS_OUTPUT), restart: docker compose down then docker compose up.
  • If frontend_multi_user can't start because host port 5000 is busy, map it elsewhere: export PLANEXE_FRONTEND_MULTIUSER_PORT=5001 (or another free port) before docker compose up.
  • To clean out containers, network, and orphans: docker compose down --remove-orphans.
  • To reclaim disk space when builds start failing with No space left on device:
  • See current usage: docker system df
  • Aggressively prune (images, caches, networks not in use): docker system prune -a
    • Expect a confirmation prompt; this removed ~37 GB here by deleting unused images and build cache.
  • If needed, prune build cache separately: docker builder prune

Port 5432 already in use (Postgres conflict)

If database_postgres fails to start with a "port already in use" error, another PostgreSQL is likely running on your machine. This is common on developer machines where you have: - macOS: Postgres.app (a popular menu-bar Postgres), Homebrew PostgreSQL (brew install postgresql), or pgAdmin's bundled server - Linux: System PostgreSQL installed via apt install postgresql or similar - Windows: PostgreSQL installer, pgAdmin, or other database tools

Solution: Set PLANEXE_POSTGRES_PORT to a different value:

export PLANEXE_POSTGRES_PORT=5433
docker compose up

This only affects the HOST port (how you access Postgres from your machine). Inside Docker, containers always connect to each other on port 5432—this is hardcoded and unaffected by PLANEXE_POSTGRES_PORT.

To make this permanent, add to your .env file:

PLANEXE_POSTGRES_PORT=5433

When connecting from your host machine (e.g., DBeaver, psql), use the port you set:

psql -h localhost -p 5433 -U planexe -d planexe

Environment notes

  • The worker exports logs to stdout when PLANEXE_WORKER_RELAY_PROCESS_OUTPUT=true (set in docker-compose.yml).
  • Shared volumes: .env and ./llm_config/ are mounted read-only. Ensure they exist on the host before starting.
  • Database: Postgres runs in database_postgres and listens on host ${PLANEXE_POSTGRES_PORT:-5432} mapped to container 5432; data is persisted in the named volume database_postgres_data.
  • Multiuser UI: binds to container port 5000, exposed on host ${PLANEXE_FRONTEND_MULTIUSER_PORT:-5001}.
  • MCP server downloads: set PLANEXE_MCP_PUBLIC_BASE_URL so clients receive a reachable /download/... URL (defaults to http://localhost:8001 in compose).