|
1 | 1 | # syntax=docker/dockerfile:1 |
2 | 2 | ARG NODE_VERSION=20-alpine |
3 | | -ARG NGINX_VERSION=alpine |
4 | 3 |
|
5 | 4 | FROM node:${NODE_VERSION} AS builder |
6 | 5 |
|
7 | | -# Install build dependencies |
8 | | -RUN apk add --no-cache libc6-compat |
| 6 | +# Public envs used by Astro in client-side code must exist at build time. |
| 7 | +ARG PUBLIC_RECAPTCHA_SITE_KEY |
| 8 | +ENV PUBLIC_RECAPTCHA_SITE_KEY=${PUBLIC_RECAPTCHA_SITE_KEY} |
9 | 9 |
|
10 | | -# Configure pnpm |
11 | 10 | ENV PNPM_HOME="/pnpm" |
12 | 11 | ENV PATH="$PNPM_HOME:$PATH" |
13 | 12 | RUN corepack enable |
14 | 13 |
|
15 | 14 | WORKDIR /app |
16 | 15 |
|
17 | | -# Copy dependency files first for better caching |
18 | 16 | COPY package.json pnpm-lock.yaml ./ |
19 | 17 | RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile |
20 | 18 |
|
21 | | -# Copy source code |
22 | 19 | COPY . . |
| 20 | +RUN pnpm run build && find /app/dist -name "*.map" -delete && pnpm prune --prod |
23 | 21 |
|
24 | | -# Build application with optimizations |
25 | | -RUN pnpm run build && \ |
26 | | - # Remove source maps and unnecessary files |
27 | | - find /app/dist -name "*.map" -delete && \ |
28 | | - # Remove dev dependencies |
29 | | - pnpm prune --prod |
| 22 | +FROM node:${NODE_VERSION} AS runtime |
30 | 23 |
|
31 | | -# Production stage |
32 | | -FROM nginx:${NGINX_VERSION} AS runtime |
| 24 | +ENV NODE_ENV=production |
| 25 | +ENV HOST=0.0.0.0 |
| 26 | +ENV PORT=4321 |
33 | 27 |
|
34 | | -# Install security updates and curl for health check |
35 | | -RUN apk --no-cache upgrade && \ |
36 | | - apk --no-cache add curl |
37 | | - |
38 | | -# Fix permissions for nginx user |
39 | | -RUN chown -R nginx:nginx /var/cache/nginx && \ |
40 | | - chown -R nginx:nginx /var/log/nginx && \ |
41 | | - chown -R nginx:nginx /etc/nginx/conf.d && \ |
42 | | - touch /var/run/nginx.pid && \ |
43 | | - chown -R nginx:nginx /var/run/nginx.pid |
44 | | - |
45 | | -# Remove default nginx assets |
46 | | -RUN rm -rf /usr/share/nginx/html/* |
47 | | - |
48 | | -# Copy built application with proper ownership |
49 | | -COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html |
| 28 | +WORKDIR /app |
50 | 29 |
|
51 | | -# Remove default nginx config |
52 | | -RUN rm /etc/nginx/conf.d/default.conf |
| 30 | +RUN addgroup -S app && adduser -S -G app app |
53 | 31 |
|
54 | | -# Copy custom nginx config with proper ownership |
55 | | -COPY --chown=nginx:nginx nginx.conf /etc/nginx/conf.d/default.conf |
| 32 | +COPY --from=builder --chown=app:app /app/dist ./dist |
| 33 | +COPY --from=builder --chown=app:app /app/package.json ./package.json |
| 34 | +COPY --from=builder --chown=app:app /app/node_modules ./node_modules |
56 | 35 |
|
57 | | -# Switch to non-root user |
58 | | -USER nginx |
| 36 | +USER app |
59 | 37 |
|
60 | | -# Expose port |
61 | | -EXPOSE 8080 |
| 38 | +EXPOSE 4321 |
62 | 39 |
|
63 | | -# Health check |
64 | | -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ |
65 | | - CMD curl -f http://localhost:8080/ || exit 1 |
| 40 | +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ |
| 41 | + CMD node -e "fetch('http://127.0.0.1:4321/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" |
66 | 42 |
|
67 | | -# Start nginx |
68 | | -ENTRYPOINT ["nginx", "-g", "daemon off;"] |
| 43 | +CMD ["node", "./dist/server/entry.mjs"] |
0 commit comments