mirror of
https://github.com/rajnandan1/kener.git
synced 2026-06-23 04:10:22 +00:00
Create Dockerfile and Docker Compose configurations for Kener v4 application
- Implement multi-stage Dockerfile for building and running the Kener application with support for Alpine and Debian variants. - Establish development and production Docker Compose files for local testing and deployment. - Configure Redis service for caching and job scheduling. - Set up environment variables for application configuration, including secret keys and database connections. - Define health checks for Redis service to ensure reliability.
This commit is contained in:
+44
-2
@@ -1,9 +1,51 @@
|
|||||||
|
# Dependencies
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
# Version control
|
||||||
.git
|
.git
|
||||||
.github
|
.github
|
||||||
|
|
||||||
|
# IDE and editor
|
||||||
.vscode
|
.vscode
|
||||||
dist
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Build outputs (rebuilt inside Docker)
|
||||||
build
|
build
|
||||||
|
dist
|
||||||
|
.svelte-kit
|
||||||
|
.docs-excluded
|
||||||
|
|
||||||
|
# Environment and secrets
|
||||||
.env
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# OS files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.log
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Docker files (prevent recursive context)
|
||||||
|
Dockerfile
|
||||||
|
docker-compose*.yml
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Documentation and meta
|
||||||
|
README.md
|
||||||
|
README.template.md
|
||||||
|
AGENTS.md
|
||||||
|
CHANGELOG.md
|
||||||
|
LICENSE
|
||||||
|
check-output.txt
|
||||||
|
|
||||||
|
# AI / tooling config
|
||||||
|
.claude
|
||||||
|
|
||||||
|
# Test artifacts
|
||||||
|
*.test.*
|
||||||
|
*.spec.*
|
||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Kener v4 — Status Page Application
|
||||||
|
# Multi-stage, multi-variant (Alpine / Debian) Dockerfile
|
||||||
|
#
|
||||||
|
# Build:
|
||||||
|
# docker build -t kener . # Alpine (default)
|
||||||
|
# docker build -t kener --build-arg VARIANT=debian . # Debian Slim
|
||||||
|
#
|
||||||
|
# Run:
|
||||||
|
# docker run -d -p 3000:3000 \
|
||||||
|
# -e KENER_SECRET_KEY=<secret> \
|
||||||
|
# -e REDIS_URL=redis://<host>:6379 \
|
||||||
|
# -v kener_db:/app/database \
|
||||||
|
# kener
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
ARG NODE_VERSION=24
|
||||||
|
ARG VARIANT=alpine
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# STAGE 1 — BUILDER (installs deps, compiles native modules, builds app)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ---------- Alpine builder ----------
|
||||||
|
FROM node:${NODE_VERSION}-alpine AS builder-alpine
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
build-base \
|
||||||
|
python3 \
|
||||||
|
sqlite \
|
||||||
|
sqlite-dev \
|
||||||
|
tzdata
|
||||||
|
|
||||||
|
# ---------- Debian builder ----------
|
||||||
|
FROM node:${NODE_VERSION}-slim AS builder-debian
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
python3 \
|
||||||
|
sqlite3 \
|
||||||
|
libsqlite3-dev \
|
||||||
|
tzdata && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# ---------- Selected variant ----------
|
||||||
|
FROM builder-${VARIANT} AS builder
|
||||||
|
|
||||||
|
ENV NPM_CONFIG_LOGLEVEL=error
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 1. Copy package manifests first (maximises layer cache hits)
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# 2. Install ALL dependencies (devDependencies needed for the build step)
|
||||||
|
RUN --mount=type=cache,target=/root/.npm \
|
||||||
|
npm ci --no-fund && \
|
||||||
|
npm cache clean --force
|
||||||
|
|
||||||
|
# 3. Copy the rest of the source tree
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# 4. Create directories that the app expects
|
||||||
|
RUN mkdir -p database
|
||||||
|
|
||||||
|
# 5. Remove docs routes before build (avoids EXDEV rename error in overlayfs)
|
||||||
|
# and clean .svelte-kit so stale route types don't persist
|
||||||
|
RUN rm -rf src/routes/\(docs\) .svelte-kit
|
||||||
|
|
||||||
|
# 6. Build: SvelteKit (vite) + server bundle (esbuild)
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# 7. Remove devDependencies from node_modules
|
||||||
|
RUN npm prune --omit=dev
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# STAGE 2 — PRODUCTION (minimal runtime image)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# ---------- Alpine runtime ----------
|
||||||
|
FROM node:${NODE_VERSION}-alpine AS final-alpine
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
sqlite \
|
||||||
|
tzdata \
|
||||||
|
iputils \
|
||||||
|
curl \
|
||||||
|
libcap && \
|
||||||
|
# Grant ping the NET_RAW capability so non-root users can send ICMP packets
|
||||||
|
setcap cap_net_raw+ep /bin/ping || true
|
||||||
|
|
||||||
|
# ---------- Debian runtime ----------
|
||||||
|
FROM node:${NODE_VERSION}-slim AS final-debian
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
sqlite3 \
|
||||||
|
tzdata \
|
||||||
|
iputils-ping \
|
||||||
|
curl \
|
||||||
|
libcap2-bin && \
|
||||||
|
setcap cap_net_raw+ep /usr/bin/ping || true && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# ---------- Selected variant ----------
|
||||||
|
FROM final-${VARIANT} AS final
|
||||||
|
|
||||||
|
ARG PORT=3000
|
||||||
|
|
||||||
|
ENV NODE_ENV=production \
|
||||||
|
PORT=${PORT} \
|
||||||
|
TZ=UTC \
|
||||||
|
# Required so Node can import .ts migration/seed files at runtime
|
||||||
|
NODE_OPTIONS="--experimental-strip-types"
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Create writable directories owned by the non-root "node" user
|
||||||
|
# (node:node is provided by the official Node.js images)
|
||||||
|
RUN mkdir -p database && \
|
||||||
|
chown -R node:node /app
|
||||||
|
|
||||||
|
# ---- Copy artifacts from builder (order: least → most likely to change) ----
|
||||||
|
|
||||||
|
# Production node_modules (largest layer, changes least often)
|
||||||
|
COPY --chown=node:node --from=builder /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
# Package manifest (needed for ESM "type":"module" resolution)
|
||||||
|
COPY --chown=node:node --from=builder /app/package.json ./package.json
|
||||||
|
|
||||||
|
# Knex migrations & seeds (run at startup by build/main.js)
|
||||||
|
COPY --chown=node:node --from=builder /app/migrations ./migrations
|
||||||
|
COPY --chown=node:node --from=builder /app/seeds ./seeds
|
||||||
|
|
||||||
|
# Seed data files imported by seeds at runtime (all are leaf modules)
|
||||||
|
COPY --chown=node:node --from=builder /app/src/lib/server/db/seedSiteData.ts ./src/lib/server/db/seedSiteData.ts
|
||||||
|
COPY --chown=node:node --from=builder /app/src/lib/server/db/seedMonitorData.ts ./src/lib/server/db/seedMonitorData.ts
|
||||||
|
COPY --chown=node:node --from=builder /app/src/lib/server/db/seedPagesData.ts ./src/lib/server/db/seedPagesData.ts
|
||||||
|
COPY --chown=node:node --from=builder /app/src/lib/server/templates/general ./src/lib/server/templates/general
|
||||||
|
|
||||||
|
# Build output (SvelteKit client/server + esbuild main.js) — changes most often
|
||||||
|
COPY --chown=node:node --from=builder /app/build ./build
|
||||||
|
|
||||||
|
# ---- Runtime configuration ----
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER node
|
||||||
|
|
||||||
|
EXPOSE ${PORT}
|
||||||
|
|
||||||
|
# Healthcheck: hit the /healthcheck endpoint exposed by Express in main.ts
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||||
|
CMD sh -c 'curl -sf http://localhost:${PORT}${KENER_BASE_PATH}/healthcheck || exit 1'
|
||||||
|
|
||||||
|
ENTRYPOINT ["node"]
|
||||||
|
CMD ["build/main.js"]
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Kener v4 — Development Docker Compose (local build testing)
|
||||||
|
#
|
||||||
|
# Builds the image from the local Dockerfile instead of pulling from a registry.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# docker compose -f docker-compose.dev.yml up -d --build
|
||||||
|
#
|
||||||
|
# Build a specific variant:
|
||||||
|
# docker compose -f docker-compose.dev.yml build --build-arg VARIANT=debian
|
||||||
|
# docker compose -f docker-compose.dev.yml up -d
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Redis
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: kener-redis-dev
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Kener — built from local Dockerfile
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
kener:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
args:
|
||||||
|
VARIANT: alpine # or "debian"
|
||||||
|
NODE_VERSION: 24
|
||||||
|
container_name: kener-dev
|
||||||
|
environment:
|
||||||
|
KENER_SECRET_KEY: dev-secret-key-for-local-testing-only
|
||||||
|
REDIS_URL: redis://redis:6379
|
||||||
|
# DATABASE_URL: sqlite://./database/kener.sqlite.db
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- dev_data:/app/database
|
||||||
|
- dev_uploads:/app/uploads
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
dev_data:
|
||||||
|
dev_uploads:
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# Kener v4 — Production Docker Compose
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# docker compose up -d
|
||||||
|
#
|
||||||
|
# Defaults to the published image. To use a local build instead:
|
||||||
|
# docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Redis — required for BullMQ queues, caching, and scheduler
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: kener-redis
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Kener — Status Page Application
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
kener:
|
||||||
|
image: rajnandan1/kener:latest
|
||||||
|
# For Alpine variant use: rajnandan1/kener:alpine
|
||||||
|
container_name: kener
|
||||||
|
environment:
|
||||||
|
# ── Required ──
|
||||||
|
KENER_SECRET_KEY: replace_me_with_a_random_string # generate: openssl rand -base64 32
|
||||||
|
REDIS_URL: redis://redis:6379
|
||||||
|
|
||||||
|
# ── Database (default: SQLite) ──
|
||||||
|
# DATABASE_URL: sqlite://./database/kener.sqlite.db
|
||||||
|
# DATABASE_URL: postgresql://user:password@postgres:5432/kener
|
||||||
|
# DATABASE_URL: mysql://user:password@mysql:3306/kener
|
||||||
|
|
||||||
|
# ── Email (optional) ──
|
||||||
|
# RESEND_API_KEY:
|
||||||
|
# RESEND_SENDER_EMAIL:
|
||||||
|
# SMTP_HOST:
|
||||||
|
# SMTP_PORT:
|
||||||
|
# SMTP_USER:
|
||||||
|
# SMTP_PASSWORD:
|
||||||
|
# SMTP_SENDER:
|
||||||
|
# SMTP_SECURE: 0
|
||||||
|
|
||||||
|
# ── Advanced (you likely don't need to change these) ──
|
||||||
|
# PORT: 3000
|
||||||
|
# KENER_BASE_PATH:
|
||||||
|
# NODE_ENV: production # already set in the image
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- data:/app/database
|
||||||
|
- uploads:/app/uploads
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Optional: PostgreSQL (uncomment and set DATABASE_URL above)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# postgres:
|
||||||
|
# image: postgres:16-alpine
|
||||||
|
# container_name: kener-postgres
|
||||||
|
# environment:
|
||||||
|
# POSTGRES_USER: kener
|
||||||
|
# POSTGRES_PASSWORD: change_me # use a strong password
|
||||||
|
# POSTGRES_DB: kener
|
||||||
|
# volumes:
|
||||||
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
|
# restart: unless-stopped
|
||||||
|
# healthcheck:
|
||||||
|
# test: ["CMD-SHELL", "pg_isready -U kener"]
|
||||||
|
# interval: 10s
|
||||||
|
# timeout: 5s
|
||||||
|
# retries: 5
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Optional: MySQL / MariaDB (uncomment and set DATABASE_URL above)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# mysql:
|
||||||
|
# image: mariadb:11
|
||||||
|
# container_name: kener-mysql
|
||||||
|
# environment:
|
||||||
|
# MYSQL_USER: kener
|
||||||
|
# MYSQL_PASSWORD: change_me # use a strong password
|
||||||
|
# MYSQL_DATABASE: kener
|
||||||
|
# MYSQL_RANDOM_ROOT_PASSWORD: "true"
|
||||||
|
# volumes:
|
||||||
|
# - mysql_data:/var/lib/mysql
|
||||||
|
# restart: unless-stopped
|
||||||
|
# healthcheck:
|
||||||
|
# test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
|
||||||
|
# interval: 10s
|
||||||
|
# timeout: 5s
|
||||||
|
# retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
name: kener_db
|
||||||
|
uploads:
|
||||||
|
name: kener_uploads
|
||||||
|
redis_data:
|
||||||
|
name: kener_redis
|
||||||
|
# postgres_data:
|
||||||
|
# name: kener_postgres
|
||||||
|
# mysql_data:
|
||||||
|
# name: kener_mysql
|
||||||
Generated
+3559
-5720
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user