Untuk membuat arsitektur **High Availability (HA)** menggunakan Docker Compose secara murni pada satu *host* (untuk kebutuhan *development/staging* yang meniru produksi), kita perlu menduplikasi *service* Odoo dan menggunakan sistem replikasi untuk PostgreSQL.

Di bawah ini adalah rancangan Docker Compose yang menggunakan:

1. **Load Balancer (Nginx):** Mengatur beban lalu lintas ke beberapa *instance* Odoo.
2. **Odoo Cluster:** Dua *instance* Odoo (Odoo 1 dan Odoo 2) yang berbagi *storage* untuk data filestore.
3. **PostgreSQL HA (Bitnami Pgpool-II + Replication):** Menggunakan *image* Bitnami untuk membuat PostgreSQL Master-Slave dengan Pgpool-II sebagai *load balancer* khusus database (mengatur *read/write splitting*).

### Arsitektur Folder

Sebelum menjalankan Docker Compose, buat struktur folder berikut untuk menyimpan data persistent:

```text
mini-ha-odoo/
├── docker-compose.yml
├── nginx.conf
├── odoo_data/
└── odoo_addons/

```

---

### 1. Konfigurasi Nginx (`nginx.conf`)

Buat file `nginx.conf` untuk membagi beban kerja ke dua kontainer Odoo.

```nginx
events { worker_connections 1024; }

http {
    upstream odoo_instances {
        # Mengarah ke nama service di docker-compose
        server odoo_app_1:8069;
        server odoo_app_2:8069;
    }

    upstream odoo_chat {
        server odoo_app_1:8072;
        server odoo_app_2:8072;
    }

    server {
        listen 80;

        # Proxy untuk longpolling (Chat/Live Notification)
        location /longpolling {
            proxy_pass http://odoo_chat;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect off;
            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 $scheme;
        }

        # Proxy untuk Traffic Utama Odoo
        location / {
            proxy_pass http://odoo_instances;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_redirect off;
            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 $scheme;
            
            # Sangat penting untuk Odoo HA: aktifkan session stickiness jika diperlukan, 
            # atau pastikan filestore tersinkronisasi dengan benar.
        }

        # Common optimization
        client_max_body_size 128M;
        proxy_read_timeout 30000s;
        proxy_connect_timeout 3000s;
        proxy_send_timeout 3000s;
    }
}

```

---

### 2. File Docker Compose (`docker-compose.yml`)

```yaml
version: '3.8'

services:
  # -------------------------------------------------------------------
  # DATABASE LAYER (HA Postgres via Bitnami Primary/Standby + Pgpool)
  # -------------------------------------------------------------------
  pg-primary:
    image: bitnami/postgresql:15
    environment:
      - POSTGRESQL_POSTGRES_PASSWORD=primary_master_pass
      - POSTGRESQL_USERNAME=odoo
      - POSTGRESQL_PASSWORD=odoo_secure_pass
      - POSTGRESQL_DATABASE=odoo_db
      - POSTGRESQL_REPLICATION_MODE=primary
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=repl_password
    volumes:
      - pg_primary_data:/bitnami/postgresql

  pg-standby:
    image: bitnami/postgresql:15
    depends_on:
      - pg-primary
    environment:
      - POSTGRESQL_POSTGRES_PASSWORD=primary_master_pass
      - POSTGRESQL_MASTER_HOST=pg-primary
      - POSTGRESQL_MASTER_PORT_NUMBER=5432
      - POSTGRESQL_REPLICATION_MODE=standby
      - POSTGRESQL_REPLICATION_USER=repl_user
      - POSTGRESQL_REPLICATION_PASSWORD=repl_password
    volumes:
      - pg_standby_data:/bitnami/postgresql

  pgpool:
    image: bitnami/pgpool:4
    ports:
      - "5432:5432"
    depends_on:
      - pg-primary
      - pg-standby
    environment:
      - PGPOOL_BACKEND_NODES=0:pg-primary:5432,1:pg-standby:5432
      - PGPOOL_SR_CHECK_USER=odoo
      - PGPOOL_SR_CHECK_PASSWORD=odoo_secure_pass
      - PGPOOL_SR_CHECK_DATABASE=odoo_db
      - PGPOOL_ENABLE_LDAP=no
      - PGPOOL_POSTGRES_USERNAME=postgres
      - PGPOOL_POSTGRES_PASSWORD=primary_master_pass
      - PGPOOL_ADMIN_USERNAME=admin
      - PGPOOL_ADMIN_PASSWORD=admin_pass

  # -------------------------------------------------------------------
  # APPLICATION LAYER (Odoo Cluster)
  # -------------------------------------------------------------------
  odoo_app_1:
    image: odoo:16.0
    depends_on:
      - pgpool
    environment:
      - HOST=pgpool
      - PORT=5432
      - USER=odoo
      - PASSWORD=odoo_secure_pass
    volumes:
      - odoo_shared_data:/var/lib/odoo
      - ./odoo_addons:/mnt/extra-addons

  odoo_app_2:
    image: odoo:16.0
    depends_on:
      - pgpool
    environment:
      - HOST=pgpool
      - PORT=5432
      - USER=odoo
      - PASSWORD=odoo_secure_pass
    volumes:
      - odoo_shared_data:/var/lib/odoo # Berbagi filestore agar session & dokumen sinkron
      - ./odoo_addons:/mnt/extra-addons

  # -------------------------------------------------------------------
  # LOAD BALANCER LAYER (Nginx)
  # -------------------------------------------------------------------
  nginx_lb:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - odoo_app_1
      - odoo_app_2

volumes:
  pg_primary_data:
  pg_standby_data:
  odoo_shared_data: # Diperlukan agar filestore Odoo 1 dan Odoo 2 sama

```

---

### Catatan Penting untuk Skala Produksi Nyata (Multi-Node):

Meskipun arsitektur di atas memberikan simulasi HA yang sangat baik di dalam satu Docker Compose, untuk lingkungan produksi yang sesungguhnya (multi-server), Anda perlu memperhatikan beberapa poin ini:

1. **Shared Filestore (`odoo_shared_data`):** Pada compose di atas, kita menggunakan Docker Volume lokal yang dibagikan antar kontainer karena mereka berada di satu mesin yang sama. Jika Anda memindahkan kontainer ke server yang berbeda (misal menggunakan Swarm atau Kubernetes), Anda harus mengganti volume ini dengan **Network File System (NFS)** atau cloud storage seperti **AWS S3** (menggunakan modul tambahan Odoo).
2. **Session Loss:** Secara *default*, Odoo menyimpan sesi pengguna di filestore. Menggunakan shared volume di atas sudah menyelesaikan masalah ini. Namun, untuk performa HA yang lebih instan, Anda disarankan menambahkan **Redis** sebagai *session store manager*.
3. **Database Failover:** Pgpool-II mengelola *load balancing* query (Baca ke Standby, Tulis ke Primary). Jika `pg-primary` mati, Pgpool perlu dikonfigurasi lebih lanjut dengan *failover script* untuk mengangkat `pg-standby` menjadi primary yang baru.