Skip to content

Make Dockerfile cross-platform (ARM support) #1

Description

@readtedium

Hey, this is pretty solid and clean, and makes me less mad than cal dot com does. One issue I ran into however is that I run an ARM server and this doesn’t currently account for an ARM build (even though it is fully capable of compiling on ARM). Here’s the replacement Dockerfile I’m working with.

# syntax=docker/dockerfile:1
# ── Frontend build stage ───────────────────────────────────────────────────────
FROM node:22-alpine AS frontend-builder
# Pin pnpm to the version in package.json's `packageManager` field (not @latest)
# so CI builds are reproducible and match the committed lockfile.
RUN corepack enable && corepack prepare pnpm@10.32.1 --activate
WORKDIR /app
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY frontend/ .
RUN pnpm build
# ── Go build stage ─────────────────────────────────────────────────────────────
FROM golang:1.26-alpine AS builder
RUN apk add --no-cache ca-certificates wget
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
COPY --from=frontend-builder /app/build ./frontend/build
# Build natively for whatever architecture this stage is running on
# (TARGETARCH is auto-populated by Docker buildx; falls back correctly
# on ARM hosts where the original hardcoded amd64 would produce a
# binary that can't execute at all).
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build \
    -ldflags="-s -w" \
    -o calnode ./cmd/calnode
# Download Litestream for the deployment target, matching TARGETARCH
ARG LITESTREAM_VERSION=0.3.13
RUN wget -qO- \
    "https://github.com/benbjohnson/litestream/releases/download/v${LITESTREAM_VERSION}/litestream-v${LITESTREAM_VERSION}-linux-${TARGETARCH}.tar.gz" \
    | tar -xz -C /usr/local/bin litestream
# ── Runtime stage ─────────────────────────────────────────────────────────────
# alpine (not scratch) — needed for the shell entrypoint and Litestream.
# No --platform pin here: inherits the build host's native architecture,
# matching whatever TARGETARCH the binary above was actually compiled for.
FROM alpine:3.21
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /usr/local/bin/litestream /usr/local/bin/litestream
COPY --from=builder /build/calnode /calnode
COPY litestream.yml /etc/litestream.yml
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
# Note: no `VOLUME` directive — persistent storage is provided by the platform's
# managed volume mounted at /data (Railway rejects the Docker VOLUME instruction;
# Fly mounts via fly.toml). The dir is created at runtime by entrypoint.sh.
EXPOSE 3000
ENV PORT=3000 \
    DATABASE_URL=sqlite:///data/calnode.db
ENTRYPOINT ["/entrypoint.sh"]

Happy to propose a merge, but given that you’re still in the throes of working on this I don’t want to cramp your style just yet.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions