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:
Raj Nandan Sharma
2026-02-10 08:36:28 +05:30
parent 8a498e902d
commit 9b99bec50b
5 changed files with 3928 additions and 5722 deletions
+44 -2
View File
@@ -1,9 +1,51 @@
# Dependencies
node_modules
# Version control
.git
.github
# IDE and editor
.vscode
dist
.idea
*.swp
*.swo
# Build outputs (rebuilt inside Docker)
build
dist
.svelte-kit
.docs-excluded
# Environment and secrets
.env
.env.*
!.env.example
# OS files
.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
View File
@@ -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"]
+55
View File
@@ -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:
+117
View File
@@ -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
+3559 -5720
View File
File diff suppressed because it is too large Load Diff