Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
84 lines (70 loc) · 3.49 KB
/
Copy pathDockerfile
File metadata and controls
84 lines (70 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
# arrowloop: two-way file synchronisation with a state database and a brake
#
# GitHub: https://github.com/junkerderprovinz/arrowloop
# Image: ghcr.io/junkerderprovinz/arrowloop
# License: AGPL-3.0-only
#
# One static Go binary. rclone is compiled in as a library rather than run as a
# second executable, so there is no version skew between the tool and the thing
# it drives.
# The web and build stages run on the runner's own platform and cross-compile,
# rather than being emulated under QEMU for the arm64 target.
ARG BUILDPLATFORM
FROM --platform=$BUILDPLATFORM node:24-slim@sha256:d6aa754f16b3197301076f047b5def2f02ea1dbbc2ca920407d46d7ec7f87b20 AS web
WORKDIR /src
COPY web/package.json web/package-lock.json ./web/
RUN npm --prefix web ci --no-audit --no-fund
COPY web/ ./web/
RUN npm --prefix web run build
FROM --platform=$BUILDPLATFORM golang:1.27-bookworm@sha256:8d48e12ec56735e9358640898b9d9b9fcca110612ed8a5567438c0a1baa24e66 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY cmd ./cmd
COPY internal ./internal
# Each file the web package embeds is named here. A file added beside embed.go
# and not here fails with "pattern ...: no matching files found", and only in
# this build, because every other build has the whole checkout.
COPY web/*.go web/placeholder.html ./web/
COPY --from=web /src/web/dist ./web/dist
ARG TARGETOS
ARG TARGETARCH
# Shown in the startup banner and the READY line; "dev" marks an unstamped
# local build.
ARG VERSION=dev
# -trimpath keeps the build machine's directory layout out of the binary, so the
# same commit produces the same bytes wherever it is built.
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \
go build -trimpath -ldflags "-s -w -X github.com/junkerderprovinz/arrowloop/internal/boot.Version=${VERSION}" \
-o /out/arrowloop ./cmd/arrowloop
FROM debian:stable-slim@sha256:eb593cf2c358cacef45ca0a424bbc7d30cfa3466265fc2662b9466a0ca6ba1c5 AS runtime
LABEL org.opencontainers.image.title="arrowloop" \
org.opencontainers.image.description="Two-way file synchronisation with a per-file state database, a trash, and brakes that refuse an implausible deletion." \
org.opencontainers.image.source="https://github.com/junkerderprovinz/arrowloop" \
org.opencontainers.image.licenses="AGPL-3.0-only"
# ca-certificates for TLS to the cloud backends, tini so a stop signal reaches
# the process rather than being swallowed by PID 1, tzdata so a cron schedule
# means local time.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates tini tzdata; \
rm -rf /var/lib/apt/lists/*
COPY --from=build /out/arrowloop /usr/local/bin/arrowloop
# Holds arrowloop.json, the per-job state databases and the run log.
VOLUME ["/config"]
EXPOSE 8422
# Inside a container the binary's loopback default would be unreachable. The
# interface has no login of its own, so the exposure decision belongs to
# whoever publishes the port.
#
# The image runs as root and writes into someone else's share. With umask 022
# every file would land as 0644 root:root, readable but not changeable by the
# share's owner; 000 matches an Unraid share's 0777 nobody:users. Set it to 022
# for the restrictive behaviour.
ENV ARROWLOOP_ADDR=0.0.0.0:8422 \
ARROWLOOP_UMASK=000 \
TZ=Europe/Berlin
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD ["/usr/local/bin/arrowloop", "healthcheck"]
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/arrowloop"]
CMD ["web", "-config", "/config/arrowloop.json"]