-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathDockerfile
More file actions
122 lines (92 loc) · 3.76 KB
/
Dockerfile
File metadata and controls
122 lines (92 loc) · 3.76 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
# syntax=docker/dockerfile:1.7
# ============================================================
# Multi-app monorepo Dockerfile
# Usage: docker build --build-arg APP_NAME=my-app .
# ============================================================
FROM node:20-alpine AS base
RUN corepack enable && corepack install -g pnpm@10
WORKDIR /app
# ============================================================
# Stage 1: Install ALL dependencies
# ============================================================
FROM base AS deps
# Copy root manifests
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
# Copy ALL package.jsons preserving directory structure
# This works because BuildKit handles globs before flattening — but we
# need to copy the whole apps/packages dirs at shallow depth.
# Simplest reliable approach: copy everything except src/dist via .dockerignore
COPY apps/ ./apps/
COPY packages/ ./packages/
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile --prefer-offline
# ============================================================
# Stage 2: Build the selected app
# ============================================================
FROM deps AS builder
ARG APP_NAME
RUN test -n "$APP_NAME" || (echo "ERROR: APP_NAME build arg is required" && exit 1)
COPY turbo.json ./
# .env.production is optional — use a shell trick to avoid hard failure
RUN --mount=type=bind,source=apps,target=/mnt/env-src \
if [ -f "/mnt/env-src/$APP_NAME/.env.production" ]; then \
cp "/mnt/env-src/$APP_NAME/.env.production" "./apps/$APP_NAME/.env.production"; \
fi
RUN --mount=type=cache,id=turbo,target=/root/.cache/turbo \
pnpm turbo build --filter=@dans-framework/$APP_NAME --cache-dir=/root/.cache/turbo
RUN test -d "apps/$APP_NAME/dist" || \
(echo "ERROR: Build did not produce apps/$APP_NAME/dist — check turbo.json outputs" && exit 1)
# ============================================================
# Stage 3: Production nginx image
# ============================================================
FROM nginx:1.27-alpine AS runtime
ARG APP_NAME
RUN test -n "$APP_NAME" || (echo "ERROR: APP_NAME build arg is required" && exit 1)
RUN cat > /etc/nginx/conf.d/default.conf <<'EOF'
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
include /etc/nginx/mime.types;
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/javascript application/javascript
application/json application/xml image/svg+xml;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
server_tokens off;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(?:js|css|woff2?|ttf|eot|ico|png|jpg|jpeg|svg|gif|webp)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
location /health {
access_log off;
return 200 "ok\n";
add_header Content-Type text/plain;
}
location ~ /\. {
deny all;
}
}
EOF
RUN chown -R nginx:nginx \
/usr/share/nginx/html \
/var/cache/nginx \
/var/log/nginx \
/etc/nginx/conf.d && \
touch /var/run/nginx.pid && chown nginx:nginx /var/run/nginx.pid
COPY --from=builder --chown=nginx:nginx \
/app/apps/$APP_NAME/dist /usr/share/nginx/html
USER nginx
EXPOSE 80
HEALTHCHECK --interval=15s --timeout=5s --start-period=30s --retries=3 \
CMD wget -qO- http://127.0.0.1/health || exit 1
CMD ["nginx", "-g", "daemon off;"]