# 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).