-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile.prod
More file actions
181 lines (133 loc) · 6.18 KB
/
Copy pathDockerfile.prod
File metadata and controls
181 lines (133 loc) · 6.18 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
# =============================================================================
# Stage 1: Build Frontend
# =============================================================================
FROM node:20-alpine AS frontend-builder
WORKDIR /build
# Install pnpm
RUN npm install -g pnpm
# Copy workspace files
COPY pnpm-workspace.yaml pnpm-lock.yaml tsconfig.json .npmrc ./
# Copy package files
COPY @typus-core/frontend/package.json @typus-core/frontend/
COPY @typus-core/shared/package.json @typus-core/shared/
# Install dependencies
RUN pnpm install --no-frozen-lockfile --filter @typus-core/frontend...
# Copy source code
COPY @typus-core/frontend @typus-core/frontend
COPY @typus-core/shared @typus-core/shared
# Copy plugins (needed for frontend build)
COPY plugins /build/plugins
# Remove plugins/tsconfig.json to avoid build errors (it extends backend tsconfig)
RUN rm -f /build/plugins/tsconfig.json
# Copy public assets (favicon, etc.)
COPY public /build/public
# Copy typus-manifest.json (needed by frontend build)
COPY typus-manifest.json /build/typus-manifest.json
# Copy custom layouts (needed for frontend build - loaded via import.meta.glob)
COPY custom /build/custom
# Build frontend for production
WORKDIR /build/@typus-core/frontend
RUN NODE_ENV=production pnpm run build
# =============================================================================
# Stage 2: Runtime - All-in-One Container (nginx + backend)
# =============================================================================
FROM node:20-slim
ARG APP_UID=1100
ARG APP_GID=150
# Install runtime dependencies
RUN apt-get update && apt-get install -y \
nginx \
supervisor \
ca-certificates \
curl \
default-mysql-client \
jq \
passwd \
&& rm -rf /var/lib/apt/lists/*
# Install tsx globally for TypeScript execution
RUN npm install -g tsx pnpm
# Create app directory
WORKDIR /app
# Create non-root user/group for backend (nginx still runs as root to bind :80)
RUN groupadd -g ${APP_GID} appgroup \
&& useradd -u ${APP_UID} -g ${APP_GID} -m -s /bin/bash appuser
# Copy pnpm workspace files
COPY pnpm-workspace.yaml pnpm-lock.yaml tsconfig.json .npmrc ./
# Copy root package.json for shared dependencies (tsyringe, etc.)
COPY package.json ./
# Copy package files for dependency installation
COPY @typus-core/backend/package.json @typus-core/backend/
COPY @typus-core/shared/package.json @typus-core/shared/
# Install all dependencies (root + backend) - root deps get hoisted for plugin access
RUN pnpm install --no-frozen-lockfile
# Create symlink for tsyringe (needed by plugins)
RUN ln -sf /app/node_modules/.pnpm/tsyringe@4.10.0/node_modules/tsyringe /app/node_modules/tsyringe
# Prisma generates engines into node_modules; backend runs as appuser so node_modules must be writable.
RUN chown -R appuser:appgroup /app/node_modules
# Copy data/prisma package.json for dependency installation
COPY data/prisma/package.json data/prisma/
# Install data/prisma dependencies (includes Prisma CLI for migrations/generation)
RUN pnpm install --no-frozen-lockfile --filter @data/prisma...
# Copy backend SOURCE files (TypeScript, NOT compiled!)
COPY @typus-core/backend @typus-core/backend
COPY @typus-core/shared @typus-core/shared
# Copy plugins (needed for backend modules and DSL)
COPY plugins /app/plugins
# Copy built frontend from Stage 1
COPY --from=frontend-builder /build/@typus-core/frontend/dist /app/@typus-core/frontend/dist
# Copy Prisma schemas and pre-generated client
COPY data/prisma /app/data/prisma
# Copy typus-manifest.json for migrations tracking
COPY typus-manifest.json /app/typus-manifest.json
# Copy public directory
COPY public /app/public
# Copy custom overrides (layouts, pages, styles) - site-specific customizations
COPY custom /app/custom
# Copy database seeds (create empty dir if not exists)
COPY data/seeds /app/data/seeds
# Copy baseline SQL files for first-time setup
COPY data/baseline /app/data/baseline
# Baseline seed scripts must be readable by backend user
RUN chown -R appuser:appgroup /app/data/baseline
# Backend runs as appuser; ensure core sources are readable even if host permissions are restrictive.
RUN chmod -R a+rX /app/@typus-core \
&& chmod -R a+rX /app/data/baseline \
&& chmod -R a+rX /app/plugins \
&& chown -R appuser:appgroup /app/plugins \
&& chown -R appuser:appgroup /app/@typus-core/backend/node_modules 2>/dev/null || true
# Copy nginx configuration (from new configs location)
COPY docker/configs/nginx.conf /etc/nginx/nginx.conf
COPY docker/configs/redirects.conf /etc/nginx/conf.d/redirects.conf
# Copy supervisord configuration (from new configs location)
COPY docker/configs/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Copy backend startup script (PROD profile for production)
COPY @typus-core/backend/backend-startup-prod.sh /app/@typus-core/backend/backend-startup-prod.sh
RUN chmod +x /app/@typus-core/backend/backend-startup-prod.sh
# Runtime entrypoint: create appuser/appgroup and fix bind-mount permissions
COPY docker/scripts/entrypoint.sh /app/docker/scripts/entrypoint.sh
RUN sed -i 's/\r$//' /app/docker/scripts/entrypoint.sh \
&& chmod +x /app/docker/scripts/entrypoint.sh
# Create required directories
RUN mkdir -p /app/storage/cache/html \
/app/storage/html-cache \
/app/logs \
/var/log/nginx \
/var/log/supervisor \
/var/run \
/app/docker/scripts
# Make runtime-generated directories writable for appuser (DSL/Prisma + manifest updates).
RUN chown -R appuser:appgroup /app/data/prisma /app/@typus-core/shared/dsl /app/typus-manifest.json /app/logs || true
# Windows safety: prevent CRLF line endings breaking runtime scripts inside the image.
RUN find /app -type f \( -name "*.sh" -o -name "manage.sh" \) -exec sed -i 's/\r$//' {} + 2>/dev/null || true
# Set environment variables
ENV NODE_ENV=production
ENV PORT=3001
# Expose HTTP port
EXPOSE 80
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost/health || exit 1
# Must run as root to bind :80 and to fix bind-mount ownership, but backend runs as appuser via supervisord.
ENTRYPOINT ["/app/docker/scripts/entrypoint.sh"]
# Start supervisord
CMD ["/usr/bin/supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]