Browse Source

chore(docker): split pdf worker build target

Use dedicated Docker build targets so pdf workers avoid web runtime extras while app services keep current behavior.

Made-with: Cursor
yemeishu 2 weeks ago
parent
commit
095723e5fe
3 changed files with 57 additions and 27 deletions
  1. 33 19
      Dockerfile
  2. 15 5
      docker-compose.pdf.yml
  3. 9 3
      docker-compose.yml

+ 33 - 19
Dockerfile

@@ -28,7 +28,7 @@ RUN bun run build
 # ========================================
 # 第二阶段:PHP 运行时(使用 php-fpm)
 # ========================================
-FROM php:8.3-fpm-alpine AS runtime
+FROM php:8.3-fpm-alpine AS base-runtime
 
 # 安装系统依赖 - 使用阿里云镜像
 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
@@ -44,8 +44,6 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
         icu-dev \
         libzip-dev \
         sqlite-dev \
-        # Nginx(高性能 Web 服务器)
-        nginx \
         # Chrome/Chromium 依赖(PDF 生成必须)
         chromium \
         nss \
@@ -66,7 +64,7 @@ RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
         npm \
         && rm -rf /var/cache/apk/* \
         && fc-cache -fv \
-        && mkdir -p /run/dbus /run/nginx /var/log/nginx
+        && mkdir -p /run/dbus
 
 # 设置 Chrome 环境变量
 ENV CHROME_BIN=/usr/bin/chromium-browser \
@@ -95,20 +93,12 @@ WORKDIR /app
 COPY composer.json composer.lock ./
 RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader --no-scripts
 
-# 复制应用代码(排除 node_modules, vendor 等)
-COPY . .
-
-# 从第一阶段复制构建好的前端资源
-COPY --from=frontend-builder /app/public/build ./public/build
-
 # 安装 KaTeX(服务端公式渲染)
 RUN npm config set registry https://registry.npmmirror.com && \
     npm install -g katex@0.16.9
 
-# 缓存路由和视图(不缓存配置,配置在运行时从 .env 读取)
-RUN php artisan route:cache && \
-    php artisan view:cache && \
-    php artisan filament:upgrade || true
+# 复制应用代码(排除 node_modules, vendor 等)
+COPY . .
 
 # 创建必要目录
 RUN mkdir -p storage/logs storage/framework/cache storage/framework/sessions storage/framework/views bootstrap/cache
@@ -118,6 +108,28 @@ RUN chown -R www-data:www-data /app && \
     chmod -R 755 /app && \
     chmod -R 777 /app/storage /app/bootstrap/cache
 
+# 通用入口脚本(queue worker 模式仅执行命令,不启动 nginx)
+COPY docker-entrypoint.sh /usr/local/bin/
+RUN chmod +x /usr/local/bin/docker-entrypoint.sh
+ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
+
+# ========================================
+# 第三阶段:App Runtime(Nginx + PHP-FPM)
+# ========================================
+FROM base-runtime AS app-runtime
+
+# 安装 Nginx(仅 Web API 容器需要)
+RUN apk add --no-cache nginx && \
+    mkdir -p /run/nginx /var/log/nginx
+
+# 从第一阶段复制构建好的前端资源
+COPY --from=frontend-builder /app/public/build ./public/build
+
+# 缓存路由和视图(不缓存配置,配置在运行时从 .env 读取)
+RUN php artisan route:cache && \
+    php artisan view:cache && \
+    php artisan filament:upgrade || true
+
 # 复制 Nginx 和 PHP-FPM 配置
 COPY docker/nginx.conf /etc/nginx/nginx.conf
 COPY docker/www.conf /usr/local/etc/php-fpm.d/www.conf
@@ -128,9 +140,11 @@ EXPOSE 8000
 HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
     CMD curl -f http://127.0.0.1:8000/health || exit 1
 
-# 启动脚本:启动 dbus、php-fpm、nginx
-COPY docker-entrypoint.sh /usr/local/bin/
-RUN chmod +x /usr/local/bin/docker-entrypoint.sh
-
-ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
 CMD ["nginx", "-g", "daemon off;"]
+
+# ========================================
+# 第四阶段:PDF Worker Runtime(无 Nginx/无前端构建)
+# ========================================
+FROM base-runtime AS pdfworker
+
+CMD ["php", "artisan", "queue:work", "--queue=pdf", "--sleep=3", "--tries=2", "--max-time=300", "--max-jobs=10"]

+ 15 - 5
docker-compose.pdf.yml

@@ -1,7 +1,9 @@
 services:
   # 主应用(Web API 服务)- 用于渲染 HTML
   app:
-    build: .
+    build:
+      context: .
+      target: app-runtime
     container_name: math_cms_app
     ports:
       - "8000:8000"
@@ -37,7 +39,9 @@ services:
 
   # PDF Worker 1
   pdf-worker-1:
-    build: .
+    build:
+      context: .
+      target: pdfworker
     container_name: pdf_worker_1
     command: php artisan queue:work --queue=pdf --sleep=3 --tries=3 --max-time=300 --max-jobs=10
     env_file:
@@ -66,7 +70,9 @@ services:
 
   # PDF Worker 2
   pdf-worker-2:
-    build: .
+    build:
+      context: .
+      target: pdfworker
     container_name: pdf_worker_2
     command: php artisan queue:work --queue=pdf --sleep=3 --tries=3 --max-time=300 --max-jobs=10
     env_file:
@@ -95,7 +101,9 @@ services:
 
   # PDF Worker 3
   pdf-worker-3:
-    build: .
+    build:
+      context: .
+      target: pdfworker
     container_name: pdf_worker_3
     command: php artisan queue:work --queue=pdf --sleep=3 --tries=3 --max-time=300 --max-jobs=10
     env_file:
@@ -124,7 +132,9 @@ services:
 
   # PDF Worker 4
   pdf-worker-4:
-    build: .
+    build:
+      context: .
+      target: pdfworker
     container_name: pdf_worker_4
     command: php artisan queue:work --queue=pdf --sleep=3 --tries=3 --max-time=300 --max-jobs=10
     env_file:

+ 9 - 3
docker-compose.yml

@@ -1,7 +1,9 @@
 services:
   # 主应用(Web API 服务)- 使用 Nginx + PHP-FPM
   app:
-    build: .
+    build:
+      context: .
+      target: app-runtime
     container_name: math_cms_app
     # 使用 Dockerfile 中的默认 CMD(nginx + php-fpm)
     ports:
@@ -21,7 +23,9 @@ services:
 
   # 队列 Worker(通用任务队列)
   queue:
-    build: .
+    build:
+      context: .
+      target: app-runtime
     container_name: math_cms_queue
     command: php artisan queue:work --sleep=3 --tries=3 --max-time=3600
     env_file:
@@ -63,7 +67,9 @@ services:
 
   # PDF 生成专用 Worker(资源隔离,防止 Chrome 吃满 CPU)
   pdf-worker:
-    build: .
+    build:
+      context: .
+      target: pdfworker
     container_name: math_cms_pdf
     command: php artisan queue:work --queue=pdf --sleep=3 --tries=2 --max-time=300 --max-jobs=10
     env_file: