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