-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
86 lines (77 loc) · 3.77 KB
/
Copy pathDockerfile
File metadata and controls
86 lines (77 loc) · 3.77 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
# UI stage: build the React admin console so a fresh copy is embedded regardless
# of what is checked in.
FROM node:22-alpine AS ui
WORKDIR /ui
COPY web/admin/package.json web/admin/package-lock.json ./
# `npm ci`, not `npm install`. install is allowed to update the lock file, so
# the published image could contain dependency versions CI never tested - and
# CI uses `npm ci`. For a build that goes straight to users that is a break in
# the supply chain, and it fails silently.
RUN npm ci --no-audit --no-fund
COPY web/admin/ ./
# Vite's outDir points at ../../internal/adminui/dist; recreate that layout so
# the build lands where the Go stage expects to embed it.
RUN mkdir -p /internal/adminui && npm run build
# Build stage: compile a static, CGO-free binary (modernc SQLite is pure Go, so
# the image needs no libc and cross-compiles cleanly).
FROM golang:1.27-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Overlay the freshly built admin UI from the UI stage.
COPY --from=ui /internal/adminui/dist ./internal/adminui/dist
ARG VERSION=docker
RUN CGO_ENABLED=0 go build -trimpath \
-ldflags "-s -w -X main.version=${VERSION}" \
-o /out/alertloop ./cmd/alertloop
# Runtime stage: minimal image with CA certs for outbound TLS (SMTP/Telegram).
#
# 3.22, not 3.20. Alpine supports a branch for two years, and 3.20 (May 2024)
# stopped receiving security updates in spring 2026 - which stopped being a
# theoretical problem the moment 0.4.0 made the published image the primary
# Docker path instead of a local build. Whatever has been found in busybox,
# musl, or ca-certificates since then would ship to every user.
#
# Track the current stable branch and rebuild on release; that is what actually
# keeps this current. Pin by digest if your policy requires reproducible bases -
# it is deliberately not pinned here, because a digest nobody updates is how an
# image quietly ages past its support window all over again.
FROM alpine:3.22
RUN apk add --no-cache ca-certificates tzdata && \
adduser -D -u 10001 alertloop && \
mkdir -p /data && chown alertloop:alertloop /data
WORKDIR /data
COPY --from=build /out/alertloop /usr/local/bin/alertloop
# Built-in configuration, so the image runs with no files supplied. Since
# 0.3.0 the config file is the only source of settings; the environment just
# fills the ${VAR} references in it, which is how the admin token gets in
# without being baked into the image. Mount your own file over this path — or
# point ALERTLOOP_CONFIG elsewhere — to replace it entirely.
#
# ${ALERTLOOP_ADMIN_TOKEN} carries NO default. With an empty token and no API
# keys the API accepts everything with full scope, so `docker run` with no
# environment used to hand out an unauthenticated service that can create,
# read, and modify events and replay deliveries. Now it refuses to start and
# names the variable. The entrypoint below turns that into an instruction
# rather than a stack trace.
RUN mkdir -p /etc/alertloop && { \
echo '# Default configuration shipped inside the AlertLoop image.'; \
echo 'admin_token: ${ALERTLOOP_ADMIN_TOKEN}'; \
echo 'database:'; \
echo ' driver: sqlite'; \
echo ' dsn: /data/alertloop.db'; \
} > /etc/alertloop/alertloop.yaml
# A first-run check that explains itself. Without it the failure is a config
# error about an unset variable, which is correct but tells a newcomer nothing
# about what to do.
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod 0755 /usr/local/bin/docker-entrypoint.sh
USER alertloop
EXPOSE 8080
ENV ALERTLOOP_CONFIG=/etc/alertloop/alertloop.yaml
VOLUME ["/data"]
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s \
CMD wget -qO- http://127.0.0.1:8080/health/ready || exit 1
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["all"]