odoo-docker-deployment
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOdoo 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
操作流程
- Activate: Mention and describe your deployment scenario.
@odoo-docker-deployment - Generate: Receive a complete and
docker-compose.ymlready to run.odoo.conf - Debug: Describe your container error and get a diagnosis with a fix.
- 触发:提及并描述你的部署场景
@odoo-docker-deployment - 生成配置:获取可直接运行的完整与
docker-compose.yml文件odoo.conf - 调试排错:描述容器错误信息,即可获得诊断结果与修复方案
Examples
示例
Example 1: Production docker-compose.yml
示例1:生产环境docker-compose.yml
yaml
undefinedyaml
undefinedNote: 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:
undefinedservices:
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:
undefinedExample 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 = 8192ini
[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 = 8192Example 3: Common Commands
示例3:常用命令
bash
undefinedbash
undefinedStart 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
undefineddocker compose exec odoo odoo -d odoo --update my_module --stop-after-init
undefinedBest Practices
最佳实践
- ✅ Do: Store all secrets in a file and reference them with
.env— never hardcode passwords in${VAR}.docker-compose.yml - ✅ Do: Use with a PostgreSQL healthcheck to prevent Odoo starting before the DB is ready.
depends_on: condition: service_healthy - ✅ Do: Put Nginx in front of Odoo for SSL termination (Let's Encrypt / Certbot) — never expose Odoo directly on port 80/443.
- ✅ Do: Set in
workers = (CPU cores × 2) + 1—odoo.confuses single-threaded mode and blocks all users.workers = 0 - ❌ Don't: Expose port 5432 (PostgreSQL) to the public internet — keep it on the internal Docker network only.
- ❌ Don't: Use the or
latestDocker image tags in production — always pin to a specific patch-level tag (e.g.,17).odoo:17.0 - ❌ Don't: Mount and rely on it for secrets in CI/CD — use Docker secrets or environment variables instead.
odoo.conf
- ✅ 推荐:将所有敏感信息存储在文件中,通过
.env引用——切勿在${VAR}中硬编码密码docker-compose.yml - ✅ 推荐:结合PostgreSQL健康检查使用,避免Odoo在数据库就绪前启动
depends_on: condition: service_healthy - ✅ 推荐:在Odoo前端部署Nginx用于SSL终止(使用Let's Encrypt / Certbot)——切勿直接将Odoo暴露在80/443端口
- ✅ 推荐:在中设置
odoo.conf——workers = (CPU核心数 × 2) + 1会启用单线程模式,导致所有用户操作阻塞workers = 0 - ❌ 禁止:将PostgreSQL的5432端口暴露到公网——仅保留在Docker内部网络中
- ❌ 禁止:在生产环境中使用或
latest这类Docker镜像标签——始终固定到具体的补丁版本标签(例如:17)odoo:17.0 - ❌ 禁止:在CI/CD中挂载并依赖它存储敏感信息——应使用Docker Secrets或环境变量替代
odoo.conf
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 inside the Docker image may change with new base image versions — always verify after upgrading the Odoo image.
addons_path
- 本方案仅覆盖自托管Docker部署——Odoo.sh(云托管服务)采用完全不同的部署模型
- 水平扩展(负载均衡器后的多个Odoo容器)需要共享文件存储(NFS或兼容S3的存储服务),本方案未包含相关配置
- 未提供Nginx配置模板——如需完整反向代理配置,请参考Odoo官方Nginx文档
- Docker镜像内部的可能会随基础镜像版本更新而变化——升级Odoo镜像后请务必验证该路径
addons_path