forked from plutonhq/pluton
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.source
More file actions
186 lines (148 loc) · 6.61 KB
/
Copy pathDockerfile.source
File metadata and controls
186 lines (148 loc) · 6.61 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
# Dockerfile
# Uses Source to Build the docker Image
# Build arguments (can be overridden at build time)
ARG APP_VERSION=0.0.1
ARG RESTIC_VERSION=0.19.1
ARG RCLONE_VERSION=1.74.4
# Stage 1: Dependencies
FROM node:24-alpine AS deps
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /workspace
# Copy workspace configuration files
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json ./
COPY frontend/package.json ./frontend/package.json
COPY backend/package.json ./backend/package.json
# Install all dependencies (needed for building)
RUN pnpm install --frozen-lockfile
# Stage 2: Frontend Builder
FROM node:24-alpine AS frontend-builder
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /workspace
# Copy dependencies from deps stage
COPY --from=deps /workspace/node_modules ./node_modules
COPY --from=deps /workspace/package.json ./package.json
COPY --from=deps /workspace/pnpm-workspace.yaml ./pnpm-workspace.yaml
COPY --from=deps /workspace/frontend/node_modules ./frontend/node_modules
COPY --from=deps /workspace/frontend/package.json ./frontend/package.json
# Copy frontend source code
COPY frontend ./frontend
# Build frontend
WORKDIR /workspace/frontend
RUN pnpm run build
# Stage 3: Backend Builder
FROM node:24-alpine AS backend-builder
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /workspace
# Copy dependencies from deps stage
COPY --from=deps /workspace/node_modules ./node_modules
COPY --from=deps /workspace/package.json ./package.json
COPY --from=deps /workspace/pnpm-workspace.yaml ./pnpm-workspace.yaml
COPY --from=deps /workspace/backend/node_modules ./backend/node_modules
COPY --from=deps /workspace/backend/package.json ./backend/package.json
# Copy backend source code
COPY backend ./backend
# Build backend (compile TypeScript)
WORKDIR /workspace/backend
RUN pnpm run build:pkg
# Generate database migrations
RUN npx drizzle-kit generate
# Stage 4: Production Dependencies
FROM node:24-alpine AS prod-deps
# Install pnpm and build tools for native modules
RUN corepack enable && corepack prepare pnpm@latest --activate && \
apk add --no-cache python3 make g++
WORKDIR /workspace
# Copy workspace configuration
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./
COPY backend/package.json ./backend/package.json
# Install production dependencies only (allow scripts for better-sqlite3)
RUN pnpm install --prod --frozen-lockfile
# Remove build tools
RUN apk del python3 make g++
# Stage 5: Production Image
FROM node:24-alpine AS production
# Install wget for healthcheck
RUN apk add --no-cache wget
WORKDIR /app
# Copy compiled backend from builder
COPY --from=backend-builder /workspace/backend/dist ./dist
COPY --from=backend-builder /workspace/backend/drizzle ./drizzle
COPY --from=backend-builder /workspace/backend/loader.mjs ./loader.mjs
COPY --from=backend-builder /workspace/backend/package.json ./package.json
# Copy frontend build to public directory
COPY --from=frontend-builder /workspace/frontend/dist ./public
# Copy production node_modules (pnpm workspace structure)
# Copy the .pnpm virtual store
COPY --from=prod-deps /workspace/node_modules/.pnpm ./node_modules/.pnpm
# Create symlinks for each package in node_modules
# This replicates what pnpm does for workspace packages
RUN cd node_modules/.pnpm && \
for dir in *; do \
if [ -d "$dir/node_modules" ]; then \
for pkg in $dir/node_modules/*; do \
pkg_name=$(basename $pkg); \
if [ ! -e "../$pkg_name" ]; then \
ln -s ".pnpm/$dir/node_modules/$pkg_name" "../$pkg_name" 2>/dev/null || true; \
fi; \
done; \
fi; \
done
# Create data directory
RUN mkdir -p /data /data/logs /data/db /data/config
# Download specific versions of restic and rclone binaries and place in system PATH
ARG TARGETARCH
ARG RESTIC_VERSION
ARG RCLONE_VERSION
RUN echo "Building for architecture: ${TARGETARCH}" && \
echo "Installing restic v${RESTIC_VERSION} and rclone v${RCLONE_VERSION}" && \
# Download restic
if [ "${TARGETARCH}" = "amd64" ]; then \
wget -q "https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_amd64.bz2" -O /tmp/restic.bz2; \
elif [ "${TARGETARCH}" = "arm64" ]; then \
wget -q "https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_arm64.bz2" -O /tmp/restic.bz2; \
fi && \
bunzip2 /tmp/restic.bz2 && \
mv /tmp/restic /usr/local/bin/restic && \
chmod +x /usr/local/bin/restic && \
# Download rclone
if [ "${TARGETARCH}" = "amd64" ]; then \
wget -q "https://downloads.rclone.org/v${RCLONE_VERSION}/rclone-v${RCLONE_VERSION}-linux-amd64.zip" -O /tmp/rclone.zip; \
elif [ "${TARGETARCH}" = "arm64" ]; then \
wget -q "https://downloads.rclone.org/v${RCLONE_VERSION}/rclone-v${RCLONE_VERSION}-linux-arm64.zip" -O /tmp/rclone.zip; \
fi && \
apk add --no-cache unzip && \
unzip -q /tmp/rclone.zip -d /tmp && \
mv /tmp/rclone-*/rclone /usr/local/bin/rclone && \
chmod +x /usr/local/bin/rclone && \
rm -rf /tmp/rclone* && \
apk del unzip && \
# Verify installations (unset env vars to avoid conflicts with rclone flags)
unset RESTIC_VERSION RCLONE_VERSION && \
restic version && \
rclone version
# Create Pluton wrapper scripts for rclone and restic
# These ensure the tools use Pluton's configuration from /data/config
RUN echo '#!/bin/sh' > /usr/local/bin/prclone && \
echo '# Pluton Wrapper for rclone' >> /usr/local/bin/prclone && \
echo '# This script ensures that rclone uses Pluton configuration.' >> /usr/local/bin/prclone && \
echo 'exec /usr/local/bin/rclone --config /data/config/rclone.conf "$@"' >> /usr/local/bin/prclone && \
chmod +x /usr/local/bin/prclone && \
echo '#!/bin/sh' > /usr/local/bin/prestic && \
echo '# Pluton Wrapper for restic' >> /usr/local/bin/prestic && \
echo '# This script ensures that restic uses Pluton rclone binary and configuration.' >> /usr/local/bin/prestic && \
echo 'export RCLONE_CONFIG=/data/config/rclone.conf' >> /usr/local/bin/prestic && \
echo 'exec /usr/local/bin/restic -o rclone.program=/usr/local/bin/rclone "$@"' >> /usr/local/bin/prestic && \
chmod +x /usr/local/bin/prestic
# Set environment variables
ARG APP_VERSION
ENV NODE_ENV=production \
IS_DOCKER=true \
SERVER_PORT=5173 \
APP_VERSION=${APP_VERSION}
# Expose the application port
EXPOSE 5173
# Start the application with custom loader for extension-less imports
CMD ["node", "--loader", "./loader.mjs", "dist/index.js"]