feat: Add Docker support and health endpoint
- Add production-ready Dockerfile with multi-stage build - Add .dockerignore for optimized builds - Add docker-compose.yml for easy deployment - Add /health endpoint for container health checks - Update README with comprehensive Docker documentation - Include security best practices (non-root user, health checks) - Support for both development and production deployments
This commit is contained in:
93
.dockerignore
Normal file
93
.dockerignore
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Environment files
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.yml
|
||||||
|
docker-compose.yaml
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
README.md
|
||||||
|
docs/
|
||||||
|
*.md
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# ESLint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# Temporary folders
|
||||||
|
tmp/
|
||||||
|
temp/
|
62
Dockerfile
Normal file
62
Dockerfile
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Multi-stage build for production
|
||||||
|
FROM node:22-alpine AS base
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN pnpm build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:22-alpine AS production
|
||||||
|
|
||||||
|
# Install pnpm
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||||
|
|
||||||
|
# Install production dependencies only
|
||||||
|
RUN pnpm install --frozen-lockfile --prod
|
||||||
|
|
||||||
|
# Copy built application from base stage
|
||||||
|
COPY --from=base /app/dist ./dist
|
||||||
|
|
||||||
|
# Copy necessary files for runtime
|
||||||
|
COPY --from=base /app/src/server/index.ts ./src/server/index.ts
|
||||||
|
COPY --from=base /app/src/server/routes ./src/server/routes
|
||||||
|
COPY --from=base /app/src/server/rpc ./src/server/rpc
|
||||||
|
COPY --from=base /app/src/server/lib ./src/server/lib
|
||||||
|
|
||||||
|
# Create non-root user for security
|
||||||
|
RUN addgroup -g 1001 -S nodejs
|
||||||
|
RUN adduser -S nextjs -u 1001
|
||||||
|
|
||||||
|
# Change ownership of the app directory
|
||||||
|
RUN chown -R nextjs:nodejs /app
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Health check
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||||
|
CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })" || exit 1
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["node", "--loader", "ts-node/esm", "src/server/index.ts"]
|
75
README.md
75
README.md
@@ -75,6 +75,81 @@ pnpm install
|
|||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker Deployment
|
||||||
|
|
||||||
|
### Docker Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker Image erstellen
|
||||||
|
docker build -t stargirlnails-booking .
|
||||||
|
|
||||||
|
# Container starten
|
||||||
|
docker run -d \
|
||||||
|
--name stargirlnails-app \
|
||||||
|
-p 3000:3000 \
|
||||||
|
--env-file .env \
|
||||||
|
stargirlnails-booking
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose (empfohlen)
|
||||||
|
|
||||||
|
Erstelle eine `docker-compose.yml` Datei:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
stargirlnails:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
```
|
||||||
|
|
||||||
|
Starten mit Docker Compose:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Container starten
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Logs anzeigen
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# Container stoppen
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
### Produktions-Deployment
|
||||||
|
|
||||||
|
Für den produktiven Einsatz:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Mit Docker Compose
|
||||||
|
docker-compose -f docker-compose.yml up -d
|
||||||
|
|
||||||
|
# Oder direkt mit Docker
|
||||||
|
docker run -d \
|
||||||
|
--name stargirlnails-prod \
|
||||||
|
-p 80:3000 \
|
||||||
|
--restart unless-stopped \
|
||||||
|
--env-file .env.production \
|
||||||
|
stargirlnails-booking
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wichtige Produktions-Hinweise:**
|
||||||
|
- Verwende eine `.env.production` Datei mit Produktions-Konfiguration
|
||||||
|
- Setze `NODE_ENV=production` in der Umgebungsdatei
|
||||||
|
- Verwende einen Reverse Proxy (nginx, Traefik) für HTTPS
|
||||||
|
- Überwache Container mit Health Checks
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- 📅 **Terminbuchung**: Kunden können online Termine buchen
|
- 📅 **Terminbuchung**: Kunden können online Termine buchen
|
||||||
|
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
stargirlnails:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
@@ -74,11 +74,6 @@ export function LoginForm() {
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div className="text-center text-sm text-gray-600">
|
|
||||||
<p>Standard Login:</p>
|
|
||||||
<p className="font-mono">Benutzername: owner</p>
|
|
||||||
<p className="font-mono">Passwort: admin123</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -11,6 +11,11 @@ app.use("*", async (c, next) => {
|
|||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Health check endpoint
|
||||||
|
app.get("/health", (c) => {
|
||||||
|
return c.json({ status: "ok", timestamp: new Date().toISOString() });
|
||||||
|
});
|
||||||
|
|
||||||
app.route("/rpc", rpcApp);
|
app.route("/rpc", rpcApp);
|
||||||
app.get("/*", clientEntry);
|
app.get("/*", clientEntry);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user