-
Notifications
You must be signed in to change notification settings - Fork 133
Expand file tree
/
Copy pathDockerfile
More file actions
132 lines (105 loc) · 5.56 KB
/
Copy pathDockerfile
File metadata and controls
132 lines (105 loc) · 5.56 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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# Build stage - Backend
FROM golang:1.26.6-alpine@sha256:af8d6740070b8906d12eae1c3e3ea0957fb63f492051ea05e354c38ef9fe88df AS backend-builder
WORKDIR /app
# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download
# Copy source
COPY . .
# Build args for version and target architecture
ARG APP_VERSION=dev
ARG TARGETARCH
# Build for the target platform (TARGETARCH is set automatically by buildx)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -ldflags="-s -w -X github.com/kubestellar/console/pkg/api.Version=${APP_VERSION}" -o console ./cmd/console
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -ldflags="-s -w -X main.version=${APP_VERSION}" -o kc-watcher ./cmd/watcher
# Build stage - MCP binaries
FROM alpine:3.22@sha256:310c62b5e7ca5b08167e4384c68db0fd2905dd9c7493756d356e893909057601 AS mcp-binaries
ARG TARGETARCH
ARG KUBESTELLAR_MCP_RELEASE_TAG=v0.8.18-nightly.20260509
# SHA256 checksums for linux/amd64 tarballs (update when bumping KUBESTELLAR_MCP_RELEASE_TAG)
ARG OPS_SHA256_AMD64="ee199aed870a074d056045e18ea0efb89af0dd817b502e8b1e2157608bd0efd2"
ARG DEPLOY_SHA256_AMD64="f49e94bce3157bd7ed450fabcc6bff8a72bc41f19735740f6b89717a3f0dc225"
# SHA256 checksums for linux/arm64 tarballs
ARG OPS_SHA256_ARM64="264678618b30a178eed02488b3c74afd49b4a85f68b474d9ae9aae2b19ba0b23"
ARG DEPLOY_SHA256_ARM64="65d4ca235e494a1a29345d28b65c8e46c66bd65c5101f1ca0a4c1bf8b83880a8"
RUN set -eux; \
apk add --no-cache ca-certificates curl tar; \
case "${TARGETARCH}" in \
amd64) mcp_arch="amd64"; ops_sha="${OPS_SHA256_AMD64}"; deploy_sha="${DEPLOY_SHA256_AMD64}" ;; \
arm64) mcp_arch="arm64"; ops_sha="${OPS_SHA256_ARM64}"; deploy_sha="${DEPLOY_SHA256_ARM64}" ;; \
*) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
esac; \
release_version="${KUBESTELLAR_MCP_RELEASE_TAG#v}"; \
base_url="https://github.com/kubestellar/kubestellar-mcp/releases/download/${KUBESTELLAR_MCP_RELEASE_TAG}"; \
mkdir -p /out; \
curl -fsSL "${base_url}/kubestellar-ops_${release_version}_linux_${mcp_arch}.tar.gz" -o /out/kubestellar-ops.tar.gz; \
echo "${ops_sha} /out/kubestellar-ops.tar.gz" | sha256sum -c -; \
tar -xzf /out/kubestellar-ops.tar.gz -C /out kubestellar-ops; \
curl -fsSL "${base_url}/kubestellar-deploy_${release_version}_linux_${mcp_arch}.tar.gz" -o /out/kubestellar-deploy.tar.gz; \
echo "${deploy_sha} /out/kubestellar-deploy.tar.gz" | sha256sum -c -; \
tar -xzf /out/kubestellar-deploy.tar.gz -C /out kubestellar-deploy; \
rm /out/kubestellar-ops.tar.gz /out/kubestellar-deploy.tar.gz; \
chmod +x /out/kubestellar-ops /out/kubestellar-deploy
# Build stage - Frontend
FROM node:22-alpine@sha256:8ea2348b068a9544dae7317b4f3aafcdc032df1647bb7d768a05a5cad1a7683f AS frontend-builder
WORKDIR /app
# Build args for version and commit hash
ARG APP_VERSION=0.0.0
ARG COMMIT_HASH=unknown
# Copy all frontend source first so we can detect a pre-built dist/.
# WARNING (local builds): if web/dist/ is present in your working tree from a
# previous build it will be copied here and the conditional below will skip
# npm ci + Vite, silently shipping stale assets. Remove web/dist/ before
# building locally if you want a fresh frontend build.
# In CI this is intentional: the build-frontend job pre-builds on amd64 and
# uploads the artifact; the docker-build job downloads it into web/dist/ so
# that QEMU arm64 never needs to run Node at all, avoiding the
# "Illegal instruction" crash caused by Node 22 using ARMv8.2+ instructions
# not supported by the default QEMU cpu model.
COPY web/ ./
# If dist/ is already present (CI pre-built path), skip npm ci and Vite
# entirely — no Node execution under QEMU arm64. Otherwise install
# dependencies and build from source (local / amd64 scratch builds).
RUN if [ -d dist ] && [ -n "$(ls -A dist 2>/dev/null)" ]; then \
echo "Using pre-built frontend dist/ — skipping npm ci and build"; \
else \
for attempt in 1 2 3; do \
npm ci --legacy-peer-deps && break; \
echo "npm ci failed on attempt ${attempt}; retrying..." >&2; \
sleep $((attempt * 5)); \
[ "${attempt}" = "3" ] && { echo "npm ci failed after 3 attempts" >&2; exit 1; }; \
done; \
VITE_APP_VERSION=${APP_VERSION} VITE_COMMIT_HASH=${COMMIT_HASH} npm run build; \
fi
# Final stage
FROM alpine:3.22@sha256:310c62b5e7ca5b08167e4384c68db0fd2905dd9c7493756d356e893909057601
WORKDIR /app
# Install runtime dependencies
RUN apk add --no-cache ca-certificates tzdata sqlite
# Copy backend and watcher binaries
COPY --from=backend-builder /app/console .
COPY --from=backend-builder /app/kc-watcher .
# Copy MCP helper binaries used by the in-cluster bridge
COPY --from=mcp-binaries /out/kubestellar-ops /usr/local/bin/kubestellar-ops
COPY --from=mcp-binaries /out/kubestellar-deploy /usr/local/bin/kubestellar-deploy
# Copy frontend build
COPY --from=frontend-builder /app/dist ./web/dist
# Create non-root user for container security
RUN addgroup -g 1001 -S appgroup && adduser -u 1001 -S appuser -G appgroup
# Create data and settings directories
RUN mkdir -p /app/data /app/.kc && chown -R appuser:appgroup /app/data /app/.kc
# Copy entrypoint script for watchdog + backend
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh
# Environment variables
ENV PORT=8080
ENV BACKEND_PORT=8081
ENV DATABASE_PATH=/app/data/console.db
ENV HOME=/app
EXPOSE 8080
# Health check hits the watchdog, which always responds
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -qO- http://localhost:8080/watchdog/health || exit 1
# Run as non-root user
USER appuser
ENTRYPOINT ["./entrypoint.sh"]