odoo-docker-deployment

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Odoo Docker Deployment

Odoo Docker 部署方案

Overview

概述

This skill provides a complete, production-ready Docker setup for Odoo, including PostgreSQL, persistent file storage, environment variable configuration, and an optional Nginx reverse proxy with SSL. It covers both development and production configurations.
本方案为Odoo提供一套完整的、可用于生产环境的Docker部署配置,包括PostgreSQL数据库、持久化文件存储、环境变量配置,以及可选的带SSL的Nginx反向代理。同时覆盖开发环境与生产环境的配置内容。

When to Use This Skill

适用场景

  • Spinning up a local Odoo development environment with Docker.
  • Deploying Odoo to a VPS or cloud server (AWS, DigitalOcean, etc.).
  • Troubleshooting Odoo container startup failures or database connection errors.
  • Adding a reverse proxy with SSL to an existing Odoo Docker setup.
  • 借助Docker快速搭建本地Odoo开发环境
  • 将Odoo部署到VPS或云服务器(AWS、DigitalOcean等)
  • 排查Odoo容器启动失败或数据库连接错误问题
  • 为现有Odoo Docker部署添加带SSL的反向代理

How It Works

操作流程

  1. Activate: Mention
    @odoo-docker-deployment
    and describe your deployment scenario.
  2. Generate: Receive a complete
    docker-compose.yml
    and
    odoo.conf
    ready to run.
  3. Debug: Describe your container error and get a diagnosis with a fix.
  1. 触发:提及
    @odoo-docker-deployment
    并描述你的部署场景
  2. 生成配置:获取可直接运行的完整
    docker-compose.yml
    odoo.conf
    文件
  3. 调试排错:描述容器错误信息,即可获得诊断结果与修复方案

Examples

示例

Example 1: Production docker-compose.yml

示例1:生产环境docker-compose.yml

yaml
undefined
yaml
undefined

Note: The top-level 'version' key is deprecated in Docker Compose v2+

Note: The top-level 'version' key is deprecated in Docker Compose v2+

and can be safely omitted. Remove it to avoid warnings.

and can be safely omitted. Remove it to avoid warnings.

services: db: image: postgres:15 restart: always environment: POSTGRES_DB: odoo POSTGRES_USER: odoo POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data networks: - odoo-net
odoo: image: odoo:17.0 restart: always depends_on: db: condition: service_healthy ports: - "8069:8069" - "8072:8072" # Longpolling for live chat / bus environment: HOST: db USER: odoo PASSWORD: ${POSTGRES_PASSWORD} volumes: - odoo-web-data:/var/lib/odoo - ./addons:/mnt/extra-addons # Custom modules - ./odoo.conf:/etc/odoo/odoo.conf networks: - odoo-net
volumes: postgres-data: odoo-web-data:
networks: odoo-net:
undefined
services: db: image: postgres:15 restart: always environment: POSTGRES_DB: odoo POSTGRES_USER: odoo POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres-data:/var/lib/postgresql/data networks: - odoo-net
odoo: image: odoo:17.0 restart: always depends_on: db: condition: service_healthy ports: - "8069:8069" - "8072:8072" # Longpolling for live chat / bus environment: HOST: db USER: odoo PASSWORD: ${POSTGRES_PASSWORD} volumes: - odoo-web-data:/var/lib/odoo - ./addons:/mnt/extra-addons # Custom modules - ./odoo.conf:/etc/odoo/odoo.conf networks: - odoo-net
volumes: postgres-data: odoo-web-data:
networks: odoo-net:
undefined

Example 2: odoo.conf

示例2:odoo.conf

ini
[options]
admin_passwd = ${ODOO_MASTER_PASSWORD}    ; set via env or .env file
db_host = db
db_port = 5432
db_user = odoo
db_password = ${POSTGRES_PASSWORD}        ; set via env or .env file

; addons_path inside the official Odoo Docker image (Debian-based)
addons_path = /mnt/extra-addons,/usr/lib/python3/dist-packages/odoo/addons

logfile = /var/log/odoo/odoo.log
log_level = warn

; Worker tuning for a 4-core / 8GB server:
workers = 9                ; (CPU cores × 2) + 1
max_cron_threads = 2
limit_memory_soft = 1610612736   ; 1.5 GB — soft kill threshold
limit_memory_hard = 2147483648   ; 2.0 GB — hard kill threshold
limit_time_cpu = 600
limit_time_real = 1200
limit_request = 8192
ini
[options]
admin_passwd = ${ODOO_MASTER_PASSWORD}    ; set via env or .env file
db_host = db
db_port = 5432
db_user = odoo
db_password = ${POSTGRES_PASSWORD}        ; set via env or .env file

; addons_path inside the official Odoo Docker image (Debian-based)
addons_path = /mnt/extra-addons,/usr/lib/python3/dist-packages/odoo/addons

logfile = /var/log/odoo/odoo.log
log_level = warn

; Worker tuning for a 4-core / 8GB server:
workers = 9                ; (CPU cores × 2) + 1
max_cron_threads = 2
limit_memory_soft = 1610612736   ; 1.5 GB — soft kill threshold
limit_memory_hard = 2147483648   ; 2.0 GB — hard kill threshold
limit_time_cpu = 600
limit_time_real = 1200
limit_request = 8192

Example 3: Common Commands

示例3:常用命令

bash
undefined
bash
undefined

Start all services in background

后台启动所有服务

docker compose up -d
docker compose up -d

Stream Odoo logs in real time

实时查看Odoo日志

docker compose logs -f odoo
docker compose logs -f odoo

Restart Odoo only (not DB — avoids data risk)

仅重启Odoo服务(不重启数据库,避免数据风险)

docker compose restart odoo
docker compose restart odoo

Stop all services

停止所有服务

docker compose down
docker compose down

Backup the database to a local SQL dump

将数据库备份为本地SQL文件

docker compose exec db pg_dump -U odoo odoo > backup_$(date +%Y%m%d).sql
docker compose exec db pg_dump -U odoo odoo > backup_$(date +%Y%m%d).sql

Update a custom module without restarting the server

无需重启服务器即可更新自定义模块

docker compose exec odoo odoo -d odoo --update my_module --stop-after-init
undefined
docker compose exec odoo odoo -d odoo --update my_module --stop-after-init
undefined

Best Practices

最佳实践

  • Do: Store all secrets in a
    .env
    file and reference them with
    ${VAR}
    — never hardcode passwords in
    docker-compose.yml
    .
  • Do: Use
    depends_on: condition: service_healthy
    with a PostgreSQL healthcheck to prevent Odoo starting before the DB is ready.
  • Do: Put Nginx in front of Odoo for SSL termination (Let's Encrypt / Certbot) — never expose Odoo directly on port 80/443.
  • Do: Set
    workers = (CPU cores × 2) + 1
    in
    odoo.conf
    workers = 0
    uses single-threaded mode and blocks all users.
  • Don't: Expose port 5432 (PostgreSQL) to the public internet — keep it on the internal Docker network only.
  • Don't: Use the
    latest
    or
    17
    Docker image tags in production — always pin to a specific patch-level tag (e.g.,
    odoo:17.0
    ).
  • Don't: Mount
    odoo.conf
    and rely on it for secrets in CI/CD — use Docker secrets or environment variables instead.
  • 推荐:将所有敏感信息存储在
    .env
    文件中,通过
    ${VAR}
    引用——切勿在
    docker-compose.yml
    中硬编码密码
  • 推荐:结合PostgreSQL健康检查使用
    depends_on: condition: service_healthy
    ,避免Odoo在数据库就绪前启动
  • 推荐:在Odoo前端部署Nginx用于SSL终止(使用Let's Encrypt / Certbot)——切勿直接将Odoo暴露在80/443端口
  • 推荐:在
    odoo.conf
    中设置
    workers = (CPU核心数 × 2) + 1
    ——
    workers = 0
    会启用单线程模式,导致所有用户操作阻塞
  • 禁止:将PostgreSQL的5432端口暴露到公网——仅保留在Docker内部网络中
  • 禁止:在生产环境中使用
    latest
    17
    这类Docker镜像标签——始终固定到具体的补丁版本标签(例如:
    odoo:17.0
  • 禁止:在CI/CD中挂载
    odoo.conf
    并依赖它存储敏感信息——应使用Docker Secrets或环境变量替代

Limitations

局限性

  • This skill covers self-hosted Docker deployments — Odoo.sh (cloud-managed hosting) has a completely different deployment model.
  • Horizontal scaling (multiple Odoo containers behind a load balancer) requires shared filestore (NFS or S3-compatible storage) not covered here.
  • Does not include an Nginx configuration template — consult the official Odoo Nginx docs for the full reverse proxy config.
  • The
    addons_path
    inside the Docker image may change with new base image versions — always verify after upgrading the Odoo image.
  • 本方案仅覆盖自托管Docker部署——Odoo.sh(云托管服务)采用完全不同的部署模型
  • 水平扩展(负载均衡器后的多个Odoo容器)需要共享文件存储(NFS或兼容S3的存储服务),本方案未包含相关配置
  • 未提供Nginx配置模板——如需完整反向代理配置,请参考Odoo官方Nginx文档
  • Docker镜像内部的
    addons_path
    可能会随基础镜像版本更新而变化——升级Odoo镜像后请务必验证该路径