Files
odoo-erp/README_odoo18.md
2026-09-11 07:19:23 +07:00

1468 lines
21 KiB
Markdown

# 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
<odoo>
<record id="view_custom_model_tree" model="ir.ui.view">
<field name="name">custom.model.tree</field>
<field name="model">custom.model</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="description"/>
<field name="active"/>
</tree>
</field>
</record>
<record id="view_custom_model_form" model="ir.ui.view">
<field name="name">custom.model.form</field>
<field name="model">custom.model</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="description"/>
<field name="active"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_custom_model" model="ir.actions.act_window">
<field name="name">Custom Models</field>
<field name="res_model">custom.model</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_custom_root"
name="Custom App"
sequence="10"/>
<menuitem id="menu_custom_model"
name="Custom Models"
parent="menu_custom_root"
action="action_custom_model"
sequence="10"/>
</odoo>
```
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.