Add CI/CD workflows for development and production deployments
Some checks failed
Deploy Development / deploy (push) Failing after 29s
Some checks failed
Deploy Development / deploy (push) Failing after 29s
- Created `deploy-dev.yml` for automated deployment to the development server on push to the `dev` branch. - Created `deploy.yml` for automated deployment to the production server on push to the `main` or `master` branches. - Added deployment instructions in `DEPLOYMENT-PORTAINER.md` for using Portainer and Traefik. - Documented Gitea Actions deployment process in `DEPLOYMENT.md`. - Configured Traefik SSL settings in `TRAEFIK-SSL-CONFIG.md` for both development and production environments. - Implemented a deployment script `deploy.sh` for manual deployments. - Added Docker Compose configurations for development (`docker-compose.portainer.dev.yml`) and production (`docker-compose.portainer.yml`) environments. - Updated main `docker-compose.yml` to support Traefik integration and environment variable configurations.
This commit is contained in:
405
DEPLOYMENT-PORTAINER.md
Normal file
405
DEPLOYMENT-PORTAINER.md
Normal file
@@ -0,0 +1,405 @@
|
||||
# Deployment with Portainer and Traefik
|
||||
|
||||
This guide covers deploying MerchBay Admin using your existing Portainer and Traefik setup.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- ✅ Gitea self-hosted with Gitea runners configured
|
||||
- ✅ Portainer installed and accessible
|
||||
- ✅ Traefik reverse proxy running with:
|
||||
- `web` entrypoint (port 80)
|
||||
- `websecure` entrypoint (port 443)
|
||||
- Let's Encrypt certificate resolver named `letsencrypt`
|
||||
- External network named `traefik`
|
||||
|
||||
## Deployment Methods
|
||||
|
||||
### Method 1: Portainer Stack Deployment (Recommended)
|
||||
|
||||
#### Step 1: Prepare the Image
|
||||
|
||||
Build the Docker image via Gitea Actions or manually:
|
||||
|
||||
```bash
|
||||
# Using Gitea Actions (will build automatically on push)
|
||||
git push origin main
|
||||
|
||||
# OR build manually
|
||||
docker build -t merchbay_admin:latest .
|
||||
```
|
||||
|
||||
#### Step 2: Deploy in Portainer
|
||||
|
||||
1. **Access Portainer** → `Stacks` → `Add stack`
|
||||
|
||||
2. **Stack Configuration:**
|
||||
- Name: `merchbay-admin`
|
||||
- Build method: `Web editor`
|
||||
|
||||
3. **Paste the content from `docker-compose.portainer.yml`** and update:
|
||||
- `APP_URL`: Your domain (e.g., `https://merchbay-admin.yourdomain.com`)
|
||||
- `DB_HOST`: Your MySQL host
|
||||
- `DB_DATABASE`: Database name
|
||||
- `DB_USERNAME`: Database username
|
||||
- `DB_PASSWORD`: Database password
|
||||
- Traefik Host rule: Replace `merchbay-admin.yourdomain.com` with your actual domain
|
||||
|
||||
4. **Deploy the stack**
|
||||
|
||||
5. **Run Initial Setup:**
|
||||
- Go to `Containers` → Find `merchbay_admin_app`
|
||||
- Click `Console` → Connect with `/bin/bash`
|
||||
- Run:
|
||||
```bash
|
||||
php artisan migrate --force
|
||||
php artisan config:cache
|
||||
php artisan route:cache
|
||||
```
|
||||
|
||||
### Method 2: Gitea Actions CI/CD (Automated)
|
||||
|
||||
#### Step 1: Configure Gitea Secrets
|
||||
|
||||
In your Gitea repository → `Settings` → `Secrets` → `Actions`, add:
|
||||
|
||||
| Secret Name | Value | Description |
|
||||
|------------|-------|-------------|
|
||||
| `DEPLOY_HOST` | `192.168.1.100` | Your server IP/hostname |
|
||||
| `DEPLOY_USER` | `deploy` | SSH username |
|
||||
| `DEPLOY_SSH_KEY` | `-----BEGIN RSA...` | Private SSH key |
|
||||
| `DEPLOY_PORT` | `22` | SSH port (optional) |
|
||||
| `DEPLOY_DIR` | `/var/www/merchbay_admin` | Deployment directory |
|
||||
| `DOMAIN` | `merchbay-admin.yourdomain.com` | Your domain for Traefik |
|
||||
|
||||
#### Step 2: Prepare Deployment Server
|
||||
|
||||
```bash
|
||||
# SSH into your server
|
||||
ssh deploy@your-server
|
||||
|
||||
# Create deployment directory
|
||||
sudo mkdir -p /var/www/merchbay_admin
|
||||
sudo chown $USER:$USER /var/www/merchbay_admin
|
||||
cd /var/www/merchbay_admin
|
||||
|
||||
# Create .env file
|
||||
nano .env
|
||||
```
|
||||
|
||||
Add to `.env`:
|
||||
```env
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=https://merchbay-admin.yourdomain.com
|
||||
DB_HOST=your-mysql-host
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=merchbay_admin
|
||||
DB_USERNAME=your-mysql-user
|
||||
DB_PASSWORD=your-mysql-password
|
||||
DOMAIN=merchbay-admin.yourdomain.com
|
||||
```
|
||||
|
||||
#### Step 3: Ensure Traefik Network Exists
|
||||
|
||||
```bash
|
||||
docker network inspect traefik >/dev/null 2>&1 || docker network create traefik
|
||||
```
|
||||
|
||||
#### Step 4: Deploy
|
||||
|
||||
Simply push to your main branch:
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Deploy application"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
Gitea Actions will automatically:
|
||||
1. Build the Docker image
|
||||
2. Transfer to your server
|
||||
3. Deploy with docker-compose
|
||||
4. Connect to Traefik network
|
||||
5. Run migrations
|
||||
6. Cache configurations
|
||||
|
||||
### Method 3: Manual Deployment with Script
|
||||
|
||||
```bash
|
||||
# On your server
|
||||
cd /var/www/merchbay_admin
|
||||
|
||||
# Pull latest code
|
||||
git pull origin main
|
||||
|
||||
# Run deployment script
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## Traefik Configuration
|
||||
|
||||
### Verify Traefik Setup
|
||||
|
||||
Ensure your Traefik configuration includes:
|
||||
|
||||
```yaml
|
||||
# traefik.yml or docker-compose.yml
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
|
||||
certificatesResolvers:
|
||||
letsencrypt:
|
||||
acme:
|
||||
email: your-email@example.com
|
||||
storage: /letsencrypt/acme.json
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
```
|
||||
|
||||
### External Network
|
||||
|
||||
Ensure Traefik network exists and is external:
|
||||
|
||||
```bash
|
||||
# Create network if it doesn't exist
|
||||
docker network create traefik
|
||||
|
||||
# Verify
|
||||
docker network inspect traefik
|
||||
```
|
||||
|
||||
## DNS Configuration
|
||||
|
||||
Point your domain to your server:
|
||||
|
||||
```
|
||||
Type: A Record
|
||||
Name: merchbay-admin (or @ for root domain)
|
||||
Value: YOUR_SERVER_IP
|
||||
TTL: 3600
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
### 1. Check Container Status
|
||||
|
||||
**Via Portainer:**
|
||||
- Navigate to `Containers`
|
||||
- Verify `merchbay_admin_app` is running
|
||||
|
||||
**Via CLI:**
|
||||
```bash
|
||||
docker ps | grep merchbay_admin
|
||||
```
|
||||
|
||||
### 2. Check Traefik Dashboard
|
||||
|
||||
If you have Traefik dashboard enabled:
|
||||
- Look for `merchbay-admin@docker` router
|
||||
- Verify it's connected to the correct service
|
||||
|
||||
### 3. Test Application
|
||||
|
||||
```bash
|
||||
# Test HTTPS
|
||||
curl -I https://merchbay-admin.yourdomain.com
|
||||
|
||||
# Should return: HTTP/2 200
|
||||
```
|
||||
|
||||
### 4. Check Logs
|
||||
|
||||
**Via Portainer:**
|
||||
- `Containers` → `merchbay_admin_app` → `Logs`
|
||||
|
||||
**Via CLI:**
|
||||
```bash
|
||||
docker logs merchbay_admin_app -f
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Container not accessible via domain
|
||||
|
||||
**Check Traefik labels:**
|
||||
```bash
|
||||
docker inspect merchbay_admin_app | grep -A 20 Labels
|
||||
```
|
||||
|
||||
**Verify network connection:**
|
||||
```bash
|
||||
docker network inspect traefik | grep merchbay_admin
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Reconnect to Traefik network
|
||||
docker network connect traefik merchbay_admin_app
|
||||
```
|
||||
|
||||
### Issue: SSL certificate not generating
|
||||
|
||||
**Check Traefik logs:**
|
||||
```bash
|
||||
docker logs traefik | grep letsencrypt
|
||||
```
|
||||
|
||||
**Common fixes:**
|
||||
1. Ensure port 80 is accessible (Let's Encrypt HTTP challenge)
|
||||
2. Verify DNS is pointing to your server
|
||||
3. Check email in Traefik's ACME configuration
|
||||
4. Ensure `acme.json` has correct permissions (600)
|
||||
|
||||
### Issue: Database connection failed
|
||||
|
||||
**Check environment variables:**
|
||||
```bash
|
||||
docker exec merchbay_admin_app env | grep DB_
|
||||
```
|
||||
|
||||
**Test connection:**
|
||||
```bash
|
||||
docker exec merchbay_admin_app php artisan tinker
|
||||
>>> DB::connection()->getPdo();
|
||||
```
|
||||
|
||||
### Issue: 502 Bad Gateway
|
||||
|
||||
**Possible causes:**
|
||||
1. Application not fully started
|
||||
2. Wrong port in Traefik label (should be 80)
|
||||
3. Application crashed
|
||||
|
||||
**Check:**
|
||||
```bash
|
||||
# Container status
|
||||
docker ps -a | grep merchbay_admin
|
||||
|
||||
# Application logs
|
||||
docker logs merchbay_admin_app --tail 100
|
||||
|
||||
# Restart container
|
||||
docker restart merchbay_admin_app
|
||||
```
|
||||
|
||||
## Updating the Application
|
||||
|
||||
### Via Gitea Actions (Automatic)
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Update application"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
### Via Portainer
|
||||
|
||||
1. Go to `Stacks` → `merchbay-admin`
|
||||
2. Click `Editor`
|
||||
3. Update image or configuration
|
||||
4. Click `Update the stack`
|
||||
5. Enable "Re-pull image and redeploy"
|
||||
|
||||
### Manual Update
|
||||
|
||||
```bash
|
||||
ssh deploy@your-server
|
||||
cd /var/www/merchbay_admin
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## Rollback
|
||||
|
||||
### Via Portainer
|
||||
|
||||
1. Go to `Stacks` → `merchbay-admin`
|
||||
2. Click on the stack
|
||||
3. Find previous version in `Stack History` (if available)
|
||||
4. Revert to previous version
|
||||
|
||||
### Manual Rollback
|
||||
|
||||
```bash
|
||||
# List available backups
|
||||
ls -lh /var/www/merchbay_admin/backups/
|
||||
|
||||
# Restore from backup
|
||||
cd /var/www/merchbay_admin
|
||||
tar -xzf backups/backup_YYYYMMDD_HHMMSS.tar.gz
|
||||
|
||||
# Restart
|
||||
docker compose restart
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Use Strong Database Passwords**: Generate with `openssl rand -base64 32`
|
||||
2. **Restrict SSH Access**: Use key-based authentication only
|
||||
3. **Firewall Rules**: Only allow necessary ports (80, 443, 22)
|
||||
4. **Regular Backups**: Automated backups of database and storage
|
||||
5. **Keep Docker Updated**: Regularly update Docker and images
|
||||
6. **Monitor Logs**: Set up log monitoring/alerting
|
||||
7. **Use Secrets**: Never commit sensitive data to repository
|
||||
8. **HTTPS Only**: Ensure HTTP redirects to HTTPS
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### PHP-FPM Configuration
|
||||
|
||||
Consider switching to PHP-FPM for better performance:
|
||||
|
||||
```dockerfile
|
||||
FROM php:7.4-fpm-alpine
|
||||
# ... additional configuration
|
||||
```
|
||||
|
||||
### Use Redis for Cache/Sessions
|
||||
|
||||
```env
|
||||
CACHE_DRIVER=redis
|
||||
SESSION_DRIVER=redis
|
||||
REDIS_HOST=redis
|
||||
```
|
||||
|
||||
Add Redis service to docker-compose:
|
||||
```yaml
|
||||
services:
|
||||
redis:
|
||||
image: redis:alpine
|
||||
networks:
|
||||
- default
|
||||
```
|
||||
|
||||
### Enable OPcache
|
||||
|
||||
Already included in Dockerfile, verify:
|
||||
```bash
|
||||
docker exec merchbay_admin_app php -i | grep opcache
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### View Real-time Logs in Portainer
|
||||
|
||||
1. Navigate to `Containers`
|
||||
2. Click on `merchbay_admin_app`
|
||||
3. Select `Logs` tab
|
||||
4. Enable `Auto-refresh`
|
||||
|
||||
### Set Up Alerts
|
||||
|
||||
Configure Portainer notifications:
|
||||
1. `Settings` → `Notifications`
|
||||
2. Add webhook or email notification
|
||||
3. Set up container health checks
|
||||
|
||||
## Support
|
||||
|
||||
For issues:
|
||||
1. Check application logs in Portainer
|
||||
2. Verify Traefik configuration
|
||||
3. Test database connectivity
|
||||
4. Review Gitea Actions logs if using CI/CD
|
||||
Reference in New Issue
Block a user