Repository navigation
Expand file tree
/
Copy pathDockerfile.fleet
More file actions
110 lines (93 loc) · 4.68 KB
/
Copy pathDockerfile.fleet
File metadata and controls
110 lines (93 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# ---------------------------------------------------------------------------------
# Fleet E2E image. Started as a copy of the old root `Dockerfile` (deleted: no
# workflow built it) with ONE addition: a BuildKit secret carrying a GitHub
# token, so the private `oxy-hq` cargo dependencies (airway-internal, airlayer,
# airform) resolve inside the build.
#
# docker build -f Dockerfile.fleet --secret id=gh_token,env=GH_TOKEN .
# ---------------------------------------------------------------------------------
# Base image for Rust and Cargo Chef
FROM lukemathwalker/cargo-chef:latest-rust-1.99.1-bookworm AS chef
WORKDIR /app
# `cargo chef cook` runs BEFORE `COPY . .`, so the repo's `.cargo/config.toml`
# — which sets `git-fetch-with-cli = true` — is not there yet. Without it cargo
# fetches through libgit2, which does not honour `url.insteadOf`, so the token
# rewrite below is ignored and the private oxy-hq deps fail as
# "revision not found". The env var says the same thing, file or no file.
ENV CARGO_NET_GIT_FETCH_WITH_CLI=true
# Stage 1: Dependency planner
FROM chef AS planner
RUN --mount=type=secret,id=gh_token \
git config --global "url.https://x-access-token:$(cat /run/secrets/gh_token)@github.com/.insteadOf" "https://github.com/" && \
git config --global --add "url.https://x-access-token:$(cat /run/secrets/gh_token)@github.com/.insteadOf" "git@github.com:"
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
# Stage 2: Build the web application
FROM node:26-slim AS web-builder
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY web-app/package.json ./web-app/
# sdk/* are pnpm-workspace members, so their manifests must exist for
# `pnpm install` to resolve the workspace lockfile — web-app does not depend
# on them, so the sdk itself is never built here.
COPY sdk/typescript/package.json ./sdk/typescript/
COPY sdk/vite-plugin/package.json ./sdk/vite-plugin/
COPY sdk/create-oxy-app/package.json ./sdk/create-oxy-app/
# Node 25 dropped bundled Corepack, so node:26-slim has no `corepack` binary —
# install it from npm. Keeps the sha512-pinned `packageManager` field authoritative.
RUN npm install -g corepack@latest && \
corepack enable && corepack prepare --activate && pnpm install
COPY web-app/ ./web-app/
ARG VITE_SENTRY_DSN
ENV VITE_SENTRY_DSN=$VITE_SENTRY_DSN
RUN pnpm -C web-app build
# Stage 3: Build the Rust application
FROM chef AS rust-builder
RUN apt-get update && \
apt-get install -y protobuf-compiler ca-certificates && \
rm -rf /var/lib/apt/lists/*
RUN --mount=type=secret,id=gh_token \
git config --global "url.https://x-access-token:$(cat /run/secrets/gh_token)@github.com/.insteadOf" "https://github.com/" && \
git config --global --add "url.https://x-access-token:$(cat /run/secrets/gh_token)@github.com/.insteadOf" "git@github.com:"
COPY --from=planner /app/recipe.json recipe.json
# `crates/app-dylib` is EXCLUDED from the workspace (root Cargo.toml `exclude`),
# so cargo-chef — which reconstructs a skeleton of workspace MEMBERS only — omits
# it from recipe.json. But `crates/server` declares it as an optional path
# dependency (`oxy-app-dylib = { path = "../app-dylib", optional = true }`), and
# cargo must parse that manifest to resolve oxy-server even with the feature off.
# `cook` runs before `COPY . .`, so without these two lines it dies with
# "failed to read /app/crates/app-dylib/Cargo.toml". The crate is a handful of
# lines and never built here (dev-dynamic is off), so copying it early costs
# nothing and does not invalidate the dependency layer in practice.
COPY crates/app-dylib/Cargo.toml crates/app-dylib/Cargo.toml
COPY crates/app-dylib/src crates/app-dylib/src
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
COPY --from=web-builder /app/web-app/dist /app/crates/app/dist
RUN cargo build --release
# Stage 4: Runtime image
FROM debian:bookworm-slim AS runtime
WORKDIR /app
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
tini \
git \
chromium \
fonts-liberation \
fonts-noto-color-emoji \
fonts-noto-cjk && \
rm -rf /var/lib/apt/lists/*
# Headless browser for server-side ECharts rendering (rust-headless-chrome)
# Point to the actual Chromium binary, not the wrapper script
ENV CHROME=/usr/lib/chromium/chromium
COPY --from=rust-builder /app/target/release/oxy /usr/local/bin
# Directory for persistent app data inside the container
ENV OXY_STATE_DIR=/var/lib/oxy/data
RUN mkdir -p ${OXY_STATE_DIR} && chown -R root:root /var/lib/oxy
VOLUME ["${OXY_STATE_DIR}"]
# Set tini as the entrypoint
ENTRYPOINT ["/usr/bin/tini", "--"]
# Default command
EXPOSE 3000 3001
CMD ["oxy", "serve", "--port", "3000", "--internal-host", "0.0.0.0"]