From 28f9e3d39acc6abd72130c2dc052654dbbfa155b Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 21 Sep 2025 17:01:16 +0800 Subject: [PATCH] chore: build ssr docker --- docker/Dockerfile.ssr | 53 ++++++++++++++++++++++++ docker/entrypoint-ssr.sh | 80 +++++++++++++++++++++++++++++++++++++ docker/supervisord-ssr.conf | 21 ++++++++++ 3 files changed, 154 insertions(+) create mode 100644 docker/Dockerfile.ssr create mode 100644 docker/entrypoint-ssr.sh create mode 100644 docker/supervisord-ssr.conf diff --git a/docker/Dockerfile.ssr b/docker/Dockerfile.ssr new file mode 100644 index 00000000..28c0798e --- /dev/null +++ b/docker/Dockerfile.ssr @@ -0,0 +1,53 @@ +# syntax=docker/dockerfile:1 +# Build stage - Build the React application +FROM node:20.12.0-alpine AS builder + +ENV NODE_ENV=production + +WORKDIR /app + +# Copy package files for better layer caching +COPY package.json pnpm-lock.yaml ./ + +# Install dependencies +RUN corepack enable && \ + pnpm install --frozen-lockfile + +# Copy source code +COPY . . + +# Build the application +RUN pnpm run build + +# Runtime stage - SSR with Bun + nginx +FROM oven/bun:latest + +WORKDIR /app + +# Install nginx and supervisor for process management +RUN apt-get update && \ + apt-get install -y nginx supervisor && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +# Install Node dependencies for SSR server +RUN bun install cheerio pino pino-pretty + +# Copy built static files from builder to BOTH locations +# nginx serves from /usr/share/nginx/html, Bun SSR reads from /app/dist +COPY --from=builder /app/dist /usr/share/nginx/html/ +COPY --from=builder /app/dist /app/dist + +# Copy only necessary files for SSR +COPY deploy/server.ts /app/server.ts +COPY deploy/nginx.conf /etc/nginx/nginx.conf +COPY docker/supervisord-ssr.conf /etc/supervisor/conf.d/supervisord.conf +COPY docker/entrypoint-ssr.sh /docker-entrypoint.sh + +# Make entrypoint executable +RUN chmod +x /docker-entrypoint.sh + +# Expose port 80 +EXPOSE 80 + +# Use entrypoint to set up environment variables and start supervisor +ENTRYPOINT ["/docker-entrypoint.sh"] \ No newline at end of file diff --git a/docker/entrypoint-ssr.sh b/docker/entrypoint-ssr.sh new file mode 100644 index 00000000..6b120784 --- /dev/null +++ b/docker/entrypoint-ssr.sh @@ -0,0 +1,80 @@ +#!/bin/sh +set -e + +# Backward compatibility: Map old environment variable names to new ones +if [ -n "${AF_BASE_URL}" ] && [ -z "${APPFLOWY_BASE_URL}" ]; then + echo "⚠️ WARNING: AF_BASE_URL is deprecated. Please use APPFLOWY_BASE_URL instead." + export APPFLOWY_BASE_URL="${AF_BASE_URL}" +fi + +if [ -n "${AF_GOTRUE_URL}" ] && [ -z "${APPFLOWY_GOTRUE_BASE_URL}" ]; then + echo "⚠️ WARNING: AF_GOTRUE_URL is deprecated. Please use APPFLOWY_GOTRUE_BASE_URL instead." + export APPFLOWY_GOTRUE_BASE_URL="${AF_GOTRUE_URL}" +fi + +# Support both AF_WS_V2_URL and AF_WS_URL for backward compatibility +if [ -n "${AF_WS_V2_URL}" ] && [ -z "${APPFLOWY_WS_BASE_URL}" ]; then + echo "⚠️ WARNING: AF_WS_V2_URL is deprecated. Please use APPFLOWY_WS_BASE_URL instead." + export APPFLOWY_WS_BASE_URL="${AF_WS_V2_URL}" +elif [ -n "${AF_WS_URL}" ] && [ -z "${APPFLOWY_WS_BASE_URL}" ]; then + echo "⚠️ WARNING: AF_WS_URL is deprecated. Please use APPFLOWY_WS_BASE_URL instead." + export APPFLOWY_WS_BASE_URL="${AF_WS_URL}" +fi + +# Check required environment variables (after mapping) +if [ -z "${APPFLOWY_BASE_URL}" ]; then + echo "ERROR: APPFLOWY_BASE_URL environment variable is required but not set" + echo "Please set APPFLOWY_BASE_URL to your AppFlowy backend URL (e.g., https://your-backend.example.com)" + echo "Note: You can also use the deprecated AF_BASE_URL for backward compatibility" + exit 1 +fi + +if [ -z "${APPFLOWY_GOTRUE_BASE_URL}" ]; then + echo "ERROR: APPFLOWY_GOTRUE_BASE_URL environment variable is required but not set" + echo "Please set APPFLOWY_GOTRUE_BASE_URL to your GoTrue authentication service URL (e.g., https://your-backend.example.com/gotrue)" + echo "Note: You can also use the deprecated AF_GOTRUE_URL for backward compatibility" + exit 1 +fi + +if [ -z "${APPFLOWY_WS_BASE_URL}" ]; then + echo "ERROR: APPFLOWY_WS_BASE_URL environment variable is required but not set" + echo "Please set APPFLOWY_WS_BASE_URL to your WebSocket URL (e.g., wss://your-backend.example.com/ws/v2)" + echo "Note: You can also use the deprecated AF_WS_V2_URL or AF_WS_URL for backward compatibility" + exit 1 +fi + +# Show deprecation summary if any old variables were used +if [ -n "${AF_BASE_URL}" ] || [ -n "${AF_GOTRUE_URL}" ] || [ -n "${AF_WS_V2_URL}" ] || [ -n "${AF_WS_URL}" ]; then + echo "" + echo "════════════════════════════════════════════════════════════════════" + echo "⚠️ DEPRECATION NOTICE: Old environment variable names detected!" + echo "Please update your configuration to use the new names:" + echo " AF_BASE_URL → APPFLOWY_BASE_URL" + echo " AF_GOTRUE_URL → APPFLOWY_GOTRUE_BASE_URL" + echo " AF_WS_V2_URL → APPFLOWY_WS_BASE_URL" + echo " AF_WS_URL → APPFLOWY_WS_BASE_URL" + echo "════════════════════════════════════════════════════════════════════" + echo "" +fi + +# IMPORTANT: For client-side React app, inject config into HTML +CONFIG_SCRIPT="" + +# Inject the config script into both nginx and Bun server locations +sed -i "s||${CONFIG_SCRIPT}|g" /usr/share/nginx/html/index.html +sed -i "s||${CONFIG_SCRIPT}|g" /app/dist/index.html + +echo "Environment variables configured:" +echo " APPFLOWY_BASE_URL: ${APPFLOWY_BASE_URL}" +echo " APPFLOWY_GOTRUE_BASE_URL: ${APPFLOWY_GOTRUE_BASE_URL}" +echo " APPFLOWY_WS_BASE_URL: ${APPFLOWY_WS_BASE_URL}" +echo "" + +# Export for Bun server to use +export APPFLOWY_BASE_URL +export APPFLOWY_GOTRUE_BASE_URL +export APPFLOWY_WS_BASE_URL + +# Start supervisor to manage both nginx and Bun server +# Supervisor will inherit the exported environment variables +exec supervisord -c /etc/supervisor/conf.d/supervisord.conf \ No newline at end of file diff --git a/docker/supervisord-ssr.conf b/docker/supervisord-ssr.conf new file mode 100644 index 00000000..9e52d253 --- /dev/null +++ b/docker/supervisord-ssr.conf @@ -0,0 +1,21 @@ +[supervisord] +nodaemon=true +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:nginx] +command=/usr/sbin/nginx -g "daemon off;" +autostart=true +autorestart=true +stdout_logfile=/var/log/nginx/access.log +stderr_logfile=/var/log/nginx/error.log +priority=10 + +[program:bun] +command=bun run /app/server.ts +autostart=true +autorestart=true +stdout_logfile=/var/log/bun.out.log +stderr_logfile=/var/log/bun.err.log +environment=NODE_ENV="production" +priority=20 \ No newline at end of file