Skip to content

Commit b82f5a9

Browse files
authored
Merge pull request #10 from ethpandaops/chore/per-client-docker-images
docker: per-client images + standalone orchestrator image via build matrix
2 parents 6381688 + 934a3ed commit b82f5a9

7 files changed

Lines changed: 308 additions & 45 deletions

File tree

.github/workflows/docker.yml

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
1-
name: Build and Push Docker Image
1+
name: Build and Push Docker Images
22

33
on:
44
push:
55
branches: [main]
6+
workflow_dispatch:
67

78
jobs:
89
docker:
10+
name: Build ${{ matrix.thing }}
911
runs-on: ubuntu-latest
1012
permissions:
1113
contents: read
1214
packages: write
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- thing: orchestrator
20+
target: orchestrator
21+
submodule: ""
22+
- thing: lighthouse
23+
target: lighthouse
24+
submodule: engines/lighthouse/lighthouse
25+
- thing: teku
26+
target: teku
27+
submodule: engines/teku/teku
28+
- thing: lodestar
29+
target: lodestar
30+
submodule: engines/lodestar/lodestar
31+
- thing: nimbus
32+
target: nimbus
33+
submodule: engines/nimbus/nimbus-eth2
34+
- thing: grandine
35+
target: grandine
36+
submodule: ""
1337
steps:
1438
- uses: actions/checkout@v4
1539
with:
16-
submodules: recursive
40+
submodules: false
41+
42+
- name: Configure HTTPS submodule URLs
43+
run: |
44+
git config --global url."https://github.com/".insteadOf "git@github.com:"
45+
git config --global url."https://github.com/".insteadOf "ssh://git@github.com/"
46+
47+
- name: Initialize engine submodule
48+
if: matrix.submodule != ''
49+
run: git submodule update --init --recursive "${{ matrix.submodule }}"
1750

1851
- uses: docker/setup-buildx-action@v3
1952

@@ -26,9 +59,13 @@ jobs:
2659
- uses: docker/build-push-action@v5
2760
with:
2861
context: .
62+
target: ${{ matrix.target }}
63+
platforms: linux/amd64
2964
push: true
3065
tags: |
31-
ghcr.io/ethpandaops/fcr-simulator:latest
32-
ghcr.io/ethpandaops/fcr-simulator:${{ github.sha }}
33-
cache-from: type=gha
34-
cache-to: type=gha,mode=max
66+
ghcr.io/ethpandaops/fcr-simulator:${{ matrix.thing }}-latest
67+
ghcr.io/ethpandaops/fcr-simulator:${{ matrix.thing }}-${{ github.sha }}
68+
build-args: |
69+
VERSION=${{ github.sha }}
70+
cache-from: type=gha,scope=fcr-${{ matrix.thing }}
71+
cache-to: type=gha,mode=max,scope=fcr-${{ matrix.thing }}

Dockerfile

Lines changed: 218 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,242 @@
1-
FROM rust:1.88-bookworm AS rust-builder
1+
# syntax=docker/dockerfile:1.7
22

3-
RUN apt-get update && apt-get install -y \
4-
cmake \
5-
clang \
6-
libclang-dev \
7-
protobuf-compiler \
8-
git \
9-
&& rm -rf /var/lib/apt/lists/*
3+
FROM golang:1.24-bookworm AS orchestrator-builder
104

11-
WORKDIR /build
12-
COPY . .
5+
ENV CGO_ENABLED=0
6+
WORKDIR /src
137

14-
RUN cd engines/lighthouse/lighthouse && git submodule update --init --recursive
8+
COPY go.mod go.sum ./
9+
RUN --mount=type=cache,target=/go/pkg/mod \
10+
go mod download
1511

16-
WORKDIR /build/engines/lighthouse/lighthouse
12+
COPY . .
13+
ARG VERSION=dev
14+
RUN --mount=type=cache,target=/go/pkg/mod \
15+
--mount=type=cache,target=/root/.cache/go-build \
16+
go build -trimpath -ldflags="-s -w -X main.version=${VERSION}" \
17+
-o /out/fcr-orchestrator ./cmd/fcr-orchestrator
18+
19+
20+
FROM rust:1.88-bookworm AS lighthouse-builder
21+
22+
RUN apt-get update && apt-get install -y --no-install-recommends \
23+
bash \
24+
ca-certificates \
25+
clang \
26+
cmake \
27+
git \
28+
libclang-dev \
29+
pkg-config \
30+
protobuf-compiler \
31+
&& rm -rf /var/lib/apt/lists/*
1732

18-
RUN CARGO_NET_GIT_FETCH_WITH_CLI=true \
19-
cargo build -p fcr-simulator --features fake_crypto --release
33+
WORKDIR /src
34+
COPY . .
35+
RUN cd /tmp \
36+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "git@github.com:" \
37+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "ssh://git@github.com/"
38+
RUN if [ ! -f engines/lighthouse/lighthouse/Cargo.toml ]; then \
39+
git submodule update --init --recursive engines/lighthouse/lighthouse; \
40+
fi
41+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
42+
--mount=type=cache,target=/usr/local/cargo/git \
43+
--mount=type=cache,target=/src/engines/lighthouse/lighthouse/target \
44+
bash engines/lighthouse/build.sh
2045

2146

2247
FROM eclipse-temurin:21-jdk-noble AS teku-builder
2348

24-
RUN apt-get update && apt-get install -y git bash && rm -rf /var/lib/apt/lists/*
49+
ARG FCR_TEKU_COMMIT=c5825d53325cd67ab91b35cc544a7b660be317ff
2550

26-
WORKDIR /build
27-
COPY . .
51+
RUN apt-get update && apt-get install -y --no-install-recommends \
52+
bash \
53+
ca-certificates \
54+
git \
55+
&& rm -rf /var/lib/apt/lists/*
2856

29-
RUN git -c protocol.file.allow=always submodule update --init --recursive engines/teku/teku
30-
RUN bash engines/teku/build.sh
57+
ENV GRADLE_USER_HOME=/root/.gradle
58+
WORKDIR /src
59+
COPY . .
60+
RUN cd /tmp \
61+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "git@github.com:" \
62+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "ssh://git@github.com/"
63+
RUN if [ -f engines/teku/teku/settings.gradle ] \
64+
&& ! git -C engines/teku/teku rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
65+
rm -rf engines/teku/teku; \
66+
mkdir -p engines/teku/teku; \
67+
git -C engines/teku/teku init; \
68+
git -C engines/teku/teku remote add origin https://github.com/Nashatyrev/teku.git; \
69+
git -C engines/teku/teku fetch --depth 1 origin "${FCR_TEKU_COMMIT}"; \
70+
git -C engines/teku/teku checkout --detach FETCH_HEAD; \
71+
elif [ ! -f engines/teku/teku/settings.gradle ]; then \
72+
git submodule update --init --recursive engines/teku/teku; \
73+
fi
74+
RUN --mount=type=cache,target=/root/.gradle \
75+
bash engines/teku/build.sh
76+
77+
78+
FROM node:24-bookworm-slim AS lodestar-builder
79+
80+
RUN apt-get update && apt-get install -y --no-install-recommends \
81+
bash \
82+
ca-certificates \
83+
git \
84+
make \
85+
python3 \
86+
&& rm -rf /var/lib/apt/lists/*
3187

88+
ENV PNPM_HOME=/pnpm
89+
ENV PATH=/pnpm:${PATH}
90+
WORKDIR /src
91+
COPY . .
92+
ARG FCR_LODESTAR_COMMIT
93+
ARG FCR_LODESTAR_DESCRIBE
94+
ENV FCR_LODESTAR_COMMIT=${FCR_LODESTAR_COMMIT}
95+
ENV FCR_LODESTAR_DESCRIBE=${FCR_LODESTAR_DESCRIBE}
96+
RUN corepack enable && corepack prepare pnpm@10 --activate
97+
RUN cd /tmp \
98+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "git@github.com:" \
99+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "ssh://git@github.com/"
100+
RUN if [ ! -f engines/lodestar/lodestar/package.json ]; then \
101+
git submodule update --init --recursive engines/lodestar/lodestar; \
102+
fi
103+
RUN --mount=type=cache,target=/pnpm/store \
104+
pnpm config set store-dir /pnpm/store \
105+
&& bash engines/lodestar/build.sh
106+
107+
108+
FROM debian:bookworm AS nimbus-builder
109+
110+
ARG FCR_NIMBUS_COMMIT=6fb05f36804d53c2e8e014cfeeea8ad7996a5efe
111+
112+
RUN apt-get update && apt-get install -y --no-install-recommends \
113+
bash \
114+
build-essential \
115+
ca-certificates \
116+
cmake \
117+
curl \
118+
file \
119+
git \
120+
git-lfs \
121+
pkg-config \
122+
&& rm -rf /var/lib/apt/lists/*
32123

33-
FROM golang:1.24-bookworm AS go-builder
124+
WORKDIR /src
125+
COPY . .
126+
RUN cd /tmp \
127+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "git@github.com:" \
128+
&& git config --file /root/.gitconfig url."https://github.com/".insteadOf "ssh://git@github.com/"
129+
RUN if [ -f engines/nimbus/nimbus-eth2/Makefile ] \
130+
&& ! git -C engines/nimbus/nimbus-eth2 rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
131+
rm -rf engines/nimbus/nimbus-eth2; \
132+
mkdir -p engines/nimbus/nimbus-eth2; \
133+
git -C engines/nimbus/nimbus-eth2 init; \
134+
git -C engines/nimbus/nimbus-eth2 remote add origin https://github.com/status-im/nimbus-eth2.git; \
135+
git -C engines/nimbus/nimbus-eth2 fetch --depth 1 origin "${FCR_NIMBUS_COMMIT}"; \
136+
git -C engines/nimbus/nimbus-eth2 checkout --detach FETCH_HEAD; \
137+
elif [ ! -f engines/nimbus/nimbus-eth2/Makefile ]; then \
138+
git submodule update --init --recursive engines/nimbus/nimbus-eth2; \
139+
fi
140+
RUN bash engines/nimbus/build.sh
141+
142+
143+
FROM rust:1.88-bookworm AS grandine-builder
144+
145+
RUN apt-get update && apt-get install -y --no-install-recommends \
146+
bash \
147+
ca-certificates \
148+
clang \
149+
cmake \
150+
git \
151+
libclang-dev \
152+
pkg-config \
153+
protobuf-compiler \
154+
&& rm -rf /var/lib/apt/lists/*
34155

35-
WORKDIR /build
156+
WORKDIR /src
36157
COPY . .
158+
RUN --mount=type=cache,target=/usr/local/cargo/registry \
159+
--mount=type=cache,target=/usr/local/cargo/git \
160+
bash engines/grandine/build.sh
37161

38-
RUN go build -o /out/fcr-orchestrator ./cmd/fcr-orchestrator
39162

163+
FROM debian:bookworm-slim AS orchestrator
40164

41-
FROM eclipse-temurin:21-jre-noble
165+
RUN apt-get update && apt-get install -y --no-install-recommends \
166+
ca-certificates \
167+
&& rm -rf /var/lib/apt/lists/*
168+
169+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
170+
ENTRYPOINT ["fcr-orchestrator"]
42171

43-
RUN apt-get update && \
44-
apt-get install -y ca-certificates && \
45-
rm -rf /var/lib/apt/lists/*
46172

47-
COPY --from=rust-builder /build/engines/lighthouse/lighthouse/target/release/fcr-lighthouse /usr/local/bin/fcr-lighthouse
48-
COPY --from=teku-builder /build/engines/teku/.build/dist/fcr-teku-all.jar /usr/local/lib/fcr-teku-all.jar
49-
COPY --from=go-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
173+
FROM debian:bookworm-slim AS lighthouse
50174

51-
RUN printf '#!/usr/bin/env sh\nexec java -jar /usr/local/lib/fcr-teku-all.jar "$@"\n' > /usr/local/bin/fcr-teku && \
52-
chmod +x /usr/local/bin/fcr-teku
175+
RUN apt-get update && apt-get install -y --no-install-recommends \
176+
ca-certificates \
177+
libgcc-s1 \
178+
&& rm -rf /var/lib/apt/lists/*
53179

180+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
181+
COPY --from=lighthouse-builder /src/results/fcr-lighthouse /usr/local/bin/fcr-lighthouse
54182
ENV FCR_ENGINE_BINARY=/usr/local/bin/fcr-lighthouse
55183
ENTRYPOINT ["fcr-orchestrator"]
184+
185+
186+
FROM eclipse-temurin:21-jre-noble AS teku
187+
188+
RUN apt-get update && apt-get install -y --no-install-recommends \
189+
ca-certificates \
190+
&& rm -rf /var/lib/apt/lists/*
191+
192+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
193+
COPY --from=teku-builder /src/engines/teku/.build/dist/fcr-teku-all.jar /usr/local/lib/fcr-teku/fcr-teku-all.jar
194+
RUN printf '%s\n' \
195+
'#!/usr/bin/env sh' \
196+
'exec java -jar /usr/local/lib/fcr-teku/fcr-teku-all.jar "$@"' \
197+
> /usr/local/bin/fcr-teku \
198+
&& chmod +x /usr/local/bin/fcr-teku
199+
ENV FCR_ENGINE_BINARY=/usr/local/bin/fcr-teku
200+
ENTRYPOINT ["fcr-orchestrator"]
201+
202+
203+
FROM node:24-bookworm-slim AS lodestar
204+
205+
RUN apt-get update && apt-get install -y --no-install-recommends \
206+
ca-certificates \
207+
&& rm -rf /var/lib/apt/lists/*
208+
209+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
210+
COPY --from=lodestar-builder /src/engines/lodestar /opt/fcr/lodestar
211+
RUN printf '%s\n' \
212+
'#!/usr/bin/env sh' \
213+
'exec node --enable-source-maps --max-old-space-size="${FCR_LODESTAR_MAX_OLD_SPACE_SIZE:-12288}" /opt/fcr/lodestar/dist/main.mjs "$@"' \
214+
> /usr/local/bin/fcr-lodestar \
215+
&& chmod +x /usr/local/bin/fcr-lodestar
216+
ENV FCR_ENGINE_BINARY=/usr/local/bin/fcr-lodestar
217+
ENTRYPOINT ["fcr-orchestrator"]
218+
219+
220+
FROM debian:bookworm-slim AS nimbus
221+
222+
RUN apt-get update && apt-get install -y --no-install-recommends \
223+
ca-certificates \
224+
&& rm -rf /var/lib/apt/lists/*
225+
226+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
227+
COPY --from=nimbus-builder /src/results/fcr-nimbus /usr/local/bin/fcr-nimbus
228+
ENV FCR_ENGINE_BINARY=/usr/local/bin/fcr-nimbus
229+
ENTRYPOINT ["fcr-orchestrator"]
230+
231+
232+
FROM debian:bookworm-slim AS grandine
233+
234+
RUN apt-get update && apt-get install -y --no-install-recommends \
235+
ca-certificates \
236+
libgcc-s1 \
237+
&& rm -rf /var/lib/apt/lists/*
238+
239+
COPY --from=orchestrator-builder /out/fcr-orchestrator /usr/local/bin/fcr-orchestrator
240+
COPY --from=grandine-builder /src/results/fcr-grandine /usr/local/bin/fcr-grandine
241+
ENV FCR_ENGINE_BINARY=/usr/local/bin/fcr-grandine
242+
ENTRYPOINT ["fcr-orchestrator"]

cmd/fcr-orchestrator/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ func run(ctx context.Context, args []string, stdout, stderr io.Writer) int {
155155

156156
cfg, printVersion, err := parseConfig(args, stderr)
157157
if err != nil {
158+
if errors.Is(err, flag.ErrHelp) {
159+
return 0
160+
}
158161
fmt.Fprintln(stderr, err)
159162
return 1
160163
}
@@ -339,6 +342,9 @@ func validateConfig(cfg *config, startSet, endSet bool) error {
339342
func runEraMirrorCommand(ctx context.Context, args []string, stdout, stderr io.Writer) int {
340343
cfg, err := parseEraMirrorConfig(args, stderr)
341344
if err != nil {
345+
if errors.Is(err, flag.ErrHelp) {
346+
return 0
347+
}
342348
fmt.Fprintln(stderr, err)
343349
return 1
344350
}

cmd/fcr-orchestrator/main_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,32 @@ func TestEndToEndSmoke(t *testing.T) {
1515
t.Skip("TODO: wire a mock beacon node plus fixture ERA cache for an orchestrator end-to-end smoke test")
1616
}
1717

18+
func TestRunHelpExitsZero(t *testing.T) {
19+
var stdout bytes.Buffer
20+
var stderr bytes.Buffer
21+
22+
code := run(context.Background(), []string{"--help"}, &stdout, &stderr)
23+
if code != 0 {
24+
t.Fatalf("run --help exit code=%d want 0; stderr=%q", code, stderr.String())
25+
}
26+
if !strings.Contains(stderr.String(), "Usage of fcr-orchestrator:") {
27+
t.Fatalf("stderr=%q want usage text", stderr.String())
28+
}
29+
}
30+
31+
func TestRunEraMirrorHelpExitsZero(t *testing.T) {
32+
var stdout bytes.Buffer
33+
var stderr bytes.Buffer
34+
35+
code := run(context.Background(), []string{"era-mirror", "--help"}, &stdout, &stderr)
36+
if code != 0 {
37+
t.Fatalf("run era-mirror --help exit code=%d want 0; stderr=%q", code, stderr.String())
38+
}
39+
if !strings.Contains(stderr.String(), "Usage of fcr-orchestrator era-mirror:") {
40+
t.Fatalf("stderr=%q want era-mirror usage text", stderr.String())
41+
}
42+
}
43+
1844
func validConfig(engine string) *config {
1945
return &config{
2046
Engine: engine,

0 commit comments

Comments
 (0)