MAATRIX / Блог / Odoo в Docker Compose: готовый файл

Odoo в Docker Compose: готовый файл

MAATRIX

Odoo — это модульная ERP/CRM-система: продажи, склад, закупки, бухгалтерия, HR и ещё пара десятков приложений под одной крышей, которые можно включать по одному. Ставить её через официальный .deb-пакет с ручной настройкой PostgreSQL и wkhtmltopdf — занятие на вечер с граблями по версиям Python. Docker Compose убирает почти всё это: два сервиса, один файл, и через пять минут у вас работающая ERP на своём сервере, без подписки и без чужих серверов с вашими данными о продажах.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Что нам понадобится

Odoo в контейнере состоит из двух частей:

  • сервис odoo — сам сервер приложения (веб-интерфейс на 8069, longpolling на 8072);
  • сервис db — PostgreSQL, куда Odoo складывает все данные.

Официальный образ odoo на Docker Hub уже включает нужную версию Python, wkhtmltopdf для генерации PDF-отчётов и все системные зависимости — та часть, где при ручной установке чаще всего что-то ломается.

Минимальные требования к серверу для одной-двух компаний с несколькими пользователями:

РесурсМинимумКомфортно
CPU2 vCPU4 vCPU
RAM4 ГБ8 ГБ
Диск40 ГБ SSD80+ ГБ SSD
ОСUbuntu 24.04Ubuntu 24.04

Если у вас уже стоит Docker — переходите к следующему разделу. Если нет, разверните его с нуля по инструкции для Ubuntu 24.04 — там же описан docker compose plugin, который понадобится дальше.

Готовый docker-compose.yml

Создайте директорию проекта и файл конфигурации:

mkdir -p ~/odoo && cd ~/odoo
mkdir -p addons config
nano docker-compose.yml

Содержимое файла:

services:
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: odoo
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - odoo-db-data:/var/lib/postgresql/data/pgdata
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U odoo"]
      interval: 10s
      timeout: 5s
      retries: 5

  odoo:
    image: odoo:17.0
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:8069:8069"
      - "127.0.0.1:8072:8072"
    environment:
      HOST: db
      USER: odoo
      PASSWORD: ${DB_PASSWORD}
    volumes:
      - odoo-web-data:/var/lib/odoo
      - ./addons:/mnt/extra-addons
      - ./config:/etc/odoo

volumes:
  odoo-db-data:
  odoo-web-data:

Рядом создайте .env с паролем базы — не хардкодьте его прямо в compose-файле:

echo "DB_PASSWORD=$(openssl rand -base64 24)" > .env
chmod 600 .env

Обратите внимание на ports: "127.0.0.1:8069:8069" — порты пробрасываются только на localhost. Наружу Odoo отдаёт реверс-прокси (об этом ниже), а не голый HTTP напрямую в интернет: без этого любой сканер портов найдёт вашу ERP с данными о клиентах и продажах за считаные минуты.

Версия образа odoo:17.0 зафиксирована сознательно — в отличие от odoo:latest, она не подменится major-обновлением при случайном docker compose pull. На момент написания статьи (конец августа 2026) актуальны ветки 17.0 LTS и более новые — проверьте на Docker Hub, какая версия вам подходит по совместимости с нужными модулями, и подставьте её тег в файл.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Первый запуск и создание базы

Поднимаем стек:

docker compose up -d
docker compose logs -f odoo

Дождитесь строки вида HTTP service (werkzeug) running — это значит, что Odoo поднялся и слушает 8069. Первый запуск обычно занимает 20–40 секунд: Odoo инициализирует служебные таблицы в PostgreSQL.

Дальше откройте http://ваш-сервер:8069 (если порт временно проброшен наружу для теста) или, что правильнее, зайдите через SSH-туннель:

ssh -L 8069:localhost:8069 user@ваш-сервер

и откройте http://localhost:8069 в браузере на своей машине. На экране мастера создания базы данных укажите:

  • имя базы (например, main);
  • email и пароль администратора;
  • демо-данные — отключите (Load demonstration data снимите), в проде они не нужны и только засоряют интерфейс;
  • язык и страну — для локали РФ подойдёт Russian / Russia.

После создания базы Odoo сразу предложит выбрать первое приложение — Sales, Inventory, Accounting и так далее. Ставить можно по одному по мере необходимости, лишние модули не установятся сами.

Модули: от продаж до склада и бухгалтерии

Сила Odoo — в том, что это не отдельная CRM плюс отдельный склад плюс отдельная бухгалтерия, а один набор данных под разными приложениями. Базовый рабочий комплект для небольшой компании:

  • Sales — коммерческие предложения, заказы, прайс-листы;
  • Inventory — складской учёт, перемещения, инвентаризация;
  • Purchase — закупки у поставщиков, автозаказ при минимальном остатке;
  • Accounting — счета, платежи, отчётность (для РФ смотрите наличие локализованного плана счетов в App Store Odoo — он не всегда идёт "из коробки" для всех версий);
  • CRM — воронка продаж, лиды, задачи по клиентам.

Модули ставятся через Apps → поиск по названию → Install. Зависимости (например, Accounting подтянет Invoicing) Odoo разрешает сам.

Если нужен свой модуль или доработка — кладите исходники в ./addons на хосте (тот самый том, примонтированный как /mnt/extra-addons), после чего перезапустите контейнер с флагом обновления списка модулей:

docker compose exec odoo odoo -u all --stop-after-init -d main
docker compose restart odoo

Реверс-прокси и HTTPS

Открывать 8069 напрямую в интернет — плохая идея: без TLS логин и пароль администратора летят в открытом виде, а Odoo своей встроенной защиты от брутфорса не имеет. Ставим перед ней Traefik или nginx proxy manager — оба варианта разобраны в статье Traefik или nginx proxy manager: что выбрать для сервера.

Если выбрали Traefik, ключевой нюанс для Odoo — два отдельных порта с разными правилами: 8069 для обычного HTTP-трафика и 8072 для longpolling (живые уведомления, чат, real-time обновления в интерфейсе). В docker-compose.yml вместо секции ports для сервиса odoo добавьте лейблы:

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.odoo.rule=Host(`erp.вашдомен.ру`)"
      - "traefik.http.routers.odoo.entrypoints=websecure"
      - "traefik.http.routers.odoo.tls.certresolver=le"
      - "traefik.http.services.odoo.loadbalancer.server.port=8069"
      - "traefik.http.routers.odoo-longpolling.rule=Host(`erp.вашдомен.ру`) && PathPrefix(`/longpolling`)"
      - "traefik.http.routers.odoo-longpolling.entrypoints=websecure"
      - "traefik.http.routers.odoo-longpolling.tls.certresolver=le"
      - "traefik.http.services.odoo-longpolling.loadbalancer.server.port=8072"

и уберите ports: совсем, оставив только expose, либо подключите сервисы к общей сети Traefik. Общий принцип настройки Traefik как реверс-прокси для Docker подробно разобран в статье Traefik как reverse proxy для докера — здесь только специфика двух портов Odoo.

Если сертификат перестал обновляться после смены домена или DNS — прежде чем разбирать Traefik, загляните в SSL-сертификат не обновился: там разобраны типичные причины (закрытый 80 порт, устаревшая A-запись, лимиты Let's Encrypt).

Бэкапы: база и файлы

В Odoo есть встроенный бэкап через веб-интерфейс (Settings → Technical → Database Structure → Backup), но он неудобен для автоматизации и требует ручного входа. Для регулярных бэкапов надёжнее дампить PostgreSQL напрямую и параллельно копировать том с файлами (вложения, логотипы, вложенные документы хранятся в odoo-web-data, а не в базе).

Скрипт для cron:

#!/bin/bash
# /opt/scripts/odoo-backup.sh
set -e
BACKUP_DIR="/backup/odoo/$(date +%F)"
mkdir -p "$BACKUP_DIR"

cd ~/odoo
docker compose exec -T db pg_dump -U odoo -Fc main > "$BACKUP_DIR/main.dump"
docker run --rm -v odoo_odoo-web-data:/data -v "$BACKUP_DIR":/backup alpine \
  tar czf /backup/filestore.tar.gz -C /data .

find /backup/odoo -mindepth 1 -maxdepth 1 -mtime +14 -exec rm -rf {} \;
chmod +x /opt/scripts/odoo-backup.sh
crontab -e
# ежедневно в 03:00
0 3 * * * /opt/scripts/odoo-backup.sh

Восстановление базы из дампа:

docker compose exec -T db pg_restore -U odoo -d main --clean < main.dump

Общие принципы бэкапа docker-томов (не только под Odoo) и частые ошибки при этом — в статье Бэкап Docker volume на сервере: частые ошибки и решения. Если хотите более системный инструмент вместо самописного скрипта — там же логика применима к связке с BorgBackup, которую можно развернуть в отдельном контейнере и направить на те же тома.

Обновление версии и производительность

Обновление Odoo между минорными релизами внутри одной major-версии (например, 17.0.x → 17.0.y) обычно сводится к смене тега образа и рестарту:

docker compose pull odoo
docker compose up -d odoo
docker compose exec odoo odoo -u all --stop-after-init -d main

Обновление между major-версиями (17.0 → 18.0) — отдельная задача с миграцией схемы данных, и Odoo такое делает не всегда гладко даже официальным механизмом. Перед major-апгрейдом обязательно снимите полный бэкап (см. раздел выше) и тестируйте обновление на копии базы, а не на боевой.

По производительности на практике узкое место чаще не CPU, а диск и объём RAM, выделенной PostgreSQL — Odoo активно кэширует и держит много открытых соединений при нескольких одновременных пользователях. Если интерфейс начал заметно тормозить при росте числа сотрудников в системе, первое, что стоит проверить, — SSD (не HDD) под том базы и объём выделенной серверу оперативной памяти, а уже потом тюнинг workers в конфиге Odoo (config/odoo.conf, параметр workers = 2 на каждые примерно 2 vCPU для продакшена вместо однопоточного dev-режима по умолчанию).

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли использовать Odoo Community бесплатно в коммерческой компании?

Да, Odoo Community распространяется под LGPL-совместимой лицензией и бесплатен для любого числа пользователей и модулей из открытой части каталога. Платная Enterprise-версия добавляет часть модулей (например, продвинутую бухгалтерию под некоторые юрисдикции) и официальную поддержку, но для старта Community закрывает основные сценарии — продажи, склад, CRM, базовую бухгалтерию.

Почему после установки не открывается страница логина, а видно только "database selector"?

Odoo не понимает, к какой базе обращаться, если их несколько или переменная dbfilter не настроена. Для одиночной установки проще всего один раз зайти на /web/database/selector, выбрать базу и дальше зафиксировать её в config/odoo.conf параметром db_name = main и list_db = False, чтобы селектор больше не показывался посторонним.

Как перенести Odoo с другого хостинга на свой сервер?

Через тот же механизм бэкап/восстановление: снимите pg_dump базы и архив filestore на старом сервере, разверните пустой стек по этой инструкции на новом, восстановите дамп командой pg_restore и распакуйте архив filestore в volume odoo-web-data (это, по сути, обратная операция к скрипту бэкапа выше).

Нужен ли отдельный SMTP-сервер для писем из Odoo?

Да, для отправки счетов, уведомлений и рассылок Odoo нужен исходящий SMTP — свой или сторонний сервис. Настраивается в Settings → Technical → Email → Outgoing Mail Servers, отдельно от основного docker-compose файла.

Сколько компаний (multi-company) можно вести в одной инсталляции?

Odoo поддерживает мультикомпанию из коробки — несколько юрлиц с раздельным или частично общим учётом в одной базе, без отдельных серверов под каждое. Настраивается в Settings → Companies после первого запуска.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →