In this article, we will consider custom modules, live chat, and blog posts in headless mode via REST API. For the frontend, we will use a Next.js app.
Docker via Image Inheritance
Instead of building an Odoo runtime from scratch, our Dockerfile inherits from the official image with FROM odoo:19.0. This gives us the full, tested Odoo 19 stack (Python deps, server, entrypoint) for free, and we only layer our own changes on top.
The customization is minimal and explicit:
- switch to root to create /mnt/extra-addons and hand ownership to the Odoo user;
- COPY our custom addons (website_blog_api, livechat_api) into that folder, so the image is self-contained and runs even without a bind mount;
- Drop back to the unprivileged Odoo user and expose ports 8069 / 8072.
docker-compose.yml ties it together: a postgres:16 service with a healthcheck, and the Odoo service that waits for the DB to be healthy. For development, the host ./addons folder is bind-mounted over /mnt/extra-addons (:rw), so code edits are picked up live without rebuilding the image. Named volumes persist in the database and Odoo filestore.
The result is a clean two-layer model: the base image stays standard and upgradeable, while our addons live in a thin layer on top — the same inheritance idea Odoo itself uses for modules.
Modules
website_blog_api — a public, read-only REST API over website_blog. It exposes blogs, posts, and tags as JSON, ready for headless frontends (Next.js, Nuxt, mobile).
livechat_api — a headless REST bridge over im_livechat so a website can chat with an operator without the bundled Odoo widget (start/resume session, send and poll messages, close). Incoming messages are answered synchronously by an OpenAI-backed AI sales agent posting as a dedicated bot user; it auto-disables on human handoff and is configurable through system parameters.
See the source code: https://github.com/StackThrower/Live-Chat-and-Blog-Headless-Odoo