Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 20 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,15 @@ RUN npm run build
# Prune dev dependencies (keep prod only for copying)
RUN npm prune --production

# Stage 2: Web (Nginx)
FROM nginx:alpine as web
RUN apk add --no-cache curl
RUN touch /var/run/nginx.pid && \
chown -R nginx:nginx /var/run/nginx.pid && \
chown -R nginx:nginx /var/cache/nginx && \
chown -R nginx:nginx /usr/share/nginx/html
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder --chown=nginx:nginx /app/dist /usr/share/nginx/html
COPY --chown=nginx:nginx nginx.conf /etc/nginx/conf.d/default.conf
USER nginx
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8080/ || exit 1
CMD ["nginx", "-g", "daemon off;"]

# Stage 3: API (Node)
FROM node:20-slim as api
# Stage 2: Production (Nginx + Node API)
FROM node:20-slim as production
WORKDIR /app

# Install runtime dependencies for node-canvas (Debian)
# Install nginx, supervisord and runtime dependencies
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
nginx \
supervisor \
curl \
libcairo2 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
Expand All @@ -55,9 +43,10 @@ RUN apt-get update && apt-get upgrade -y && apt-get install -y \
&& rm -rf ~/.npm \
&& rm -rf /var/lib/apt/lists/*

# Copy built assets
COPY package*.json ./
# Copy built node_modules from builder
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist /usr/share/nginx/html
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/src ./src
COPY --from=builder /app/tsconfig.json ./
Expand All @@ -66,14 +55,16 @@ COPY --from=builder /app/tsconfig.json ./
RUN npm install -g tsx \
&& rm -rf /root/.npm

USER node
EXPOSE 3000
# wget is not in slim? use curl or node script? node:20-slim usually has curl?
# Let's check. Standard slim has minimal.
# Installing curl/wget in api stage if missing.
USER root
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
USER node
# Configure nginx
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -f /etc/nginx/sites-enabled/default

# Configure supervisord
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:3000/health || exit 1
CMD ["npm", "run", "api"]
# Health check
HEALTHCHECK --interval=30s --timeout=3s CMD curl -f http://localhost:8080/api/health || exit 1

EXPOSE 8080
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
16 changes: 16 additions & 0 deletions nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,22 @@ server {
try_files $uri $uri/ /index.html;
}

# API reverse proxy
location /api/ {
proxy_pass http://localhost:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
client_max_body_size 50M;
}

# Cache static assets
location /assets {
expires 1y;
Expand Down
20 changes: 20 additions & 0 deletions supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[supervisord]
nodaemon=true
user=root

[program:nginx]
command=nginx -g 'daemon off;'
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.error.log
priority=10

[program:api]
command=npm run api
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/api.log
stderr_logfile=/var/log/supervisor/api.error.log
priority=20
environment=PORT="3000",HOST="0.0.0.0"