feat: Add Docker support with production and development configurations for backend and frontend
This commit is contained in:
46
.dockerignore
Normal file
46
.dockerignore
Normal file
@@ -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/
|
||||||
355
DOCKER.md
Normal file
355
DOCKER.md
Normal file
@@ -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_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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!** 🐳✨
|
||||||
22
client/Dockerfile
Normal file
22
client/Dockerfile
Normal file
@@ -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"]
|
||||||
19
client/Dockerfile.dev
Normal file
19
client/Dockerfile.dev
Normal file
@@ -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"]
|
||||||
@@ -6,7 +6,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"serve": "vite preview --host 0.0.0.0 --port 3000"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|||||||
43
docker-compose.dev.yml
Normal file
43
docker-compose.dev.yml
Normal file
@@ -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
|
||||||
48
docker-compose.yml
Normal file
48
docker-compose.yml
Normal file
@@ -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
|
||||||
23
server/Dockerfile
Normal file
23
server/Dockerfile
Normal file
@@ -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"]
|
||||||
22
server/Dockerfile.dev
Normal file
22
server/Dockerfile.dev
Normal file
@@ -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"]
|
||||||
Reference in New Issue
Block a user