DockerでMySQL、Caddyが利用されるよう変更したほか不具合を修正

This commit is contained in:
2026-01-11 23:16:01 +09:00
parent b982c8acee
commit 5b10b90bf5
6 changed files with 150 additions and 15 deletions

33
Caddyfile Normal file
View File

@@ -0,0 +1,33 @@
# Caddyfile - Reverse Proxy Configuration
#
# 使用方法:
# 1. example.com を実際のドメインに置き換えてください
# 2. DNS の A レコードをこのサーバーの IP アドレスに向けてください
# 3. docker compose up -d で起動すると、自動的に HTTPS 証明書が取得されます
#
# ローカル開発用の場合は、以下のように変更してください
# :80 {
# reverse_proxy app:8080
# }
example.com {
reverse_proxy app:8080
# ログ設定
log {
output file /data/access.log
format json
}
# セキュリティヘッダー
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
-Server
}
# gzip 圧縮
encode gzip
}

View File

@@ -1,12 +1,8 @@
# Builder stage
FROM golang:1.24-alpine AS builder
FROM golang:1.24-trixie AS builder
# Set working directory
WORKDIR /app
# Install git if needed for fetching dependencies (sometimes needed even with go modules)
# RUN apk add --no-cache git
# Copy go mod and sum files
COPY go.mod go.sum ./
@@ -21,12 +17,18 @@ COPY . .
RUN CGO_ENABLED=0 go build -o server ./cmd/server/main.go
# Runtime stage
FROM alpine:latest
FROM debian:trixie-slim
# Install runtime dependencies
RUN apk add --no-cache ca-certificates tzdata
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
tzdata \
curl \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN useradd -r -u 1000 -s /bin/false appuser
# Set working directory
WORKDIR /app
# Copy binary from builder
@@ -35,8 +37,21 @@ COPY --from=builder /app/server .
# Copy web assets (templates, static files)
COPY --from=builder /app/web ./web
# Expose port (adjust if your app uses a different port)
# Create data directory for SQLite
RUN mkdir -p /app/data && chown -R appuser:appuser /app
# Switch to non-root user
USER appuser
# Expose port
EXPOSE 8080
# Volume for persistent data
VOLUME ["/app/data"]
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/ || exit 1
# Run the application
ENTRYPOINT ["./server"]

34
config.ini.docker.example Normal file
View File

@@ -0,0 +1,34 @@
; Homework Manager 設定ファイル (Docker用)
; docker-compose.yml と一緒に使用してください
; ローカル実行する場合securityセクションのhttpsをfalseに変更するのを忘れないでください
[server]
port = 8080
debug = false
[database]
driver = mysql
host = db
port = 3306
user = homework
password = homework_password
name = homework_manager
[session]
; 本番環境では必ず変更してください
secret = CHANGE_THIS_TO_A_SECURE_RANDOM_STRING
[auth]
allow_registration = true
[security]
https = true
; こちらも本番環境では必ず変更してください
csrf_secret = CHANGE_THIS_TO_A_SECURE_RANDOM_STRING
rate_limit_enabled = true
rate_limit_requests = 100
rate_limit_window = 60
trusted_proxies = 172.16.0.0/12
[notification]
telegram_bot_token =

View File

@@ -1,11 +1,64 @@
services:
app:
build: .
ports:
- "8080:8080"
container_name: homework-manager
volumes:
- ./homework.db:/app/homework.db
- ./config.ini:/app/config.ini
- ./config.ini:/app/config.ini:ro
environment:
- TZ=Asia/Tokyo
restart: unless-stopped
networks:
- internal
expose:
- "8080"
depends_on:
db:
condition: service_healthy
db:
image: mysql:8.0
container_name: homework-db
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-rootpassword}
MYSQL_DATABASE: ${MYSQL_DATABASE:-homework_manager}
MYSQL_USER: ${MYSQL_USER:-homework}
MYSQL_PASSWORD: ${MYSQL_PASSWORD:-homework_password}
TZ: Asia/Tokyo
volumes:
- db-data:/var/lib/mysql
networks:
- internal
restart: unless-stopped
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD:-rootpassword}" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
caddy:
image: caddy:2-alpine
container_name: homework-caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
environment:
- TZ=Asia/Tokyo
restart: unless-stopped
networks:
- internal
depends_on:
- app
networks:
internal:
driver: bridge
volumes:
db-data:
caddy-data:
caddy-config:

View File

@@ -10,7 +10,7 @@ type APIKey struct {
ID uint `gorm:"primarykey" json:"id"`
UserID uint `gorm:"not null;index" json:"user_id"`
Name string `gorm:"not null" json:"name"`
KeyHash string `gorm:"not null;uniqueIndex" json:"-"`
KeyHash string `gorm:"not null;uniqueIndex;size:255" json:"-"`
LastUsed *time.Time `json:"last_used,omitempty"`
CreatedAt time.Time `json:"created_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`

View File

@@ -8,7 +8,7 @@ import (
type User struct {
ID uint `gorm:"primarykey" json:"id"`
Email string `gorm:"uniqueIndex;not null" json:"email"`
Email string `gorm:"uniqueIndex;not null;size:255" json:"email"`
PasswordHash string `gorm:"not null" json:"-"`
Name string `gorm:"not null" json:"name"`
Role string `gorm:"not null;default:user" json:"role"` // "admin" or "user"