Docker Configuration#
Blinko uses a three-stage multi-stage Dockerfile to produce a lean production image. The image is built from dockerfile at the repo root and is published to Docker Hub as blinkospace/blinko.
Build Stages#
| Stage | Base Image | Role |
|---|---|---|
builder | oven/bun:1.2.8 | Installs all dependencies, runs Prisma codegen, builds the web app and seed script |
init-downloader | node:20-alpine | Downloads the dumb-init process supervisor binary |
runner | node:20-alpine | Production runtime β receives only compiled artifacts and re-installs a curated dependency set |
Builder stage : runs bun install, bunx prisma generate, bun run build:web, and bun run build:seed. It also generates a start.sh entrypoint that runs Prisma migrations and seeds before starting the server.
Runner stage : copies only what is needed from builder:
dist/β./server(compiled server bundle)server/lute.min.js(Markdown renderer)prisma/and.prisma/client(schema + generated client)start.shanddumb-init
node_modules from the builder stage is not copied. Instead, a smaller, explicit dependency set is installed at runtime via npm (see Runtime Dependencies below).
ARM Architecture Support#
Both the builder and runner stages detect ARM (aarch64 / arm64) and pre-install the platform-specific sharp@0.34.1 / @img/sharp-linux-arm64 binary before the main dependency installation . The SHARP_IGNORE_GLOBAL_LIBVIPS=1 environment variable and custom mirror URLs ensure the native binding is fetched reliably during the build .
Mirror / Registry Override#
A build argument USE_MIRROR (default false) switches npm/bun to use the Taobao mirror (https://registry.npmmirror.com). This is useful in China or other environments with poor access to the default npm registry .
Runtime Dependencies#
The runner stage installs the following packages from scratch via npm :
@node-rs/crc32 lightningcss sharp@0.34.1 prisma@5.21.1
sqlite3@5.1.7
llamaindex @langchain/community@0.3.40 (via --legacy-peer-deps)
@libsql/client @libsql/core
The --legacy-peer-deps flag is required because llamaindex and @langchain/community declare optional peer dependencies that are not installed in the runtime stage. The Dockerfile comment explains this directly:
"legacy peer deps avoids optional peer conflicts from LangChain."
Known omission: pdf-parse#
@langchain/community's PDFLoader lists pdf-parse as an optional peer dependency. Because it is not installed in the runtime stage, PDF parsing will fail at runtime with:
ERR_MODULE_NOT_FOUND
Cannot find package 'pdf-parse' imported from
/app/node_modules/@langchain/community/dist/document_loaders/fs/pdf.cjs
This is a known open issue . The workaround is to install it manually inside the running container:
cd /app && npm install pdf-parse
Until this is included in the Dockerfile, PDF attachment indexing for RAG is broken in the default Docker image .
Startup Sequence#
The container entrypoint is dumb-init wrapping start.sh . At container start, start.sh runs:
npx prisma migrate deployβ applies pending DB migrationsnode server/seed.jsβ seeds initial datanode server/index.jsβ starts the application on port 1111
Compose Files#
| File | Purpose |
|---|---|
docker-compose.yml | Dev / local build β builds the image from ./dockerfile, includes a bundled PostgreSQL 14 service |
docker-compose.prod.yml | Production β pulls blinkospace/blinko:latest from Docker Hub; PostgreSQL service is commented out (expects external DB) |
The dev compose file uses USE_MIRROR: "true" by default . The prod compose file uses host network mode and includes log rotation (max-size: 10m, max-file: 3) .
.dockerignore#
.dockerignore excludes node_modules, build artifacts (dist/, .next/, .turbo/), test directories, logs, documentation, and macOS/IDE metadata from the build context. The one exception is **/dist-js/*, which is explicitly allowed .
Key Environment Variables (Runtime)#
| Variable | Default | Purpose |
|---|---|---|
NODE_ENV | production | Node environment |
DATABASE_URL | (required) | Postgres or LibSQL connection string |
NEXTAUTH_SECRET | (required) | Auth signing secret |
DISABLE_SECURE_COOKIE | false | Set true if behind an HTTP proxy |
TRUST_PROXY | 1 | Express trust-proxy setting |