# syntax=docker.m.daocloud.io/docker/dockerfile:1 # Aether 运行镜像:Rust gateway 直接服务 API + 前端静态文件(国内镜像源版本) # 构建命令: docker build --build-arg AETHER_BUILD_VERSION=v0.7.2 -f Dockerfile.app.local -t aether-app:latest . ARG RUST_VERSION=1.95.0 ARG NODE_BASE_IMAGE=docker.m.daocloud.io/library/node:22-slim ARG RUST_BASE_IMAGE=docker.m.daocloud.io/library/rust:${RUST_VERSION}-slim # ==================== 前端构建 ==================== FROM ${NODE_BASE_IMAGE} AS frontend-builder ARG AETHER_BUILD_VERSION ENV AETHER_BUILD_VERSION=${AETHER_BUILD_VERSION} \ AETHER_VERSION=${AETHER_BUILD_VERSION} WORKDIR /app/aether-vscodex/web COPY aether-vscodex/web/package*.json ./ RUN --mount=type=cache,id=aether-vscodex-npm-cache,target=/root/.npm,sharing=locked \ npm config set registry https://registry.npmmirror.com && \ npm ci --no-audit --no-fund COPY aether-vscodex/public /app/aether-vscodex/public COPY aether-vscodex/web/ ./ RUN npm run build WORKDIR /app/frontend COPY frontend/package*.json ./ RUN --mount=type=cache,id=aether-npm-cache,target=/root/.npm,sharing=locked \ npm config set registry https://registry.npmmirror.com && \ npm ci --no-audit --no-fund COPY frontend/ ./ RUN npm run build # ==================== Rust gateway 构建 ==================== FROM ${RUST_BASE_IMAGE} AS gateway-base WORKDIR /build # 生产级 release 构建:保留 thin LTO,同时用 lld 缩短最终链接阶段。 ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse \ CARGO_PROFILE_RELEASE_LTO=thin \ CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16 \ RUSTFLAGS="-C linker=clang -C link-arg=-fuse-ld=lld" RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt,sharing=locked \ sed -i 's/deb.debian.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list.d/debian.sources && \ apt-get update && apt-get install -y --no-install-recommends \ build-essential \ ca-certificates \ clang \ cmake \ git \ libclang-dev \ libssl-dev \ lld \ pkg-config \ perl RUN --mount=type=cache,id=aether-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=aether-cargo-git,target=/usr/local/cargo/git,sharing=locked \ cargo install cargo-chef --locked FROM gateway-base AS gateway-planner COPY Cargo.toml Cargo.lock ./ COPY apps/ ./apps/ COPY crates/ ./crates/ RUN cargo chef prepare --recipe-path recipe.json FROM gateway-base AS gateway-builder ARG AETHER_BUILD_VERSION ENV AETHER_BUILD_VERSION=${AETHER_BUILD_VERSION} \ AETHER_VERSION=${AETHER_BUILD_VERSION} COPY --from=gateway-planner /build/recipe.json ./recipe.json RUN --mount=type=cache,id=aether-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=aether-cargo-git,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,id=aether-cargo-target-local,target=/build/target,sharing=locked \ cargo chef cook --release --locked --package aether-gateway --bin aether-gateway --features jemalloc --recipe-path recipe.json COPY Cargo.toml Cargo.lock ./ COPY apps/ ./apps/ COPY crates/ ./crates/ RUN --mount=type=cache,id=aether-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=aether-cargo-git,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,id=aether-cargo-target-local,target=/build/target,sharing=locked \ set -eux; \ cargo build --release --locked -p aether-gateway --bin aether-gateway --features jemalloc; \ cp target/release/aether-gateway /tmp/aether-gateway # ==================== 最小运行时打包 ==================== FROM gateway-builder AS runtime-prep RUN set -eux; \ mkdir -p \ /runtime-root/app/data \ /runtime-root/app/logs \ /runtime-root/etc \ /runtime-root/etc/ssl \ /runtime-root/lib \ /runtime-root/lib64 \ /runtime-root/usr/local/bin; \ cp /tmp/aether-gateway /runtime-root/usr/local/bin/aether-gateway; \ : > /tmp/runtime-libs.txt; \ : > /tmp/runtime-scan-queue.txt; \ printf '%s\n' /tmp/aether-gateway >> /tmp/runtime-scan-queue.txt; \ while [ -s /tmp/runtime-scan-queue.txt ]; do \ current="$(head -n1 /tmp/runtime-scan-queue.txt)"; \ sed -i '1d' /tmp/runtime-scan-queue.txt; \ ldd "$current" | awk '/=>/ { print $3 } $1 ~ /^\// { print $1 }' | while read -r lib; do \ [ -n "$lib" ]; \ if ! grep -Fxq "$lib" /tmp/runtime-libs.txt; then \ printf '%s\n' "$lib" >> /tmp/runtime-libs.txt; \ printf '%s\n' "$lib" >> /tmp/runtime-scan-queue.txt; \ fi; \ done; \ done; \ sort -u /tmp/runtime-libs.txt -o /tmp/runtime-libs.txt; \ while read -r lib; do \ [ -n "$lib" ]; \ dest="/runtime-root$(dirname "$lib")"; \ mkdir -p "$dest"; \ cp -L "$lib" "$dest/"; \ done < /tmp/runtime-libs.txt; \ for lib in \ /lib/x86_64-linux-gnu/libnss_dns.so.2 \ /lib/x86_64-linux-gnu/libnss_files.so.2 \ /lib/x86_64-linux-gnu/libresolv.so.2; do \ if [ -f "$lib" ]; then \ dest="/runtime-root$(dirname "$lib")"; \ mkdir -p "$dest"; \ cp -L "$lib" "$dest/"; \ fi; \ done; \ cp -a /usr/lib/ssl /runtime-root/usr/lib/; \ cp -a /etc/ssl/certs /runtime-root/etc/ssl/; \ if [ -f /etc/ssl/openssl.cnf ]; then \ cp /etc/ssl/openssl.cnf /runtime-root/etc/ssl/openssl.cnf; \ fi; \ if [ -f /etc/nsswitch.conf ]; then \ cp /etc/nsswitch.conf /runtime-root/etc/nsswitch.conf; \ fi # ==================== 运行时镜像 ==================== FROM scratch # 复制 gateway 二进制 COPY --from=runtime-prep /runtime-root/ / # 复制前端构建产物 COPY --from=frontend-builder /app/frontend/dist /srv/frontend WORKDIR /app ENV LANG=C.UTF-8 \ LC_ALL=C.UTF-8 \ RUST_LOG=aether_gateway=info \ APP_PORT=8084 \ AETHER_UPDATE_STRATEGY=manual \ AETHER_GATEWAY_STATIC_DIR=/srv/frontend EXPOSE 8084 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD ["/usr/local/bin/aether-gateway", "--healthcheck"] USER 0:0 ENTRYPOINT ["/usr/local/bin/aether-gateway"]