mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 10:35:51 +00:00
32e0d453c4
Windows 11 25H2 ships exclusively on ARM64 hardware. When users on ARM64 attempt to install the host agent, the Service Control Manager fails to load the amd64 binary with ERROR_BAD_EXE_FORMAT, surfaced as "The Pulse Host Agent is not compatible with this Windows version". Changes: - Dockerfile: Build pulse-host-agent-windows-arm64.exe alongside amd64 - Dockerfile: Copy windows-arm64 binary and create symlink for download endpoint - install-host-agent.ps1: Use RuntimeInformation.OSArchitecture to detect ARM64 - build-release.sh: Build darwin-amd64, darwin-arm64, windows-amd64, windows-arm64 - build-release.sh: Package Windows binaries as .zip archives - validate-release.sh: Check for windows-arm64 binary and symlink - validate-release.sh: Add architecture validation for all darwin/windows variants The installer now correctly detects ARM64 and downloads the appropriate binary.
248 lines
11 KiB
Docker
248 lines
11 KiB
Docker
# syntax=docker/dockerfile:1.7-labs
|
|
ARG BUILD_AGENT=1
|
|
|
|
# Build stage for frontend (must be built first for embedding)
|
|
FROM node:20-alpine AS frontend-builder
|
|
|
|
WORKDIR /app/frontend-modern
|
|
|
|
# Copy package files
|
|
COPY frontend-modern/package*.json ./
|
|
RUN --mount=type=cache,id=pulse-npm-cache,target=/root/.npm \
|
|
npm ci
|
|
|
|
# Copy frontend source
|
|
COPY frontend-modern/ ./
|
|
|
|
# Build frontend
|
|
RUN --mount=type=cache,id=pulse-npm-cache,target=/root/.npm \
|
|
npm run build
|
|
|
|
# Build stage for Go backend
|
|
FROM golang:1.24-alpine AS backend-builder
|
|
|
|
ARG BUILD_AGENT
|
|
WORKDIR /app
|
|
|
|
# Install build dependencies
|
|
RUN apk add --no-cache git
|
|
|
|
# Copy go mod files for better layer caching
|
|
COPY go.mod go.sum ./
|
|
RUN --mount=type=cache,id=pulse-go-mod,target=/go/pkg/mod \
|
|
--mount=type=cache,id=pulse-go-build,target=/root/.cache/go-build \
|
|
go mod download
|
|
|
|
# Copy only necessary source code
|
|
COPY cmd/ ./cmd/
|
|
COPY internal/ ./internal/
|
|
COPY pkg/ ./pkg/
|
|
COPY VERSION ./
|
|
|
|
# Copy built frontend from frontend-builder stage for embedding
|
|
# Must be at internal/api/frontend-modern for Go embed
|
|
COPY --from=frontend-builder /app/frontend-modern/dist ./internal/api/frontend-modern/dist
|
|
|
|
# Build the binaries with embedded frontend
|
|
RUN --mount=type=cache,id=pulse-go-mod,target=/go/pkg/mod \
|
|
--mount=type=cache,id=pulse-go-build,target=/root/.cache/go-build \
|
|
VERSION="v$(cat VERSION | tr -d '\n')" && \
|
|
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") && \
|
|
GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") && \
|
|
CGO_ENABLED=0 GOOS=linux go build \
|
|
-ldflags="-s -w -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT} -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse ./cmd/pulse
|
|
|
|
# Build docker-agent binaries (optional cross-arch builds controlled by BUILD_AGENT)
|
|
RUN --mount=type=cache,id=pulse-go-mod,target=/go/pkg/mod \
|
|
--mount=type=cache,id=pulse-go-build,target=/root/.cache/go-build \
|
|
VERSION="v$(cat VERSION | tr -d '\n')" && \
|
|
if [ "${BUILD_AGENT:-1}" = "1" ]; then \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-docker-agent-linux-amd64 ./cmd/pulse-docker-agent && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-docker-agent-linux-arm64 ./cmd/pulse-docker-agent && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-docker-agent-linux-armv7 ./cmd/pulse-docker-agent; \
|
|
else \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/dockeragent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-docker-agent-linux-amd64 ./cmd/pulse-docker-agent && \
|
|
cp pulse-docker-agent-linux-amd64 pulse-docker-agent-linux-arm64 && \
|
|
cp pulse-docker-agent-linux-amd64 pulse-docker-agent-linux-armv7; \
|
|
fi && \
|
|
cp pulse-docker-agent-linux-amd64 pulse-docker-agent
|
|
|
|
# Build host-agent binaries for all platforms (for download endpoint)
|
|
RUN --mount=type=cache,id=pulse-go-mod,target=/go/pkg/mod \
|
|
--mount=type=cache,id=pulse-go-build,target=/root/.cache/go-build \
|
|
VERSION="v$(cat VERSION | tr -d '\n')" && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-linux-amd64 ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-linux-arm64 ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-linux-armv7 ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-darwin-amd64 ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-darwin-arm64 ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-windows-amd64.exe ./cmd/pulse-host-agent && \
|
|
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X github.com/rcourtman/pulse-go-rewrite/internal/hostagent.Version=${VERSION}" \
|
|
-trimpath \
|
|
-o pulse-host-agent-windows-arm64.exe ./cmd/pulse-host-agent
|
|
|
|
# Build pulse-sensor-proxy for all Linux architectures (for download endpoint)
|
|
RUN --mount=type=cache,id=pulse-go-mod,target=/go/pkg/mod \
|
|
--mount=type=cache,id=pulse-go-build,target=/root/.cache/go-build \
|
|
VERSION="v$(cat VERSION | tr -d '\n')" && \
|
|
BUILD_TIME=$(date -u '+%Y-%m-%d_%H:%M:%S') && \
|
|
GIT_COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown') && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|
-ldflags="-s -w -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" \
|
|
-trimpath \
|
|
-o pulse-sensor-proxy-linux-amd64 ./cmd/pulse-sensor-proxy && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build \
|
|
-ldflags="-s -w -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" \
|
|
-trimpath \
|
|
-o pulse-sensor-proxy-linux-arm64 ./cmd/pulse-sensor-proxy && \
|
|
CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build \
|
|
-ldflags="-s -w -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME} -X main.GitCommit=${GIT_COMMIT}" \
|
|
-trimpath \
|
|
-o pulse-sensor-proxy-linux-armv7 ./cmd/pulse-sensor-proxy && \
|
|
cp pulse-sensor-proxy-linux-amd64 pulse-sensor-proxy
|
|
|
|
# Runtime image for the Docker agent (offered via --target agent_runtime)
|
|
FROM alpine:3.20 AS agent_runtime
|
|
|
|
# Use TARGETARCH to select the correct binary for the build platform
|
|
ARG TARGETARCH
|
|
ARG TARGETVARIANT
|
|
|
|
RUN apk --no-cache add ca-certificates tzdata
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy all agent binaries first
|
|
COPY --from=backend-builder /app/pulse-docker-agent-linux-* /tmp/
|
|
|
|
# Select the appropriate architecture binary
|
|
# Docker buildx automatically sets TARGETARCH (amd64, arm64, arm) and TARGETVARIANT (v7)
|
|
RUN if [ "$TARGETARCH" = "arm64" ]; then \
|
|
cp /tmp/pulse-docker-agent-linux-arm64 /usr/local/bin/pulse-docker-agent; \
|
|
elif [ "$TARGETARCH" = "arm" ]; then \
|
|
cp /tmp/pulse-docker-agent-linux-armv7 /usr/local/bin/pulse-docker-agent; \
|
|
else \
|
|
cp /tmp/pulse-docker-agent-linux-amd64 /usr/local/bin/pulse-docker-agent; \
|
|
fi && \
|
|
chmod +x /usr/local/bin/pulse-docker-agent && \
|
|
rm -rf /tmp/pulse-docker-agent-*
|
|
|
|
COPY --from=backend-builder /app/VERSION /VERSION
|
|
|
|
ENV PULSE_NO_AUTO_UPDATE=true
|
|
|
|
ENTRYPOINT ["/usr/local/bin/pulse-docker-agent"]
|
|
|
|
# Final stage (Pulse server runtime)
|
|
FROM alpine:3.20
|
|
|
|
RUN apk --no-cache add ca-certificates tzdata su-exec openssh-client
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy binaries from builder (frontend is embedded)
|
|
COPY --from=backend-builder /app/pulse .
|
|
COPY --from=backend-builder /app/pulse-docker-agent .
|
|
|
|
# Copy VERSION file
|
|
COPY --from=backend-builder /app/VERSION .
|
|
|
|
# Copy entrypoint script
|
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
|
RUN chmod +x /docker-entrypoint.sh
|
|
|
|
# Provide installer scripts for HTTP download endpoints
|
|
RUN mkdir -p /opt/pulse/scripts
|
|
COPY scripts/install-docker-agent.sh /opt/pulse/scripts/install-docker-agent.sh
|
|
COPY scripts/install-container-agent.sh /opt/pulse/scripts/install-container-agent.sh
|
|
COPY scripts/install-host-agent.sh /opt/pulse/scripts/install-host-agent.sh
|
|
COPY scripts/install-host-agent.ps1 /opt/pulse/scripts/install-host-agent.ps1
|
|
COPY scripts/uninstall-host-agent.sh /opt/pulse/scripts/uninstall-host-agent.sh
|
|
COPY scripts/uninstall-host-agent.ps1 /opt/pulse/scripts/uninstall-host-agent.ps1
|
|
COPY scripts/install-sensor-proxy.sh /opt/pulse/scripts/install-sensor-proxy.sh
|
|
COPY scripts/install-docker.sh /opt/pulse/scripts/install-docker.sh
|
|
RUN chmod 755 /opt/pulse/scripts/install-docker-agent.sh /opt/pulse/scripts/install-container-agent.sh /opt/pulse/scripts/install-host-agent.sh /opt/pulse/scripts/install-host-agent.ps1 /opt/pulse/scripts/uninstall-host-agent.sh /opt/pulse/scripts/uninstall-host-agent.ps1 /opt/pulse/scripts/install-sensor-proxy.sh /opt/pulse/scripts/install-docker.sh
|
|
|
|
# Copy multi-arch docker-agent binaries for download endpoint
|
|
RUN mkdir -p /opt/pulse/bin
|
|
COPY --from=backend-builder /app/pulse-docker-agent-linux-amd64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-docker-agent-linux-arm64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-docker-agent-linux-armv7 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-docker-agent /opt/pulse/bin/pulse-docker-agent
|
|
|
|
# Copy multi-arch host-agent binaries for download endpoint
|
|
COPY --from=backend-builder /app/pulse-host-agent-linux-amd64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-linux-arm64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-linux-armv7 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-darwin-amd64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-darwin-arm64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-windows-amd64.exe /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-host-agent-windows-arm64.exe /opt/pulse/bin/
|
|
# Create symlinks for Windows without .exe extension
|
|
RUN ln -s pulse-host-agent-windows-amd64.exe /opt/pulse/bin/pulse-host-agent-windows-amd64 && \
|
|
ln -s pulse-host-agent-windows-arm64.exe /opt/pulse/bin/pulse-host-agent-windows-arm64
|
|
|
|
# Copy multi-arch pulse-sensor-proxy binaries for download endpoint
|
|
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-amd64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-arm64 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-sensor-proxy-linux-armv7 /opt/pulse/bin/
|
|
COPY --from=backend-builder /app/pulse-sensor-proxy /opt/pulse/bin/pulse-sensor-proxy
|
|
|
|
# Create config directory
|
|
RUN mkdir -p /etc/pulse /data
|
|
|
|
# Expose port
|
|
EXPOSE 7655
|
|
|
|
# Set environment variables
|
|
# Only PULSE_DATA_DIR is used - all node config is done via web UI
|
|
ENV PULSE_DATA_DIR=/data
|
|
ENV PULSE_DOCKER=true
|
|
|
|
# Create default user (will be adjusted by entrypoint if PUID/PGID are set)
|
|
RUN adduser -D -u 1000 -g 1000 pulse && \
|
|
chown -R pulse:pulse /app /etc/pulse /data /opt/pulse
|
|
|
|
# Health check
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:7655 || exit 1
|
|
|
|
# Use entrypoint script to handle UID/GID
|
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
|
|
|
# Run the binary
|
|
CMD ["./pulse"]
|