mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-17 13:55:08 +00:00
Add deployment tooling: Makefile, scripts, docs
- Makefile: единые команды build/up/update/migrate/assets/backup/shell - scripts/build.sh: сборка образа с apps.json → base64 - scripts/update-apps.sh: проверка последних коммитов приложений через GitHub API - scripts/new-site.sh: создание нового сайта со всеми приложениями - .env.example: шаблон конфигурации с комментариями - DEPLOY.md: документация по развёртыванию и обновлению Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7f5b0a2c47
commit
c60ecbbabc
6 changed files with 444 additions and 0 deletions
45
.env.example
Normal file
45
.env.example
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# ============================================================
|
||||
# Frappe ERP — пример конфигурации (.env.example)
|
||||
# Скопируй в .env и заполни реальными значениями:
|
||||
# cp .env.example .env
|
||||
# ============================================================
|
||||
|
||||
# Версия ERPNext (используется только при PULL_POLICY=always)
|
||||
ERPNEXT_VERSION=v16.9.1
|
||||
|
||||
# Кастомный образ, собранный из apps.json
|
||||
# Собрать: make build
|
||||
CUSTOM_IMAGE=frappe-custom
|
||||
CUSTOM_TAG=v16
|
||||
PULL_POLICY=missing
|
||||
|
||||
# Пароль MariaDB (сгенерируй: openssl rand -base64 32)
|
||||
DB_PASSWORD=CHANGE_ME_use_strong_password
|
||||
|
||||
# Внешняя БД (оставь пустым для встроенной MariaDB)
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
|
||||
# Внешний Redis (оставь пустым для встроенного)
|
||||
REDIS_CACHE=
|
||||
REDIS_QUEUE=
|
||||
|
||||
# Имя сайта (должно совпадать с именем, созданным через bench new-site)
|
||||
FRAPPE_SITE_NAME_HEADER=erp.local
|
||||
|
||||
# HTTP-порт публикации
|
||||
HTTP_PUBLISH_PORT=8090
|
||||
|
||||
# Политика перезапуска контейнеров
|
||||
RESTART_POLICY=unless-stopped
|
||||
|
||||
# Таймаут nginx (секунды)
|
||||
PROXY_READ_TIMEOUT=300
|
||||
|
||||
# Максимальный размер тела запроса
|
||||
CLIENT_MAX_BODY_SIZE=100m
|
||||
|
||||
# Расписание автобэкапа (формат ofelia/cron)
|
||||
# @every 6h — каждые 6 часов
|
||||
# 0 2 * * * — каждый день в 02:00
|
||||
BACKUP_CRONSTRING=@every 6h
|
||||
148
DEPLOY.md
Normal file
148
DEPLOY.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# Frappe ERP — развёртывание и обновление
|
||||
|
||||
## Структура репозитория
|
||||
|
||||
```
|
||||
frappe_docker/
|
||||
├── apps.json ← список приложений для образа
|
||||
├── compose.yaml ← основной docker-compose
|
||||
├── .env ← конфигурация (не в git, создать из .env.example)
|
||||
├── .env.example ← шаблон конфигурации
|
||||
├── Makefile ← все команды управления
|
||||
├── DEPLOY.md ← эта документация
|
||||
│
|
||||
├── images/
|
||||
│ ├── layered/Containerfile ← сборка на базе frappe/build (быстро)
|
||||
│ └── custom/Containerfile ← сборка с нуля (полный контроль)
|
||||
│
|
||||
├── overrides/
|
||||
│ ├── compose.assets-volume.yaml ← общий том assets (обязателен)
|
||||
│ ├── compose.mariadb.yaml ← встроенная MariaDB
|
||||
│ └── ... ← другие оверрайды (proxy, ssl, etc.)
|
||||
│
|
||||
└── scripts/
|
||||
├── build.sh ← сборка образа
|
||||
├── update-apps.sh ← проверка обновлений приложений
|
||||
└── new-site.sh ← создание нового сайта
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Первый запуск
|
||||
|
||||
```bash
|
||||
# 1. Создать конфигурацию
|
||||
cp .env.example .env
|
||||
# Отредактировать .env: задать DB_PASSWORD, FRAPPE_SITE_NAME_HEADER и т.д.
|
||||
|
||||
# 2. Собрать образ с приложениями из apps.json
|
||||
make build
|
||||
|
||||
# 3. Запустить стек
|
||||
make up
|
||||
|
||||
# 4. Создать сайт (если ещё не создан)
|
||||
./scripts/new-site.sh erp.local YourAdminPassword
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Обновление приложений
|
||||
|
||||
### Шаг 1 — проверить доступные обновления
|
||||
|
||||
```bash
|
||||
./scripts/update-apps.sh
|
||||
```
|
||||
|
||||
Скрипт покажет последние коммиты каждого приложения из `apps.json`.
|
||||
|
||||
### Шаг 2 — обновить apps.json при необходимости
|
||||
|
||||
Если нужна конкретная ветка или тег:
|
||||
|
||||
```json
|
||||
// apps.json
|
||||
[
|
||||
{ "url": "https://github.com/frappe/erpnext", "branch": "version-16" },
|
||||
{ "url": "https://github.com/frappe/crm", "branch": "main" }
|
||||
]
|
||||
```
|
||||
|
||||
### Шаг 3 — полный цикл обновления
|
||||
|
||||
```bash
|
||||
make update
|
||||
```
|
||||
|
||||
Это выполнит:
|
||||
1. `make build` — пересборка образа frappe-custom:v16
|
||||
2. `docker compose up -d --no-deps` — замена контейнеров без даунтайма DB/Redis
|
||||
3. `bench migrate` — применение миграций БД
|
||||
4. `bench build` — пересборка JS/CSS assets
|
||||
5. Перезапуск nginx
|
||||
|
||||
---
|
||||
|
||||
## Частичные операции
|
||||
|
||||
```bash
|
||||
make migrate # только миграции (после ручного обновления)
|
||||
make assets # только пересборка JS/CSS
|
||||
make restart # перезапуск backend/frontend
|
||||
make backup # резервная копия сайта
|
||||
make logs # логи backend в реальном времени
|
||||
make shell # bash в контейнере backend
|
||||
make ps # статус всех контейнеров
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Смена версии (например, v16 → v17)
|
||||
|
||||
```bash
|
||||
# 1. Обновить ветки в apps.json
|
||||
# 2. Пересобрать с новым тегом
|
||||
make build TAG=v17
|
||||
|
||||
# 3. Обновить .env
|
||||
# CUSTOM_TAG=v17
|
||||
|
||||
# 4. Пересоздать стек
|
||||
make up
|
||||
make migrate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Добавление нового приложения
|
||||
|
||||
1. Добавить в `apps.json`:
|
||||
```json
|
||||
{ "url": "https://github.com/frappe/hrms", "branch": "version-16" }
|
||||
```
|
||||
|
||||
2. Пересобрать образ и обновить:
|
||||
```bash
|
||||
make update
|
||||
```
|
||||
|
||||
3. Установить на сайт:
|
||||
```bash
|
||||
make shell
|
||||
bench --site erp.local install-app hrms
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Переменные окружения (.env)
|
||||
|
||||
| Переменная | Описание | Пример |
|
||||
|-------------------------|------------------------------------------|---------------------|
|
||||
| `CUSTOM_IMAGE` | Имя Docker-образа | `frappe-custom` |
|
||||
| `CUSTOM_TAG` | Тег образа | `v16` |
|
||||
| `PULL_POLICY` | `missing` — использовать локальный образ | `missing` |
|
||||
| `DB_PASSWORD` | Пароль MariaDB | (сильный пароль) |
|
||||
| `FRAPPE_SITE_NAME_HEADER` | Имя сайта | `erp.local` |
|
||||
| `HTTP_PUBLISH_PORT` | Внешний порт HTTP | `8090` |
|
||||
| `BACKUP_CRONSTRING` | Расписание бэкапов | `@every 6h` |
|
||||
109
Makefile
Normal file
109
Makefile
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# ============================================================
|
||||
# Frappe ERP — управление стеком
|
||||
# Использование: make <target>
|
||||
# ============================================================
|
||||
|
||||
SHELL := /bin/bash
|
||||
SITE ?= erp.local
|
||||
TAG ?= v16
|
||||
|
||||
COMPOSE_OVERRIDES := \
|
||||
-f compose.yaml \
|
||||
-f overrides/compose.assets-volume.yaml
|
||||
|
||||
APPS_JSON_B64 := $(shell base64 -w 0 apps.json)
|
||||
|
||||
.PHONY: help build up down restart update migrate assets backup logs ps shell
|
||||
|
||||
# ── Справка ─────────────────────────────────────────────────
|
||||
help:
|
||||
@echo ""
|
||||
@echo " Frappe ERP — доступные команды:"
|
||||
@echo ""
|
||||
@echo " Образ:"
|
||||
@echo " make build — собрать frappe-custom:$(TAG) из apps.json"
|
||||
@echo " make build TAG=v17 — собрать с другим тегом"
|
||||
@echo ""
|
||||
@echo " Стек:"
|
||||
@echo " make up — запустить все контейнеры"
|
||||
@echo " make down — остановить и удалить контейнеры"
|
||||
@echo " make restart — перезапустить backend/frontend"
|
||||
@echo " make ps — статус контейнеров"
|
||||
@echo ""
|
||||
@echo " Обновление:"
|
||||
@echo " make update — rebuild образа + up + migrate + assets"
|
||||
@echo " make migrate — bench migrate на сайте $(SITE)"
|
||||
@echo " make assets — пересобрать JS/CSS бандлы"
|
||||
@echo ""
|
||||
@echo " Обслуживание:"
|
||||
@echo " make backup — создать резервную копию сайта"
|
||||
@echo " make logs — логи backend (live)"
|
||||
@echo " make shell — bash в backend контейнере"
|
||||
@echo ""
|
||||
|
||||
# ── Сборка образа ────────────────────────────────────────────
|
||||
build:
|
||||
@echo "→ Сборка frappe-custom:$(TAG) из apps.json..."
|
||||
docker build \
|
||||
--build-arg APPS_JSON_BASE64=$(APPS_JSON_B64) \
|
||||
--build-arg FRAPPE_BRANCH=version-16 \
|
||||
-t frappe-custom:$(TAG) \
|
||||
-f images/layered/Containerfile \
|
||||
.
|
||||
@echo "✓ Образ frappe-custom:$(TAG) готов"
|
||||
|
||||
# ── Запуск стека ─────────────────────────────────────────────
|
||||
up:
|
||||
docker compose $(COMPOSE_OVERRIDES) up -d
|
||||
@echo "✓ Стек запущен. Сайт: http://localhost:$${HTTP_PUBLISH_PORT:-8090}"
|
||||
|
||||
down:
|
||||
docker compose $(COMPOSE_OVERRIDES) down
|
||||
|
||||
restart:
|
||||
docker compose $(COMPOSE_OVERRIDES) restart backend frontend websocket
|
||||
|
||||
ps:
|
||||
docker compose $(COMPOSE_OVERRIDES) ps
|
||||
|
||||
# ── Обновление (полный цикл) ─────────────────────────────────
|
||||
update: build
|
||||
@echo "→ Пересоздаём контейнеры с новым образом..."
|
||||
docker compose $(COMPOSE_OVERRIDES) up -d --no-deps backend websocket queue-short queue-long scheduler
|
||||
@echo "→ Ждём готовности backend..."
|
||||
sleep 10
|
||||
$(MAKE) migrate
|
||||
$(MAKE) assets
|
||||
docker compose $(COMPOSE_OVERRIDES) restart frontend
|
||||
@echo "✓ Обновление завершено"
|
||||
|
||||
# ── Миграции БД ──────────────────────────────────────────────
|
||||
migrate:
|
||||
@echo "→ bench migrate --site $(SITE)..."
|
||||
docker compose $(COMPOSE_OVERRIDES) exec backend \
|
||||
bench --site $(SITE) migrate
|
||||
@echo "✓ Миграция завершена"
|
||||
|
||||
# ── Пересборка JS/CSS ────────────────────────────────────────
|
||||
assets:
|
||||
@echo "→ Пересборка assets..."
|
||||
docker compose $(COMPOSE_OVERRIDES) exec backend \
|
||||
bash -c "cd apps/frappe && node esbuild --production"
|
||||
docker compose $(COMPOSE_OVERRIDES) exec backend \
|
||||
bench build
|
||||
docker compose $(COMPOSE_OVERRIDES) restart frontend
|
||||
@echo "✓ Assets пересобраны"
|
||||
|
||||
# ── Резервная копия ──────────────────────────────────────────
|
||||
backup:
|
||||
@echo "→ Создание резервной копии сайта $(SITE)..."
|
||||
docker compose $(COMPOSE_OVERRIDES) exec backend \
|
||||
bench --site $(SITE) backup --with-files
|
||||
@echo "✓ Бэкап создан (см. sites/$(SITE)/private/backups/)"
|
||||
|
||||
# ── Логи и отладка ───────────────────────────────────────────
|
||||
logs:
|
||||
docker compose $(COMPOSE_OVERRIDES) logs -f backend
|
||||
|
||||
shell:
|
||||
docker compose $(COMPOSE_OVERRIDES) exec backend bash
|
||||
48
scripts/build.sh
Executable file
48
scripts/build.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# Сборка образа frappe-custom
|
||||
# Использование: ./scripts/build.sh [tag]
|
||||
# По умолчанию: tag = v16
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
TAG="${1:-v16}"
|
||||
FRAPPE_BRANCH="${FRAPPE_BRANCH:-version-16}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
echo "╔══════════════════════════════════════════════╗"
|
||||
echo " Сборка frappe-custom:${TAG}"
|
||||
echo " Ветка Frappe : ${FRAPPE_BRANCH}"
|
||||
echo " Репозиторий : ${REPO_DIR}"
|
||||
echo "╚══════════════════════════════════════════════╝"
|
||||
|
||||
cd "$REPO_DIR"
|
||||
|
||||
# Проверяем apps.json
|
||||
if [ ! -f apps.json ]; then
|
||||
echo "✗ Файл apps.json не найден"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "→ Приложения из apps.json:"
|
||||
python3 -c "import json; [print(' -', a['url'].split('/')[-1], '@', a['branch']) for a in json.load(open('apps.json'))]"
|
||||
|
||||
# Кодируем apps.json в base64
|
||||
APPS_JSON_B64=$(base64 -w 0 apps.json)
|
||||
|
||||
echo ""
|
||||
echo "→ Запуск docker build..."
|
||||
docker build \
|
||||
--build-arg APPS_JSON_BASE64="$APPS_JSON_B64" \
|
||||
--build-arg FRAPPE_BRANCH="$FRAPPE_BRANCH" \
|
||||
-t "frappe-custom:${TAG}" \
|
||||
-f images/layered/Containerfile \
|
||||
.
|
||||
|
||||
echo ""
|
||||
echo "✓ Образ frappe-custom:${TAG} собран"
|
||||
echo ""
|
||||
echo "Следующий шаг:"
|
||||
echo " make update # пересоздать контейнеры, мигрировать БД, пересобрать assets"
|
||||
echo " make up # просто запустить (если контейнеры не существуют)"
|
||||
48
scripts/new-site.sh
Executable file
48
scripts/new-site.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# Создание нового Frappe-сайта
|
||||
# Использование: ./scripts/new-site.sh <site-name> <admin-password>
|
||||
# Пример: ./scripts/new-site.sh mycompany.local Admin123
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
SITE="${1:-}"
|
||||
ADMIN_PASS="${2:-}"
|
||||
|
||||
if [ -z "$SITE" ] || [ -z "$ADMIN_PASS" ]; then
|
||||
echo "Использование: $0 <site-name> <admin-password>"
|
||||
echo "Пример: $0 mycompany.local Admin123"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
cd "$REPO_DIR"
|
||||
|
||||
COMPOSE_OVERRIDES="-f compose.yaml -f overrides/compose.assets-volume.yaml"
|
||||
|
||||
echo "→ Создание сайта: $SITE"
|
||||
|
||||
docker compose $COMPOSE_OVERRIDES exec backend \
|
||||
bench new-site "$SITE" \
|
||||
--mariadb-root-password "$(grep DB_PASSWORD .env | cut -d= -f2)" \
|
||||
--admin-password "$ADMIN_PASS" \
|
||||
--install-app erpnext
|
||||
|
||||
echo "→ Устанавливаем дополнительные приложения..."
|
||||
for APP in crm helpdesk payments insights lms; do
|
||||
echo " + $APP"
|
||||
docker compose $COMPOSE_OVERRIDES exec backend \
|
||||
bench --site "$SITE" install-app "$APP" || echo " ! $APP пропущен (возможно не нужен)"
|
||||
done
|
||||
|
||||
echo "→ Запуск миграций..."
|
||||
docker compose $COMPOSE_OVERRIDES exec backend \
|
||||
bench --site "$SITE" migrate
|
||||
|
||||
echo ""
|
||||
echo "✓ Сайт $SITE создан"
|
||||
echo " URL: http://localhost:${HTTP_PUBLISH_PORT:-8090}"
|
||||
echo " Логин: Administrator"
|
||||
echo " Пароль: $ADMIN_PASS"
|
||||
46
scripts/update-apps.sh
Executable file
46
scripts/update-apps.sh
Executable file
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# Обновление версий приложений в apps.json
|
||||
# Проверяет последние коммиты каждого приложения
|
||||
# Использование: ./scripts/update-apps.sh
|
||||
# ============================================================
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
APPS_FILE="$REPO_DIR/apps.json"
|
||||
|
||||
echo "╔══════════════════════════════════════════════╗"
|
||||
echo " Проверка обновлений приложений"
|
||||
echo "╚══════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
python3 -c "
|
||||
import json, urllib.request, sys
|
||||
|
||||
apps = json.load(open('$APPS_FILE'))
|
||||
|
||||
for app in apps:
|
||||
url = app['url']
|
||||
branch = app['branch']
|
||||
name = url.rstrip('/').split('/')[-1]
|
||||
|
||||
# GitHub API: последний коммит ветки
|
||||
api_url = url.replace('https://github.com/', 'https://api.github.com/repos/') + '/commits/' + branch
|
||||
try:
|
||||
req = urllib.request.Request(api_url, headers={'User-Agent': 'frappe-update-check'})
|
||||
data = json.loads(urllib.request.urlopen(req, timeout=5).read())
|
||||
sha = data['sha'][:8]
|
||||
date = data['commit']['committer']['date'][:10]
|
||||
msg = data['commit']['message'].splitlines()[0][:60]
|
||||
print(f' {name:20s} [{branch}] последний коммит: {sha} ({date})')
|
||||
print(f' {msg}')
|
||||
except Exception as e:
|
||||
print(f' {name:20s} [{branch}] ошибка проверки: {e}')
|
||||
print()
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "Чтобы обновить образ после изменения apps.json:"
|
||||
echo " make build — только пересобрать образ"
|
||||
echo " make update — полный цикл (build + migrate + assets)"
|
||||
Loading…
Reference in a new issue