# Odoo Docker Development Environment This project provides a Docker-based development environment for running Odoo using local Odoo core source code and separate custom addons. This setup is useful for: - Odoo custom module development - Studying Odoo core source code - Keeping custom addons in a separate Git repository - Running Odoo and PostgreSQL with Docker Compose - Managing multiple Odoo versions cleanly --- ## Project Structure Recommended folder structure: ```text odoo-dev/ │ ├── Dockerfile ├── docker-compose.yml ├── README.md │ ├── config/ │ └── odoo.conf │ ├── odoo/ │ ├── odoo-bin │ ├── addons/ │ ├── odoo/ │ └── requirements.txt │ ├── custom_addons/ │ └── my_custom_module/ │ ├── __init__.py │ └── __manifest__.py │ └── enterprise/ └── optional_enterprise_modules/ ``` --- ## Folder Explanation | Folder/File | Description | |---|---| | `Dockerfile` | Builds the Odoo development image | | `docker-compose.yml` | Runs Odoo and PostgreSQL containers | | `config/odoo.conf` | Odoo configuration file | | `odoo/` | Local Odoo core source code | | `custom_addons/` | Your custom Odoo modules | | `enterprise/` | Optional Odoo Enterprise addons | | `README.md` | Project documentation | --- ## Requirements Install these tools before starting: - Docker - Docker Compose - Git - Code editor, for example VS Code or PyCharm Check installation: ```bash docker --version docker compose version git --version ``` --- ## Clone Odoo Source Code Example for Odoo 17: ```bash git clone https://github.com/odoo/odoo.git --branch 17.0 --depth 1 odoo ``` Example for Odoo 18: ```bash git clone https://github.com/odoo/odoo.git --branch 18.0 --depth 1 odoo ``` Example for Odoo 16: ```bash git clone https://github.com/odoo/odoo.git --branch 16.0 --depth 1 odoo ``` Make sure your Docker image version and Odoo source branch match. Examples: ```text Docker image: odoo:17 Odoo source branch: 17.0 ``` ```text Docker image: odoo:18 Odoo source branch: 18.0 ``` ```text Docker image: odoo:16 Odoo source branch: 16.0 ``` --- ## Create Custom Addons Folder Create a folder for your custom modules: ```bash mkdir custom_addons ``` Example custom addons structure: ```text custom_addons/ └── my_custom_module/ ├── __init__.py └── __manifest__.py ``` --- ## Dockerfile Create a file named: ```text Dockerfile ``` Use this content: ```dockerfile FROM odoo:17 USER root RUN apt-get update && apt-get install -y \ git \ nano \ vim \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt/odoo USER odoo CMD ["python3", "/opt/odoo/odoo-bin", "-c", "/etc/odoo/odoo.conf"] ``` If you are using Odoo 18, change: ```dockerfile FROM odoo:17 ``` to: ```dockerfile FROM odoo:18 ``` If you are using Odoo 16, change it to: ```dockerfile FROM odoo:16 ``` --- ## docker-compose.yml Create a file named: ```text docker-compose.yml ``` Use this content: ```yaml services: db: image: postgres:15 container_name: odoo_db environment: POSTGRES_DB: postgres POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo volumes: - odoo-db-data:/var/lib/postgresql/data odoo: build: . container_name: odoo_app depends_on: - db ports: - "8069:8069" volumes: - ./odoo:/opt/odoo - ./custom_addons:/mnt/extra-addons - ./config/odoo.conf:/etc/odoo/odoo.conf - odoo-web-data:/var/lib/odoo command: python3 /opt/odoo/odoo-bin -c /etc/odoo/odoo.conf volumes: odoo-db-data: odoo-web-data: ``` --- ## Odoo Configuration Create the config folder: ```bash mkdir config ``` Create the Odoo config file: ```text config/odoo.conf ``` Use this content: ```ini [options] admin_passwd = admin db_host = db db_port = 5432 db_user = odoo db_password = odoo addons_path = /opt/odoo/addons,/mnt/extra-addons log_level = info ``` --- ## Using Odoo Enterprise If you have Odoo Enterprise source code, place it in: ```text enterprise/ ``` Update `docker-compose.yml`: ```yaml services: db: image: postgres:15 container_name: odoo_db environment: POSTGRES_DB: postgres POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo volumes: - odoo-db-data:/var/lib/postgresql/data odoo: build: . container_name: odoo_app depends_on: - db ports: - "8069:8069" volumes: - ./odoo:/opt/odoo - ./enterprise:/mnt/enterprise - ./custom_addons:/mnt/extra-addons - ./config/odoo.conf:/etc/odoo/odoo.conf - odoo-web-data:/var/lib/odoo command: python3 /opt/odoo/odoo-bin -c /etc/odoo/odoo.conf volumes: odoo-db-data: odoo-web-data: ``` Update `config/odoo.conf`: ```ini [options] admin_passwd = admin db_host = db db_port = 5432 db_user = odoo db_password = odoo addons_path = /opt/odoo/addons,/mnt/enterprise,/mnt/extra-addons log_level = info ``` Recommended addons path order: ```text /opt/odoo/addons /mnt/enterprise /mnt/extra-addons ``` --- ## Start the Environment Build and start containers: ```bash docker compose up -d --build ``` Open Odoo in your browser: ```text http://localhost:8069 ``` View Odoo logs: ```bash docker compose logs -f odoo ``` Stop containers: ```bash docker compose down ``` Stop containers and remove database volumes: ```bash docker compose down -v ``` Be careful with: ```bash docker compose down -v ``` It removes your PostgreSQL database data. --- ## Access the Odoo Container Enter the Odoo container: ```bash docker compose exec odoo bash ``` Check mounted custom addons: ```bash ls -la /mnt/extra-addons ``` Check Odoo config: ```bash cat /etc/odoo/odoo.conf ``` Check local Odoo source: ```bash ls -la /opt/odoo ``` Exit container: ```bash exit ``` --- ## Access the PostgreSQL Container Enter the PostgreSQL container: ```bash docker compose exec db bash ``` Connect to PostgreSQL: ```bash psql -U odoo -d postgres ``` List databases: ```sql \l ``` Exit PostgreSQL: ```sql \q ``` Exit container: ```bash exit ``` --- ## Create a Custom Module Create a sample custom module: ```bash mkdir -p custom_addons/my_custom_module touch custom_addons/my_custom_module/__init__.py touch custom_addons/my_custom_module/__manifest__.py ``` Example structure: ```text custom_addons/my_custom_module/ ├── __init__.py └── __manifest__.py ``` Example `__manifest__.py`: ```python { "name": "My Custom Module", "version": "17.0.1.0.0", "category": "Custom", "summary": "My first custom Odoo module", "description": """ This is a sample custom module for Odoo development. """, "author": "Your Name", "website": "https://example.com", "depends": ["base"], "data": [], "installable": True, "application": False, "license": "LGPL-3", } ``` Restart Odoo: ```bash docker compose restart odoo ``` Then in Odoo: ```text Settings → Activate Developer Mode Apps → Update Apps List ``` Search for: ```text My Custom Module ``` Important: Remove the default `Apps` filter from the search bar if your module does not appear. --- ## Example Custom Model Module Create this structure: ```text custom_addons/my_custom_module/ ├── __init__.py ├── __manifest__.py ├── models/ │ ├── __init__.py │ └── custom_model.py └── views/ └── custom_model_views.xml ``` Create folders: ```bash mkdir -p custom_addons/my_custom_module/models mkdir -p custom_addons/my_custom_module/views touch custom_addons/my_custom_module/models/__init__.py ``` Update root `__init__.py`: ```python from . import models ``` Update `models/__init__.py`: ```python from . import custom_model ``` Create `models/custom_model.py`: ```python from odoo import models, fields class CustomModel(models.Model): _name = "custom.model" _description = "Custom Model" name = fields.Char(string="Name", required=True) description = fields.Text(string="Description") active = fields.Boolean(string="Active", default=True) ``` Create `views/custom_model_views.xml`: ```xml custom.model.tree custom.model custom.model.form custom.model
Custom Models custom.model tree,form
``` Update `__manifest__.py`: ```python { "name": "My Custom Module", "version": "17.0.1.0.0", "category": "Custom", "summary": "My first custom Odoo module", "author": "Your Name", "depends": ["base"], "data": [ "views/custom_model_views.xml", ], "installable": True, "application": True, "license": "LGPL-3", } ``` Upgrade the module: ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -u my_custom_module \ --stop-after-init ``` Restart Odoo: ```bash docker compose restart odoo ``` --- ## Git Setup Recommended Git structure: ```text odoo-dev/ ├── odoo/ # Odoo core repository ├── custom_addons/ # Your custom addons repository ├── enterprise/ # Optional Enterprise repository ├── Dockerfile ├── docker-compose.yml └── config/ ``` ### Odoo Core Remote Check the remote: ```bash cd odoo git remote -v ``` Example result: ```text origin https://github.com/odoo/odoo.git ``` ### Custom Addons Remote Initialize Git inside `custom_addons`: ```bash cd custom_addons git init git add . git commit -m "Initial custom addons" git branch -M main git remote add origin git@github.com:yourname/odoo-custom-addons.git git push -u origin main ``` This keeps Odoo core and your custom modules separate. Do not put your custom modules inside: ```text odoo/addons/ ``` Recommended: ```text custom_addons/ ``` --- ## Addons Path The `addons_path` tells Odoo where to find modules. Example without Enterprise: ```ini addons_path = /opt/odoo/addons,/mnt/extra-addons ``` Example with Enterprise: ```ini addons_path = /opt/odoo/addons,/mnt/enterprise,/mnt/extra-addons ``` Make sure the paths match your Docker volume mounts. Example: ```yaml volumes: - ./custom_addons:/mnt/extra-addons ``` Then `odoo.conf` must include: ```ini /mnt/extra-addons ``` If your compose file has: ```yaml - ./custom_addons:/mnt/custom-addons ``` Then your config must use: ```ini /mnt/custom-addons ``` The names must match exactly. --- ## Common Commands ### Start Containers ```bash docker compose up -d ``` ### Build and Start Containers ```bash docker compose up -d --build ``` ### Stop Containers ```bash docker compose down ``` ### Stop Containers and Delete Volumes ```bash docker compose down -v ``` ### Restart Odoo ```bash docker compose restart odoo ``` ### View Odoo Logs ```bash docker compose logs -f odoo ``` ### View Database Logs ```bash docker compose logs -f db ``` ### Enter Odoo Container ```bash docker compose exec odoo bash ``` ### Enter PostgreSQL Container ```bash docker compose exec db bash ``` ### Check Mounted Custom Addons ```bash docker compose exec odoo ls -la /mnt/extra-addons ``` ### Check Odoo Config ```bash docker compose exec odoo cat /etc/odoo/odoo.conf ``` ### Upgrade a Module Replace `your_database_name` and `your_module_name`: ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -u your_module_name \ --stop-after-init ``` Then restart: ```bash docker compose restart odoo ``` ### Install a Module from Command Line Replace `your_database_name` and `your_module_name`: ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -i your_module_name \ --stop-after-init ``` Then restart: ```bash docker compose restart odoo ``` --- ## Database Management ### List Databases ```bash docker compose exec db psql -U odoo -d postgres -c "\l" ``` ### Backup Database Replace `your_database_name`: ```bash docker compose exec db pg_dump -U odoo your_database_name > backup.sql ``` ### Restore Database Create database first if needed: ```bash docker compose exec db createdb -U odoo restored_database ``` Restore: ```bash cat backup.sql | docker compose exec -T db psql -U odoo restored_database ``` --- ## Development Workflow Recommended workflow: ### 1. Start Docker containers ```bash docker compose up -d ``` ### 2. Create or edit modules in custom addons ```text custom_addons/ ``` ### 3. Restart Odoo if Python files changed ```bash docker compose restart odoo ``` ### 4. Update Apps List in Odoo In the Odoo web interface: ```text Settings → Activate Developer Mode Apps → Update Apps List ``` ### 5. Upgrade your module ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -u your_module_name \ --stop-after-init ``` ### 6. Restart Odoo again ```bash docker compose restart odoo ``` --- ## Updating Apps List In Odoo UI: ```text Settings → Activate Developer Mode Apps → Update Apps List ``` Then search your module. Important: Remove the default search filter: ```text Apps ``` Sometimes custom technical modules do not appear because the default `Apps` filter is active. --- ## Troubleshooting --- ### Problem: `/mnt/extra-addons` is not shown Check the volume mount in `docker-compose.yml`: ```yaml volumes: - ./custom_addons:/mnt/extra-addons ``` Check inside the container: ```bash docker compose exec odoo ls -la /mnt/extra-addons ``` If it is empty, check that your local `custom_addons` folder contains modules. --- ### Problem: Custom module does not appear in Apps Check these items. #### 1. Is the folder mounted? ```bash docker compose exec odoo ls -la /mnt/extra-addons ``` #### 2. Is the path in `odoo.conf`? ```bash docker compose exec odoo cat /etc/odoo/odoo.conf ``` Expected: ```ini addons_path = /opt/odoo/addons,/mnt/extra-addons ``` #### 3. Does the module have `__manifest__.py`? Valid: ```text custom_addons/my_module/__manifest__.py ``` Invalid: ```text custom_addons/my_module/something_else/__manifest__.py ``` unless your `addons_path` points to the correct parent folder. #### 4. Is the module installable? In `__manifest__.py`: ```python "installable": True ``` #### 5. Did you update Apps List? In Odoo: ```text Apps → Update Apps List ``` #### 6. Did you remove the default Apps filter? In the Apps search bar, remove: ```text Apps ``` #### 7. Check logs ```bash docker compose logs -f odoo ``` --- ### Problem: Docker build fails on `pip3 install` If you use the official Odoo Docker image, do not reinstall the full Odoo core `requirements.txt`. Avoid this: ```dockerfile COPY ./odoo/requirements.txt /tmp/requirements.txt RUN pip3 install --break-system-packages -r /tmp/requirements.txt ``` Usually, this Dockerfile is enough: ```dockerfile FROM odoo:17 USER root RUN apt-get update && apt-get install -y \ git \ nano \ vim \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt/odoo USER odoo CMD ["python3", "/opt/odoo/odoo-bin", "-c", "/etc/odoo/odoo.conf"] ``` If your custom modules need extra Python packages, create: ```text requirements-extra.txt ``` Example: ```text requests openpyxl boto3 ``` Then update Dockerfile: ```dockerfile FROM odoo:17 USER root RUN apt-get update && apt-get install -y \ git \ nano \ vim \ python3-pip \ && rm -rf /var/lib/apt/lists/* COPY ./requirements-extra.txt /tmp/requirements-extra.txt RUN pip3 install --break-system-packages --no-cache-dir -r /tmp/requirements-extra.txt WORKDIR /opt/odoo USER odoo CMD ["python3", "/opt/odoo/odoo-bin", "-c", "/etc/odoo/odoo.conf"] ``` --- ### Problem: Odoo image version and source version mismatch Make sure these match: ```dockerfile FROM odoo:17 ``` with: ```text Odoo source branch 17.0 ``` Check branch: ```bash cd odoo git branch ``` Switch branch: ```bash git checkout 17.0 ``` For Odoo 18: ```dockerfile FROM odoo:18 ``` Use branch: ```bash git checkout 18.0 ``` --- ### Problem: Database connection error Check `config/odoo.conf`: ```ini db_host = db db_port = 5432 db_user = odoo db_password = odoo ``` Check `docker-compose.yml`: ```yaml db: environment: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo ``` The database user and password must match. --- ### Problem: Permission issue in custom addons Check file permissions: ```bash ls -la custom_addons ``` On Linux or macOS, you may fix ownership with: ```bash sudo chown -R $USER:$USER custom_addons ``` Then restart: ```bash docker compose restart odoo ``` --- ### Problem: Changes in Python files are not applied Restart Odoo: ```bash docker compose restart odoo ``` Then upgrade the module: ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -u your_module_name \ --stop-after-init ``` Restart again: ```bash docker compose restart odoo ``` --- ### Problem: XML view changes are not applied Upgrade your module: ```bash docker compose exec odoo python3 /opt/odoo/odoo-bin \ -c /etc/odoo/odoo.conf \ -d your_database_name \ -u your_module_name \ --stop-after-init ``` Then restart: ```bash docker compose restart odoo ``` --- ## Recommended Best Practices ### Keep Odoo Core Clean Do not modify Odoo core unless absolutely necessary. Avoid editing files inside: ```text odoo/addons/ odoo/odoo/ ``` Instead, create custom modules inside: ```text custom_addons/ ``` Use inheritance instead of changing core files. Example: ```python from odoo import models, fields class SaleOrder(models.Model): _inherit = "sale.order" x_custom_note = fields.Char(string="Custom Note") ``` --- ### Use Separate Git Repositories Recommended: ```text odoo/ → Odoo official source code custom_addons/ → Your custom addons repository enterprise/ → Odoo Enterprise source code, optional ``` This makes upgrades and maintenance easier. --- ### Use Version-Specific Folders Example: ```text odoo16-dev/ odoo17-dev/ odoo18-dev/ ``` Each project can have its own: ```text Dockerfile docker-compose.yml odoo.conf custom_addons database volume ``` --- ### Use Meaningful Module Names Good module names: ```text sale_order_customization stock_barcode_extension school_management account_report_custom ``` Avoid unclear names: ```text test module1 custom new_module ``` --- ### Use Git Frequently Inside `custom_addons`: ```bash git status git add . git commit -m "Add sale order customization" git push ``` --- ## Full Example Final Files ### Dockerfile ```dockerfile FROM odoo:17 USER root RUN apt-get update && apt-get install -y \ git \ nano \ vim \ && rm -rf /var/lib/apt/lists/* WORKDIR /opt/odoo USER odoo CMD ["python3", "/opt/odoo/odoo-bin", "-c", "/etc/odoo/odoo.conf"] ``` --- ### docker-compose.yml ```yaml services: db: image: postgres:15 container_name: odoo_db environment: POSTGRES_DB: postgres POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo volumes: - odoo-db-data:/var/lib/postgresql/data odoo: build: . container_name: odoo_app depends_on: - db ports: - "8069:8069" volumes: - ./odoo:/opt/odoo - ./custom_addons:/mnt/extra-addons - ./config/odoo.conf:/etc/odoo/odoo.conf - odoo-web-data:/var/lib/odoo command: python3 /opt/odoo/odoo-bin -c /etc/odoo/odoo.conf volumes: odoo-db-data: odoo-web-data: ``` --- ### config/odoo.conf ```ini [options] admin_passwd = admin db_host = db db_port = 5432 db_user = odoo db_password = odoo addons_path = /opt/odoo/addons,/mnt/extra-addons log_level = info ``` --- ## Final Notes This setup runs Odoo from your local source code inside Docker. Local Odoo source: ```text ./odoo → /opt/odoo ``` Custom addons: ```text ./custom_addons → /mnt/extra-addons ``` Odoo detects custom modules using: ```ini addons_path = /opt/odoo/addons,/mnt/extra-addons ``` After creating or modifying modules: ```bash docker compose restart odoo ``` Then update the Apps List from the Odoo interface. For normal Odoo development, always prefer custom addons over editing Odoo core directly.