Skip to content

Commit 4c105de

Browse files
committed
optimize docker image with multi-layer build
1 parent 09b3efb commit 4c105de

File tree

10 files changed

+242
-70
lines changed

10 files changed

+242
-70
lines changed

mimir-rag/.dockerignore

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,54 @@
1+
# Dependencies
12
node_modules
3+
4+
# Build outputs
25
dist
36
tmp
7+
8+
# Git
49
.git
10+
.github
511
.gitignore
12+
13+
# Docker
614
Dockerfile
15+
.dockerignore
16+
docker-compose*.yml
17+
18+
# Environment files (use .env.example instead)
19+
.env
20+
.env.*
21+
!.env.example
22+
23+
# Logs
724
npm-debug.log*
25+
yarn-debug.log*
26+
yarn-error.log*
827
*.log
28+
29+
# OS files
930
.DS_Store
31+
Thumbs.db
32+
33+
# IDE
34+
.vscode
35+
.idea
36+
*.swp
37+
*.swo
38+
*~
39+
40+
# Config files
1041
mimir.config.json
42+
43+
# Documentation
44+
README.md
45+
*.md
46+
!.env.example
47+
48+
# Test files
49+
coverage
50+
.nyc_output
51+
test
52+
tests
53+
**/*.test.ts
54+
**/*.spec.ts

mimir-rag/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ MIMIR_SUPABASE_TABLE=documents
2121
MIMIR_SUPABASE_ANON_KEY=your_anon_key
2222
MIMIR_SUPABASE_ENABLE_HYBRID_SEARCH=true
2323

24+
# Database Setup (optional - for automatic schema initialization)
25+
# If not provided, DATABASE_URL will be auto-constructed from MIMIR_SUPABASE_URL
26+
# DATABASE_URL=postgresql://postgres:[email protected]:5432/postgres
27+
# MIMIR_SUPABASE_DB_PASSWORD=your_db_password
28+
2429
# LLM - Embedding Provider
2530
# Supported: openai, google, mistral
2631
MIMIR_LLM_EMBEDDING_PROVIDER=openai

mimir-rag/Dockerfile

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
# syntax=docker/dockerfile:1.7
22

3-
FROM node:20-slim AS deps
3+
FROM node:20-alpine AS builder
44
WORKDIR /app
5-
65
COPY package*.json ./
7-
RUN npm ci --omit=optional
6+
COPY tsconfig.json ./
7+
COPY src ./src
8+
RUN npm ci --omit=optional && \
9+
npm run build && \
10+
npm prune --omit=dev --omit=optional && \
11+
# Remove unnecessary files from node_modules
12+
find node_modules -type f \( -name "*.md" -o -name "*.ts" -o -name "*.map" \) -delete && \
13+
find node_modules -type d \( -name "test" -o -name "tests" -o -name "__tests__" -o -name "docs" \) -exec rm -rf {} + 2>/dev/null || true
814

9-
FROM node:20-slim AS runner
15+
FROM node:20-alpine AS runner
1016
WORKDIR /app
1117
ENV NODE_ENV=production
1218

13-
RUN apt-get update \
14-
&& apt-get install -y --no-install-recommends postgresql-client \
15-
&& rm -rf /var/lib/apt/lists/*
19+
# Install only postgresql-client and clean up in same layer
20+
RUN apk add --no-cache postgresql-client && \
21+
rm -rf /var/cache/apk/* /tmp/*
1622

17-
COPY --from=deps /app/node_modules ./node_modules
18-
COPY package*.json ./
19-
COPY tsconfig.json ./
20-
COPY mimir.config.example.json ./mimir.config.example.json
21-
COPY src ./src
23+
# Copy only production dependencies and built code
24+
COPY --from=builder /app/node_modules ./node_modules
25+
COPY --from=builder /app/dist ./dist
26+
COPY --from=builder /app/package.json ./package.json
27+
COPY --from=builder /app/src/supabase/setup.sql ./src/supabase/setup.sql
28+
COPY .env.example ./
2229
COPY scripts ./scripts
2330

24-
RUN chown -R node:node /app
25-
USER node
31+
# Create non-root user and switch to it
32+
RUN addgroup -g 1001 -S nodejs && \
33+
adduser -S nodejs -u 1001 && \
34+
chown -R nodejs:nodejs /app
35+
36+
USER nodejs
2637

2738
EXPOSE 3000
2839
ENTRYPOINT ["./scripts/docker-entrypoint.sh"]
29-
CMD ["npm", "run", "server"]
40+
CMD ["node", "dist/server/start.js"]

mimir-rag/Makefile

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
.PHONY: setup-db server ingest clean docker-build docker-run
1+
.PHONY: setup-db server ingest clean docker-build docker-run docker-run-build
22

33
DB_URL ?= $(DATABASE_URL)
44
DB_PASSWORD ?= $(PGPASSWORD)
55
PSQL ?= psql
66
SETUP_SQL := src/supabase/setup.sql
77
IMAGE_NAME ?= mimir-rag:local
8-
CONFIG_PATH ?= mimir.config.json
8+
CONFIG_PATH ?= .env
99
CONFIG_ABS := $(abspath $(CONFIG_PATH))
1010
PORT ?= 3000
1111

@@ -24,31 +24,23 @@ server: setup-db
2424
npm run server
2525

2626
ingest:
27-
npm run ingest:cli -- --config mimir.config.json
27+
npm run ingest:cli -- --config .env
2828

2929
clean:
3030
rm -rf dist tmp
3131

3232
docker-build:
3333
docker build -t $(IMAGE_NAME) .
3434

35-
docker-run: docker-build
35+
docker-run:
3636
@if [ ! -f "$(CONFIG_ABS)" ]; then \
3737
echo "Error: config file '$(CONFIG_PATH)' not found. Pass CONFIG_PATH=... to point at a valid file."; \
3838
exit 1; \
3939
fi
40-
@DOCKER_ENV_ARGS=""; \
41-
if [ -n "$(strip $(DB_URL))" ]; then \
42-
DOCKER_ENV_ARGS="$$DOCKER_ENV_ARGS -e DATABASE_URL=$(DB_URL)"; \
43-
fi; \
44-
if [ -n "$(strip $(DB_PASSWORD))" ]; then \
45-
DOCKER_ENV_ARGS="$$DOCKER_ENV_ARGS -e DB_PASSWORD=$(DB_PASSWORD)"; \
46-
fi; \
47-
set -x; \
48-
docker run --rm \
49-
$$DOCKER_ENV_ARGS \
50-
-e PORT=$(PORT) \
51-
-e MIMIR_CONFIG_PATH=/app/mimir.config.json \
40+
@echo "Starting Docker container with config from $(CONFIG_PATH)..."
41+
@docker run --rm \
5242
-p $(PORT):$(PORT) \
53-
-v $(CONFIG_ABS):/app/mimir.config.json:ro \
43+
-v $(CONFIG_ABS):/app/.env:ro \
5444
$(IMAGE_NAME)
45+
46+
docker-run-build: docker-build docker-run

mimir-rag/README.md

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,49 +2,132 @@
22

33
Utility CLI + API that ingests docs into Supabase and exposes OpenAI-compatible chat completions, MCP endpoints, and ingestion endpoints.
44

5-
## Local workflow
6-
7-
1. Copy `.env.example` to `.env` and fill in the Supabase + LLM details plus a `MIMIR_SERVER_API_KEY`, which every HTTP call must send in the `x-api-key` header (or `Authorization: Bearer <key>`). Run `npm run generate-apikey` any time you want the project to mint a new random key and write it into your `.env` file.
8-
2. Bootstrap the database schema (runs `psql src/supabase/setup.sql`):
5+
## Quick Start
96

7+
1. **Configure environment:**
108
```bash
11-
make setup-db DB_URL=postgresql://user@host:5432/db DB_PASSWORD=secret
9+
cp .env.example .env
10+
# Edit .env with your Supabase + LLM credentials
1211
```
1312

14-
3. Start the API (automatically re-runs `setup-db` beforehand):
13+
2. **Generate API key:**
14+
```bash
15+
npm run generate-apikey
16+
```
1517

18+
3. **Start the server:**
1619
```bash
1720
make server
1821
```
1922

20-
4. Kick off ingestion on demand:
23+
The server automatically:
24+
- Loads your `.env` configuration
25+
- Bootstraps the database schema (if `DATABASE_URL` is set)
26+
- Starts the API on port 3000
2127

28+
4. **Trigger ingestion:**
2229
```bash
2330
npm run ingest:cli
2431
```
2532

26-
Or with a custom .env file:
33+
## Local Development
2734

28-
```bash
29-
npm run ingest:cli -- --config /path/to/custom.env
30-
```
35+
### Database Setup
36+
37+
The database schema is automatically initialized when you run `make server` if you provide database credentials in your `.env` file. You have two options:
3138

32-
## Docker workflow
39+
**Option 1: Automatic (Recommended)**
40+
Add your Supabase database password to `.env`:
41+
```bash
42+
MIMIR_SUPABASE_DB_PASSWORD=your_db_password
43+
```
44+
The system will automatically construct the `DATABASE_URL` from your `MIMIR_SUPABASE_URL`.
45+
46+
**Option 2: Manual DATABASE_URL**
47+
Provide the full database URL in `.env`:
48+
```bash
49+
DATABASE_URL=postgresql://postgres:[email protected]:5432/postgres
50+
```
3351

34-
The repository includes a Node 20–based image for CI/CD and for developers who prefer not to install Node locally.
52+
### Manual Database Setup
3553

54+
If you need to run the schema setup manually:
3655
```bash
37-
make docker-build IMAGE_NAME=mimir-rag:local
38-
make docker-run IMAGE_NAME=mimir-rag:local \
39-
CONFIG_PATH=./.env \
40-
DB_URL=postgresql://user@host:5432/db \
41-
DB_PASSWORD=secret \
42-
PORT=3000
56+
make setup-db DB_URL=postgresql://user@host:5432/db DB_PASSWORD=secret
4357
```
4458

45-
`docker-run` binds your local `.env` file into `/app/.env`, forwards the chosen port, and passes any database credentials so the container can reach Supabase.
46-
When `DATABASE_URL` (or `DB_URL`) is provided, the container's entrypoint automatically runs `src/supabase/setup.sql`
47-
before starting the server, mirroring the local `make setup-db` behavior.
59+
## Docker Deployment
60+
61+
The repository includes a Node 20–based Alpine Linux image (~302MB) optimized for CI/CD and production deployments.
62+
63+
### One-Line Setup
64+
65+
**Build and run with your `.env` file:**
66+
```bash
67+
make docker-run-build
68+
```
69+
70+
That's it! The container automatically:
71+
- Loads all configuration from your `.env` file
72+
- Sets up the database schema (no manual psql commands needed)
73+
- Starts the server on port 3000
74+
75+
### Customization
76+
77+
**Use a different port:**
78+
```bash
79+
make docker-run-build PORT=8080
80+
```
81+
82+
**Use a different config file:**
83+
```bash
84+
make docker-run-build CONFIG_PATH=.env.production
85+
```
86+
87+
**Custom image name:**
88+
```bash
89+
make docker-run-build IMAGE_NAME=mimir:v1.0
90+
```
91+
92+
### Separate Build and Run
93+
94+
If you prefer to build and run separately:
95+
96+
**Build:**
97+
```bash
98+
make docker-build
99+
```
100+
101+
**Run:**
102+
```bash
103+
make docker-run
104+
```
105+
106+
### Manual Docker Commands
107+
108+
**Build:**
109+
```bash
110+
docker build -t mimir-rag:local .
111+
```
112+
113+
**Run:**
114+
```bash
115+
docker run --rm \
116+
-p 3000:3000 \
117+
-v $(pwd)/.env:/app/.env:ro \
118+
mimir-rag:local
119+
```
120+
121+
### How It Works
122+
123+
The Docker container:
124+
1. Mounts your `.env` file to `/app/.env` (read-only)
125+
2. Automatically loads all environment variables from `.env`
126+
3. Auto-constructs `DATABASE_URL` from `MIMIR_SUPABASE_URL` + `MIMIR_SUPABASE_DB_PASSWORD` (if not already set)
127+
4. Runs the database schema setup SQL automatically
128+
5. Starts the server
129+
130+
**No manual database setup required!** Just add your database password to `.env` and everything else is automatic.
48131

49132
## Configuration
50133

0 commit comments

Comments
 (0)