346 lines
9.6 KiB
Markdown
346 lines
9.6 KiB
Markdown
|
|
# Dish Planner - Self-Hosted Deployment Guide
|
||
|
|
|
||
|
|
This directory contains everything you need to deploy Dish Planner as a self-hosted all-in-one container.
|
||
|
|
|
||
|
|
> **Note**: This guide uses an embedded docker-compose configuration (no separate file to download). Simply copy the YAML configuration shown below and save it as `docker-compose.yml`.
|
||
|
|
|
||
|
|
## Quick Start
|
||
|
|
|
||
|
|
### For End Users (Using Pre-Built Image)
|
||
|
|
|
||
|
|
> **Image Versioning**: This guide uses the `:latest` tag for simplicity. For production deployments, consider using a specific version tag (e.g., `:v0.3`) for stability and predictable updates.
|
||
|
|
|
||
|
|
1. **Create a docker-compose.yml file:**
|
||
|
|
|
||
|
|
Copy the following configuration and save it as `docker-compose.yml`:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# ============================================
|
||
|
|
# Dish Planner - Self-Hosted Deployment
|
||
|
|
# ============================================
|
||
|
|
#
|
||
|
|
# QUICK START:
|
||
|
|
# 1. Save this file as docker-compose.yml
|
||
|
|
# 2. (Optional) Edit the environment variables below
|
||
|
|
# 3. Run: docker compose up -d
|
||
|
|
# 4. Access your app at http://localhost:3000
|
||
|
|
#
|
||
|
|
# IMPORTANT SECURITY NOTES:
|
||
|
|
# - Database credentials are auto-generated on first run
|
||
|
|
# - Check the container logs to see generated credentials:
|
||
|
|
# docker logs dishplanner
|
||
|
|
# - For production, set a custom APP_URL environment variable
|
||
|
|
#
|
||
|
|
# CUSTOMIZATION:
|
||
|
|
# You can override any environment variable by uncommenting
|
||
|
|
# and editing the values below, or by creating a .env file.
|
||
|
|
#
|
||
|
|
# ============================================
|
||
|
|
|
||
|
|
services:
|
||
|
|
dishplanner:
|
||
|
|
# Pre-built all-in-one image from Codeberg Container Registry
|
||
|
|
image: codeberg.org/lvl0/dish-planner:latest
|
||
|
|
|
||
|
|
container_name: dishplanner
|
||
|
|
restart: unless-stopped
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Port Configuration
|
||
|
|
# ----------------------------------------
|
||
|
|
# The application will be accessible on port 3000
|
||
|
|
# Change the left number to use a different host port
|
||
|
|
# Example: "8080:80" to access on port 8080
|
||
|
|
ports:
|
||
|
|
- "3000:80"
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Environment Variables
|
||
|
|
# ----------------------------------------
|
||
|
|
# Uncomment and customize as needed
|
||
|
|
environment:
|
||
|
|
# Application URL (set this to your domain)
|
||
|
|
- APP_URL=http://localhost:3000
|
||
|
|
|
||
|
|
# Application environment (production recommended)
|
||
|
|
- APP_ENV=production
|
||
|
|
|
||
|
|
# Debug mode (set to false in production for security)
|
||
|
|
- APP_DEBUG=false
|
||
|
|
|
||
|
|
# Database configuration
|
||
|
|
# Note: Credentials are auto-generated on first run if not set
|
||
|
|
# Check logs for generated credentials: docker logs dishplanner
|
||
|
|
# - DB_DATABASE=dishplanner
|
||
|
|
# - DB_USERNAME=dishuser
|
||
|
|
# - DB_PASSWORD=change-this-secure-password
|
||
|
|
|
||
|
|
# Timezone (optional)
|
||
|
|
# - APP_TIMEZONE=UTC
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Persistent Data Volumes
|
||
|
|
# ----------------------------------------
|
||
|
|
# These volumes ensure data persists across container restarts
|
||
|
|
volumes:
|
||
|
|
# MySQL database data
|
||
|
|
- dishplanner_mysql_data:/var/lib/mysql
|
||
|
|
|
||
|
|
# Laravel storage (uploaded files, logs, cache)
|
||
|
|
- dishplanner_storage:/var/www/backend/storage
|
||
|
|
|
||
|
|
# Supervisor logs
|
||
|
|
- dishplanner_logs:/var/log/supervisor
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Health Check (optional)
|
||
|
|
# ----------------------------------------
|
||
|
|
# Uncomment to enable container health monitoring
|
||
|
|
# healthcheck:
|
||
|
|
# test: ["CMD", "curl", "-f", "http://localhost/api/health"]
|
||
|
|
# interval: 30s
|
||
|
|
# timeout: 10s
|
||
|
|
# retries: 3
|
||
|
|
# start_period: 60s
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Named Volumes
|
||
|
|
# ----------------------------------------
|
||
|
|
# Docker manages these volumes - data persists even if container is removed
|
||
|
|
volumes:
|
||
|
|
dishplanner_mysql_data:
|
||
|
|
driver: local
|
||
|
|
dishplanner_storage:
|
||
|
|
driver: local
|
||
|
|
dishplanner_logs:
|
||
|
|
driver: local
|
||
|
|
|
||
|
|
# ----------------------------------------
|
||
|
|
# Network Configuration
|
||
|
|
# ----------------------------------------
|
||
|
|
# Uses default bridge network (suitable for single-host deployment)
|
||
|
|
# For advanced setups, you can define custom networks here
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Start the application:**
|
||
|
|
```bash
|
||
|
|
docker compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **View the initialization logs to get your database credentials:**
|
||
|
|
```bash
|
||
|
|
docker logs dishplanner
|
||
|
|
```
|
||
|
|
|
||
|
|
Save the auto-generated database credentials shown in the logs!
|
||
|
|
|
||
|
|
4. **Access the application:**
|
||
|
|
Open your browser to `http://localhost:3000`
|
||
|
|
|
||
|
|
That's it! The application is now running with:
|
||
|
|
- MySQL database
|
||
|
|
- Laravel backend API
|
||
|
|
- React Router frontend
|
||
|
|
- Nginx reverse proxy
|
||
|
|
- Background queue worker
|
||
|
|
|
||
|
|
### For DockGE Users
|
||
|
|
|
||
|
|
1. In the DockGE web UI, click "Add Stack"
|
||
|
|
2. Copy the entire YAML configuration from the code block above (starting from `services:` and including all volumes)
|
||
|
|
3. Paste it into the DockGE compose editor
|
||
|
|
4. Optionally edit the environment variables
|
||
|
|
5. Click "Start"
|
||
|
|
6. View logs to get auto-generated database credentials
|
||
|
|
|
||
|
|
## Configuration
|
||
|
|
|
||
|
|
### Environment Variables
|
||
|
|
|
||
|
|
You can customize the deployment by setting these environment variables in the docker-compose file:
|
||
|
|
|
||
|
|
| Variable | Default | Description |
|
||
|
|
|----------|---------|-------------|
|
||
|
|
| `APP_URL` | `http://localhost:3000` | The URL where your app is accessible |
|
||
|
|
| `APP_ENV` | `production` | Environment mode (production/local) |
|
||
|
|
| `APP_DEBUG` | `false` | Enable debug mode (never use in production!) |
|
||
|
|
| `DB_DATABASE` | `dishplanner` | Database name |
|
||
|
|
| `DB_USERNAME` | `dishuser` | Database username |
|
||
|
|
| `DB_PASSWORD` | Auto-generated | Database password (check logs for generated value) |
|
||
|
|
|
||
|
|
### Changing the Port
|
||
|
|
|
||
|
|
By default, the app runs on port 3000. To use a different port, edit the `ports` section:
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
ports:
|
||
|
|
- "8080:80" # This makes the app available on port 8080
|
||
|
|
```
|
||
|
|
|
||
|
|
### Persistent Data
|
||
|
|
|
||
|
|
The following data is persisted in Docker volumes:
|
||
|
|
- **MySQL database** - All your dishes, schedules, and users
|
||
|
|
- **Laravel storage** - Uploaded files, logs, and cache
|
||
|
|
- **Supervisor logs** - Application and service logs
|
||
|
|
|
||
|
|
Even if you remove the container, this data remains intact.
|
||
|
|
|
||
|
|
## Building the Image Yourself
|
||
|
|
|
||
|
|
If you prefer to build the image yourself instead of using the pre-built one:
|
||
|
|
|
||
|
|
1. **Clone the repository:**
|
||
|
|
```bash
|
||
|
|
git clone https://codeberg.org/lvl0/dish-planner.git
|
||
|
|
cd dish-planner
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Build the image:**
|
||
|
|
```bash
|
||
|
|
docker build -f .docker/production/Dockerfile -t codeberg.org/lvl0/dish-planner:latest .
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Create a docker-compose.yml file** using the configuration shown in the Quick Start section above (or save the embedded compose config to a file)
|
||
|
|
|
||
|
|
4. **Run it:**
|
||
|
|
```bash
|
||
|
|
docker compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
## Management
|
||
|
|
|
||
|
|
### Viewing Logs
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# All logs
|
||
|
|
docker logs dishplanner
|
||
|
|
|
||
|
|
# Follow logs in real-time
|
||
|
|
docker logs -f dishplanner
|
||
|
|
|
||
|
|
# Last 100 lines
|
||
|
|
docker logs --tail 100 dishplanner
|
||
|
|
```
|
||
|
|
|
||
|
|
### Stopping the Application
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker compose down
|
||
|
|
```
|
||
|
|
|
||
|
|
### Restarting the Application
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker compose restart
|
||
|
|
```
|
||
|
|
|
||
|
|
### Updating to a New Version
|
||
|
|
|
||
|
|
1. Pull the latest image:
|
||
|
|
```bash
|
||
|
|
docker compose pull
|
||
|
|
```
|
||
|
|
|
||
|
|
2. Recreate the container:
|
||
|
|
```bash
|
||
|
|
docker compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Your data persists in volumes automatically!
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### "Cannot connect to database"
|
||
|
|
|
||
|
|
Check that MySQL started successfully:
|
||
|
|
```bash
|
||
|
|
docker logs dishplanner | grep mysql
|
||
|
|
```
|
||
|
|
|
||
|
|
### "502 Bad Gateway"
|
||
|
|
|
||
|
|
One of the services may not have started. Check supervisor logs:
|
||
|
|
```bash
|
||
|
|
docker exec dishplanner supervisorctl status
|
||
|
|
```
|
||
|
|
|
||
|
|
### Reset Everything (CAUTION: Deletes all data!)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker compose down -v # The -v flag removes volumes
|
||
|
|
docker compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
### Access the Container Shell
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker exec -it dishplanner bash
|
||
|
|
```
|
||
|
|
|
||
|
|
### Run Laravel Commands
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Run migrations
|
||
|
|
docker exec dishplanner php /var/www/backend/artisan migrate
|
||
|
|
|
||
|
|
# Create a new user (if needed)
|
||
|
|
docker exec -it dishplanner php /var/www/backend/artisan tinker
|
||
|
|
```
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
This all-in-one container includes:
|
||
|
|
|
||
|
|
- **MySQL 8.0** - Database server
|
||
|
|
- **PHP 8.2-FPM** - Runs the Laravel backend
|
||
|
|
- **Node.js 20** - Runs the React Router frontend
|
||
|
|
- **Nginx** - Web server and reverse proxy
|
||
|
|
- **Supervisord** - Process manager that keeps everything running
|
||
|
|
|
||
|
|
All services start automatically and are monitored by supervisord. If any service crashes, it will be automatically restarted.
|
||
|
|
|
||
|
|
## Security Recommendations
|
||
|
|
|
||
|
|
For production deployments:
|
||
|
|
|
||
|
|
1. **Set a strong database password:**
|
||
|
|
```yaml
|
||
|
|
environment:
|
||
|
|
- DB_PASSWORD=your-very-secure-password-here
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Use HTTPS:** Put the container behind a reverse proxy (Nginx, Caddy, Traefik) with SSL/TLS
|
||
|
|
|
||
|
|
3. **Set APP_DEBUG to false:**
|
||
|
|
```yaml
|
||
|
|
environment:
|
||
|
|
- APP_DEBUG=false
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **Keep the image updated:** Regularly pull and deploy new versions
|
||
|
|
|
||
|
|
5. **Backup your data:**
|
||
|
|
```bash
|
||
|
|
# Backup volumes
|
||
|
|
docker run --rm -v dishplanner_mysql_data:/data -v $(pwd):/backup ubuntu tar czf /backup/mysql-backup.tar.gz /data
|
||
|
|
```
|
||
|
|
|
||
|
|
## Support
|
||
|
|
|
||
|
|
For issues and questions:
|
||
|
|
- Codeberg Issues: https://codeberg.org/lvl0/dish-planner/issues
|
||
|
|
- Documentation: https://codeberg.org/lvl0/dish-planner
|
||
|
|
|
||
|
|
## What's Inside
|
||
|
|
|
||
|
|
The container runs these processes (managed by supervisord):
|
||
|
|
|
||
|
|
1. **MySQL** - Database (port 3306, internal only)
|
||
|
|
2. **PHP-FPM** - Laravel application (port 9000, internal only)
|
||
|
|
3. **Node.js** - React frontend (port 3000, internal only)
|
||
|
|
4. **Nginx** - Reverse proxy (port 80, exposed)
|
||
|
|
5. **Queue Worker** - Background job processor
|
||
|
|
|
||
|
|
Only Nginx's port 80 is exposed to the host (mapped to 3000 by default).
|