Skip to content

feat: containerize + publish to sei ECR - #10

Merged
bdchatham merged 2 commits into
mainfrom
feat/dockerfile-ecr-publish
May 15, 2026
Merged

bdchatham merged 2 commits into
mainfrom
feat/dockerfile-ecr-publish

Conversation

@bdchatham

@bdchatham bdchatham commented May 15, 2026 •

Copy link
Copy Markdown
Contributor

Why

Legacy sei-infra built this binary from source on every EC2 host (install-sei-cosmos-exporter.sh + systemd). The K8s migration runs it as a sidecar in seid pods (rendered by sei-k8s-controller, see sei-k8s-controller#249), which needs a published OCI image at a known registry.

No image existed; nothing in this repo built one. This PR fixes that.

What

Dockerfile (multi-stage)

  • golang:1.20-alpine builder → gcr.io/distroless/static-debian12:nonroot runtime
  • UID/GID 65532 matches sei-k8s-controller/internal/noderesource.sidecarSecurityContext.RunAsUser so pod fsGroup propagation works without extra config
  • CGO_ENABLED=0 static binary; -trimpath -ldflags=\"-s -w\" -buildvcs=false
  • Final image: 56MB (verified locally)
  • CMD carries Sei-flavored defaults (--denom usei --denom-coefficient 1000000 --bech-prefix sei --listen-address :9300) so a bare docker run Just Works; K8s pod spec passes explicit Args which overrides CMD

.github/workflows/ecr.yaml

Mirrors sei-k8s-controller/.github/workflows/ecr.yml exactly:

  • Triggers on push: branches: [main] and workflow_dispatch (with optional tag input)
  • Same IAM role via OIDC: arn:aws:iam::189176372795:role/common/gha
  • Same shared build cache: <registry>/sei/build-cache:shared
  • linux/amd64 only
  • Image path: <registry>/sei/sei-cosmos-exporter:<github.sha>

Compatibility

  • Go pinned to 1.20 because cosmos-sdk v0.45.4 (this repo's transitive dep) doesn't compile cleanly on 1.21+ stdlib changes. Bump in lock-step with any cosmos-sdk upgrade.
  • Existing actions.yaml (go build + go vet) and release.yaml (GoReleaser binary releases on tags) are untouched — parallel artifact paths.

Test plan

  • docker build -t sei-cosmos-exporter:test . succeeds locally
  • docker run --rm sei-cosmos-exporter:test --help prints flag help (binary loads, no immediate Fatal)
  • Image size verified at 56.3MB (docker images)
  • CI publishes on merge to main; digest goes into sei-k8s-controller's SEI_COSMOS_EXPORTER_IMAGE env via a follow-up bump

Legacy sei-infra built this binary from source on every EC2 host via
install-sei-cosmos-exporter.sh + systemd. The K8s migration runs it
as a sidecar in seid pods (rendered by sei-k8s-controller), which
needs a published OCI image.

Adds:
- Multi-stage Dockerfile: golang:1.20-alpine builder → distroless
  static-debian12:nonroot runtime. UID 65532 matches the controller's
  sidecarSecurityContext.RunAsUser so fsGroup propagation works
  without extra config. CGO disabled for a static binary; binary
  built with -trimpath -ldflags="-s -w" (final image ~56MB).
- .github/workflows/ecr.yaml: builds + pushes to AWS ECR on every
  main-branch push, tagged by github.sha (workflow_dispatch accepts
  an override tag). Mirrors sei-k8s-controller/.github/workflows/ecr.yml
  exactly — same IAM role (arn:aws:iam::189176372795:role/common/gha),
  same shared build cache at sei/build-cache:shared.

Image path: <account>.dkr.ecr.us-east-2.amazonaws.com/sei/sei-cosmos-exporter:<sha>

The image's CMD passes Sei-flavored defaults (--denom usei,
--denom-coefficient 1000000, --bech-prefix sei, --listen-address :9300)
so a bare `docker run` Just Works. K8s pod spec passes explicit Args
which overrides CMD.

Pinned Go to 1.20 because cosmos-sdk v0.45.4 doesn't compile cleanly
on 1.21+ stdlib changes — bump this in lock-step with any cosmos-sdk
upgrade.

Tested locally with `docker build` + `docker run --help`. CI will
publish on merge to main; the digest from that push goes into
sei-k8s-controller's SEI_COSMOS_EXPORTER_IMAGE env to pin the operator.
@cursor

cursor Bot commented May 15, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your free trial for your GitHub account on this workspace.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

Cross-review flagged `:1.20-alpine` and `:nonroot` as floating tags
that retag over time. Pin both by sha256 so the image is a one-way
door — supply-chain reviewers see exactly which content went into
which build.

Resolved digests (Linux/amd64):
- golang:1.20-alpine → sha256:e47f1218...
- gcr.io/distroless/static-debian12:nonroot → sha256:a9329520...

Bump these in lock-step with any base-image upgrade.

Also performed a deeper smoke test than --help: ran the image against
an unreachable gRPC + Tendermint RPC, confirmed the binary boots,
exercises Cobra + Cosmos SDK init paths, and emits a well-formed
zerolog Fatal on dial failure (the exact path the K8s controller's
startup probe on seid:9090 was designed to mitigate). No static-link
symbol issues from CGO_ENABLED=0.
@cursor

cursor Bot commented May 15, 2026

Copy link
Copy Markdown

You have used all Bugbot PR reviews included in your free trial for your GitHub account on this workspace.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@bdchatham
bdchatham merged commit 6a02f1a into main May 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant