From 30647fca50b04e5ea7cf09fc69c45a7b4f6798c4 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Mon, 16 Feb 2026 00:08:49 -0500 Subject: [PATCH] feat: Add Docker support with production and development configurations for backend and frontend --- .dockerignore | 46 ++++++ DOCKER.md | 355 +++++++++++++++++++++++++++++++++++++++++ client/Dockerfile | 22 +++ client/Dockerfile.dev | 19 +++ client/package.json | 3 +- docker-compose.dev.yml | 43 +++++ docker-compose.yml | 48 ++++++ server/Dockerfile | 23 +++ server/Dockerfile.dev | 22 +++ 9 files changed, 580 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 DOCKER.md create mode 100644 client/Dockerfile create mode 100644 client/Dockerfile.dev create mode 100644 docker-compose.dev.yml create mode 100644 docker-compose.yml create mode 100644 server/Dockerfile create mode 100644 server/Dockerfile.dev diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9f30a12 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,46 @@ +# Docker ignore patterns + +# Node modules +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist/ +build/ + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Git +.git/ +.gitignore + +# Documentation (not needed in container) +*.md +!README.md + +# Test files +*.test.js +*.spec.js +coverage/ + +# Logs +*.log +logs/ diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000..4149dc6 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,355 @@ +# 🐳 Docker Deployment Guide + +## Quick Start + +### Production Deployment + +Start everything with one command: +```bash +docker-compose up -d +``` + +This will: +- Build and start the backend server (ports 3001, 3002) +- Build and start the frontend client (port 3000) +- Set up networking between containers + +### Development Mode (with hot reload) + +```bash +docker-compose -f docker-compose.dev.yml up +``` + +This enables: +- Hot reload for both server and client +- Volume mounting for live code changes +- Development dependencies + +## Architecture + +``` +┌─────────────────────────────────────┐ +│ Zoraxy Reverse Proxy │ +│ (Your external proxy) │ +└────────┬────────────────┬───────────┘ + │ │ + │ │ + ┌────▼─────┐ ┌────▼─────┐ + │ Client │ │ Server │ + │ :3000 │ │ :3001 │ + │ (Vite) │ │ :3002 │ + └──────────┘ └──────────┘ + │ │ + └────────┬───────┘ + │ + turtle-network +``` + +## Services + +### Backend Server (turtle-server) +- **Ports**: 3001 (HTTP), 3002 (WebSocket) +- **Image**: Built from `server/Dockerfile` +- **Health Check**: HTTP GET /api/turtles + +### Frontend Client (turtle-client) +- **Port**: 3000 (Vite preview server) +- **Image**: Built from `client/Dockerfile` +- **Serves**: Pre-built static React app + +## Docker Commands + +### Start Services +```bash +# Production (detached) +docker-compose up -d + +# Development (with logs) +docker-compose -f docker-compose.dev.yml up + +# Build and start +docker-compose up --build +``` + +### Stop Services +```bash +docker-compose down + +# Remove volumes too +docker-compose down -v +``` + +### View Logs +```bash +# All services +docker-compose logs -f + +# Specific service +docker-compose logs -f server +docker-compose logs -f client +``` + +### Restart Services +```bash +# All services +docker-compose restart + +# Specific service +docker-compose restart server +``` + +### Shell Access +```bash +# Server container +docker-compose exec server sh + +# Client container +docker-compose exec client sh +``` + +## Zoraxy Configuration + +Configure your Zoraxy reverse proxy to forward: + +### Frontend (Web UI) +- **Domain**: `turtles.yourdomain.com` (or your choice) +- **Target**: `http://localhost:3000` +- **WebSocket**: Enabled + +### Backend API +- **Domain**: `turtles-api.yourdomain.com` (or your choice) +- **Target**: `http://localhost:3001` +- **WebSocket**: Enabled (for port 3002) + +### Alternative: Single Domain Setup +Forward all `/api/*` requests to backend: +- **Domain**: `turtles.yourdomain.com` +- **Path `/`**: → `http://localhost:3000` (Frontend) +- **Path `/api`**: → `http://localhost:3001` (Backend) +- **WebSocket**: → `ws://localhost:3002` + +### Update Client Configuration + +Edit `client/src/store/turtleStore.js` before building: +```javascript +const WS_URL = 'wss://turtles.yourdomain.com/ws'; // or your WebSocket endpoint +const API_URL = 'https://turtles.yourdomain.com/api'; // or your API endpoint +``` + +## Environment Variables + +Create `.env` files if needed: + +### server/.env +```env +NODE_ENV=production +PORT=3001 +WS_PORT=3002 +``` + +### client/.env.production +```env +VITE_API_URL=https://turtles-api.yourdomain.com +VITE_WS_URL=wss://turtles-api.yourdomain.com/ws +``` + +## Building Images + +### Build all images +```bash +docker-compose build +``` + +### Build specific service +```bash +docker-compose build server +docker-compose build client +``` + +### Rebuild without cache +```bash +docker-compose build --no-cache +``` + +## Minecraft Bridge Configuration + +Update `webbridge.lua` to point to your Docker host: + +```lua +-- If running on same machine +local SERVER_URL = "http://localhost:3001" + +-- If running on different machine +local SERVER_URL = "http://YOUR_DOCKER_HOST_IP:3001" + +-- If using Zoraxy reverse proxy +local SERVER_URL = "https://turtles-api.yourdomain.com" +``` + +## Troubleshooting + +### Port Already in Use +```bash +# Check what's using the port +sudo lsof -i :3000 +sudo lsof -i :3001 + +# Stop the containers +docker-compose down + +# Remove any conflicting containers +docker ps -a +docker rm +``` + +### Container Won't Start +```bash +# Check logs +docker-compose logs server +docker-compose logs client + +# Rebuild +docker-compose up --build +``` + +### Can't Connect from Minecraft +- Verify firewall allows ports 3001-3002 +- Check Docker host IP is correct +- Ensure HTTP API is enabled in ComputerCraft config +- Test: `http.get("http://YOUR_IP:3001/api/turtles")` + +### Health Check Failing +```bash +# Check container health +docker-compose ps + +# Manually test health endpoint +curl http://localhost:3001/api/turtles +curl http://localhost:3000 +``` + +## Production Checklist + +- [ ] Set up Zoraxy reverse proxy +- [ ] Configure SSL/TLS certificates +- [ ] Update API URLs in client code +- [ ] Build images: `docker-compose build` +- [ ] Start services: `docker-compose up -d` +- [ ] Verify health checks: `docker-compose ps` +- [ ] Test web interface +- [ ] Update Minecraft bridge script +- [ ] Test turtle connection + +## Updating the Application + +```bash +# Pull latest code +git pull + +# Rebuild and restart +docker-compose down +docker-compose up --build -d + +# Or use rolling update +docker-compose up -d --build +``` + +## Performance Tips + +### Reduce Image Size +- Images use Alpine Linux (minimal) +- Production builds exclude dev dependencies +- Multi-stage builds where applicable + +### Resource Limits +Add to docker-compose.yml: +```yaml +services: + server: + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M +``` + +### Volume Management +```bash +# List volumes +docker volume ls + +# Clean up unused volumes +docker volume prune +``` + +## Backup and Restore + +### Backup Container Data +```bash +# Export container +docker export turtle-server > server-backup.tar +docker export turtle-client > client-backup.tar +``` + +### Backup Logs +```bash +docker-compose logs > logs-backup.txt +``` + +## Security + +### Best Practices +1. Use Zoraxy for SSL/TLS termination +2. Don't expose Docker ports directly to internet +3. Use environment variables for sensitive data +4. Keep Docker and images updated +5. Use non-root user in containers (already configured) + +### Network Isolation +Containers use `turtle-network` bridge network: +- Isolated from host network +- Can communicate with each other +- Exposed ports defined in docker-compose.yml + +## Monitoring + +### Container Stats +```bash +docker stats +``` + +### Health Status +```bash +docker-compose ps +``` + +### System Resources +```bash +docker system df +``` + +## Common Issues + +**Problem**: Client can't connect to server +**Solution**: Make sure both containers are on same network and server is healthy + +**Problem**: WebSocket connection fails through Zoraxy +**Solution**: Enable WebSocket support in Zoraxy proxy rules + +**Problem**: Changes not reflected after rebuild +**Solution**: Use `--no-cache` flag: `docker-compose build --no-cache` + +--- + +## Summary + +**Start**: `docker-compose up -d` +**Stop**: `docker-compose down` +**Logs**: `docker-compose logs -f` +**Rebuild**: `docker-compose up --build -d` + +Set up your Zoraxy reverse proxy to forward traffic to: +- Frontend: `localhost:3000` +- Backend: `localhost:3001` + `localhost:3002` (WebSocket) + +**Easy deployment with Docker + Zoraxy!** 🐳✨ diff --git a/client/Dockerfile b/client/Dockerfile new file mode 100644 index 0000000..c15602d --- /dev/null +++ b/client/Dockerfile @@ -0,0 +1,22 @@ +# Production build with Vite preview server +FROM node:18-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy source code +COPY . . + +# Build the app +RUN npm run build + +# Expose port for Vite preview server +EXPOSE 3000 + +# Serve built files with Vite preview +CMD ["npm", "run", "preview", "--", "--host", "0.0.0.0", "--port", "3000"] diff --git a/client/Dockerfile.dev b/client/Dockerfile.dev new file mode 100644 index 0000000..b9e21f2 --- /dev/null +++ b/client/Dockerfile.dev @@ -0,0 +1,19 @@ +# Development Dockerfile with hot reload +FROM node:18-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy source code +COPY . . + +# Expose Vite dev server port +EXPOSE 3000 + +# Start Vite dev server +CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] diff --git a/client/package.json b/client/package.json index 1409449..9aa619e 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "serve": "vite preview --host 0.0.0.0 --port 3000" }, "dependencies": { "react": "^18.2.0", diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..b0cbfac --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,43 @@ +version: '3.8' + +services: + # Backend server (development with hot reload) + server: + build: + context: ./server + dockerfile: Dockerfile.dev + container_name: turtle-server-dev + ports: + - "3001:3001" + - "3002:3002" + volumes: + - ./server:/app + - /app/node_modules + environment: + - NODE_ENV=development + command: npm run dev + networks: + - turtle-network + + # Frontend client (development with hot reload) + client: + build: + context: ./client + dockerfile: Dockerfile.dev + container_name: turtle-client-dev + ports: + - "3000:3000" + volumes: + - ./client:/app + - /app/node_modules + environment: + - NODE_ENV=development + depends_on: + - server + command: npm run dev + networks: + - turtle-network + +networks: + turtle-network: + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..708da27 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,48 @@ +version: '3.8' + +services: + # Backend server + server: + build: + context: ./server + dockerfile: Dockerfile + container_name: turtle-server + ports: + - "3001:3001" # HTTP API + - "3002:3002" # WebSocket + environment: + - NODE_ENV=production + - PORT=3001 + - WS_PORT=3002 + restart: unless-stopped + networks: + - turtle-network + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/api/turtles', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] + interval: 30s + timeout: 3s + retries: 3 + start_period: 10s + + # Frontend client + client: + build: + context: ./client + dockerfile: Dockerfile + container_name: turtle-client + ports: + - "3000:3000" # Vite preview server + depends_on: + - server + restart: unless-stopped + networks: + - turtle-network + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000"] + interval: 30s + timeout: 3s + retries: 3 + +networks: + turtle-network: + driver: bridge diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..bab12c4 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,23 @@ +# Node.js backend +FROM node:18-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm ci --only=production + +# Copy server code +COPY server.js ./ + +# Expose ports +EXPOSE 3001 3002 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD node -e "require('http').get('http://localhost:3001/api/turtles', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" + +# Start server +CMD ["node", "server.js"] diff --git a/server/Dockerfile.dev b/server/Dockerfile.dev new file mode 100644 index 0000000..d7ac742 --- /dev/null +++ b/server/Dockerfile.dev @@ -0,0 +1,22 @@ +# Development Dockerfile with hot reload +FROM node:18-alpine + +WORKDIR /app + +# Install nodemon for hot reload +RUN npm install -g nodemon + +# Copy package files +COPY package*.json ./ + +# Install all dependencies (including dev) +RUN npm install + +# Copy source code +COPY . . + +# Expose ports +EXPOSE 3001 3002 + +# Start with nodemon for hot reload +CMD ["nodemon", "server.js"]