✨ feat(vscode): 代码阅读支持 Dockerfile:解析指令、每个 FROM 一个阶段(阶段名能跳过去)、RUN 交给 shell 按命令拆、复制、构建参数 / 环境变量、设置、标签、健康检查、启动,连着写的 ENV / ARG / COPY / LABEL 并成一块加一张表;语法包取自 npm 包 tree-sitter-wasm,打包时复制进扩展

This commit is contained in:
cruldra committed 2026-09-28 11:54:01 +08:00
1 parent 0665f35821
commit d4ec0e7de4
11 files changed
+1619 -4

No files matched your search

@@ -0,0 +1,110 @@
# ── 统一 Backend 镜像 ─────────────────────────────────────────────────
# 一个镜像同时承载 api / worker / beat / flower 四种角色;
# 由 docker-compose 传入不同 command 区分角色,避免重复构建/传输。
FROM python:3.12-slim AS base
LABEL maintainer="Cruldra" \
description="luffy-agent-platform - 统一 Backend 镜像 (API/Worker/Beat/Flower)"
# git: deployment 模块创建 bare repo;postgresql-client: alembic / psql 运维;curl: healthcheck
# postgresql-16-repack: lap checkpoint repack 的 CLI (与线上 PG16 大版本对齐).
# 扩展本体在目标库执行 CREATE EXTENSION pg_repack (运维一次性, 不在镜像构建时做).
# 官方 slim 默认源只有当前大版本 repack, 故加 PGDG 装 16 客户端.
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates curl gnupg postgresql-client git && \
install -d /usr/share/keyrings && \
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
| gpg --dearmor -o /usr/share/keyrings/postgresql.gpg && \
. /etc/os-release && \
echo "deb [signed-by=/usr/share/keyrings/postgresql.gpg] http://apt.postgresql.org/pub/repos/apt ${VERSION_CODENAME}-pgdg main" \
> /etc/apt/sources.list.d/pgdg.list && \
apt-get update && \
apt-get install -y --no-install-recommends postgresql-16-repack && \
pg_repack --version && \
rm -rf /var/lib/apt/lists/*
# Node.js:agent MCP 节点 (如 context7) 用 stdio + npx 拉子进程, api 容器必须有 npx。
# 不走 apt install nodejs (拉 ~250 MB Recommends), 从官方 node:22-slim 拷贝必要
# 文件; node:22-slim 同基于 debian:bookworm-slim, glibc 兼容, 二进制可直接跑。
# npm / npx 在官方镜像里是指向 node_modules/npm/bin/{npm-cli,npx-cli}.js 的 symlink,
# 拷贝 node_modules 后手建 symlink (COPY 单文件会 dereference, 不能保留 symlink).
COPY --from=node:22-slim /usr/local/bin/node /usr/local/bin/node
COPY --from=node:22-slim /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN ln -sf /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
ln -sf /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# appuser 先建、/app /lib 先归属:.venv 由 appuser 直接创建,末尾无需 chown -R
# (chown -R 会在 overlayfs 里把 ~2GB venv 完整复制进新层:镜像翻倍,
# 且该层排在源码层后,每次代码变更都重建,打爆 registry 增量分发)
RUN useradd -m -s /bin/false appuser && \
mkdir -p /app /lib && \
chown appuser:appuser /app /lib
USER appuser
ENV UV_CACHE_DIR=/home/appuser/.cache/uv
WORKDIR /app
# ── 依赖层(仅随 pyproject/uv.lock 变化重建)───────────────────────────
# 只放元数据:backend 的 pyproject+lock,以及 ../lib/* 路径依赖的 pyproject
# (uv 解析 [tool.uv.sources] 需要路径存在)。源码后置,改代码不打爆本层,
# registry 分发时该 ~2GB 层可被远端复用,日常部署只传源码层。
COPY --chown=appuser:appuser backend/pyproject.toml backend/uv.lock ./
COPY --chown=appuser:appuser lib/agent-dsl/pyproject.toml /lib/agent-dsl/
COPY --chown=appuser:appuser lib/agent-compiler-deepagents/pyproject.toml /lib/agent-compiler-deepagents/
COPY --chown=appuser:appuser lib/vendor-tools/pyproject.toml /lib/vendor-tools/
COPY --chown=appuser:appuser lib/code-sandbox-core/pyproject.toml /lib/code-sandbox-core/
COPY --chown=appuser:appuser lib/code-sandbox-daytona/pyproject.toml /lib/code-sandbox-daytona/
COPY --chown=appuser:appuser lib/code-sandbox-e2b/pyproject.toml /lib/code-sandbox-e2b/
COPY --chown=appuser:appuser lib/code-sandbox-local/pyproject.toml /lib/code-sandbox-local/
COPY --chown=appuser:appuser lib/code-publish-core/pyproject.toml /lib/code-publish-core/
COPY --chown=appuser:appuser lib/code-publish-compose-runner/pyproject.toml /lib/code-publish-compose-runner/
COPY --chown=appuser:appuser lib/luffy-billing-sdk/pyproject.toml /lib/luffy-billing-sdk/
COPY --chown=appuser:appuser lib/luffy-observability/pyproject.toml /lib/luffy-observability/
# 三方依赖先装;本项目与 lib editable 包此时无源码,跳过安装留给第二次 sync
RUN uv sync --frozen --no-dev --no-install-project \
--no-install-package agent-dsl \
--no-install-package agent-compiler-deepagents \
--no-install-package vendor-tools \
--no-install-package code-sandbox-core \
--no-install-package code-sandbox-daytona \
--no-install-package code-sandbox-e2b \
--no-install-package code-sandbox-local \
--no-install-package code-publish-core \
--no-install-package code-publish-compose-runner \
--no-install-package luffy-billing-sdk \
--no-install-package luffy-observability
# ── 源码层(每次代码变更只重建这里往下)────────────────────────────────
COPY --chown=appuser:appuser lib /lib
# agent 定义 (vendor/agents/*/agent.yaml + nodes/*.py) 与代码是同一个版本, 必须随镜像原子切换;
# 路径与 settings 默认值 <_BASE_DIR>/../vendor/agents 对齐, 容器内即 /vendor/agents.
COPY --chown=appuser:appuser vendor /vendor
COPY --chown=appuser:appuser backend/src/ ./src/
COPY --chown=appuser:appuser backend/alembic/ ./alembic/
COPY --chown=appuser:appuser backend/alembic.ini ./
COPY --chown=appuser:appuser backend/scripts/ ./scripts/
# 补装本项目 + lib editable 包(三方依赖已就位,秒级)
RUN uv sync --frozen --no-dev
# 远程调试支持:装入 uv 创建的 venv,按需通过 DEBUGPY_ENABLE=1 开启。
# 必须在最后一次 uv sync 之后:sync 会精确对齐 lock,把 lock 外的包卸掉。
RUN uv pip install debugpy
ENV UV_NO_SYNC=1
# 部署 ID (Jenkins IMAGE_TAG): /health 回显、日志定位后端出自哪次构建. 选择性发布时 api 与 client 镜像 tag 可不同, 客户端是否过期以 client 镜像 (浏览器包 vs BFF) 为准.
ARG DEPLOYMENT_ID
ENV DEPLOYMENT_ID=$DEPLOYMENT_ID
EXPOSE 8000
# 默认 CMD 走 api,celery worker/beat/flower 由 compose 覆盖 command
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
CMD ["uv", "run", "uvicorn", "luffy_agent.main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -0,0 +1,41 @@
# syntax=docker/dockerfile:1.7
FROM node:22-alpine AS deps
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile --ignore-scripts
FROM node:22-alpine AS builder
WORKDIR /app
RUN corepack enable && corepack prepare pnpm@latest --activate
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
# 部署 ID 烙进本次构建: Next 据此给静态资源加 ?dpl=、页内跳转时比对版本;
# 浏览器包与服务端包都能读 process.env.NEXT_DEPLOYMENT_ID (见 src/lib/version-skew).
ARG DEPLOYMENT_ID
ENV NEXT_DEPLOYMENT_ID=$DEPLOYMENT_ID
RUN pnpm build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
ARG DEPLOYMENT_ID
ENV NEXT_DEPLOYMENT_ID=$DEPLOYMENT_ID
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# standalone 输出不含 public/, 必须显式拷贝 (字体等静态资源)
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]