refactor: Migrating Comprehensive Guide

The Comprehensive Getting Started guide is broken into smaller pieces
and added to respective sections.
This commit is contained in:
adithya 2026-03-16 00:02:01 +05:30
parent 655a1f4ec8
commit c1e545f3e5
10 changed files with 591 additions and 2 deletions

View file

@ -0,0 +1,92 @@
---
title: Introduction
---
# Introduction to Frappe Docker
This is the documentation for the Frappe Docker repository, which contains all the information on how to develop, deploy and share Frappe app, using Docker containers.
## Repository Architecture
Frappe Docker provides a comprehensive containerized environment for developing and deploying Frappe/ERPNext applications. It uses a **multi-service architecture** that handles everything from web serving to background job processing.
### Core Services
The base compose file includes these essential services:
- **configurator** - Initialization service that configures database and Redis connections; runs on startup and exits
- **backend** - Werkzeug development server for dynamic content processing
- **frontend** - Nginx reverse proxy that serves static assets and routes requests
- **websocket** - Node.js server running Socket.IO for real-time communications
- **queue-short/long** - Python workers using RQ (Redis Queue) for asynchronous background job processing
- **scheduler** - Python service that runs scheduled tasks using the schedule library
Additional services are added through compose overrides:
- **db** - MariaDB or PostgreSQL database server (via `compose.mariadb.yaml` or `compose.postgres.yaml`)
- **redis-cache/queue** - Redis instances for caching and job queues (via `compose.redis.yaml`)
### How Services Work Together
```
User Request
[frontend (Nginx)] → Static files served directly
[backend (Werkzeug)] → Dynamic content processing
↓ ↓
[db (MariaDB)] [redis-cache]
Background Tasks:
[scheduler] → [redis-queue] → [queue-short/long workers]
Real-time:
[websocket (Socket.IO)] ←→ [redis-cache]
```
## Repository Structure
### `/` Root: Core Configuration Files
- **compose.yaml** - Main Docker Compose file defining all services
- **example.env** - Environment variables template (copy to `.env`)
- **pwd.yml** - "Play with Docker" - simplified single-file setup for quick testing
- **docker-bake.hcl** - Advanced Docker Buildx configuration for multi-architecture builds
- **docs/container-setup/env-variables.md** - Central reference for environment configuration logic and defaults
### `images/`: Docker Image Definitions
Four predefined Dockerfiles are available, each serving different use cases:
- **images/bench/** - Sets up only the Bench CLI for development or debugging; does not include runtime services
- **images/custom/** - Multi-purpose Python backend built from plain Python base image; installs apps from `apps.json`; suitable for **production** and testing; ideal when you need control over Python/Node versions
- **images/layered/** - Same final contents as `custom` but based on prebuilt images from Docker Hub; faster builds for production when using Frappe-managed dependency versions
- **images/production/** - Installs only Frappe and ERPNext (not customizable with `apps.json`); best for **quick starts or exploration**; for real deployments, use `custom` or `layered`
> **Note:** For detailed build arguments and advanced configuration options, see [Setup Overview](../02-setup/01-overview.md).
### `overrides/`: Compose File Extensions
Docker Compose "overrides" that extend the base compose.yaml for different scenarios:
- **compose.mariadb.yaml** - Adds MariaDB database service
- **compose.redis.yaml** - Adds Redis caching service
- **compose.proxy.yaml** - Adds Traefik reverse proxy for multi-site hosting (label-based routing)
- **compose.https.yaml** - Adds Traefik HTTPS + automatic certs (uses `SITES_RULE`)
- **compose.nginxproxy.yaml** - Adds nginx-proxy reverse proxy (HTTP, env-based `VIRTUAL_HOST`)
- **compose.nginxproxy-ssl.yaml** - Adds nginx-proxy + acme-companion (HTTPS, env-based `LETSENCRYPT_HOST`)
**Proxy choice:**
- Traefik is more flexible for advanced routing and multi-bench setups
- nginx-proxy is simpler for a single bench with host-based routing.
### `development/`: Dev Environment
- **development/installer.py** - Automated bench/site creation and configuration script
- Contains your local development files (git-ignored to prevent accidental commits)
### `resources/`: Runtime Templates
- **core/nginx/nginx-entrypoint.sh** - Dynamic Nginx configuration generator script
- **core/nginx/nginx-template.conf** - Nginx configuration template with variable substitution

View file

@ -101,6 +101,26 @@ PYENV_VERSION=3.9.17 bench init --skip-redis-config-generation --frappe-branch v
cd frappe-bench
```
At this point the the directory structure will be very close to this, if not exact,
```
development/
├── frappe-bench/ # Your actual Frappe installation
│ ├── apps/ # All installed Frappe applications
│ │ ├── frappe/ # Core framework (don't modify directly)
│ │ ├── erpnext/ # ERPNext application (if installed)
│ │ └── my_custom_app/ # Your custom apps (edit freely)
│ ├── sites/ # Multi-tenant sites
│ │ ├── development.localhost/ # Default dev site
│ │ │ ├── site_config.json # Site-specific config
│ │ │ └── private/files/ # Uploaded files
│ │ └── common_site_config.json # Shared configuration
│ ├── env/ # Python virtual environment
│ ├── logs/ # Application logs
│ └── config/ # Bench-level configuration
└── .vscode/ # VSCode workspace settings
```
### Setup hosts
We need to tell bench to use the right containers instead of localhost. Run the following commands inside the container:

View file

@ -0,0 +1,10 @@
---
title: ARM64 / Apple Silicon
---
## Notes on ARM64 and Apple Silicon
- Enable Docker Desktop's Rosetta emulation for initial builds when running on Apple Silicon with x86-only images.
- Prefer published multi-arch images (`frappe/bench`, `frappe/erpnext`) or build locally with `docker buildx bake --set *.platform=linux/amd64,linux/arm64` to cover both architectures in one pass.
- When using `pwd.yml`, export `DOCKER_DEFAULT_PLATFORM=linux/arm64` (or select the provided compose profile) to avoid unexpected emulation.
- Keep bind mounts under your user home directory and apply `:cached` or `:delegated` consistency flags for better performance on macOS.

View file

@ -33,11 +33,11 @@ pnpm install
pnpm run docs:dev
```
4. Open `http://localhost:5173` in your browser to see the development version which will update the preview as you make changes.
4. Open `http://localhost:5173/frappe_docker` in your browser to see the development version which will update the preview as you make changes.
## Configurations
1. Public assets related to VitePress site is added in the `docs/public` folder. This folder should not be used for adding images added inside the `.md` file.
1. Public assets related to VitePress site is added in the `docs/public` folder. This folder should **NOT** be used for adding images added inside the `.md` file.
2. VitePress uses `index.md` files to do some special things. For example the home page is configured using the `docs/index.md` file. Checkout the file for more details.
3. VitePress uses 'file based routing', meaning the URL paths mimics the directory and file structure inside the `docs/` directory.
4. VitePress specific config is `docs/.vitepress/config.mts`.

View file

@ -0,0 +1,161 @@
---
title: Fork Management
---
# Fork Management Best Practices
## Initial Fork Setup
```bash
# 1. Fork on GitHub (use the Fork button)
# 2. Clone YOUR fork
git clone https://github.com/YOUR_USERNAME/frappe_docker
cd frappe_docker
# 3. Add upstream remote (original repo)
git remote add upstream https://github.com/frappe/frappe_docker.git
# 4. Verify remotes
git remote -v
# origin https://github.com/YOUR_USERNAME/frappe_docker (your fork)
# upstream https://github.com/frappe/frappe_docker (original)
# 5. Create development branch
git checkout -b my-custom-setup
```
## Safe Customization Zones
**✅ Safe (Won't conflict with upstream):**
```
development/ # Your entire dev environment
├── frappe-bench/ # Local installation
└── .vscode/ # Your editor settings
compose.my-*.yaml # Your custom compose overrides
scripts/my-*.sh # Your custom scripts
docs/my-*.md # Your custom documentation
.env.local # Local environment overrides
.gitignore.local # Additional gitignore rules
```
**⚠️ Modification Needed (May conflict):**
```
compose.yaml # Core - use overrides instead
docker-bake.hcl # Build config - use custom files
images/*/Dockerfile # Core images - extend rather than modify
```
**❌ Never Modify (Will break upstream sync):**
```
.github/workflows/ # CI/CD pipelines
images/*/ # Core image definitions
resources/ # Core templates
```
## Keeping Fork Updated
```bash
# Regularly sync with upstream (weekly recommended)
git checkout main
git fetch upstream
git merge upstream/main
git push origin main
# Update your development branch
git checkout my-custom-setup
git rebase main # Or: git merge main
# If conflicts occur during rebase:
# 1. Fix conflicts in files
# 2. git add <fixed-files>
# 3. git rebase --continue
# Or: git rebase --abort (to cancel)
```
## Custom Environment Pattern
Create override files for your customizations:
```yaml
# compose.my-env.yaml
version: "3.7"
services:
backend:
environment:
# Your custom environment variables
- DEVELOPER_MODE=true
- MY_API_KEY=${MY_API_KEY}
volumes:
# Your custom bind mounts
- ./development/my-scripts:/home/frappe/my-scripts
- ./development/my-config:/home/frappe/config
# Your additional services
my-monitoring:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
# Use it:
# docker compose -f compose.yaml -f compose.my-env.yaml up
```
## .gitignore Strategy
Add to `.gitignore` (or create `.gitignore.local`):
```gitignore
# Local environment files
.env.local
*.local.yaml
compose.my-*.yaml
# Development artifacts
development/frappe-bench/sites/*
development/frappe-bench/apps/*
!development/frappe-bench/apps.json
development/frappe-bench/logs/
development/frappe-bench/env/
# Local customizations
my-local-configs/
scripts/my-*.sh
docs/internal-*.md
# IDE
.vscode/settings.json.local
.idea/
# Temporary files
*.swp
*.swo
*~
.DS_Store
```
## Contributing Back to Upstream
```bash
# 1. Create feature branch from main
git checkout main
git pull upstream main
git checkout -b feature/my-improvement
# 2. Make changes and commit
git add .
git commit -m "feat: add awesome feature"
# 3. Push to YOUR fork
git push origin feature/my-improvement
# 4. Create Pull Request on GitHub
# Go to: https://github.com/frappe/frappe_docker
# Click "Compare & pull request"
```

View file

@ -0,0 +1,159 @@
---
title: Framework Comparisons
---
# Framework Comparisons
> **Note:** This section provides comparisons to other frameworks for developers familiar with them. If you're new to all frameworks, you can skip this section - the rest of the guide is self-contained.
## Frappe vs Django Concepts
### Project Structure Comparison
**Django Project:**
```python
myproject/
├── myproject/ # Project settings
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blog/ # Django app
│ ├── models.py
│ ├── views.py
│ └── urls.py
├── shop/ # Django app
└── users/ # Django app
```
**Frappe Bench:**
```
bench/
├── apps/
│ ├── frappe/ # Core framework (comparable to Django itself)
│ ├── erpnext/ # Complete business app (like Django + DRF + Celery + admin)
│ ├── hrms/ # HR Management app
│ └── my_custom_app/ # YOUR custom app
└── sites/
└── mysite.com/ # Site instance (like Django project + database)
├── site_config.json
└── private/files/
```
### Conceptual Mapping
| Django | Frappe | Notes |
| ------------------ | ----------------- | ----------------------------------------------- |
| Model | DocType | But includes UI, permissions, API automatically |
| View | Controller method | Much less code needed |
| Admin | Desk | More powerful, auto-generated |
| DRF Serializer | Built-in | Automatic from DocType |
| Celery task | Background job | Built-in, no separate setup |
| signals | hooks.py | More structured |
| Management command | bench command | More discoverable |
### Key Architectural Differences
1. **Multi-tenancy**
- Django: One app = one database (typically)
- Frappe: One installation = many sites, each with own database
2. **Background Jobs**
- Django: Requires Celery + Redis + worker setup
- Frappe: Built-in queue system, just use `enqueue()`
3. **Real-time**
- Django: Requires Channels + Redis + ASGI setup
- Frappe: Socket.IO built-in, automatic for DocType updates
4. **Admin/Management**
- Django: Admin for models, basic CRUD
- Frappe: Full-featured Desk with reports, dashboards, permissions
5. **API**
- Django: Manual DRF setup, serializers, views
- Frappe: Automatic REST + RPC from DocType definitions
### Code Comparison Example
**Creating a "Customer" model:**
Django (requires ~50+ lines):
```python
# models.py
class Customer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
# serializers.py
class CustomerSerializer(serializers.ModelSerializer):
# ...
# views.py
class CustomerViewSet(viewsets.ModelViewSet):
# ...
# urls.py
router.register(r'customers', CustomerViewSet)
# admin.py
@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
# ...
```
Frappe (DocType JSON + ~10 lines Python):
```json
// customer.json (auto-generated via UI or code)
{
"name": "Customer",
"fields": [
{ "fieldname": "customer_name", "fieldtype": "Data" },
{ "fieldname": "email", "fieldtype": "Data", "unique": 1 }
]
}
```
```python
# customer.py (only for custom business logic)
import frappe
from frappe.model.document import Document
class Customer(Document):
def validate(self):
# Custom validation logic only
pass
```
✅ **Automatically includes:**
- REST API (`/api/resource/Customer`)
- List view, Form view
- Search, Filters, Sorting
- Permissions (Create, Read, Update, Delete)
- Audit trail (created_by, modified_by, versions)
- Print formats, Email templates
### When to Choose Frappe vs Django
**Choose Frappe when:**
- Building business applications (ERP, CRM, project management)
- Need multi-tenancy out-of-the-box
- Want rapid development with auto-generated UI
- Need role-based permissions and workflows
- Building for non-technical users who need customization
**Choose Django when:**
- Building consumer web apps (social media, e-commerce frontend)
- Need full control over every aspect
- Have highly custom UI requirements
- Team is already Django-expert
- Building API-only services
**Hybrid Approach:**
Many teams use both: Frappe for back-office/admin tools, Django for customer-facing web apps.

View file

@ -0,0 +1,18 @@
---
title: External Links
---
# External Links
## Official Documentation
- [Frappe Framework Docs](https://frappeframework.com/docs) - Core framework documentation
- [Frappe Docker Docs](https://github.com/frappe/frappe_docker/tree/main/docs) - This repository's docs
- [ERPNext Documentation](https://docs.erpnext.com) - ERPNext user and developer docs
- [Docker Documentation](https://docs.docker.com) - Docker fundamentals
## Community Resources
- [Frappe Forum](https://discuss.frappe.io) - Community Q&A
- [Frappe School](https://frappe.school) - Video tutorials
- [Frappe GitHub](https://github.com/frappe/frappe) - Framework source code

View file

@ -0,0 +1,64 @@
---
title: Custom Apps
---
# Frappe Custom Applications
## What Are Frappe Custom Apps?
Custom apps are self-contained, modular business applications that extend Frappe's functionality. They follow a convention-over-configuration approach where the framework provides most boilerplate automatically.
## Custom App Structure
```
my_custom_app/
├── hooks.py # App configuration and hooks into Frappe lifecycle
├── modules.txt # List of business modules in this app
├── my_custom_app/
│ ├── __init__.py
│ ├── config/
│ │ └── desktop.py # Desktop workspace icons and shortcuts
│ ├── my_module/ # Business domain module (e.g., sales, inventory)
│ │ ├── doctype/ # Document Types (data models)
│ │ │ ├── customer/
│ │ │ │ ├── customer.py # Python controller (business logic)
│ │ │ │ ├── customer.json # Model definition (schema, validation)
│ │ │ │ └── customer.js # Frontend logic (UI interactions)
│ │ └── page/ # Custom pages (dashboards, reports)
│ ├── public/ # Static assets (CSS, JS, images)
│ ├── templates/ # Jinja2 templates for web pages
│ └── www/ # Web pages accessible via routes
└── requirements.txt # Python package dependencies
```
## Built-in Features (Auto-generated)
Every Frappe app automatically includes:
- **REST API** - Automatic CRUD endpoints from DocType definitions
- **Permissions system** - Row-level and field-level access control
- **Audit trails** - Automatic version tracking and change history
- **Custom fields** - Runtime field additions without code changes
- **Workflows** - Configurable approval and state management
- **Reports** - Query builder and report designer
- **Print formats** - PDF generation with custom templates
- **Email integration** - Template-based email sending
- **File attachments** - Document attachment management
## Creating Custom Apps
```bash
# Enter the development container
docker exec -it <container_name> bash
# Create new app (interactive prompts will ask for details)
bench new-app my_custom_app
# Install app to a site
bench --site mysite.com install-app my_custom_app
# Create a new DocType (data model)
bench --site mysite.com console
>>> bench.new_doc("DocType", {...})
# Or use the web UI: Setup → Customize → DocType → New
```

View file

@ -0,0 +1,62 @@
---
title: Docker Bind Mounts
---
# Docker Bind Mounts
## What Are Bind Mounts?
Bind mounts create a direct connection between a directory on your host machine and a directory inside a container. Changes in either location are immediately reflected in the other - perfect for development where you want to edit code on your host and see changes in the container.
## Bind Mount vs Named Volume vs Anonymous Volume
| Type | Syntax | Use Case | Persistence |
| -------------------- | ------------------------------ | -------------------------- | ---------------------------- |
| **Bind Mount** | `./local/path:/container/path` | Development, config files | On host filesystem |
| **Named Volume** | `volume_name:/container/path` | Production data, databases | Docker-managed |
| **Anonymous Volume** | `/container/path` | Temporary/cache data | Docker-managed, auto-deleted |
## Bind Mount Examples
```yaml
services:
backend:
volumes:
# Development: Edit code on host, run in container
- ./my_custom_app:/home/frappe/frappe-bench/apps/my_custom_app
# Configuration: Override container config with host file
- ./custom-config.json:/home/frappe/frappe-bench/sites/common_site_config.json:ro # :ro = read-only
# Logs: Access container logs on host for debugging
- ./logs:/home/frappe/frappe-bench/logs
# Database (not recommended for production)
- ./data/mysql:/var/lib/mysql
# Named volume for production database
db:
volumes:
- db_data:/var/lib/mysql # Managed by Docker, survives container deletion
volumes:
db_data: # Define named volume
```
## Performance Optimization (macOS/Windows)
Docker on macOS/Windows uses a VM, making bind mounts slower. Use these flags:
```yaml
volumes:
# :cached - Host writes are buffered (good for general development)
- ./development:/home/frappe/frappe-bench:cached
# :delegated - Container writes are buffered (best when container writes heavily)
- ./development:/home/frappe/frappe-bench:delegated
# :consistent - Full synchronization (slowest but safest)
- ./development:/home/frappe/frappe-bench:consistent
```
**Recommendation:** Use `:cached` for most development work on macOS/Windows.

View file

@ -0,0 +1,3 @@
---
title: Concepts
---