-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathDockerfile
More file actions
218 lines (180 loc) · 8.98 KB
/
Dockerfile
File metadata and controls
218 lines (180 loc) · 8.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# All-in-one Dockerfile for Inker
# Bundles: frontend (nginx), backend (bun/nestjs), PostgreSQL 17, Redis 8
# =============================================================================
# Stage 1: Build frontend
# =============================================================================
FROM oven/bun:1-alpine AS frontend-builder
WORKDIR /app
COPY frontend/package.json frontend/bun.lock* ./
RUN bun install --frozen-lockfile
COPY frontend/ .
RUN bun run build
# =============================================================================
# Stage 2: Install backend production dependencies
# =============================================================================
FROM oven/bun:1-slim AS backend-install
WORKDIR /app
# Node.js binary for Prisma generate (bun segfaults with Prisma CLI)
COPY --from=node:22-slim /usr/local/bin/node /usr/local/bin/node
RUN apt-get update && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/*
COPY backend/package.json backend/bun.lock* ./
COPY backend/prisma ./prisma/
# Install all deps → generate prisma → reinstall production-only → prune
RUN bun install --frozen-lockfile && \
node ./node_modules/prisma/build/index.js generate && \
cp -r node_modules/.prisma /tmp/.prisma && \
rm -rf node_modules && \
bun install --production --frozen-lockfile && \
cp -r /tmp/.prisma node_modules/.prisma && \
rm -rf /tmp/.prisma \
node_modules/typescript \
node_modules/@types && \
# Prune unnecessary files from production node_modules
find node_modules \( \
-name "*.md" -o -name "*.map" -o -name "CHANGELOG*" -o \
-name "README*" -o -name "LICENSE*" -o -name "*.d.ts" -o \
-name "*.test.*" -o -name "*.spec.*" -o \
-name "__tests__" -o -name "docs" -o -name ".github" -o \
-name "example" -o -name "examples" -o -name ".npmignore" -o \
-name "tsconfig.json" -o -name ".eslintrc*" -o -name ".prettierrc*" \
\) -exec rm -rf {} + 2>/dev/null || true && \
# Remove swagger UI (not needed in production)
rm -rf node_modules/swagger-ui-dist && \
# Remove musl variants of sharp (only glibc needed on Debian)
rm -rf node_modules/@img/sharp-libvips-linuxmusl-x64 \
node_modules/@img/sharp-linuxmusl-x64
# =============================================================================
# Stage 3: Build backend
# =============================================================================
FROM oven/bun:1-slim AS backend-builder
WORKDIR /app
COPY --from=node:22-slim /usr/local/bin/node /usr/local/bin/node
RUN apt-get update && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/*
COPY backend/package.json backend/bun.lock* ./
RUN bun install --frozen-lockfile
COPY backend/prisma ./prisma/
RUN node ./node_modules/prisma/build/index.js generate
COPY backend/ .
RUN bun run build
# =============================================================================
# Stage 4: Production (all-in-one)
# =============================================================================
FROM debian:trixie-slim AS production
ARG S6_OVERLAY_VERSION=3.2.1.0
# Install all system packages in one layer
RUN apt-get update && apt-get install -y --no-install-recommends \
# PostgreSQL
postgresql-17 \
# Redis
redis-server \
# Nginx
nginx \
# Chrome headless shell dependencies
wget ca-certificates openssl unzip \
fonts-liberation fonts-noto-color-emoji fonts-noto-cjk fontconfig \
libnss3 libatk-bridge2.0-0t64 libdrm2 libxkbcommon0 \
libgbm1 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
libasound2t64 libcups2t64 libatk1.0-0t64 libnspr4 libdbus-1-3 \
# s6-overlay dependencies
xz-utils \
&& \
# Install Chrome Headless Shell
CHROME_VERSION=$(wget -qO- "https://googlechromelabs.github.io/chrome-for-testing/LATEST_RELEASE_STABLE") && \
wget -q "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chrome-headless-shell-linux64.zip" -O /tmp/chrome.zip && \
unzip /tmp/chrome.zip -d /opt/ && \
chmod +x /opt/chrome-headless-shell-linux64/chrome-headless-shell && \
rm /tmp/chrome.zip && \
# Strip Chrome: remove GPU libs (--disable-gpu), keep locale packs for Unicode/CJK shaping
rm -f /opt/chrome-headless-shell-linux64/libEGL.so \
/opt/chrome-headless-shell-linux64/libGLESv2.so \
/opt/chrome-headless-shell-linux64/libvk_swiftshader.so \
/opt/chrome-headless-shell-linux64/libvulkan.so.1 \
/opt/chrome-headless-shell-linux64/vk_swiftshader_icd.json \
/opt/chrome-headless-shell-linux64/LICENSE.headless_shell && \
# Install s6-overlay
wget -q "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz" -O /tmp/s6-noarch.tar.xz && \
tar -C / -Jxpf /tmp/s6-noarch.tar.xz && \
wget -q "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-x86_64.tar.xz" -O /tmp/s6-x86_64.tar.xz && \
tar -C / -Jxpf /tmp/s6-x86_64.tar.xz && \
rm /tmp/s6-noarch.tar.xz /tmp/s6-x86_64.tar.xz && \
# Install PostgreSQL 15 from PGDG for data migration (15→17) support
# Existing users upgrading from bookworm need PG 15 binaries to dump their data
echo "deb http://apt.postgresql.org/pub/repos/apt trixie-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
wget -qO /etc/apt/trusted.gpg.d/pgdg.asc https://www.postgresql.org/media/keys/ACCC4CF8.asc && \
apt-get update -qq && \
apt-get install -y -qq --no-install-recommends postgresql-15 >/dev/null 2>&1 && \
rm -rf /var/lib/postgresql/15 /etc/apt/sources.list.d/pgdg.list && \
# Remove build-only tools normally
apt-get purge -y unzip xz-utils wget && apt-get autoremove -y && \
# Force-remove transitive deps not needed at runtime
# (bypass dependency checks to avoid cascading removal of postgresql/chrome)
dpkg --purge --force-depends \
libllvm19 libz3-4 libperl5.40 perl perl-modules-5.40 \
libavahi-client3 libavahi-common-data libavahi-common3 \
libelf1t64 \
2>/dev/null || true && \
rm -rf /var/lib/apt/lists/* /var/log/dpkg.log /var/log/apt && \
# Remove unused data (keep locales and i18n for Unicode/CJK support)
rm -rf /usr/share/doc /usr/share/man \
/usr/share/info /usr/share/lintian /usr/share/X11/xkb \
/var/cache/debconf/*-old && \
# Remove auto-created PostgreSQL cluster (will be initialized on first run)
rm -rf /var/lib/postgresql/17/main/*
# Install Bun runtime (copy from build image)
COPY --from=oven/bun:1-slim /usr/local/bin/bun /usr/local/bin/bun
RUN ln -s /usr/local/bin/bun /usr/local/bin/bunx
# Node.js binary for Prisma CLI (Bun's baseline mode crashes on non-AVX2 hardware)
COPY --from=node:22-slim /usr/local/bin/node /usr/local/bin/node
# Puppeteer configuration
ENV PUPPETEER_EXECUTABLE_PATH=/opt/chrome-headless-shell-linux64/chrome-headless-shell
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
# Application environment defaults
ENV NODE_ENV=production \
PORT=3002 \
DATABASE_URL=postgresql://inker_user:inker_password@localhost:5432/inker_db \
REDIS_HOST=localhost \
REDIS_PORT=6379 \
REDIS_PASSWORD=inker_redis \
REDIS_URL=redis://:inker_redis@localhost:6379 \
ADMIN_PIN="1111" \
CORS_ORIGINS=* \
LOG_LEVEL=info
# Set up application directory
WORKDIR /app
# Copy backend production dependencies
COPY --from=backend-install /app/node_modules ./node_modules
# Copy Prisma schema and generated client
COPY backend/prisma ./prisma/
COPY --from=backend-install /app/node_modules/.prisma ./node_modules/.prisma
COPY --from=backend-install /app/node_modules/@prisma ./node_modules/@prisma
# Copy backend build
COPY --from=backend-builder /app/dist ./dist
COPY backend/package.json ./
# Copy backend font assets
COPY backend/assets/fonts /app/assets/fonts
# Copy frontend build to nginx html directory
COPY --from=frontend-builder /app/dist /usr/share/nginx/html
# Copy frontend font files
COPY frontend/public/fonts /usr/share/nginx/html/fonts
# Copy nginx config
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -f /etc/nginx/sites-enabled/default
# Copy s6-overlay service definitions
COPY docker/cont-init.d/ /etc/cont-init.d/
COPY docker/services.d/ /etc/services.d/
RUN chmod +x /etc/cont-init.d/* && \
chmod +x /etc/services.d/*/run
# Create required directories
RUN mkdir -p /app/uploads/screens /app/uploads/firmware /app/uploads/widgets \
/app/uploads/captures /app/uploads/drawings /app/logs \
/data /var/lib/postgresql/17/main /run/postgresql && \
chown -R postgres:postgres /var/lib/postgresql /run/postgresql
# Create non-root user for backend process
RUN useradd --system --no-create-home --shell /usr/sbin/nologin inker && \
chown -R inker:inker /app
EXPOSE 80
# Health check via nginx
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
CMD bun -e "const r=await fetch('http://127.0.0.1/health');process.exit(r.ok?0:1)" || exit 1
# s6-overlay entrypoint
ENTRYPOINT ["/init"]