Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Git
.git
.gitignore
.gitattributes

# Documentation
README.md
*.md
docs/

# Development files
.env
.env.local
.env.development
.env.test
.env.production

# IDE files
.vscode/
.idea/
*.swp
*.swo
*~

# OS files
.DS_Store
Thumbs.db

# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Dependencies
node_modules/
frontend/node_modules/

# Build artifacts
frontend/dist/
server/server

# Deploy scripts
deploy_scripts/

# Maintenance page
maintenance_page/

# Kill switch
kill-sw.js

# Temporary files
tmp/
temp/

# Test files
test/
tests/
*_test.go
*_test.js

# Coverage reports
coverage/

# Runtime files
*.pid
*.seed
*.pid.lock

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# 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

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
public

# Storybook build outputs
.out
.storybook-out

# Temporary folders
tmp/
temp/
75 changes: 75 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Multi-stage build for production image
FROM node:22-alpine AS frontend-builder

WORKDIR /app/frontend

COPY frontend/package*.json ./
RUN npm ci && npm install -g vue-cli-service

COPY frontend/ ./
RUN npm run build


# Go build stage
FROM golang:1.20-alpine AS go-builder

RUN apk add --no-cache git

WORKDIR /app/server

# Copy go mod files
COPY server/go.mod server/go.sum ./

# Download dependencies
RUN go mod download

# Copy source code
COPY server/ ./

# Build Go application
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server .


# Production stage
FROM alpine:latest

# Install runtime dependencies
RUN apk --no-cache add ca-certificates tzdata

# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup

WORKDIR /app

# Copy built frontend from frontend-builder stage
COPY --from=frontend-builder /app/frontend/dist ./frontend/dist

# Copy built Go binary from go-builder stage
COPY --from=go-builder /app/server/server ./server

# Copy static files if they exist
COPY --from=go-builder /app/server/static ./static

# Create logs directory
RUN mkdir -p logs && chown -R appuser:appgroup /app

# Change ownership
RUN chown -R appuser:appgroup /app

# Switch to non-root user
USER appuser

# Expose port
EXPOSE 3002

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3002/api/health || exit 1

# Environment variables
ENV GIN_MODE=release
ENV PORT=3002

# Start server
CMD ["./server", "-release=true"]
80 changes: 80 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
version: '3.8'

services:
# MongoDB database
mongodb:
image: mongo:7.0
container_name: timeful-mongodb
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: timeful
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
- ./server/db/init:/docker-entrypoint-initdb.d:ro
networks:
- timeful-network


# Timeful application
timeful-app:
build:
context: .
dockerfile: Dockerfile
container_name: timeful-app
restart: unless-stopped
ports:
- "80:3002"
environment:
# Database configuration
MONGODB_URI: mongodb://admin:password@mongodb:27017/timeful?authSource=admin

# Server configuration
GIN_MODE: release
PORT: 3002

# CORS origins
CORS_ORIGINS: http://localhost:8080,https://www.timeful.app,https://timeful.app

# Session secret (change in production)
SESSION_SECRET: your-super-secret-session-key-change-in-production

# Stripe configuration (add your own keys)
# STRIPE_API_KEY: sk_test_...
# STRIPE_WEBHOOK_SECRET: whsec_...

# Google Cloud configuration (if you use it)
# GOOGLE_APPLICATION_CREDENTIALS: /app/credentials.json

# Email configuration (if you use it)
# SMTP_HOST: smtp.gmail.com
# SMTP_PORT: 587
# SMTP_USER: your-email@gmail.com
# SMTP_PASS: your-app-password
depends_on:
- mongodb
volumes:
# Mount logs directory for persistence
- ./logs:/app/logs
# Mount static files if they exist
- ./server/static:/app/static:ro
networks:
- timeful-network
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3002/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s


volumes:
mongodb_data:
driver: local

networks:
timeful-network:
driver: bridge
34 changes: 34 additions & 0 deletions env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Database Configuration
MONGO_ROOT_USERNAME=admin
MONGO_ROOT_PASSWORD=your-secure-password
MONGO_DATABASE=timeful

# Server Configuration
GIN_MODE=release
PORT=3002

# CORS Configuration
CORS_ORIGINS=https://www.timeful.app,https://timeful.app,https://www.schej.it,https://schej.it

# Session Configuration
SESSION_SECRET=your-super-secret-session-key-change-in-production

# Stripe Configuration
STRIPE_API_KEY=sk_test_your_stripe_key_here
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret_here

# Google Cloud Configuration
GOOGLE_APPLICATION_CREDENTIALS=/app/credentials.json

# Email Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password

# Domain Configuration
DOMAIN=timeful.app

# Optional: Development overrides
# NODE_ENV=development
# DEBUG=true
Loading