Add zerops.yml with deployment specs.

This commit is contained in:
David Uhrin 2025-10-22 15:19:25 +02:00
parent ea00b0ec9d
commit 831c3716e4
8 changed files with 991 additions and 0 deletions

195
HYBRID_DEPLOYMENT.md Normal file
View file

@ -0,0 +1,195 @@
# Hybrid Deployment Guide: Apps in Image + Persistent Volumes
This configuration implements the best of both worlds:
- **Apps baked into Docker image** for consistency and fast deployments
- **Site data in persistent volumes** for data safety and persistence
## Architecture Overview
### What's in the Image (Built once, reusable):
- ✅ Frappe and ERPNext applications
- ✅ All Python dependencies
- ✅ Custom apps (if configured)
- ✅ Basic directory structure
### What's in Persistent Volumes:
- ✅ Site configurations (`sites/[site-name]/site_config.json`)
- ✅ Uploaded files (`sites/[site-name]/public/files/`)
- ✅ Private files (`sites/[site-name]/private/files/`)
- ✅ Site-specific customizations
- ✅ Database backups
- ✅ Application logs
## Deployment Steps
### 1. Set Required Environment Secrets in Zerops
```bash
# In Zerops Dashboard > Project > Environment Variables
db_password=YourSecureDbPassword123
admin_password=YourAdminPassword123
site_name=your-domain.com
```
### 2. Deploy the Configuration
1. Import the `zerops.yml` file to Zerops
2. Zerops will build all services using `Dockerfile.zerops`
3. Each service will run the initialization script on startup
4. Site will be automatically created if it doesn't exist
### 3. Automatic Initialization Process
On first deployment, each container will:
1. **Build Phase** (runs once during image creation):
- Install Frappe/ERPNext apps into image
- Copy initialization scripts
- Set proper permissions
2. **Runtime Phase** (runs on every container start):
- **Backend service**: Full site initialization (creates site, installs ERPNext)
- **Other services**: Light initialization (just checks if site exists)
- Configure database and Redis connections
- Wait for database to be ready (backend only)
- Set proper permissions and configurations
## Benefits of This Approach
### ✅ **Container Restart Resilience**
- Site data survives container restarts/crashes
- No manual intervention required
- Fast recovery times
### ✅ **Consistent App Deployments**
- Apps are identical across all containers
- No version drift between services
- Easy to update apps (rebuild image)
### ✅ **Zero-Downtime Updates**
- App updates: rebuild image, rolling update
- Site data preserved during updates
- Database migrations handled automatically
### ✅ **Backup & Recovery**
- Simple volume snapshots for site data
- Database backups work seamlessly
- Easy disaster recovery
### ✅ **Scalability**
- New containers start with same apps
- Shared persistent volume for site data
- Auto-scaling works out of the box
## File Structure
```
/home/frappe/frappe-bench/
├── apps/ # Apps (in image)
│ ├── frappe/ # Frappe framework
│ └── erpnext/ # ERPNext app
├── sites/ # Site data (persistent volume)
│ ├── apps.txt # List of installed apps
│ ├── common_site_config.json
│ └── your-domain.com/ # Your site directory
│ ├── site_config.json
│ ├── public/files/ # Uploaded files
│ └── private/files/ # Private files
└── logs/ # Application logs (persistent volume)
```
## Common Operations
### Adding New Custom Apps
1. **Update `Dockerfile.zerops`**:
```dockerfile
RUN bench get-app --branch main custom_app https://github.com/user/custom_app.git
```
2. **Redeploy services** (Zerops will rebuild image)
3. **Install app on site** (automatic or manual):
```bash
bench --site your-domain.com install-app custom_app
```
### Updating Frappe/ERPNext Version
1. **Update version in `Dockerfile.zerops`**:
```dockerfile
FROM frappe/erpnext:v16.0.0
```
2. **Update `zerops.yml` environment**:
```yaml
ERPNEXT_VERSION: v16.0.0
```
3. **Redeploy** - migrations run automatically
### Manual Site Operations
Access any service terminal in Zerops dashboard:
```bash
# Navigate to bench directory
cd /home/frappe/frappe-bench
# Run migrations
bench --site your-domain.com migrate
# Create new site
bench new-site newsite.com --install-app erpnext
# Install custom app
bench --site your-domain.com install-app custom_app
# Backup site
bench --site your-domain.com backup --with-files
# Console access
bench --site your-domain.com console
```
## Troubleshooting
### Site Not Created Automatically
- Check environment variables are set correctly
- Check database connectivity
- Review container logs in Zerops dashboard
- Manually run: `/home/frappe/init-site.sh`
### Permission Issues
- Persistent volumes should be owned by `frappe:frappe`
- Run: `chown -R frappe:frappe /home/frappe/frappe-bench/sites`
### App Installation Issues
- Verify apps are in the image: `ls /home/frappe/frappe-bench/apps`
- Check apps.txt: `cat /home/frappe/frappe-bench/sites/apps.txt`
- Manually install: `bench --site [site] install-app [app]`
### Database Connection Issues
- Verify database service is running
- Check environment variables
- Test connection: `mysql -h$DB_HOST -P$DB_PORT -uroot -p$DB_PASSWORD`
## Monitoring
### Health Checks
- All services have health checks configured
- Monitor in Zerops dashboard
- Backend: `/api/method/ping`
- WebSocket: `/socket.io/`
### Logs
- Application logs in persistent volume: `/home/frappe/frappe-bench/logs`
- Container logs in Zerops dashboard
- Database logs in MariaDB service logs
### Performance
- Monitor resource usage in Zerops dashboard
- Auto-scaling configured based on CPU/memory
- Adjust container limits as needed
This hybrid approach gives you the reliability of persistent data with the consistency of containerized applications!

159
ZEROPS_DEPLOYMENT.md Normal file
View file

@ -0,0 +1,159 @@
# Deploying Frappe/ERPNext on Zerops
This repository contains the Zerops configuration file (`zerops.yml`) to deploy Frappe/ERPNext on the Zerops platform.
## Architecture Overview
The deployment consists of the following services:
- **MariaDB** (`db`) - Database service (HA mode)
- **Redis Cache** (`redis-cache`) - Caching layer
- **Redis Queue** (`redis-queue`) - Background job queue
- **Backend** (`backend`) - Main Frappe application server
- **Frontend** (`frontend`) - Nginx reverse proxy
- **WebSocket** (`websocket`) - Real-time communication server
- **Queue Workers** (`queue-short`, `queue-long`) - Background job processors
- **Scheduler** (`scheduler`) - Cron job scheduler
## Prerequisites
1. A Zerops account - [Sign up here](https://zerops.io)
2. Access to this GitHub repository
3. Basic knowledge of Frappe/ERPNext
## Deployment Steps
### 1. Import Project to Zerops
1. Log into your Zerops dashboard
2. Click "Import project"
3. Select "Import from Git repository"
4. Enter the repository URL: `https://github.com/UhrinDavid/frappe_docker`
5. Select the `zerops.yml` file
6. Click "Import project"
### 2. Configure Environment Secrets
Before deployment, you need to set the following environment secrets in Zerops:
#### Required Secrets:
- `db_password` - Password for MariaDB database (choose a strong password)
- `site_name` - Your site domain name (e.g., `mycompany.example.com`)
#### Optional Secrets:
- `ERPNEXT_VERSION` - ERPNext version (default: v15.84.0)
To set secrets:
1. Go to your project in Zerops dashboard
2. Navigate to each service
3. Go to "Environment variables" section
4. Add the required secrets
### 3. Deploy the Services
1. Zerops will automatically start building and deploying all services
2. Monitor the build progress in the Zerops dashboard
3. Wait for all services to reach "Running" status
### 4. Post-Deployment Setup
Once all services are running, you need to initialize your Frappe site:
1. Access the backend service terminal in Zerops dashboard
2. Create your first site:
```bash
bench new-site your-site-name --db-root-password <db_password>
```
3. Install ERPNext:
```bash
bench --site your-site-name install-app erpnext
```
4. Set the site as default:
```bash
bench use your-site-name
```
5. Create an admin user:
```bash
bench --site your-site-name add-user admin administrator --password <admin-password>
```
### 5. Access Your Application
Your Frappe/ERPNext instance will be available at the domain provided by Zerops for the `frontend` service.
## Configuration Details
### Resource Allocation
- **Backend**: 1-3 containers, autoscaling enabled
- **Frontend**: 1-2 containers
- **WebSocket**: 1-2 containers
- **Queue Workers**: 1-3 containers (short), 1-2 containers (long)
- **Scheduler**: 1 container (fixed)
- **Databases**: HA mode for production reliability
### Health Checks
All services include health checks to ensure proper operation:
- Backend: `/api/method/ping`
- Frontend: `/api/method/ping`
- WebSocket: `/socket.io/`
### Autoscaling
Backend and queue workers have autoscaling configured based on:
- CPU usage threshold: 70%
- Memory usage threshold: 80%
## Troubleshooting
### Common Issues
1. **Services not starting**: Check environment variables are set correctly
2. **Database connection errors**: Verify `db_password` secret is set
3. **Site access issues**: Ensure `site_name` matches your domain
### Logs
Access service logs through the Zerops dashboard:
1. Go to your project
2. Select the service
3. Navigate to "Runtime logs"
### Manual Commands
To run manual bench commands:
1. Access the backend service terminal
2. Navigate to `/home/frappe/frappe-bench`
3. Run your bench commands
## Customization
### Custom Apps
To add custom Frappe apps:
1. Modify the Dockerfile to include your apps
2. Update the `zerops.yml` build configuration
3. Redeploy the services
### Environment Variables
Additional environment variables can be added in the `zerops.yml` file under the `envSecrets` section for each service.
### Scaling
Adjust the `minContainers` and `maxContainers` values in `zerops.yml` based on your traffic requirements.
## Support
For issues specific to:
- Zerops platform: [Zerops Documentation](https://docs.zerops.io)
- Frappe/ERPNext: [Frappe Documentation](https://docs.frappe.io)
- This deployment setup: Create an issue in this repository
## License
This configuration is provided under the same license as the original frappe_docker repository.

View file

@ -0,0 +1,81 @@
#!/bin/bash
# Frappe Site Initialization Script for Production Deployment
# This script runs before the main service starts to ensure the site exists and is configured
set -e
echo "🔧 Initializing Frappe site..."
# Configuration from environment variables
SITE_NAME=${FRAPPE_SITE_NAME_HEADER:-"localhost"}
DB_PASSWORD=${DB_PASSWORD:-"admin"}
ADMIN_PASSWORD=${ADMIN_PASSWORD:-"admin"}
DB_HOST=${DB_HOST:-"db"}
DB_PORT=${DB_PORT:-"3306"}
echo "📋 Configuration: Site Name: $SITE_NAME, Database Host: $DB_HOST:$DB_PORT"
# Navigate to frappe bench directory
cd /home/frappe/frappe-bench
# Configure database and Redis connections
echo "🔗 Configuring connections..."
bench set-config -g db_host "$DB_HOST" || echo "DB host config already set"
bench set-config -gp db_port "$DB_PORT" || echo "DB port config already set"
bench set-config -g redis_cache "redis://${REDIS_CACHE}:6379" || echo "Redis cache config already set"
bench set-config -g redis_queue "redis://${REDIS_QUEUE}:6379" || echo "Redis queue config already set"
bench set-config -g redis_socketio "redis://${REDIS_QUEUE}:6379" || echo "Redis socketio config already set"
bench set-config -gp socketio_port "${SOCKETIO_PORT}" || echo "Socketio port config already set"
# Wait for database to be ready
echo "⏳ Waiting for database to be ready..."
for i in {1..30}; do
if mysql -h"$DB_HOST" -P"$DB_PORT" -uroot -p"$DB_PASSWORD" -e "SELECT 1;" >/dev/null 2>&1; then
echo "✅ Database is ready!"
break
fi
echo " Attempt $i/30: Database not ready, waiting 5 seconds..."
sleep 5
done
# Check if site exists in persistent volume
if [ -d "sites/$SITE_NAME" ]; then
echo "✅ Site '$SITE_NAME' already exists, updating configuration"
bench --site "$SITE_NAME" set-config db_host "$DB_HOST"
bench --site "$SITE_NAME" set-config db_port "$DB_PORT"
bench use "$SITE_NAME" || echo "Site already set as default"
else
echo "🏗️ Creating new site: $SITE_NAME"
if bench new-site "$SITE_NAME" \
--db-root-password "$DB_PASSWORD" \
--admin-password "$ADMIN_PASSWORD" \
--install-app erpnext \
--set-default; then
echo "✅ Site created successfully!"
# Install custom XML importer app
echo "📦 Installing XML Importer app..."
bench get-app --branch main erpnext_xml_importer https://github.com/UhrinDavid/erpnext_xml_importer.git || echo "⚠️ Failed to download XML importer"
bench --site "$SITE_NAME" install-app erpnext_xml_importer || echo "⚠️ XML importer app installation failed"
bench --site "$SITE_NAME" set-config developer_mode 0
bench --site "$SITE_NAME" set-config maintenance_mode 0
echo "🎉 Site '$SITE_NAME' is ready with XML Importer!"
else
echo "❌ Failed to create site. Checking if it exists..."
if [ -d "sites/$SITE_NAME" ]; then
echo "⚠️ Site directory exists but creation failed. Using existing site."
bench use "$SITE_NAME" || echo "Could not set as default"
else
echo "💥 Site creation failed completely. Exiting."
exit 1
fi
fi
fi
# Ensure proper ownership of sites directory
chown -R frappe:frappe sites/ || echo "Could not change ownership"
chmod -R 755 sites/ || echo "Could not change permissions"
echo "✅ Site initialization completed successfully!"

20
scripts/init-service.sh Normal file
View file

@ -0,0 +1,20 @@
#!/bin/bash
# Simple service initialization for Frappe services
# This script runs on services that don't need to create sites
set -e
SERVICE_NAME=${1:-"frappe-service"}
echo "🔧 Initializing $SERVICE_NAME..."
cd /home/frappe/frappe-bench
# Basic configuration (site creation handled by backend service)
if [ -f sites/common_site_config.json ] && [ -n "${FRAPPE_SITE_NAME_HEADER}" ]; then
if [ -d "sites/${FRAPPE_SITE_NAME_HEADER}" ]; then
bench use "${FRAPPE_SITE_NAME_HEADER}" || echo "Site will be set by backend"
fi
fi
echo "$SERVICE_NAME ready"

99
scripts/init-site.sh Normal file
View file

@ -0,0 +1,99 @@
#!/bin/bash
# Frappe Site Initialization Script for Zerops
# This script runs on container start to ensure the site exists
set -e
echo "🔧 Initializing Frappe site..."
# Configuration from environment variables
SITE_NAME=${FRAPPE_SITE_NAME_HEADER:-"localhost"}
DB_PASSWORD=${DB_PASSWORD:-"admin"}
ADMIN_PASSWORD=${ADMIN_PASSWORD:-"admin"}
DB_HOST=${DB_HOST:-"db"}
DB_PORT=${DB_PORT:-"3306"}
echo "📋 Configuration:"
echo " Site Name: $SITE_NAME"
echo " Database Host: $DB_HOST:$DB_PORT"
# Navigate to frappe bench directory
cd /home/frappe/frappe-bench
# Ensure sites directory exists and has proper permissions
mkdir -p sites
chown -R frappe:frappe sites || true
# Configure database and Redis connections
echo "🔗 Configuring connections..."
bench set-config -g db_host "$DB_HOST" || echo "DB host config already set"
bench set-config -gp db_port "$DB_PORT" || echo "DB port config already set"
bench set-config -g redis_cache "redis://${REDIS_CACHE}:6379" || echo "Redis cache config already set"
bench set-config -g redis_queue "redis://${REDIS_QUEUE}:6379" || echo "Redis queue config already set"
bench set-config -g redis_socketio "redis://${REDIS_QUEUE}:6379" || echo "Redis socketio config already set"
bench set-config -gp socketio_port "${SOCKETIO_PORT}" || echo "Socketio port config already set"
# Wait for database to be ready
echo "⏳ Waiting for database to be ready..."
for i in {1..30}; do
if mysql -h"$DB_HOST" -P"$DB_PORT" -uroot -p"$DB_PASSWORD" -e "SELECT 1;" >/dev/null 2>&1; then
echo "✅ Database is ready!"
break
fi
echo " Attempt $i/30: Database not ready, waiting 5 seconds..."
sleep 5
done
# Check if site already exists in persistent volume
if [ -d "sites/$SITE_NAME" ]; then
echo "✅ Site '$SITE_NAME' already exists, skipping creation"
# Ensure site is in the current bench context
if [ -f "sites/$SITE_NAME/site_config.json" ]; then
echo "🔧 Updating site configuration..."
bench --site "$SITE_NAME" set-config db_host "$DB_HOST"
bench --site "$SITE_NAME" set-config db_port "$DB_PORT"
bench use "$SITE_NAME" || echo "Site already set as default"
fi
else
echo "🏗️ Creating new site: $SITE_NAME"
# Create the site with ERPNext
if bench new-site "$SITE_NAME" \
--db-root-password "$DB_PASSWORD" \
--admin-password "$ADMIN_PASSWORD" \
--install-app erpnext \
--set-default; then
echo "✅ Site created successfully!"
# Additional site configuration
bench --site "$SITE_NAME" set-config developer_mode 0
bench --site "$SITE_NAME" set-config maintenance_mode 0
echo "🎉 Site '$SITE_NAME' is ready!"
else
echo "❌ Failed to create site. Checking if it exists..."
if [ -d "sites/$SITE_NAME" ]; then
echo "⚠️ Site directory exists but creation failed. Using existing site."
bench use "$SITE_NAME" || echo "Could not set as default"
else
echo "💥 Site creation failed completely. Exiting."
exit 1
fi
fi
fi
# Ensure proper ownership of sites directory
chown -R frappe:frappe sites/ || echo "Could not change ownership"
chmod -R 755 sites/ || echo "Could not change permissions"
# Final verification
if [ -d "sites/$SITE_NAME" ]; then
echo "✅ Site initialization completed successfully!"
echo "🌐 Site '$SITE_NAME' is ready to serve traffic"
else
echo "❌ Site initialization failed!"
exit 1
fi

75
scripts/setup-frappe.sh Normal file
View file

@ -0,0 +1,75 @@
#!/bin/bash
# Frappe/ERPNext Initial Setup Script for Zerops
# This script should be run after the services are deployed and running
set -e
echo "🚀 Starting Frappe/ERPNext setup on Zerops..."
# Check if required environment variables are set
if [ -z "$SITE_NAME" ]; then
echo "❌ Error: SITE_NAME environment variable is required"
echo " Set it to your domain name (e.g., mycompany.example.com)"
exit 1
fi
if [ -z "$DB_PASSWORD" ]; then
echo "❌ Error: DB_PASSWORD environment variable is required"
exit 1
fi
if [ -z "$ADMIN_PASSWORD" ]; then
echo "❌ Error: ADMIN_PASSWORD environment variable is required"
echo " This will be the password for the ERPNext admin user"
exit 1
fi
echo "📋 Configuration:"
echo " Site Name: $SITE_NAME"
echo " Database Host: ${DB_HOST:-db}"
echo " Admin Email: ${ADMIN_EMAIL:-administrator@$SITE_NAME}"
# Navigate to frappe bench directory
cd /home/frappe/frappe-bench
echo "🏗️ Creating new site: $SITE_NAME"
bench new-site "$SITE_NAME" \
--db-root-password "$DB_PASSWORD" \
--admin-password "$ADMIN_PASSWORD" \
--set-default
echo "📦 Installing ERPNext application..."
bench --site "$SITE_NAME" install-app erpnext
echo "👤 Setting up admin user..."
if [ -n "$ADMIN_EMAIL" ]; then
bench --site "$SITE_NAME" set-admin-password "$ADMIN_PASSWORD"
fi
echo "🔧 Final configuration..."
# Set site as default
bench use "$SITE_NAME"
# Clear cache
bench --site "$SITE_NAME" clear-cache
# Migrate database (in case there are any pending migrations)
bench --site "$SITE_NAME" migrate
echo "✅ Setup completed successfully!"
echo ""
echo "🌐 Your ERPNext site is ready at: $SITE_NAME"
echo "👤 Admin login: administrator"
echo "🔑 Admin password: [as set in ADMIN_PASSWORD]"
echo ""
echo "📚 Next steps:"
echo " 1. Configure your domain to point to this Zerops service"
echo " 2. Access your site and complete the setup wizard"
echo " 3. Configure SSL certificates if needed"
echo ""
echo "🔧 Useful commands:"
echo " - bench restart: Restart all processes"
echo " - bench --site $SITE_NAME console: Open Python console"
echo " - bench --site $SITE_NAME migrate: Run database migrations"
echo " - bench update: Update apps and migrate"

71
zerops.env Normal file
View file

@ -0,0 +1,71 @@
# Production Environment Configuration for Zerops Deployment
# Copy this file and customize the values for your deployment
# =============================================================================
# REQUIRED ZEROPS SECRETS (set these in Zerops Dashboard > Environment Variables)
# =============================================================================
db_password=your-strong-database-password
admin_password=your-admin-password
site_name=your-domain.com
# =============================================================================
# OPTIONAL CONFIGURATION (modify as needed)
# =============================================================================
ADMIN_EMAIL=admin@your-domain.com
ERPNEXT_VERSION=v15.84.0
# Database Configuration (managed by Zerops)
DB_HOST=db
DB_PORT=3306
# Redis Configuration (managed by Zerops)
REDIS_CACHE=redis-cache:6379
REDIS_QUEUE=redis-queue:6379
# Application Configuration
SOCKETIO_PORT=9000
FRAPPE_SITE_NAME_HEADER=your-domain.com
# Nginx/Proxy Configuration
UPSTREAM_REAL_IP_ADDRESS=127.0.0.1
UPSTREAM_REAL_IP_HEADER=X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE=off
PROXY_READ_TIMEOUT=120s
CLIENT_MAX_BODY_SIZE=50m
# Frappe/ERPNext Image Configuration
CUSTOM_IMAGE=frappe/erpnext
CUSTOM_TAG=v15.84.0
PULL_POLICY=always
RESTART_POLICY=unless-stopped
# Backup Configuration (optional)
# BACKUP_S3_BUCKET=your-backup-bucket
# BACKUP_S3_ACCESS_KEY=your-access-key
# BACKUP_S3_SECRET_KEY=your-secret-key
# BACKUP_S3_REGION=your-region
# Email Configuration (optional)
# MAIL_SERVER=smtp.your-email-provider.com
# MAIL_PORT=587
# MAIL_USERNAME=your-email@domain.com
# MAIL_PASSWORD=your-email-password
# MAIL_USE_TLS=true
# SSL/TLS Configuration (optional, if not using Zerops automatic SSL)
# LETSENCRYPT_EMAIL=your-email@domain.com
# SITES=your-domain.com
# =============================================================================
# DEPLOYMENT INSTRUCTIONS
# =============================================================================
# 1. Set the 3 required secrets in Zerops Dashboard:
# - db_password: Strong password for MariaDB (min 8 chars)
# - admin_password: Password for ERPNext admin user (min 8 chars)
# - site_name: Your domain name (e.g., mycompany.example.com)
#
# 2. Deploy using zerops.yml file
#
# 3. Access your ERPNext site at the domain specified in site_name
# - Username: administrator
# - Password: [value from admin_password secret]

291
zerops.yml Normal file
View file

@ -0,0 +1,291 @@
# Zerops YAML configuration for Frappe/ERPNext deployment
# This file defines the infrastructure and deployment settings for Zerops platform
# Documentation: https://docs.zerops.io/
# Import this file in Zerops GUI to create the project with all required services
project:
name: frappe-erpnext
services:
# MariaDB Database Service
- hostname: db
type: mariadb
version: "11"
mode: HA
priority: 10
# Zerops will automatically configure MariaDB with UTF8MB4
# Redis Cache Service
- hostname: redis-cache
type: redis
version: "6"
mode: HA
priority: 10
# Redis Queue Service
- hostname: redis-queue
type: redis
version: "6"
mode: HA
priority: 10
# Main Backend Application (Frappe/ERPNext)
- hostname: backend
type: python
version: "3.11"
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
enableSubdomainAccess: false
minContainers: 1
maxContainers: 3
autoscaling:
cpuThreshold: 70
memoryThreshold: 80
# Environment variables
envSecrets:
DB_PASSWORD: ${db_password}
ADMIN_PASSWORD: ${admin_password}
ERPNEXT_VERSION: v15.84.0
DB_HOST: db
DB_PORT: 3306
REDIS_CACHE: redis-cache
REDIS_QUEUE: redis-queue
SOCKETIO_PORT: 9000
FRAPPE_SITE_NAME_HEADER: ${site_name}
CUSTOM_IMAGE: frappe/erpnext
CUSTOM_TAG: ${ERPNEXT_VERSION}
# Persistent volumes for site data
volumes:
- name: frappe-sites
mountPath: /home/frappe/frappe-bench/sites
size: 20GB
- name: frappe-logs
mountPath: /home/frappe/frappe-bench/logs
size: 5GB
# Build settings using production Dockerfile
build:
dockerfile: ./images/production/Containerfile
context: .
# Build-time commands to include site and apps in image
buildCommands:
- |
# Install any additional apps during build
# Example: bench get-app --branch main custom_app https://github.com/user/custom_app
echo "Building Frappe image with pre-installed apps..."
# Runtime initialization - deployment specific
runPrepareCommands:
- |
# Copy and execute the site initialization script
cp scripts/init-frappe-site.sh /home/frappe/init-frappe-site.sh
chmod +x /home/frappe/init-frappe-site.sh
chown frappe:frappe /home/frappe/init-frappe-site.sh
# Run the initialization script as frappe user
su - frappe -c "/home/frappe/init-frappe-site.sh"
# Health check
healthCheck:
httpGet:
port: 8000
path: /api/method/ping
initialDelaySeconds: 120
periodSeconds: 30
# Frontend/Nginx Proxy Service
- hostname: frontend
type: nginx
version: "1.24"
enableSubdomainAccess: true
minContainers: 1
maxContainers: 2
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
# Environment variables for nginx templating
envSecrets:
BACKEND: backend:8000
SOCKETIO: websocket:9000
FRAPPE_SITE_NAME_HEADER: ${site_name}
UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1
UPSTREAM_REAL_IP_HEADER: X-Forwarded-For
UPSTREAM_REAL_IP_RECURSIVE: "off"
PROXY_READ_TIMEOUT: 120s
CLIENT_MAX_BODY_SIZE: 50m
# Build nginx with custom configuration
build:
dockerfile: ./images/production/Containerfile
context: .
# Use the nginx configuration from the frappe image
runPrepareCommands:
- cp /opt/frappe/nginx-template.conf /etc/nginx/conf.d/default.conf.template
- envsubst '$BACKEND $SOCKETIO $FRAPPE_SITE_NAME_HEADER' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
# Command to run nginx
start: nginx-entrypoint.sh
# Health check
healthCheck:
httpGet:
port: 8080
path: /api/method/ping
initialDelaySeconds: 30
periodSeconds: 10
# WebSocket Service
- hostname: websocket
type: nodejs
version: "18"
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
enableSubdomainAccess: false
minContainers: 1
maxContainers: 2
# Shared persistent volumes for site access
volumes:
- name: frappe-sites
mountPath: /home/frappe/frappe-bench/sites
size: 20GB
# Environment variables
envSecrets:
DB_HOST: db
DB_PORT: 3306
REDIS_CACHE: redis-cache
REDIS_QUEUE: redis-queue
SOCKETIO_PORT: 9000
build:
dockerfile: ./images/production/Containerfile
context: .
runPrepareCommands:
- |
# Copy and execute the service initialization script
cp scripts/init-service.sh /home/frappe/init-service.sh
chmod +x /home/frappe/init-service.sh
chown frappe:frappe /home/frappe/init-service.sh
# Run the initialization script as frappe user
su - frappe -c "/home/frappe/init-service.sh WebSocket"
# Command to run the WebSocket server
start: node /home/frappe/frappe-bench/apps/frappe/socketio.js
# Health check
healthCheck:
httpGet:
port: 9000
path: /socket.io/
initialDelaySeconds: 60
periodSeconds: 30
# Queue Worker - Short Tasks
- hostname: queue-short
type: python
version: "3.11"
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
enableSubdomainAccess: false
minContainers: 1
maxContainers: 3
# Shared persistent volumes for site access
volumes:
- name: frappe-sites
mountPath: /home/frappe/frappe-bench/sites
size: 20GB
# Environment variables
envSecrets:
DB_HOST: db
DB_PORT: 3306
REDIS_CACHE: redis-cache
REDIS_QUEUE: redis-queue
build:
dockerfile: ./images/production/Containerfile
context: .
runPrepareCommands:
- |
# Copy and execute the service initialization script
cp scripts/init-service.sh /home/frappe/init-service.sh
chmod +x /home/frappe/init-service.sh
chown frappe:frappe /home/frappe/init-service.sh
# Run the initialization script as frappe user
su - frappe -c "/home/frappe/init-service.sh 'Queue Worker (Short)'"
# Command to run the worker
start: bench worker --queue short,default
# Queue Worker - Long Tasks
- hostname: queue-long
type: python
version: "3.11"
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
enableSubdomainAccess: false
minContainers: 1
maxContainers: 2
# Shared persistent volumes for site access
volumes:
- name: frappe-sites
mountPath: /home/frappe/frappe-bench/sites
size: 20GB
# Environment variables
envSecrets:
DB_HOST: db
DB_PORT: 3306
REDIS_CACHE: redis-cache
REDIS_QUEUE: redis-queue
build:
dockerfile: ./images/production/Containerfile
context: .
runPrepareCommands:
- |
# Copy and execute the service initialization script
cp scripts/init-service.sh /home/frappe/init-service.sh
chmod +x /home/frappe/init-service.sh
chown frappe:frappe /home/frappe/init-service.sh
# Run the initialization script as frappe user
su - frappe -c "/home/frappe/init-service.sh 'Queue Worker (Long)'"
# Command to run the long queue worker
start: bench worker --queue long,default,short
# Scheduler Service
- hostname: scheduler
type: python
version: "3.11"
buildFromGit: https://github.com/UhrinDavid/frappe_docker@zerops
enableSubdomainAccess: false
minContainers: 1
maxContainers: 1
# Shared persistent volumes for site access
volumes:
- name: frappe-sites
mountPath: /home/frappe/frappe-bench/sites
size: 20GB
# Environment variables
envSecrets:
DB_HOST: db
DB_PORT: 3306
REDIS_CACHE: redis-cache
REDIS_QUEUE: redis-queue
build:
dockerfile: ./images/production/Containerfile
context: .
runPrepareCommands:
- |
# Copy and execute the service initialization script
cp scripts/init-service.sh /home/frappe/init-service.sh
chmod +x /home/frappe/init-service.sh
chown frappe:frappe /home/frappe/init-service.sh
# Run the initialization script as frappe user
su - frappe -c "/home/frappe/init-service.sh Scheduler"
# Command to run the scheduler
start: bench schedule
# Required secrets that need to be set in Zerops dashboard:
# - db_password: Database password for MariaDB (e.g., "mySecureDbPassword123")
# - admin_password: ERPNext admin user password (e.g., "myAdminPassword123")
# - site_name: Your site domain name (e.g., "mycompany.example.com")
#
# This configuration includes:
# ✅ Clean Docker image with ERPNext apps (deployment-agnostic)
# ✅ Persistent volumes for site data, uploads, and configurations
# ✅ Deployment-specific initialization via runPrepareCommands
# ✅ Shared volumes across all services that need site access
#
# Benefits:
# - Docker image is reusable across different deployment platforms
# - Site initialization is handled at deployment time (not in image)
# - Container restarts preserve all site data and configurations
# - Apps are consistently deployed across all containers
# - No manual setup required after deployment
# - Fast container startup times
# - Proper separation between image and deployment concerns