Development Odoo w Dockerze

Marzec 30, 2024 | #docker , #odoo

010000
001100
000001
111011

Zaprezentowany na stornie oficjalnego obrazu Dockera dla Odoo pełny przykład pliku docker-compose.yml - na dzień pisania tego artykułu - prezentuje się następująco. Zmieniono jedynie wersję obrazu odoo na 17.0 bo w oryginale była jeszcze 16 i wersję obrazu postgres na 16 bo w oryginale była 15.

version: '3.1'
services:
  web:
    image: odoo:17.0
    depends_on:
      - db
    ports:
      - "8069:8069"
    volumes:
      - odoo-web-data:/var/lib/odoo
      - ./config:/etc/odoo
      - ./addons:/mnt/extra-addons
    environment:
      - PASSWORD_FILE=/run/secrets/postgresql_password
    secrets:
      - postgresql_password
  db:
    image: postgres:16
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_PASSWORD_FILE=/run/secrets/postgresql_password
      - POSTGRES_USER=odoo
      - PGDATA=/var/lib/postgresql/data/pgdata
    volumes:
      - odoo-db-data:/var/lib/postgresql/data/pgdata
    secrets:
      - postgresql_password
volumes:
  odoo-web-data:
  odoo-db-data:

secrets:
  postgresql_password:
    file: odoo_pg_pass

Właściwie nie wiadomo do czego taka konfiguracja miałaby służyć. Na serwer się nie nadaje, a jak się za chwilę okaże do lokalnego developmentu też nie bo na tak przygotowanym środowisku praca dewelopera byłaby utrapieniem.

Modyfikowanie konfiguracji docker compose dla projektu Odoo na potrzeby wygodnego środowiska developerskiego

Aby się wygodnie rozwijało oprogramowanie z użyciem Dockera, konfiguracja kontenerów na komputerze lokalnym różni się od tej stosowanej na serwerach gdzie priorytetem jest bezpieczeństwo i łatwość wdrażania zmian. W tym celu m.in pewne pliki "wyciąga się" z kontenerów na zewnątrz (na hosta) i jedynie podmontowuje tak aby po uruchomieniu kontenera mogły być uruchamiane w jego kontekście.

Wyżej zaprezentowana konfiguracja ma podmontowane dwa katalogi hosta:

  • ./addons na niestandardowe moduły Odoo
  • ./config na pliki konfiguracyjne Odoo (ale pusty)

Dodatkowo zostaną dodane jeszcze:

  • ./odoo - katalog na pliki korowe frameworka tak aby IDE mogło do nich bezproblemowo odsyłać i aby można było także w kodzie Odoo stawiać breakpointy w trakcie debugowania
  • opcjonalnie ./web_data - katalog przeznaczony na dane, które Odoo trzyma poza bazą danych np. pliki sesji, pliki statyczne (filestore).

Struktura projektu po zmianach będzie wyglądać tak:

odoo/
├── addons/
├── config/
│   └── odoo.conf
├── odoo/
├── web_data/
├── docker-compose.yml
├── odoo_pg_pass

Plik konfiguracyjny odoo.conf, dane plikowe oraz pliki frameworka Odoo najprościej pobrać z kontenera.

Kopiowanie plików z kontanera do katalogu projektu na hoście

W tym celu należy uruchomić kontenery (najlepiej w tle żeby nie trzeba było skakać między konsolami).

UWAGA - zakomentuj najpierw w docker-compose.yml linijkę - ./config:/etc/odoo, żeby móc skopiować oryginalny plik konfiguracyjny

$ docker compose up -d
[+] Building 0.0s (0/0)                    docker:default
[+] Running 2/2
  Container odoo-db-1   Started           0.3s 
  Container odoo-web-1  Started           0.2s

Sprawdzić identyfikator kontenera z Odoo

$ docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                                                      NAMES
7fd2d452c290   odoo:17.0     "/entrypoint.sh odoo"    11 seconds ago   Up 10 seconds   0.0.0.0:8069->8069/tcp, :::8069->8069/tcp, 8071-8072/tcp   odoo-web-1
25b7cc9c7a5b   postgres:16   "docker-entrypoint.s…"   11 seconds ago   Up 11 seconds   5432/tcp                                                   odoo-db-1

Skopiować plik konfiguracyjny.

docker cp 7fd2d452c290:/etc/odoo/odoo.conf ./conf/odoo.conf

Skopiować dane plikowe i zmienić im uprawnienia żeby Odoo z poziomu kontenera mogło dodawać nowe pliki i modyfikować istniejące

docker cp 1de53ad270af:/var/lib/odoo ./web_data
sudo chmod -R 777 ./web_data

Skopiować katalog z kodem Odoo

$ docker cp 7fd2d452c290:/usr/lib/python3/dist-packages/odoo - | tar -x

UWAGA !

Dlaczego nie można po prostu przekopiować plików poleceniem jak poniżej?

$ docker cp 7fd2d452c290:/usr/lib/python3/dist-packages/odoo ./odoo

Ponieważ w strukturze plików Odoo są relatywne symlinki, a polecenie docker cp sobie z nimi nie radzi i w rezultacie kopiowanie zostaje przerwane. Dlatego dane kopiowane są na standardowe wyjście a następnie odbierane i za pomocą tar-a i rozpakowywane w bieżącym katalogu.


Modyfikowanie konfiguracji w pliku docker-compose.yml

Teraz pozostaje nam zaktualizowanie pliku docker-compose.yml. Nie rób tego zanim nie przekopiujesz wszystkich plików z kontenera bo dodasz sobie dodatkowej roboty.

version: '3.1'
services:
  web:
    image: odoo:17.0
    depends_on:
      - db
    ports:
      - "8069:8069"
    command: --dev xml,reload,qweb
    volumes:
      - ./web_data:/var/lib/odoo
      - ./config:/etc/odoo
      - ./addons:/mnt/extra-addons
      - ./odoo:/usr/lib/python3/dist-packages/odoo
    environment:
      - PASSWORD_FILE=/run/secrets/postgresql_password
    secrets:
      - postgresql_password
  db:
    image: postgres:16
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_PASSWORD_FILE=/run/secrets/postgresql_password
      - POSTGRES_USER=odoo
      - PGDATA=/var/lib/postgresql/data/pgdata
    volumes:
      - odoo-db-data:/var/lib/postgresql/data/pgdata
    secrets:
      - postgresql_password
volumes:
  odoo-db-data:

secrets:
  postgresql_password:
    file: odoo_pg_pass

Po wprowadzeniu zmian zatrzymaj i ponownie uruchom projekt

docker compose stop
docker compose up

Pewnie nie zwróciłeś uwagi bo jeszcze o tym nie wspominano, ale dodałem do docker compose komendę command: --dev xml,reload,qweb. Bardzo przydatne jeśli nie chcesz co chwilę restartować kontenerów tylko po to aby zobaczyć proste zmiany w działaniu.

Konfigurowanie projektu Odoo

Po odpaleniu adresu w przeglądarce

http://localhost:8069/

Na początku koniecznym będzie skonfigurowanie nowej instancji Odoo

Master Password odnosi się do bazy danych dlatego dobrze jest ustawić takie samo jak w pliku ./odoo_pg_pass. To samo dotyczy nazwy bazy danych. Tu także zgodność z tym co zostało podane w docker-compose.yml jest pożądana.

Password związane jest z kątem użytkownika - posłuży do zalogowania się w serwisie w kolejnym kroku.

Po zatwierdzeniu następuje przekierowanie na stronę główną http://localhost:8069/, która pokaże się natychmiast po zalogowaniu.

Aby sprawdzić prawidłowe podmontowanie katalogu ./addons będzie potrzebny przykładowy moduł. W tym celu najprościej odwiedzić dokumentację prezentującą jak stworzyć pierwszy moduł w Odoo. Można w niej znaleźć między innymi opis struktury projektu, a nawet pobrać tę przykładową strukturę modułu Odoo w formie archiwum zip. Po rozpakowaniu katalog my_module należy przenieść go do katalogu ./addons. Wszystkie pliki w module zawierają przykładowy kod, ale jest on zakomentowany. Można go odkomentować ale zawiera błędy (przynajmniej na chwilę pisania tego artykułu) więc jeśli nie zostaną skorygowane instalacja modułu zakończy się błędem.


Złośliwa uwaga ;)

I pomyśleć, że w 2024 roku deweloperzy Odoo nadal dodają do plików komentarz # -*- coding: utf-8 -*- wskazujący na rodzaj zastosowanego kodowania, jakbyśmy wciąż żyli w erze Pythona 2.x, gdy tymczasem utf-8 jest domyślnym kodowaniem w Python 3.x i już od dawna nie trzeba tego robić.


Na szczęście aby moduł dał się zainstalować wymagana jest minimalna ilości plików w tym plik __manifest__.py, a ten jest gotowy do użycia.

W tym celu należy przejść do ustawień (settings)

Przewinąć stronę aż do sekcji Developer Tools i uruchomić tryb developerski klikając Activate the developer mode.

Po przekierowaniu na stronę z aplikacjami w trybie deweloperskim pojawią się dodatkowe opcje w tym przycisk do aktualizacji listy aplikacji Update Apps List, który należy kliknąć

Po tej operacji dodatkowy moduł my_module powinien pojawić się na liście. Ponieważ jednak aplikacji Odoo jest cała masa można posiłkować się polem wyszukiwania.

Kliknięcie przycisku Activate powinno zainstalować moduł, ale sam fakt że pojawił się on na liście świadczy o prawidłowej konfiguracji w tym zakresie.

Konfiguracja projektu Odoo z użyciem Dockera w IntelliJ IDEA lub Pycharm

Osobiście używam IntelliJ IDEA, więc wszystkie zrzuty ekranu pochodzą z tego programu, ale różnic nie jest tak wiele aby użytkownicy Pycharm-a nie poradzili sobie z nimi.

Tworzenie projektu w IDE

Po uruchomieniu IDE wybieramy nowy projekt

Mamy już pliki w projekcie więc tworzymy projektu uwzględniając ten fakt. Jako interpreter wybieramy cokolwiek. I tak to później zmienimy

Po utworzeniu projektu musimy przede wszystkim zadbać o prawidłowe ustawienie katalogu głównego. Dlatego wchodzimy w File -> Project Structure i na zastanym widoku w Project Settings -> Modules modyfikujemy Content Root (usuwamy i dodajemy nowy) tak aby wskazywał na nasz główny katalog projektu.

W kolejnym kroku czeka nas zmiana interpretera. W końcu chcemy aby nasz projekt działał w Dockerze i w tym środowisku uruchamiał Odoo. Ponownie otwieramy File -> Project Structure i po wybraniu w podmenu Platform Settings -> SDK pokazuje nam się lista istniejących SDK. My natomiast chcemy utworzyć nowe dlatego klikamy znak plusa + i z dostępnych opcji wybieramy Add Python SDK.

W kolejnym wizardzie jaki ukarze się naszym oczom wybieramy Docker Compose i przystępujemy do konfiguracji interpretera.

  • W polu Server wybieramy Docker
  • W polu Configuration files wskazujemy na plik `docker-compose.yml
  • Jako Service wybieramy w tym wypadku web
  • Environment variables zostawiamy puste
  • A jako interpreter wskazujemy python3 (uwaga w starszych wersjach obrazu Odoo np. w wersji 13 python wskazywał na 2 wersję tego języka dlatego istotnym było wybranie python3)

Po utworzeniu SDK opartego o docker compose przypisujemy je do projektu i zatwierdzamy. Pycharm przebuduje projekt i będziemy mogli edytować pliki korzystając ze wsparcia w zakresie kolorowania i podpowiadania składni, linkowania nazw metod czy klas do plików źródłowych itd.

Debugger

Narzędzia IntalliJ-a oferują jednak większe wsparcie w zakresie integracji z Docker-em. Jednym z bardziej wymagających wyzwań, ale wartym zachodu jest zmuszenie wbudowanego debuggera do współpracy z kontenerami. O ile w projektach Pythona bazujących na wirtualnym środowisku czy standardowym interpreterze debugger jest praktycznie dostępny od ręki o tyle w projektach zamkniętych w kontenerach jest to już kwestia bardziej złożona, a Odoo dokłada tu coś jeszcze od siebie.

Aby uruchomić debugger należy dodać dodatkową konfigurację. W prawym górnym rogu edytora, obok symbolu play znajduje się menu, po kliknięciu którego rozwinie się podmenu z dwoma opcjami. Wybieramy Edit Configurations.

W oknie Run/Debug Configurations po kliknięciu plusika + w lewym górnym narożniku ukarze nam się lista dostępnych szablonów konfiguracji. Dla nas interesujące są dwa szablony. Docker -> Docker compose i Python

Konfiguracja debuggera dla docker compose

Pierwsza z wymienionych jest banalnie prosta i sprowadza się jedynie do wskazania:

  • Docker jako Servera
  • pliku ./docker-compose.yml jako Compose files.

Umożliwia ona uruchomienie docker compose w środowisku IDE i zapewnia przyjemny i funkcjonalny interfejs pozwalający m.in w łatwy sposób przeglądać logi uruchomionych kontenerów.

Ma niestety tę wadę, że nie umożliwia uruchomienia samego debuggera.

Konfiguracja debuggera bez użycia docker compose

Druga z opcji jest mniej przyjazna i wymaga więcej zachodu, ale za to pozwala cieszyć się z dobrodziejstw debuggera. Aby zrozumieć na jakich zasadach ona działa i jakie mato konsekwencje musimy sobie wyobrazić, że Odoo odpalane jest niejako wewnątrz kontenera. Czyli tak jakbyśmy weszli do kontenera z Odoo i w powłoce ręcznie je odpalili. Dlatego musimy wskazać:

  • interpreter Use specified interpreter (oczywiście na ten, który utworzyliśmy w trakcie tworzenia nowego SDK)
  • script - wskazując położenie pliku wykonywalnego Odoo w strukturze plików wewnątrz kontenera /usr/bin/odoo
  • koniecznym jest wskazanie pliku konfiguracyjnego i dodatkowych opcji jeśli chcemy ich użyć - dlatego w linii przeznaczonej na dodatkowe parametry dajemy -c /etc/odoo/odoo.conf --dev xml,qweb
  • wskazać Working directory na katalog główny, w którym znajduje się projekt

Ale to nie wszystko. "Ręcznie" odpalany projekt będzie miał problemy z połączeniem z bazą danych ponieważ w takim trybie nie jest wywoływany skrypt entrypoint.sh odpowiedzialny za przekształcanie zmiennych środowiskowych ustawianych docker-compose.yml w parametry, z którymi zostanie odpalone Odoo. Dlatego też dane dostępowe do bazy danych
należy przekazać albo jako parametry wywołania (zalecane),

-c /etc/odoo/odoo.conf --dev xml,qweb \
--db_host db --db_port 5432 --db_user odoo --db_password odoo -d odoo

albo ustawić je w odoo.conf (niezalecane - patrz uwagi poniżej)

[options]  
...
db_host = db
db_port = 5432
db_user = odoo
db_name = odoo
db_password = odoo

UWAGA!

Plik z danymi wrażliwymi nie powinien trafić do repozytorium - nawet jeśli to konfiguracja nieprodukcyjna.

Jeśli to pierwsze uruchomienie kontenerów, albo baza danych została zresetowana np. poleceniem docker compose down -v, dodanie danych dostępowych do bazy danych do oddo.conf uniemożliwi użycie managera baz danych Odoo do ustawienia danych autoryzacyjnych pozwalających na zalogowanie się do Odoo. Dane dostępowe do bazy danych w pliku konfiguracyjnym można ustawić tylko wtedy gdy baza danych została już poprawnie utworzona i zostały w niej ustawione dane do logowania.


Po takich zapisaniu uruchomienie debuggera powinno być już możliwe, co czynimy klikając ikonę robaczka w menu w górnym prawym narożniku

Ustawiamy breakpoint w jakimś miejscu w kodzie, o którym wiemy, że na pewno zostanie wywołane w trakcie przeładowania strony głównej np. w pliku ./odoo/http.py w linii 361 exposed_dbs = {db.strip() for db in config['db_name'].split(',')}

Odświeżamy widok w przeglądarce i cieszymy się działającym debuggerem.


Uwaga

Może się zdarzyć, że po uruchomieniu debuggera pojawi się problem z połączeniem z adresem IP 172.17.0.1 Przyczyny tego mogą być różne ale najczęściej chodzi o firewalla. Jeśli tak jak ja pracujesz na Ubuntu, najprościej zweryfikujesz to po prostu wyłączając na chwilę firewalla

sudo ufw disable

Po zakończeniu testu nie zapomnij go ponownie włączyć. Po co ryzykować ;)?

sudo ufw enable

Przedstawiony wyżej artykuł nie wyczerpuje tematu ale myślę przekazuje garść pomocnych wskazówek ułatwiających przygotowanie środowiska w celu przyjemniejszej pracy z modułami Odoo.

Akceptuję Ta strona zapisuje niewielkie pliki tekstowe, nazywane ciasteczkami (ang. cookies) na Twoim urządzeniu w celu lepszego dostosowania treści oraz dla celów statystycznych. Możesz wyłączyć możliwość ich zapisu, zmieniając ustawienia Twojej przeglądarki. Korzystanie z tej strony bez zmiany ustawień oznacza zgodę na przechowywanie cookies w Twoim urządzeniu.