-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDockerfile
More file actions
executable file
·89 lines (72 loc) · 3.49 KB
/
Dockerfile
File metadata and controls
executable file
·89 lines (72 loc) · 3.49 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
# Sentinel Gate OSS - Multi-stage Dockerfile
#
# This builds the open-source version of Sentinel Gate with:
# - Single binary: /sentinel-gate
# - Single port: 8080 (no admin port)
# - No database dependencies (PostgreSQL, Redis)
# - Distroless runtime for minimal attack surface
#
# Build: docker build -t sentinel-gate:latest .
# Run: docker run -p 8080:8080 -v ./config.yaml:/etc/sentinel-gate/sentinel-gate.yaml:ro sentinel-gate:latest
# Stage 1: Build
FROM golang:1.26-alpine AS builder
WORKDIR /app
# Build configuration for static binary (no GOARCH: let Docker Buildx handle architecture)
ENV CGO_ENABLED=0 GOOS=linux
# Version info (override at build time with --build-arg)
ARG VERSION=dev
ARG COMMIT=none
ARG BUILD_DATE=unknown
# Download dependencies first (better layer caching)
COPY go.mod go.sum ./
COPY sdks/go/go.mod sdks/go/
RUN go mod download
# Copy source and build
COPY . .
RUN go build -trimpath \
-ldflags="-s -w \
-X github.com/Sentinel-Gate/Sentinelgate/cmd/sentinel-gate/cmd.Version=${VERSION} \
-X github.com/Sentinel-Gate/Sentinelgate/cmd/sentinel-gate/cmd.Commit=${COMMIT} \
-X github.com/Sentinel-Gate/Sentinelgate/cmd/sentinel-gate/cmd.BuildDate=${BUILD_DATE}" \
-o /sentinel-gate ./cmd/sentinel-gate
# Stage 2: Prepare data directory with correct ownership
FROM busybox:1.36-uclibc AS perms
RUN mkdir -p /data && chown 65532:65532 /data
# Stage 3: Runtime
FROM gcr.io/distroless/static-debian12 AS runtime
# Copy wget from busybox for healthcheck (distroless has no shell tools)
COPY --from=busybox:1.36-uclibc /bin/wget /usr/bin/wget
# OCI labels for GitHub Container Registry
LABEL org.opencontainers.image.source="https://github.com/Sentinel-Gate/Sentinelgate"
LABEL org.opencontainers.image.description="MCP proxy with policy enforcement for AI agents"
LABEL org.opencontainers.image.licenses="AGPL-3.0"
# Copy binary and CA certificates for HTTPS
COPY --from=builder /sentinel-gate /sentinel-gate
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# State persistence volume with correct ownership for non-root user (UID 65532).
# --chown is REQUIRED: COPY --from=<stage> does not preserve ownership by default
# (copies as 0:0), which would strip the chown done in the perms stage and leave
# /data owned by root, breaking write access for the nonroot user.
COPY --chown=65532:65532 --from=perms /data /data
VOLUME ["/data"]
ENV SENTINEL_GATE_STATE_PATH=/data/state.json
# Bind to all interfaces inside container (default is localhost-only for security).
# Cloud platforms (Smithery, Cloud Run) override PORT at runtime.
ENV PORT=8080
# Allow admin API/dashboard access from host (Docker doesn't preserve localhost RemoteAddr).
# Disable with -e SENTINEL_GATE_ADMIN_OPEN=false if running behind a reverse proxy with its own auth.
ENV SENTINEL_GATE_ADMIN_OPEN=true
# Working directory under writable volume (evidence-key.pem auto-generates here)
WORKDIR /data
# Run as non-root user
USER nonroot:nonroot
# Expose HTTP port (no admin port in OSS)
EXPOSE 8080
# Liveness check: verifies the process is alive and responding.
# Uses /health (not /readyz) so a persistent kill switch does not trigger a restart loop.
# The kill switch is a deliberate security state, not a failure — the admin can resume
# via the dashboard or POST /admin/api/v1/system/resume.
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD ["/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
ENTRYPOINT ["/sentinel-gate"]
CMD ["start"]