# Docker: setup, coding, dan migrasi laptop

Snippet ini mengikuti repo odoo-containers: Odoo 19.0, PostgreSQL 15, project tutorial, dan terminal Bash. Buka langkah yang dibutuhkan lalu tekan Salin; tidak perlu memutar animasi.

Project baru: 01–04. Coding: 05–06. Migrasi: 07 di laptop lama, lalu 01–02 dan 08 di laptop baru.

## 01. Cek alat di laptop baru

Gunakan terminal Bash di Linux / WSL2, atau Bash di macOS. Instal Git, OpenSSL, serta Docker Engine + Compose plugin atau Docker Desktop. Docker harus sedang berjalan. Semua langkah berikut memakai project tutorial dan Odoo 19.0; migrasi harus memakai versi Odoo yang sama dengan laptop lama.

### Terminal · cek prasyarat

```bash
git --version
openssl version
docker version
docker compose version
docker info
```

## 02. Ambil repo dan source Enterprise

Untuk checkout baru. Masukkan URL repo odoo-containers milikmu saat diminta. Akses GitHub Enterprise Odoo diperlukan. Layout Enterprise di bawah mengikuti bind mount dan Dockerfile repo ini. Setelah cd, jalankan semua snippet berikut dari root odoo-containers. Untuk migrasi, gunakan commit repo, addons, dan Enterprise yang sama dengan laptop lama.

### Terminal · checkout baru

```bash
read -r -p "URL Git repo odoo-containers: " tutorial_repo_url &&
git clone --recurse-submodules "$tutorial_repo_url" odoo-containers &&
cd odoo-containers &&
mkdir -p projects/tutorial/addons src/odoo-19e/odoo &&
git clone --branch 19.0 --single-branch \
  git@github.com:odoo/enterprise.git src/odoo-19e/odoo/addons &&
test -d src/odoo-19e/odoo/addons/web_enterprise
```

## 03. Buat konfigurasi untuk project baru

Hanya untuk instalasi baru: snippet ini menulis projects/tutorial/.env dan config/odoo.conf. Untuk migrasi, pulihkan file konfigurasi lama dari arsip pada langkah 08. Password PostgreSQL dibuat acak; master password di odoo.conf berbeda dari password database dan login Odoo. Simpan master password di password manager. Port 5432, 8069, 8072, dan 5678 harus tersedia.

### Terminal · tulis .env dan odoo.conf

```bash
(
  set -e
  umask 077
  mkdir -p projects/tutorial/addons config
  tutorial_db_password="$(openssl rand -hex 24)"
  tutorial_master_password="$(openssl rand -hex 24)"
  cat > projects/tutorial/.env <<EOF
COMPOSE_PROJECT_NAME=tutorial
PROJECT_NAME=tutorial
PROJECT_DIR=./projects/tutorial
ODOO_VERSION=19.0
ENTERPRISE_SRC=./src/odoo-19e
REGISTRY_HOST=localhost
IMAGE_NAME=odoo-enterprise-dev
ODOO_PORT=8069
ODOO_LONGPOLLING_PORT=8072
DEBUG_PORT=5678
DB_HOST=db
DB_PORT=5432
DB_USER=odoo
DB_PASSWORD=$tutorial_db_password
COMPOSE_PROFILES=local-db
DEBUG_MODE=off
EOF
  cat > config/odoo.conf <<EOF
[options]
admin_passwd = $tutorial_master_password
addons_path = /mnt/enterprise,/mnt/extra-addons,/usr/lib/python3/dist-packages/odoo/addons
data_dir = /var/lib/odoo
workers = 0
EOF
  # Container harus bisa membaca config meskipun UID-nya berbeda.
  chmod 755 config
  chmod 644 config/odoo.conf
)
```

## 04. Build, jalankan, lalu buat database

Build memakai ENTERPRISE_SRC secara eksplisit karena Compose repo ini hanya meneruskan ODOO_VERSION sebagai build arg. Setelah kedua service berjalan, buka http://localhost:8069/web/database/manager. Untuk instalasi baru, buat database tutorial memakai admin_passwd dari config/odoo.conf. Untuk migrasi, jangan buat database kosong; lanjutkan restore langkah 08.

### Terminal · root odoo-containers

```bash
docker compose --env-file projects/tutorial/.env config --quiet &&
docker compose --env-file projects/tutorial/.env build \
  --build-arg ENTERPRISE_SRC=src/odoo-19e odoo &&
bash ./switch.sh tutorial &&
docker compose ps
```

### Terminal · lihat log terakhir

```bash
docker compose logs --tail=100 odoo
# Tambahkan -f untuk mengikuti log; Ctrl+C berhenti mengikuti log.
```

## 05. Kembali coding: scaffold, instal, upgrade, shell

Jalankan hanya blok yang dibutuhkan, dari root repo dengan project tutorial aktif. Scaffold hanya sekali jika folder estate belum ada. Instal/upgrade menghentikan web sementara untuk menghindari dua proses menulis schema yang sama. Jika perintah gagal, baca log lalu jalankan docker compose up -d odoo setelah masalah selesai.

### Scaffold · hanya sebelum membuat module

```bash
docker compose run --rm -e DEBUG_MODE=off odoo \
  odoo scaffold estate /mnt/extra-addons
```

### Instal module estate

```bash
docker compose stop odoo &&
docker compose run --rm -e DEBUG_MODE=off odoo \
  -d tutorial -i estate --stop-after-init --no-http &&
docker compose up -d odoo
```

### Upgrade setelah mengubah field / XML / CSV

```bash
docker compose stop odoo &&
docker compose run --rm -e DEBUG_MODE=off odoo \
  -d tutorial -u estate --stop-after-init --no-http &&
docker compose up -d odoo
```

### Muat ulang Python

```bash
docker compose restart odoo
```

### Buka shell Odoo

```bash
docker compose run --rm -e DEBUG_MODE=off odoo odoo shell -d tutorial
```

### Python · jalankan di shell Odoo, bukan terminal Bash

```python
env["estate.property"].search([("state", "=", "new")]).mapped("name")
# Perubahan shell di-rollback saat keluar kecuali kamu memanggil env.cr.commit().
```

## 06. Pasang breakpoint di VS Code

Buka root odoo-containers sebagai workspace VS Code, instal ekstensi Python Debugger, lalu simpan JSON ini sebagai .vscode/launch.json (gabungkan configurations jika file sudah ada). Ubah DEBUG_MODE=on di projects/tutorial/.env dan jalankan bash ./switch.sh tutorial. Pilih Attach Odoo lalu F5. Port 5678 di sini sesuai contoh .env.

### .vscode/launch.json

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach Odoo",
      "type": "debugpy",
      "request": "attach",
      "connect": { "host": "localhost", "port": 5678 },
      "pathMappings": [
        {
          "localRoot": "${workspaceFolder}/projects/tutorial/addons",
          "remoteRoot": "/mnt/extra-addons"
        },
        {
          "localRoot": "${workspaceFolder}/src/odoo-19e/odoo/addons",
          "remoteRoot": "/mnt/enterprise"
        }
      ],
      "justMyCode": false
    }
  ]
}
```

## 07. Laptop lama: backup database, filestore, dan kode

Khusus project tutorial dengan database tutorial dan Postgres local-db yang sedang berjalan. Aktifkan project itu dulu. ZIP Odoo menyertakan database dan filestore; arsip kedua menyimpan addons (termasuk perubahan belum di-commit) serta konfigurasi. Web dihentikan sementara agar backup konsisten. Folder backup berisi data dan password: pindahkan secara privat. Jika ADDONS_DIR menunjuk folder lain, sertakan folder tersebut secara terpisah. Jangan gunakan docker compose down -v untuk migrasi.

### Terminal · laptop lama, root repo

```bash
(
  set -e
  umask 077
  migration_dir="$PWD/backups/$(date +%Y%m%d-%H%M%S)"
  mkdir -p "$migration_dir"
  docker compose stop odoo
  trap 'docker compose start odoo' EXIT
  docker compose run --rm --no-deps \
    -v "$migration_dir:/backup" odoo bash -c '
      odoo db -c /etc/odoo/odoo.conf \
        --db_host "$HOST" --db_port "$PORT" \
        --db_user "$USER" --db_password "$PASSWORD" \
        dump tutorial /backup/tutorial.zip
    '
  tar -czf "$migration_dir/project-files.tgz" \
    projects/tutorial config docker-compose.yml \
    Dockerfile.bundled entrypoint.sh switch.sh
  git rev-parse HEAD > "$migration_dir/stack-commit.txt"
  git -C src/odoo-19e/odoo/addons rev-parse HEAD \
    > "$migration_dir/enterprise-commit.txt"
  ls -lh "$migration_dir"
)
```

## 08. Laptop baru: pulihkan dan lanjutkan pekerjaan

Siapkan tools dan checkout source yang sama lewat langkah 01–02. Salin seluruh isi folder backup bertanggal dari laptop lama ke backups/migration/ di root repo baru. Jalankan di checkout baru: ekstraksi menimpa konfigurasi contoh dengan konfigurasi lama. Source Enterprise harus sesuai commit di enterprise-commit.txt; jika ada modifikasi Enterprise lokal di laptop lama, pindahkan juga. Restore memakai nama tutorial_restored sehingga tidak menimpa database tutorial. --neutralize menonaktifkan aktivitas otomatis untuk salinan development. Ini migrasi laptop pada versi Odoo yang sama, bukan upgrade database lintas versi.

### Terminal · pulihkan file dan bangun image

```bash
(
  set -e
  test -s backups/migration/tutorial.zip
  test -s backups/migration/project-files.tgz
  git switch -c laptop-migration "$(cat backups/migration/stack-commit.txt)"
  git -C src/odoo-19e/odoo/addons checkout \
    "$(cat backups/migration/enterprise-commit.txt)"
  tar -xzf backups/migration/project-files.tgz
  docker compose --env-file projects/tutorial/.env build \
    --build-arg ENTERPRISE_SRC=src/odoo-19e odoo
  bash ./switch.sh tutorial
)
```

### Terminal · restore database dan filestore

```bash
(
  set -e
  docker compose stop odoo
  trap 'docker compose start odoo' EXIT
  docker compose run --rm --no-deps \
    -v "$PWD/backups/migration:/backup:ro" odoo bash -c '
      odoo db -c /etc/odoo/odoo.conf \
        --db_host "$HOST" --db_port "$PORT" \
        --db_user "$USER" --db_password "$PASSWORD" \
        load tutorial_restored /backup/tutorial.zip --neutralize
    '
)
```

### Terminal · cek setelah restore

```bash
docker compose ps
docker compose logs --tail=100 odoo
# Buka http://localhost:8069/web?db=tutorial_restored
# Login memakai user database lama. Cek module custom dan buka satu lampiran.
# Untuk coding di database ini, ganti -d tutorial menjadi -d tutorial_restored.
```

## 09. Opsional: ubah view XML tanpa `-u`
Simpan sebagai `docker-compose.override.yml` di root repo. Berlaku untuk semua project; hapus jika tidak dipakai.

```yaml
# Opsional: Odoo membaca view XML langsung dari file, jadi perubahan
# arch view terlihat tanpa -u. Berlaku untuk SEMUA project di repo ini.
# Hapus file ini jika tidak dipakai lagi.
services:
  odoo:
    command: ["odoo", "--dev", "xml"]
```

```bash
docker compose up -d odoo
echo docker-compose.override.yml >> .git/info/exclude
```

## Jalur B: tanpa source Enterprise (pull image)
Memakai `docker-compose.simple.yml`. Tidak memakai `switch.sh`; setiap perintah compose butuh `-f` dan `--env-file`. Hanya port 8069, tanpa debugpy. Postgres harus ada di host port 5432 karena file ini tidak meneruskan `DB_PORT`.

### B1. Folder dan login registry
```bash
mkdir -p projects/tutorial/addons
docker login registry.example.com
```

### B2. Postgres di port 5432
```bash
ss -ltn | grep -q ':5432 ' && echo "5432 sudah dipakai: pakai opsi 2" || echo "5432 kosong: pakai opsi 1"
# Opsi 1: port kosong
docker run -d --name pg-tutorial --restart unless-stopped \
  -e POSTGRES_USER=odoo -e POSTGRES_PASSWORD=odoo \
  -p 5432:5432 -v pg-tutorial-data:/var/lib/postgresql/data \
  postgres:15
# Opsi 2: Postgres host yang sudah ada (izinkan juga 172.16.0.0/12 di pg_hba.conf, listen_addresses = '*')
sudo -u postgres psql -c "CREATE ROLE odoo LOGIN CREATEDB PASSWORD 'odoo';"
```

### B3. `projects/tutorial/.env.pull`
```ini
# Jalur B: pull image jadi dari registry tim (tanpa source Enterprise).
# Simpan sebagai projects/tutorial/.env.pull di repo odoo-containers.
# Pakai dengan: docker compose -f docker-compose.simple.yml --env-file projects/tutorial/.env.pull ...

COMPOSE_PROJECT_NAME=tutorial
PROJECT_NAME=tutorial
PROJECT_DIR=./projects/tutorial

# Ganti REGISTRY_HOST dan IMAGE_NAME sesuai info dari tim
REGISTRY_HOST=registry.example.com
IMAGE_NAME=odoo-enterprise-dev
ODOO_VERSION=19.0

ODOO_PORT=8069

# Postgres di mesin host. docker-compose.simple.yml tidak meneruskan DB_PORT,
# jadi Postgres harus mendengarkan di port 5432.
DB_HOST=host.docker.internal
DB_USER=odoo
DB_PASSWORD=odoo
```

### B4. Jalankan
```bash
alias dcs='docker compose -f docker-compose.simple.yml --env-file projects/tutorial/.env.pull'
dcs pull && dcs up -d && dcs ps
dcs logs --tail=100 odoo
```

### B5. Instal / upgrade module
```bash
dcs stop odoo &&
dcs run --rm odoo -d tutorial -u estate --stop-after-init --no-http &&
dcs up -d odoo
```

## Troubleshooting
Mulai dengan `odoo-doctor.sh` (ada di `files/` repo tutorial ini; hanya membaca, tidak menjalankan up/down/build):

```bash
bash odoo-doctor.sh                                                  # Jalur A
bash odoo-doctor.sh --simple --env-file projects/tutorial/.env.pull   # Jalur B
```

| Gejala | Cek | Solusi |
|---|---|---|
| Odoo restart terus / `wait-for-psql` timeout | `docker compose ps -a`, `docker compose logs --tail=50 odoo` | Jalur A: `COMPOSE_PROFILES=local-db`. Jalur B: Postgres di port 5432 |
| `port is already allocated` | `docker ps --format 'table {{.Names}}\t{{.Ports}}'` | `docker compose down` di project lain, atau ganti `ODOO_PORT` |
| Module tidak muncul di Apps | `docker compose exec odoo ls /mnt/extra-addons` | developer mode, Update Apps List, hapus filter Apps |
| Perubahan tidak muncul | | Python: `docker compose restart odoo`. Field/XML/CSV: `-u estate` |
| `Permission denied` di addons | `ls -ln projects/tutorial/addons` | `sudo chown -R "$USER:$USER" projects/tutorial` |
| Build gagal, Enterprise tidak ada | `test -d src/odoo-19e/odoo/addons/web_enterprise` | resep 02, atau Jalur B |
| Breakpoint tidak berhenti | `docker compose logs odoo \| grep -i debugpy` | `DEBUG_MODE=on`, `./switch.sh tutorial`, cek `pathMappings` |
| `exec` tidak bisa ke database | | pakai `docker compose run --rm odoo ...` |

`docker compose down -v` menghapus volume (database dan filestore). Untuk berhenti biasa pakai `docker compose down`.

## Referensi
- [Instalasi Docker Compose](https://docs.docker.com/compose/install/)
- [Odoo 19 CLI: backup dan restore](https://www.odoo.com/documentation/19.0/developer/reference/cli.html)
- [Debug Python di VS Code](https://code.visualstudio.com/docs/python/debugging)
