diff --git a/README.md b/README.md index 39f843eb..08ad3352 100644 --- a/README.md +++ b/README.md @@ -1,90 +1,641 @@ [![Build Stable](https://github.com/frappe/frappe_docker/actions/workflows/build_stable.yml/badge.svg)](https://github.com/frappe/frappe_docker/actions/workflows/build_stable.yml) [![Build Develop](https://github.com/frappe/frappe_docker/actions/workflows/build_develop.yml/badge.svg)](https://github.com/frappe/frappe_docker/actions/workflows/build_develop.yml) -Everything about [Frappe](https://github.com/frappe/frappe) and [ERPNext](https://github.com/frappe/erpnext) in containers. +# Frappe Docker -# Getting Started +Production-ready containerized setup for [Frappe](https://github.com/frappe/frappe) and [ERPNext](https://github.com/frappe/erpnext) applications. This repository provides Docker images and deployment configurations for running Frappe/ERPNext in both development and production environments. -To get started you need [Docker](https://docs.docker.com/get-docker/), [docker-compose](https://docs.docker.com/compose/), and [git](https://docs.github.com/en/get-started/getting-started-with-git/set-up-git) setup on your machine. For Docker basics and best practices refer to Docker's [documentation](http://docs.docker.com). +## Table of Contents -Once completed, chose one of the following two sections for next steps. +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) +- [Deployment Options](#deployment-options) +- [Architecture](#architecture) +- [Common Tasks](#common-tasks) +- [Configuration](#configuration) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) -### Try in Play With Docker +## Overview -To play in an already set up sandbox, in your browser, click the button below: +Frappe Docker provides a complete containerized solution for deploying the Frappe framework and ERPNext ERP system. It includes: + +- **Pre-built Docker images** for Frappe and ERPNext (versions 13, 14, and 15) +- **Multiple deployment configurations** (development, production, single-server) +- **Docker Compose setups** for easy orchestration +- **Support for custom apps** and extensions +- **Built-in backup and restore capabilities** +- **TLS/SSL support** via Traefik reverse proxy +- **Multi-tenancy support** with port-based routing +- **Development containers** with VSCode integration + +## Prerequisites + +Before you begin, ensure you have: + +- **Docker** (v20.10+) - [Installation Guide](https://docs.docker.com/get-docker/) +- **Docker Compose** (v2.0+) - [Installation Guide](https://docs.docker.com/compose/install/) +- **Git** - [Installation Guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- **System Requirements:** + - Minimum 4GB RAM (8GB recommended for production) + - 20GB free disk space + - Linux, macOS, or Windows with WSL2 + +## Quick Start + +Choose one of the following options to get started quickly: + +### Option 1: Try in Browser (Play With Docker) + +Click below to instantly spin up a Frappe/ERPNext instance in your browser: Try in PWD -### Try on your Dev environment +### Option 2: Local Development Setup -First clone the repo: +1. **Clone the repository:** -```sh +```bash git clone https://github.com/frappe/frappe_docker cd frappe_docker ``` -Then run: `docker compose -f pwd.yml up -d` +2. **Start the containers:** -### To run on ARM64 architecture follow this instructions +```bash +docker compose -f pwd.yml up -d +``` -After cloning the repo run this command to build multi-architecture images specifically for ARM64. +3. **Wait for initialization** (approximately 5 minutes) -`docker buildx bake --no-cache --set "*.platform=linux/arm64"` +```bash +# Monitor the setup progress +docker compose -f pwd.yml logs -f create-site +``` -and then +4. **Access ERPNext:** -- add `platform: linux/arm64` to all services in the `pwd.yml` -- replace the current specified versions of erpnext image on `pwd.yml` with `:latest` +- URL: `http://localhost:8080` +- Username: `Administrator` +- Password: `admin` -Then run: `docker compose -f pwd.yml up -d` +### Option 3: Production Setup -## Final steps +1. **Clone and configure:** -Wait for 5 minutes for ERPNext site to be created or check `create-site` container logs before opening browser on port 8080. (username: `Administrator`, password: `admin`) +```bash +git clone https://github.com/frappe/frappe_docker +cd frappe_docker +cp example.env .env +# Edit .env file with your configuration +``` -If you ran in a Dev Docker environment, to view container logs: `docker compose -f pwd.yml logs -f create-site`. Don't worry about some of the initial error messages, some services take a while to become ready, and then they go away. +2. **Deploy with production settings:** -# Documentation +```bash +docker compose up -d +``` -### [Frequently Asked Questions](https://github.com/frappe/frappe_docker/wiki/Frequently-Asked-Questions) +### ARM64 Architecture Support -### [Production](#production) +For ARM64 systems (Apple Silicon, Raspberry Pi): -- [List of containers](docs/list-of-containers.md) -- [Single Compose Setup](docs/single-compose-setup.md) +```bash +# Build ARM64 images +docker buildx bake --no-cache --set "*.platform=linux/arm64" + +# Modify pwd.yml to add platform: linux/arm64 to all services +# Then deploy +docker compose -f pwd.yml up -d +``` + +## Bench Wrapper Script + +To simplify working with bench commands, we provide a convenient wrapper script `bench.sh` that eliminates the need to type `docker compose exec backend bench` repeatedly. + +### Setup + +```bash +# Make the script executable (one-time setup) +chmod +x bench.sh +``` + +### Usage + +The script automatically detects which compose file you're using and provides a simpler interface: + +```bash +# Instead of: docker compose exec backend bench new-site mysite.local +./bench.sh new-site mysite.local + +# Instead of: docker compose exec backend bench --site mysite.local migrate +./bench.sh --site mysite.local migrate + +# With specific project name +./bench.sh -p erpnext-prod --site production.local backup + +# Get help +./bench.sh --help +``` + +### Features + +- **Auto-detection**: Automatically finds and uses the correct compose file (pwd.yml or compose.yaml) +- **Project support**: Use `-p` flag for specific docker-compose projects +- **Full compatibility**: Supports all bench commands and arguments +- **Error handling**: Checks if containers are running before executing commands +- **Help system**: Built-in help with common command examples + +## Deployment Options + +### Development Environment + +Perfect for developers working on Frappe apps: + +```bash +# Setup development environment with VSCode integration +cp -R devcontainer-example .devcontainer +cp -R development/vscode-example development/.vscode + +# Open in VSCode with Dev Containers extension +code . +# Then: "Reopen in Container" +``` + +**Features:** + +- Hot-reload support +- Debugging capabilities +- Pre-configured VSCode settings +- Multiple Python/Node versions + +### Production Environment + +For production deployments: + +```bash +# Using standard compose file +docker compose up -d + +# With external database/Redis +# Configure DB_HOST, REDIS_CACHE, REDIS_QUEUE in .env +docker compose up -d +``` + +**Features:** + +- Auto-restart on failure +- Health checks +- Log rotation +- Backup capabilities + +### Single Server Setup + +Simplified setup for single server deployments: + +```bash +docker compose -f pwd.yml up -d +``` + +This creates a complete ERPNext instance with all required services. + +## Architecture + +The Frappe Docker setup consists of multiple interconnected services: + +### Core Services + +| Service | Purpose | Port | +| --------------- | --------------------------- | ---- | +| **backend** | Gunicorn application server | 8000 | +| **frontend** | Nginx reverse proxy | 8080 | +| **websocket** | Socket.io real-time server | 9000 | +| **scheduler** | Background job scheduler | - | +| **queue-short** | Short-running job worker | - | +| **queue-long** | Long-running job worker | - | + +### Supporting Services + +| Service | Purpose | Default | +| --------------- | --------------------------- | ------------ | +| **db** | MariaDB/PostgreSQL database | MariaDB 10.6 | +| **redis-cache** | Redis cache server | Redis 6.2 | +| **redis-queue** | Redis queue server | Redis 6.2 | + +### Service Flow + +``` +User Request → Nginx (frontend) → Gunicorn (backend) → Database + ↓ ↓ + WebSocket Redis Cache + ↓ + Job Queues → Workers +``` + +## Common Tasks + +### Using the Bench Wrapper Script + +For convenience, we provide a `bench.sh` wrapper script that simplifies running bench commands from your host machine. + +```bash +# Make the script executable (first time only) +chmod +x bench.sh + +# Create a new site +./bench.sh new-site mysite.local --admin-password=admin --install-app erpnext + +# Run migrations +./bench.sh --site mysite.local migrate + +# Backup a site +./bench.sh --site mysite.local backup + +# Get help +./bench.sh --help +``` + +The script automatically detects which compose file you're using and handles the docker compose execution for you. + +### Site Management + +#### Create a new site + +Using wrapper script: + +```bash +./bench.sh new-site mysite.local \ + --mariadb-user-host-login-scope=% \ + --db-root-password=admin \ + --admin-password=admin \ + --install-app erpnext +``` + +Or directly with docker compose: + +```bash +docker compose exec backend bench new-site mysite.local \ + --mariadb-user-host-login-scope=% \ + --db-root-password=admin \ + --admin-password=admin \ + --install-app erpnext +``` + +#### List all sites + +Using wrapper script: + +```bash +./bench.sh --site all list-apps +``` + +Or directly: + +```bash +docker compose exec backend bench --site all list-apps +``` + +#### Migrate a site + +Using wrapper script: + +```bash +./bench.sh --site mysite.local migrate +``` + +Or directly: + +```bash +docker compose exec backend bench --site mysite.local migrate +``` + +#### Backup a site + +Using wrapper script: + +```bash +./bench.sh --site mysite.local backup +``` + +Or directly: + +```bash +docker compose exec backend bench --site mysite.local backup +``` + +### App Management + +#### Install an app + +Using wrapper script: + +```bash +# Get the app +./bench.sh get-app https://github.com/frappe/app_name + +# Install on site +./bench.sh --site mysite.local install-app app_name +``` + +Or directly: + +```bash +# Get the app +docker compose exec backend bench get-app https://github.com/frappe/app_name + +# Install on site +docker compose exec backend bench --site mysite.local install-app app_name +``` + +#### Update apps + +Using wrapper script: + +```bash +./bench.sh update --pull --apps +``` + +Or directly: + +```bash +docker compose exec backend bench update --pull --apps +``` + +### Database Operations + +#### Access MariaDB console + +```bash +docker compose exec db mysql -uroot -padmin +``` + +#### Import database + +Using wrapper script: + +```bash +./bench.sh --site mysite.local --force restore path/to/backup.sql.gz +``` + +Or directly: + +```bash +docker compose exec backend bench --site mysite.local \ + --force restore path/to/backup.sql.gz +``` + +### Monitoring & Logs + +#### View all logs + +```bash +docker compose logs -f +``` + +#### View specific service logs + +```bash +docker compose logs -f backend +docker compose logs -f frontend +``` + +#### Check service health + +```bash +docker compose ps +docker compose exec backend healthcheck.sh +``` + +### Security & SSL + +#### Setup Let's Encrypt SSL + +```bash +# Configure in .env +LETSENCRYPT_EMAIL=your@email.com +SITES=`yourdomain.com` + +# Deploy with Traefik +docker compose -f compose.yaml -f overrides/compose.https.yaml up -d +``` + +## Configuration + +### Environment Variables + +Create a `.env` file from the example: + +```bash +cp example.env .env +``` + +Key configuration options: + +| Variable | Description | Default | +| ------------------------- | ------------------------- | ---------- | +| `ERPNEXT_VERSION` | ERPNext version to deploy | `v15.69.2` | +| `DB_PASSWORD` | Database root password | `123` | +| `DB_HOST` | External database host | - | +| `REDIS_CACHE` | External Redis cache URL | - | +| `REDIS_QUEUE` | External Redis queue URL | - | +| `HTTP_PUBLISH_PORT` | HTTP port | `8080` | +| `FRAPPE_SITE_NAME_HEADER` | Site resolution header | `$$host` | + +### Custom Apps Configuration + +To include custom apps, create `apps.json`: + +```json +[ + { + "url": "https://github.com/frappe/erpnext", + "branch": "version-15" + }, + { + "url": "https://github.com/yourusername/custom-app", + "branch": "main" + } +] +``` + +Build custom image: + +```bash +export APPS_JSON_BASE64=$(base64 -i apps.json) +docker buildx bake -f docker-bake.hcl custom +``` + +### Multi-tenancy Setup + +For hosting multiple sites on different ports: + +```yaml +# compose.override.yml +services: + frontend: + ports: + - "8081:8080" # Site 1 + - "8082:8080" # Site 2 +``` + +## Advanced Features + +### Backup Automation + +Setup automated backups to S3: + +```bash +# Create backup script +docker compose exec backend push_backup.py \ + --site-name mysite.local \ + --bucket my-bucket \ + --region-name us-east-1 \ + --endpoint-url https://s3.amazonaws.com \ + --aws-access-key-id KEY \ + --aws-secret-access-key SECRET +``` + +### Custom Build Arguments + +Build with specific versions: + +```bash +docker buildx bake \ + --set "*.args.FRAPPE_VERSION=v15.0.0" \ + --set "*.args.ERPNEXT_VERSION=v15.0.0" \ + --set "*.args.PYTHON_VERSION=3.11.6" \ + --set "*.args.NODE_VERSION=18.18.2" +``` + +### Development with Bench + +Inside development container: + +```bash +# Create new bench +bench init --skip-redis-config-generation frappe-bench +cd frappe-bench + +# Start bench +bench start + +# Create new app +bench new-app my_custom_app + +# Install app +bench --site mysite.local install-app my_custom_app +``` + +## Troubleshooting + +### Container won't start + +```bash +# Check logs +docker compose logs backend + +# Verify configuration +docker compose config + +# Restart services +docker compose restart +``` + +### Site not accessible + +```bash +# Check site configuration (using wrapper script) +./bench.sh --site mysite.local show-config + +# Or directly +docker compose exec backend bench --site mysite.local show-config + +# Verify nginx is running +docker compose exec frontend nginx -t +``` + +### Database connection issues + +```bash +# Test database connection (using wrapper script) +./bench.sh --site mysite.local mariadb + +# Or directly +docker compose exec backend bench --site mysite.local mariadb + +# Check database logs +docker compose logs db +``` + +### Permission errors + +```bash +# Fix permissions +docker compose exec backend chown -R frappe:frappe /home/frappe/frappe-bench +``` + +### Reset admin password + +```bash +# Using wrapper script +./bench.sh --site mysite.local set-admin-password newpassword + +# Or directly +docker compose exec backend bench --site mysite.local set-admin-password newpassword +``` + +## Documentation + +### Essential Guides + +- [Frequently Asked Questions](https://github.com/frappe/frappe_docker/wiki/Frequently-Asked-Questions) - [Environment Variables](docs/environment-variables.md) +- [Site Operations](docs/site-operations.md) +- [Custom Apps](docs/custom-apps.md) +- [Development Guide](docs/development.md) +- [Troubleshooting](docs/troubleshoot.md) + +### Production Deployment + - [Single Server Example](docs/single-server-example.md) - [Setup Options](docs/setup-options.md) -- [Site Operations](docs/site-operations.md) - [Backup and Push Cron Job](docs/backup-and-push-cronjob.md) - [Port Based Multi Tenancy](docs/port-based-multi-tenancy.md) -- [Migrate from multi-image setup](docs/migrate-from-multi-image-setup.md) -- [running on linux/mac](docs/setup_for_linux_mac.md) - [TLS for local deployment](docs/tls-for-local-deployment.md) +- [Migrate from multi-image setup](docs/migrate-from-multi-image-setup.md) -### [Custom Images](#custom-images) - -- [Custom Apps](docs/custom-apps.md) -- [Custom Apps with podman](docs/custom-apps-podman.md) -- [Build Version 10 Images](docs/build-version-10-images.md) - -### [Development](#development) +### Development - [Development using containers](docs/development.md) - [Bench Console and VSCode Debugger](docs/bench-console-and-vscode-debugger.md) - [Connect to localhost services](docs/connect-to-localhost-services-from-containers-for-local-app-development.md) -### [Troubleshoot](docs/troubleshoot.md) +### Customization -# Contributing +- [Custom Apps](docs/custom-apps.md) +- [Custom Apps with Podman](docs/custom-apps-podman.md) +- [Build Version 10 Images](docs/build-version-10-images.md) -If you want to contribute to this repo refer to [CONTRIBUTING.md](CONTRIBUTING.md) +## Contributing -This repository is only for container related stuff. You also might want to contribute to: +We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. -- [Frappe framework](https://github.com/frappe/frappe#contributing), -- [ERPNext](https://github.com/frappe/erpnext#contributing), -- [Frappe Bench](https://github.com/frappe/bench). +### Related Projects + +- [Frappe Framework](https://github.com/frappe/frappe) - Full-stack web framework +- [ERPNext](https://github.com/frappe/erpnext) - Open source ERP +- [Frappe Bench](https://github.com/frappe/bench) - CLI tool for Frappe deployments + +## Support + +- [Official Documentation](https://frappeframework.com/docs) +- [Community Forum](https://discuss.frappe.io/) +- [Report Issues](https://github.com/frappe/frappe_docker/issues) +- [Commercial Support](https://frappe.io/support) + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. diff --git a/bench.sh b/bench.sh new file mode 100755 index 00000000..23ce2758 --- /dev/null +++ b/bench.sh @@ -0,0 +1,150 @@ +#!/bin/bash + +# Bench wrapper script for Frappe Docker +# This script simplifies running bench commands in the Docker container + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Default values +PROJECT_NAME="" +COMPOSE_FILE="" +SHOW_HELP=0 + +# Function to show help +show_help() { + cat << EOF +Frappe Docker Bench Wrapper Script +=================================== + +This script simplifies running bench commands in the Frappe Docker container. + +Usage: + ./bench.sh [OPTIONS] [BENCH_COMMAND] [ARGS...] + +Options: + -p, --project NAME Docker Compose project name + -f, --file FILE Docker Compose file to use (default: auto-detect) + -h, --help Show this help message + +Examples: + # Create a new site + ./bench.sh new-site mysite.local --admin-password=admin --install-app erpnext + + # Run bench command on specific site + ./bench.sh --site mysite.local migrate + + # Use with specific project + ./bench.sh -p erpnext-prod --site production.local backup + + # List all sites + ./bench.sh --site all list-apps + + # Get a new app + ./bench.sh get-app https://github.com/frappe/app_name + + # Install app on site + ./bench.sh --site mysite.local install-app app_name + + # Update bench + ./bench.sh update --pull --apps + + # Set admin password + ./bench.sh --site mysite.local set-admin-password newpassword + +Common Commands: + new-site Create a new site + backup Backup a site + restore Restore a site from backup + migrate Run migrations + list-apps List installed apps + install-app Install an app on a site + uninstall-app Uninstall an app from a site + get-app Download an app + update Update bench and apps + console Open Python console + mariadb Open MariaDB console + redis-cache Open Redis cache console + redis-queue Open Redis queue console + +Note: For new-site with MariaDB, you may need to add: + --mariadb-user-host-login-scope=% --db-root-password= + +EOF +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -p|--project) + PROJECT_NAME="$2" + shift 2 + ;; + -f|--file) + COMPOSE_FILE="$2" + shift 2 + ;; + -h|--help) + SHOW_HELP=1 + shift + ;; + *) + # Stop parsing options when we hit bench commands + break + ;; + esac +done + +# Show help if requested +if [ $SHOW_HELP -eq 1 ] || [ $# -eq 0 ]; then + show_help + exit 0 +fi + +# Auto-detect compose file if not specified +if [ -z "$COMPOSE_FILE" ]; then + if [ -f "pwd.yml" ] && docker compose -f pwd.yml ps --quiet backend 2>/dev/null | grep -q .; then + COMPOSE_FILE="pwd.yml" + echo -e "${GREEN}Using pwd.yml (detected running containers)${NC}" + elif [ -f "compose.yaml" ] && docker compose -f compose.yaml ps --quiet backend 2>/dev/null | grep -q .; then + COMPOSE_FILE="compose.yaml" + echo -e "${GREEN}Using compose.yaml (detected running containers)${NC}" + elif [ -f "docker-compose.yml" ] && docker compose -f docker-compose.yml ps --quiet backend 2>/dev/null | grep -q .; then + COMPOSE_FILE="docker-compose.yml" + echo -e "${GREEN}Using docker-compose.yml (detected running containers)${NC}" + elif [ -f "pwd.yml" ]; then + COMPOSE_FILE="pwd.yml" + echo -e "${YELLOW}Using pwd.yml (default, no running containers detected)${NC}" + elif [ -f "compose.yaml" ]; then + COMPOSE_FILE="compose.yaml" + echo -e "${YELLOW}Using compose.yaml (default, no running containers detected)${NC}" + else + echo -e "${RED}Error: No docker-compose file found (pwd.yml or compose.yaml)${NC}" + exit 1 + fi +fi + +# Build the docker compose command +DOCKER_CMD="docker compose" +if [ -n "$COMPOSE_FILE" ]; then + DOCKER_CMD="$DOCKER_CMD -f $COMPOSE_FILE" +fi +if [ -n "$PROJECT_NAME" ]; then + DOCKER_CMD="$DOCKER_CMD -p $PROJECT_NAME" +fi + +# Check if backend container is running +if ! $DOCKER_CMD ps --quiet backend 2>/dev/null | grep -q .; then + echo -e "${RED}Error: Backend container is not running${NC}" + echo -e "${YELLOW}Start containers with: docker compose -f $COMPOSE_FILE up -d${NC}" + exit 1 +fi + +# Execute the bench command +echo -e "${GREEN}Executing: bench $@${NC}" +$DOCKER_CMD exec backend bench "$@" \ No newline at end of file diff --git a/development/installer.py b/development/installer.py index edd62147..d61445cd 100755 --- a/development/installer.py +++ b/development/installer.py @@ -207,11 +207,11 @@ def create_site_in_bench(args): new_site_cmd = [ "bench", "new-site", - f"--db-root-username=root", - f"--db-host=mariadb", # Should match the compose service name + "--db-root-username=root", + "--db-host=mariadb", # Should match the compose service name f"--db-type={args.db_type}", # Add the selected database type - f"--mariadb-user-host-login-scope=%", - f"--db-root-password=123", # Replace with your MariaDB password + "--mariadb-user-host-login-scope=%", + "--db-root-password=123", # Replace with your MariaDB password f"--admin-password={args.admin_password}", ] else: @@ -223,10 +223,10 @@ def create_site_in_bench(args): new_site_cmd = [ "bench", "new-site", - f"--db-root-username=root", - f"--db-host=postgresql", # Should match the compose service name + "--db-root-username=root", + "--db-host=postgresql", # Should match the compose service name f"--db-type={args.db_type}", # Add the selected database type - f"--db-root-password=123", # Replace with your PostgreSQL password + "--db-root-password=123", # Replace with your PostgreSQL password f"--admin-password={args.admin_password}", ] apps = os.listdir(f"{os.getcwd()}/{args.bench_name}/apps")