Thực tế hay gặp: bạn phải bảo trì Odoo 17 cho một khách cũ, đồng thời phát triển dự án mới trên Odoo 19 — cả hai trên cùng một máy chủ. Hoặc đơn giản là muốn một instance "chạy thật" và một instance "thử nghiệm" tách biệt. Chuyện này hoàn toàn làm được: Odoo không "độc chiếm" máy, chỉ cần mỗi bản dùng tài nguyên riêng. Sau bài nhiều database, đây là bước tách xa hơn — nhiều tiến trình Odoo.

Phân biệt hai khái niệm

  • Nhiều database, một Odoo: một tiến trình phục vụ nhiều db (bài trước). Chỉ hợp khi các db dùng cùng phiên bản Odoo và cùng bộ module.
  • Nhiều instance Odoo: nhiều tiến trình độc lập, có thể khác phiên bản (17 vs 19), khác bộ addons. Đây là nội dung bài này.

Khi cần chạy hai phiên bản Odoo khác nhau, bắt buộc phải là nhiều instance.

Ba thứ phải khác nhau

Mỗi instance là một tiến trình riêng, và ba thứ tuyệt đối không được đụng nhau:

Cấu hình chạy nhiều phiên bản Odoo song song mỗi bản một bộ cổng riêng: bản A Odoo 19 cho database blog19 dùng file odoo19.conf với http_port 8069, gevent_port 8072, db_name blog19, addons_path opt odoo19 addons, data_dir opt odoo19 data; bản B instance khác cho database shop19 dùng file odoo-shop.conf với http_port 8070 khác, gevent_port 8073 khác, db_name shop19, addons_path opt shop addons, data_dir opt shop data khác; chạy mỗi bản với file cấu hình riêng bằng odoo -c odoo19.conf nghe cổng 8069 và odoo -c odoo-shop.conf nghe cổng 8070; ba thứ bắt buộc khác nhau giữa các bản là http_port cộng gevent_port để tránh đụng cổng, data_dir để tránh đè session và filestore, và db_name hoặc db-filter để tránh nhầm database

Hình 1: Hai file cấu hình cho hai instance. Ba thứ bắt buộc khác: (1) http_port + gevent_port — hai instance nghe cùng cổng sẽ đụng nhau; (2) data_dir — nơi chứa session và filestore, dùng chung là ghi đè lên nhau; (3) db_name/db-filter — để mỗi bản đúng database của nó.

Chạy thật — hai instance cùng lúc

Tôi khởi chạy một instance Odoo thứ hai (trỏ shop19, cổng 8070) bên cạnh instance chính (blog19, cổng 8069), và đây là bằng chứng thật:

Bằng chứng thật hai phiên bản Odoo chạy cùng lúc: lệnh ps liệt kê tiến trình bin odoo cho thấy tiến trình PID 1 là python3 odoo với db_host odoo19-db phục vụ cổng 8069 database blog19, và tiến trình PID 702 là python3 odoo với tham số -d shop19 http-port bằng 8070 gevent-port bằng 8073 db-filter mũ shop19 đô la phục vụ cổng 8070 database shop19; cả hai đều trả lời HTTP mỗi cổng một database, curl tới cổng 8069 web login trả về mã 200 là bản A và curl tới cổng 8070 web login trả về mã 200 là bản B; kết luận hai tiến trình master độc lập hai PID khác nhau là 1 và 702, hai bộ cổng, hai database chạy hoàn toàn tách biệt

Hình 2: Bằng chứng thật. ps cho thấy hai tiến trình master độc lập — PID 1 (cổng 8069, blog19) và PID 702 (cổng 8070, shop19, với --http-port=8070 --gevent-port=8073 --db-filter=^shop19$). Cả hai cổng đều trả HTTP 200. Hai bản chạy song song, hoàn toàn tách biệt.

nginx đứng trước: mỗi tên miền một instance

Người dùng không gõ cổng. Bạn đặt nginx phía trước, mỗi tên miền proxy vào một instance:

server {
    server_name blog.congty.vn;
    location / { proxy_pass http://127.0.0.1:8069; }
}
server {
    server_name shop.congty.vn;
    location / { proxy_pass http://127.0.0.1:8070; }
}

Cần cấu hình proxy đúng (WebSocket cho cổng gevent, header X-Forwarded-*) — đây cũng đúng mô hình mà blog này đang chạy trên máy chủ thật.

Cách gọn hơn: mỗi instance một container

Với Docker, thay vì tự quản cổng và data_dir, bạn cho mỗi instance một container — cách ly hoàn toàn:

services:
  odoo17:
    image: odoo:17
    ports: ["8069:8069"]
    volumes: ["./o17-data:/var/lib/odoo", "./o17-addons:/mnt/extra-addons"]
  odoo19:
    image: odoo:19
    ports: ["8070:8069"]      # ánh xạ ra cổng host khác
    volumes: ["./o19-data:/var/lib/odoo", "./o19-addons:/mnt/extra-addons"]

Mỗi container có phiên bản, addons, và data_dir riêng — không lo đụng nhau. Đây là lý do Docker rất hợp để chạy nhiều phiên bản Odoo.

Những cái bẫy

  • Quên đổi data_dir: hai instance ghi đè session/filestore của nhau — lỗi lạ, ảnh mất.
  • Quên gevent_port: cổng longpolling/websocket mặc định 8072 cũng phải khác giữa các bản.
  • Chung PostgreSQL: các instance có thể dùng chung một PostgreSQL (khác database), hoặc mỗi bản một server — tuỳ tải. Dùng chung thì nhớ đủ db_maxconn.

Nhớ ba ý

  1. Nhiều database ≠ nhiều instance: khác phiên bản Odoo (17 vs 19) thì bắt buộc nhiều tiến trình riêng.
  2. Ba thứ phải khác nhau giữa các bản: http_port + gevent_port, data_dir, và database — tôi đã chứng minh 2 bản chạy thật trên cổng 8069/8070.
  3. Đặt nginx phía trước để map tên miền → instance; hoặc gọn hơn, mỗi instance một container Docker để cách ly hoàn toàn.

Đã biết chạy nhiều instance, ta quay lại làm cho môi trường dev thật tiện. Phần sau dựng một Docker Compose cho dev với addons mount nóng — sửa code trên máy, container thấy ngay.