Linkmetax
← 返回博客
·Linkmetax 运维团队·13 分钟阅读

如何将核心开源 ERP 系统平滑迁移至 Ubuntu 生产环境?避开这 10 个权限与数据卷大坑

Odoo / Dolibarr / ERPNext 等开源 ERP 迁移至 Ubuntu Docker 生产环境实战指南。权限隔离、数据卷持久化、数据库选型、备份恢复 10 大坑全解析。

ERPUbuntuDocker数据库迁移

「我们公司用 Odoo 跑了 5 年,原来部署在 Windows Server 上。最近想迁到 Ubuntu + Docker,没想到部署完员工登录看不到自己的数据、附件全丢、定时任务不执行……」

这是开源 ERP 系统迁移最常见的灾难现场。Odoo / ERPNext / Dolibarr 这些 ERP 部署看似简单,生产环境配置不当 = 数据丢、性能崩、备份失效。这篇把 10 个最常踩的坑讲透。


一、迁移前必做的 5 件事

1. 完整盘点

  • 数据库类型 + 版本(PostgreSQL? MySQL? MariaDB? 版本?)
  • 文件存储路径(附件、报表、自定义模块)
  • 定时任务 / cron
  • 第三方集成(短信网关、邮件、支付)
  • 自定义代码 / 插件

2. 备份完整数据

# 数据库
pg_dump -Fc -d production_db -f backup_$(date +%Y%m%d).dump

# 文件目录
tar -czf files_$(date +%Y%m%d).tar.gz /var/lib/odoo/

# 配置
cp /etc/odoo/odoo.conf ./odoo.conf.bak

3. 准备测试环境

  • 测试环境完整跑通迁移流程
  • 不要直接在生产环境试

4. 用户培训 + 业务暂停窗口

  • 通知所有用户停业 X 小时
  • 关键流程暂停(订单、发票)

5. 回滚预案

  • 万一失败如何回到旧环境
  • 数据库快照保留至少 30 天

二、10 个最常见的坑

🚨 坑 1:Docker volume 权限不对

症状:容器启动后无法写入文件,附件上传失败

原因:容器内用户 ID(如 odoo 是 101)和宿主机目录 owner 不一致

解法

# 宿主机
sudo chown -R 101:101 /opt/odoo/data
sudo chmod -R 755 /opt/odoo/data

# 或在 docker-compose 里指定 user
services:
  odoo:
    user: "101:101"

🚨 坑 2:数据库连接名 / 端口错误

症状:容器启动报错 connection refusedunknown host

原因:迁移后服务名变了(如 localhost → postgres 容器名)

解法

# odoo.conf
db_host = postgres   # 不是 localhost
db_port = 5432
db_user = odoo
db_password = ...

🚨 坑 3:数据库字符集不一致

症状:迁移完中文乱码、特殊字符丢失

原因:旧库是 LATIN1,新库用了 UTF8

解法

-- 创建新库时必须指定
CREATE DATABASE odoo_production
  WITH ENCODING 'UTF8'
  LC_COLLATE 'en_US.utf8'
  LC_CTYPE 'en_US.utf8'
  TEMPLATE template0;

恢复时:

pg_restore -d odoo_production --no-owner --no-privileges backup.dump

🚨 坑 4:文件路径硬编码

症状:导出的报表 / 模板找不到

原因:模块里写死了 C:\odoo\addons\.../var/lib/odoo/

解法

# 全局搜索硬编码路径
grep -r "C:\\\\" /path/to/addons/
grep -r "/var/lib/odoo" /path/to/addons/

# 替换为环境变量或相对路径

🚨 坑 5:cron 任务时区不对

症状:每天 9 点的报表 5 点就发了 / 17 点才发

原因:Docker 默认 UTC,宿主机是 UTC+8

解法

services:
  odoo:
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - /etc/localtime:/etc/localtime:ro

数据库也要:

services:
  postgres:
    environment:
      - PGTZ=Asia/Shanghai
      - TZ=Asia/Shanghai

🚨 坑 6:附件 / Filestore 没迁移

症状:登录后所有上传的图片、合同、二维码都丢了

原因:Odoo 默认把附件存在 data_dir/filestore/不在数据库里

解法

# 必须同时迁移:
# 1. 数据库
# 2. /var/lib/odoo/filestore/<dbname>/
# 3. /var/lib/odoo/sessions/

rsync -avz old-server:/var/lib/odoo/ /opt/odoo/data/

🚨 坑 7:自定义模块依赖缺失

症状:升级后某些功能消失 / 报错 module not found

原因:自定义模块用了系统 Python 包,Docker 镜像没装

解法

# 自定义 Dockerfile
FROM odoo:17
USER root
RUN pip3 install --no-cache-dir \
    requests \
    openpyxl \
    qrcode \
    your-custom-deps
USER odoo

🚨 坑 8:内存限制太小导致 worker 崩

症状:长报表 / 大批量导出时 worker 自动重启

原因:Odoo 默认 limit_memory_soft / hard 太低

解法

# odoo.conf
workers = 4
limit_memory_soft = 2147483648    # 2GB
limit_memory_hard = 2684354560    # 2.5GB
limit_time_cpu = 600
limit_time_real = 1200

🚨 坑 9:反代缺 X-Forwarded-Proto

症状:登录页 HTTPS,登录后变 HTTP、各种功能失效

原因:Nginx 反代没传协议头

解法

location / {
  proxy_pass http://odoo:8069;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto https;   # ⭐ 关键
}

Odoo 配置:

proxy_mode = True

🚨 坑 10:备份脚本备的是空目录

症状:迁移 3 个月后磁盘满了想恢复,发现备份只有 0 字节

原因:备份脚本备的是 /opt/data 但容器把数据写到了 /var/lib/odoo

解法:备份脚本必须从容器内部或正确的挂载点执行:

#!/bin/bash
# backup.sh
BACKUP_DIR="/opt/backups/odoo"
DATE=$(date +%Y%m%d_%H%M%S)

# 数据库
docker exec postgres pg_dump -Fc -U odoo production > $BACKUP_DIR/db_$DATE.dump

# 附件
docker run --rm -v odoo_data:/data -v $BACKUP_DIR:/backup alpine \
    tar -czf /backup/files_$DATE.tar.gz -C /data .

# 验证大小
find $BACKUP_DIR -name "*_$DATE.*" -size 0 && echo "⚠️ 备份为空文件!"

三、标准 docker-compose.yml(生产级)

version: "3.8"

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: odoo
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
      TZ: Asia/Shanghai
      PGTZ: Asia/Shanghai
    volumes:
      - postgres-data:/var/lib/postgresql/data
    secrets:
      - db_password
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U odoo"]
      interval: 10s

  odoo:
    image: odoo:17
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8069:8069"
    environment:
      HOST: postgres
      USER: odoo
      PASSWORD_FILE: /run/secrets/db_password
      TZ: Asia/Shanghai
    volumes:
      - odoo-data:/var/lib/odoo
      - ./addons:/mnt/extra-addons
      - ./config/odoo.conf:/etc/odoo/odoo.conf:ro
    secrets:
      - db_password
    restart: unless-stopped
    user: "101:101"
    deploy:
      resources:
        limits:
          memory: 4G

  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - odoo
    restart: unless-stopped

volumes:
  postgres-data:
  odoo-data:

secrets:
  db_password:
    file: ./secrets/db_password.txt

四、迁移完成检查清单

  • [ ] 所有用户能登录
  • [ ] 历史数据完整(订单数、客户数对得上)
  • [ ] 附件 / 图片可见
  • [ ] 报表能生成 PDF
  • [ ] 邮件能发送
  • [ ] 定时任务执行
  • [ ] 备份脚本测试恢复成功
  • [ ] HTTPS 证书有效
  • [ ] 监控告警接通
  • [ ] 性能测试通过(10 并发 / 1 分钟)

五、性能调优

PostgreSQL 调优

shared_buffers = 4GB                 # 内存 25%
effective_cache_size = 12GB          # 内存 75%
maintenance_work_mem = 1GB
work_mem = 64MB
max_connections = 200
random_page_cost = 1.1               # SSD

Odoo 调优

workers = (CPU 核数 × 2 + 1)
max_cron_threads = 2
limit_memory_hard = 内存 / workers

写在最后

迁移开源 ERP 不是 docker-compose up 就完事。我们整理了一份《标准 ERP 系统生产环境一键式 Docker-Compose 部署脚本(带安全加固)》:

  • 支持 Odoo / ERPNext / Dolibarr / iDempiere
  • 含 SSL / 反代 / 备份 / 监控完整方案
  • 含数据迁移迁移脚本(旧库 → 新库)
  • 含 10 大坑预防机制

📥 扫码加助手免费获取联系销售取脚本 →

或了解我们的 企业 IT 运维方案,含 ERP 部署 / 迁移 / 维保一站式服务。

📥PDF 白皮书

下载《如何将核心开源 ERP 系统平滑迁移至 Ubuntu 生产环境?避开这 10 个权限与数据卷大坑》PDF 完整版

留下邮箱,立刻获取本文 PDF + 后续企业 AI / 软件采购干货

  • ✓ 含全部图表、检查清单、参考链接
  • ✓ 可用于内部分享 / 招投标资料引用
  • ✓ 后续更新自动推送 · 不发垃圾邮件

提交即表示同意我们处理你的邮箱用于发送资料 · 不会用于第三方营销

想把这些经验落到你的企业?

1 个工作日内出方案 · 可签 NDA · 支持招投标

联系解决方案架构师 →