Repository navigation
Expand file tree
/
Copy pathDockerfile.local
More file actions
89 lines (71 loc) 路 3.8 KB
/
Copy pathDockerfile.local
File metadata and controls
89 lines (71 loc) 路 3.8 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
# Cargo.toml sets default = ["embed-ui"], and build.rs silently substitutes a
# placeholder index.html when ui/dist is missing, which would produce an image
# with no dashboard. Building the SPA here is required, not optional.
# Registry mirror prefix for the base images, e.g. registry.example/org/mirror/; empty pulls from Docker Hub.
ARG BASE_REGISTRY=""
FROM ${BASE_REGISTRY}oven/bun:1.3.14 AS web
# webcomponents' own build script shells out to `npm run copy-types`, which runs
# `node scripts/copy-types.mjs`. The oven/bun image ships bun only; CI gets away
# with `bun run build` because the GitHub runner already has node on PATH.
RUN apt-get update \
&& apt-get install -y --no-install-recommends nodejs npm \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY bindings/ ./bindings/
COPY webcomponents/ ./webcomponents/
RUN cd webcomponents && bun install --frozen-lockfile && bun run build
# ui/src/index.css @imports the brand tokens from the docs site, which is the source of truth for them (docs/design-system/).
COPY docs/assets/css/ ./docs/assets/css/
COPY ui/ ./ui/
RUN cd ui && bun install --frozen-lockfile && bun run build
# rusqlite is features = ["bundled"], so a C toolchain is required.
FROM ${BASE_REGISTRY}rust:1.98 AS build
WORKDIR /src
COPY . .
COPY --from=web /src/ui/dist ./ui/dist
# Compile-time license material; defaults match a plain source build.
ARG OPERATOR_RELEASE=""
ARG OPERATOR_LICENSE_ISSUER=operator-licensing
ARG OPERATOR_LICENSE_ROOT_KEYS={}
ARG OPERATOR_PURCHASE_URL=""
RUN cargo build --release --locked --bin operator
# opr8r is a separate cargo project with its own Cargo.lock, not a workspace member, so it needs its own invocation.
RUN cd opr8r && cargo build --release --locked
# Mirrors Dockerfile; only the operator/opr8r binary source differs.
# glibc 2.41 >= the ubuntu-24.04 build runners' 2.39, so the GNU binary runs.
FROM ${BASE_REGISTRY}debian:trixie-slim@sha256:d7e12182ce18b85b93007c1dedf31f2d29e01ccf3182cc4017c709b6259bc132
LABEL org.opencontainers.image.title="Operator" \
org.opencontainers.image.description="Agent orchestration server and CLI (local build)" \
org.opencontainers.image.url="https://operator.untra.io" \
org.opencontainers.image.source="https://github.com/untra/operator" \
org.opencontainers.image.licenses="MIT"
# Substrate Operator needs to launch agents: git (VCS ops), tmux (session
# wrapper), ca-certificates (TLS to LLM/kanban APIs), openssh-client (every
# ssh and coder target launch, and git over SSH remotes), curl (in-pod
# reachability checks). The LLM CLI (claude / codex / gemini) and its auth are
# supplied by the user via a derived image or a mount + env vars -- not baked
# in here.
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl git openssh-client tmux \
&& rm -rf /var/lib/apt/lists/*
# Both halves ship: agent sessions launched by the operator server call the
# opr8r client to report step completion for multi-step ticket workflows.
COPY --from=build --chown=0:0 --chmod=0755 /src/target/release/operator /usr/local/bin/operator
COPY --from=build --chown=0:0 --chmod=0755 /src/opr8r/target/release/opr8r /usr/local/bin/opr8r
# Fail the build before use if a binary can't execute on this base.
# --version short-circuits in clap before any config or tmux load.
RUN ["/usr/local/bin/operator", "--version"]
RUN ["/usr/local/bin/opr8r", "--version"]
# Run as an unprivileged user with a dedicated uid and gid.
RUN groupdel operator \
&& groupadd -g 10001 operator \
&& useradd -u 10001 -g 10001 -m -d /home/operator operator \
&& mkdir /op \
&& chown operator:operator /op
ENV HOME=/home/operator
USER operator
# Mount your projects root here: `docker run -v $(pwd):/op:rw ...`.
# Operator auto-loads .tickets/operator/config.toml relative to the cwd.
WORKDIR /op
EXPOSE 7008
ENTRYPOINT ["operator"]