forked from activepieces/activepieces
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
144 lines (118 loc) · 5.85 KB
/
Copy pathDockerfile
File metadata and controls
144 lines (118 loc) · 5.85 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
FROM node:24.14.0-bullseye-slim AS base
# C.UTF-8 ships with Debian, so no locale generation is needed.
# REDISMS_VERSION pins the Redis that redis-memory-server (AP_REDIS_TYPE=MEMORY)
# compiles at image build and looks up at runtime — the default "stable" drifted
# to Redis 8, whose in-tree modules need cmake/pkg-config and break the build;
# Redis 7.x compiles with gcc/make alone. Keep this pin in the base stage so the
# runtime binary-cache key matches the one baked at build.
ENV LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
REDISMS_VERSION=7.4.2
# Install all system dependencies in a single layer. No apt cache mounts: docker-clean in the
# node base image wipes /var/cache/apt anyway, and a persisted /var/lib/apt/lists goes stale
# against rotated bullseye-security packages, failing the build with hash/size fetch errors.
# libcap2 is isolate's runtime lib (the isolate binaries ship prebuilt in api assets).
RUN apt-get update && \
apt-get install -y --no-install-recommends \
openssh-client \
python3 \
g++ \
build-essential \
git \
poppler-utils \
poppler-data \
procps \
unzip \
curl \
ca-certificates \
iptables \
libcap2 && \
rm -rf /var/lib/apt/lists/*
# Download, extract, and clean up bun in a single layer so the zip never ships
RUN export ARCH=$(uname -m) && \
if [ "$ARCH" = "x86_64" ]; then \
curl -fSL --retry 5 --retry-delay 2 https://github.com/oven-sh/bun/releases/download/bun-v1.3.1/bun-linux-x64-baseline.zip -o bun.zip; \
elif [ "$ARCH" = "aarch64" ]; then \
curl -fSL --retry 5 --retry-delay 2 https://github.com/oven-sh/bun/releases/download/bun-v1.3.1/bun-linux-aarch64.zip -o bun.zip; \
fi && \
unzip bun.zip && \
mv bun-*/bun /usr/local/bin/bun && \
chmod +x /usr/local/bin/bun && \
rm -rf bun.zip bun-* && \
bun --version
# Install global npm packages in a single layer
RUN --mount=type=cache,target=/root/.npm \
npm install -g --no-fund --no-audit \
node-gyp \
npm@11.11.0 \
esbuild@0.25.0
# Install isolated-vm globally (needed for sandboxes)
RUN --mount=type=cache,target=/root/.bun/install/cache \
cd /usr/src && bun install isolated-vm@6.0.2
### STAGE 1: Build ###
FROM base AS build
WORKDIR /usr/src/app
# Copy dependency files and workspace package.json files for resolution
COPY .npmrc package.json bun.lock bunfig.toml ./
COPY packages/ ./packages/
# Install all dependencies with frozen lockfile
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --frozen-lockfile
# Copy remaining source code (turbo config, etc.)
COPY . .
# Build frontend, engine, server API, and worker
RUN npx turbo run build --filter=web --filter=@activepieces/engine --filter=api --filter=worker
# The web build emits hidden source maps (vite build.sourcemap='hidden') used to
# symbolicate production stack traces in Sentry/BetterStack error tracking. Upload
# them here (cloud CI, guarded by a token) BEFORE stripping, then always remove the
# .map files so source is never served from the shipped image (self-hosted too).
# TODO(cloud-ci): inject + upload maps with sentry-cli when SENTRY_AUTH_TOKEN is set.
RUN find dist/packages/web -name '*.map' -delete
# Generate migration manifest (ordered list of migration names) for image-tag-based rollback
RUN node -e "\
const {getMigrations} = require('./packages/server/api/dist/src/app/database/postgres-connection');\
const names = getMigrations().map(M => new M().name);\
process.stdout.write(JSON.stringify(names));\
" > packages/server/api/dist/src/migration-manifest.json
# Remove workspaces not needed at runtime: pieces except the 4 the api imports,
# plus web/cli/tests-e2e/embed-sdk whose deps (react & friends) would otherwise land
# in the runtime node_modules. dist/packages/web is already built and kept.
# Then drop the removed entries from the root workspaces list and regenerate bun.lock.
RUN rm -rf packages/pieces/core packages/pieces/custom \
packages/web packages/cli packages/tests-e2e packages/ee && \
find packages/pieces/community -mindepth 1 -maxdepth 1 -type d \
! -name slack \
! -name square \
! -name facebook-leads \
! -name intercom \
-exec rm -rf {} + && \
node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json','utf8'));p.workspaces=p.workspaces.filter(w=>fs.existsSync(w.replace('/*','')));fs.writeFileSync('package.json',JSON.stringify(p,null,2))" && \
rm -f bun.lock && bun install
### STAGE 2: Run ###
FROM base AS run
WORKDIR /usr/src/app
# Copy static configuration files first (better layer caching)
COPY --from=build /usr/src/app/packages/server/api/src/assets/default.cf /usr/local/etc/isolate
COPY docker-entrypoint.sh .
# Copy root config files needed for dependency resolution
COPY --from=build /usr/src/app/package.json ./
COPY --from=build /usr/src/app/.npmrc ./
COPY --from=build /usr/src/app/bun.lock ./
COPY --from=build /usr/src/app/bunfig.toml ./
COPY --from=build /usr/src/app/LICENSE .
# Copy workspace package.json files (needed for bun workspace resolution)
COPY --from=build /usr/src/app/packages ./packages
# Copy built engine
COPY --from=build /usr/src/app/dist/packages/engine/ ./dist/packages/engine/
# Regenerate lockfile and install production dependencies (pieces were trimmed from workspace)
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --production
# Copy frontend files
COPY --from=build /usr/src/app/dist/packages/web ./dist/packages/web/
ENV NODE_ENV=production
LABEL service=activepieces
# WORKER containers have no HTTP server; treat them as healthy (probe only the app).
HEALTHCHECK --interval=10s --timeout=5s --start-period=60s --retries=5 \
CMD [ "$AP_CONTAINER_TYPE" = "WORKER" ] && exit 0 || curl -fsS "http://localhost:${AP_PORT:-80}/api/v1/health" || exit 1
ENTRYPOINT ["./docker-entrypoint.sh"]
EXPOSE 80