1b-agent fff19a9e17 feat: stateless hot-reload Odoo 19 dev workspace for onebspace
- Dockerfile: verbatim upstream odoo/docker 19.0 + pip install requirements.txt
- easypanel.schema.json: source.type=dockerfile with inline Dockerfile
- deploy.py: calls Easypanel tRPC API directly (bypass MCP that only supports image)
- .gitea/workflows/build.yml: optional Gitea Actions CI
- README.md: full research + reproduction steps
2026-08-30 18:55:00 +00:00

stateless-container-for-onebspace-development

Stateless hot-reload Odoo 19 development workspace for the 1b-agent/os-dev repo, deployed on the Easypanel project onebspace.

This repo is the blueprint — the live state is on the Easypanel onebspace project (odoo-dev + odoo-dev-db services) and the bind-mounted workspace at /root/Documents/trae_projects/one_b_os/os-dev/.


1. What this gives you

  • No image rebuilds for code edits. Edit any .py in os-dev/odoo/addons/... and --dev=reload (watchdog) restarts Odoo in milliseconds.
  • Full hot-reload flags baked into odoo.conf:
    dev_mode = reload,qweb,assets,xml,werkzeug
    
    • reload → restart on .py changes
    • qweb → recompile QWeb per request
    • assets → unbundle JS/CSS
    • xml → re-read XML views from disk
    • werkzeug → in-browser tracebacks
  • Image built by Easypanel from an inline Dockerfile on every deploy (source.type=dockerfile), no Gitea Container Registry needed.
  • Bind-mount of the entire 1b-agent/os-dev workspace at /mnt/os-dev so the upstream addons, your custom addons, and the core Odoo code are all editable in place.

2. Components

File Purpose
Dockerfile Verbatim copy of github.com/odoo/docker/19.0/Dockerfile + pip install -r requirements.txt --break-system-packages. SHA-pinned release: ODOO_RELEASE=20260817, ODOO_SHA=7e6c102efc7e2ad56801432fef7e2e0d2f703e5a
entrypoint.sh Postgres env-var → --db_host/--db_user/... propagation (copied from upstream)
wait-for-psql.py Waits for Postgres before starting Odoo (copied from upstream)
odoo.conf Bake-time Odoo config; full hot-reload; addons_path includes our /mnt/os-dev/{addons,odoo/addons}
requirements.txt Python deps from the upstream odoo/19.0 requirements.txt
easypanel.schema.json Easypanel service payload using source.type=dockerfile + inline Dockerfile
deploy.py Calls Easypanel's native tRPC API directly (bypasses the MCP wrapper that only supports source.type=image) to push the inline Dockerfile, set env, and deploy
.gitea/workflows/build.yml Optional: auto-build & push os-dev:19.0 to a Gitea Container Registry on every push to 1b-agent/os-dev's 19.0 branch

3. How it was built (research summary)

3.1 The official odoo/docker image

  • Base: ubuntu:noble (not Debian)
  • Pre-installs python3-watchdog (what makes --dev=reload work)
  • Entrypoint waits for Postgres (wait-for-psql.py --timeout=30)
  • Default odoo.conf has addons_path = /mnt/extra-addons, data_dir = /var/lib/odoo — both declared as VOLUME

3.2 dev_mode flags (Odoo 19 CLI reference)

Flag Effect
reload restart odoo-bin on .py change (needs python3-watchdog)
qweb recompile QWeb templates per request
assets serve JS/CSS unbundled → edit-and-refresh
xml re-read XML view files on update
werkzeug show full Python tracebacks in browser

3.3 Why source.type=dockerfile (not image pull)

Easypanel's services.app.createFromSchema (the MCP wrapper) only supports source.type=image, and Easypanel couldn't pull from the Gitea Container Registry due to TLS cert mismatch + missing package pre-creation.

Easypanel itself supports source.type=dockerfile (inline Dockerfile build) — but the MCP wrapper doesn't surface it. We bypassed the MCP and called the native tRPC API directly:

POST /api/trpc/services.app.createService
POST /api/trpc/services.app.updateSourceDockerfile
POST /api/trpc/services.app.updateEnv
POST /api/trpc/services.app.deployService

The Dockerfile is stored on Easypanel's filesystem at /etc/easypanel/projects/<project>/<service>/code/Dockerfile and rebuilt on every deploy.

3.4 Self-contained inline Dockerfile

Easypanel's source.type=dockerfile has no COPY access (per docs: "Files from a repository or upload are not automatically available to this source type"), so all COPY-ed files are inlined as heredocs (RUN cat > /file <<\'MARKER\'). This produces a single ~17 KB Dockerfile with zero COPY instructions.


4. Reproducing this setup on a fresh Easypanel

4.1 Prereqs

  • An Easypanel instance with a project (we used onebspace)
  • A clone of 1b-agent/os-dev at /root/Documents/trae_projects/one_b_os/os-dev/
  • An Easypanel bearer token (Settings → API → Generate Token, or grab the MCP token from /root/.trae-server/data/Machine/mcp.json)

4.2 Run the deploy script

cd stateless-container-for-onebspace-development
python3 deploy.py deploy

This will:

  1. Generate the inline Dockerfile from ../os-dev/* files
  2. Generate a fresh DB password and save to .db_password
  3. Patch CHANGE_ME_DB_PASSWORD in the env block
  4. Call the four Easypanel tRPC procedures in order
  5. Build the image in-place and start the container

Verify:

curl -sS -o /dev/null -w "HTTP %{http_code}  bytes=%{size_download}\\n" \
  http://127.0.0.1:18069/web/database/manager
# expected: HTTP 200  bytes=70194

5. Daily workflow

# edit code in place — auto-reload picks it up
vim /root/Documents/trae_projects/one_b_os/os-dev/odoo/addons/web/controllers/main.py

# restart Odoo manually if needed
docker restart $(docker ps --filter "name=onebspace_odoo-dev" --format "{{.ID}}" | head -1)

# rebuild the image (only when requirements.txt or Dockerfile changes)
python3 deploy.py redeploy

6. Verified working state

  • Odoo version 19.0-20260817 (matches ODOO_SHA=7e6c102e…)
  • HTTP 200 (70,194 bytes) on /web/database/manager
  • Addons loaded from /mnt/os-dev/addons, /mnt/os-dev/odoo/addons, plus upstream /usr/lib/python3/dist-packages/odoo/addons
  • AutoReload watcher running with watchdog + HTTP service (werkzeug) running
  • Bind-mount /root/Documents/trae_projects/one_b_os/os-dev/ → /mnt/os-dev/ verified (24 addons in both views)
S
Description
Stateless hot-reload Odoo 19 dev workspace deployed on Easypanel/onebspace. Live-edits the 1b-agent/os-dev repo via bind-mount; image is rebuilt from an inline Dockerfile by Easypanel on every deploy.
Readme
51 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 70.1%
Dockerfile 23.8%
Shell 6.1%