Development Odoo w Dockerze
Marzec 30, 2024 | #docker , #odoo
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
wybieramyDocker
- W polu
Configuration files
wskazujemy na plik `docker-compose.yml - Jako
Service
wybieramy w tym wypadkuweb
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
jakoServera
- pliku
./docker-compose.yml
jakoCompose 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.