Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ jobs:
uses: actions/checkout@v7
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
with:
# Pin QEMU: newer (v9.x) binfmt releases segfault emulating
# ppc64le while configuring the systemd package. v8.1.5 is the
# last known-good version for this multi-arch build.
image: tonistiigi/binfmt:qemu-v8.1.5
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
Expand Down
56 changes: 52 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM kjake/base
LABEL maintainer="kjake"

ENV PERSISTENT_RUNTIME_DEPS \

Check warning on line 4 in Dockerfile

View workflow job for this annotation

GitHub Actions / Anchore-Build-Scan

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/
libwrap0 \
libcrack2 \
libavahi-client3 \
Expand All @@ -10,20 +10,41 @@
python3 \
perl

ENV DEBIAN_FRONTEND noninteractive

Check warning on line 13 in Dockerfile

View workflow job for this annotation

GitHub Actions / Anchore-Build-Scan

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/

# netatalk 4.5 hard-depends on the Spotlight stack (localsearch/tinysparql),
# which needs a D-Bus session bus. Left to apt, that pulls dbus-user-session ->
# libpam-systemd -> systemd, whose postinst hangs/segfaults under QEMU during
# the multi-arch build (and systemd is never run in this container). Installing
# dbus-x11 -- which also provides default-dbus-session-bus -- satisfies that
# dependency without dragging in systemd. The guard below fails the build if
# real systemd is ever pulled in again, so this stays honest over time.
RUN apt-get update \
&& apt-get install \
--no-install-recommends \
--fix-missing \
--assume-yes \
$PERSISTENT_RUNTIME_DEPS \
dbus-x11 \
elogind \
avahi-daemon \
curl \
ca-certificates \
xz-utils \
netatalk \
\
&& apt-get --assume-yes upgrade \
&& if dpkg-query -W -f='${Status}\n' systemd 2>/dev/null | grep -q '^install ok installed'; then \
echo "ERROR: the systemd package is installed; something still pulls it in."; \
echo "Installed packages that depend on systemd:"; \
apt-cache rdepends --installed systemd; \
echo "--- their systemd/logind dependency lines ---"; \
for p in $(apt-cache rdepends --installed systemd | tail -n +3 | tr -d ' |'); do \
echo "## $p:"; \
apt-cache show "$p" 2>/dev/null | grep -iE '^(Pre-)?Depends:' | grep -iE 'systemd|logind' || true; \
done; \
exit 1; \
fi \
&& apt-get --quiet --yes autoclean \
&& apt-get --quiet --yes autoremove \
&& apt-get --quiet --yes clean \
Expand All @@ -39,9 +60,36 @@
&& ln -s /usr/lib/netatalk /etc/netatalk/uams \
&& mkdir /media/share

COPY docker-entrypoint.sh /docker-entrypoint.sh
# Install s6-overlay as PID 1 so the container properly supervises its services
# (dbus, avahi, netatalk): zombie reaping, signal forwarding, restart-on-crash.
# Replaces the old single-process docker-entrypoint.sh.
ARG S6_OVERLAY_VERSION=3.2.1.0
ARG TARGETARCH
ARG TARGETVARIANT
RUN set -eux \
&& case "${TARGETARCH}${TARGETVARIANT:+/${TARGETVARIANT}}" in \
amd64) s6_arch=x86_64 ;; \
arm64) s6_arch=aarch64 ;; \
arm/v7) s6_arch=arm ;; \
386) s6_arch=i686 ;; \
ppc64le) s6_arch=powerpc64le ;; \
s390x) s6_arch=s390x ;; \
riscv64) s6_arch=riscv64 ;; \
*) echo "unsupported target arch: ${TARGETARCH}${TARGETVARIANT}" >&2; exit 1 ;; \
esac \
&& base="https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}" \
&& curl -fsSL "${base}/s6-overlay-noarch.tar.xz" -o /tmp/s6-noarch.tar.xz \
&& curl -fsSL "${base}/s6-overlay-${s6_arch}.tar.xz" -o /tmp/s6-arch.tar.xz \
&& tar -C / -Jxpf /tmp/s6-noarch.tar.xz \
&& tar -C / -Jxpf /tmp/s6-arch.tar.xz \
&& rm -f /tmp/s6-noarch.tar.xz /tmp/s6-arch.tar.xz

# s6 service definitions: cont-init.d one-shots + supervised services.d daemons.
COPY root/ /
COPY afp.conf /etc/afp.conf
ENV DEBIAN_FRONTEND newt
RUN chmod -R 0755 /etc/cont-init.d /etc/services.d

# Abort the boot if one-time init (cont-init.d) fails, instead of running half-up.
ENV S6_BEHAVIOUR_IF_STAGE2_FAILS=2

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD [ "/usr/sbin/netatalk", "-F","/etc/afp.conf","-d"]
ENTRYPOINT ["/init"]
50 changes: 0 additions & 50 deletions docker-entrypoint.sh

This file was deleted.

35 changes: 35 additions & 0 deletions root/etc/cont-init.d/10-setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/command/with-contenv bash
# One-shot initialisation, run by s6-overlay before the long-running services
# start. Mirrors what the old docker-entrypoint.sh did, minus launching the
# daemons (those are now supervised services under /etc/services.d).
set -e

if [ -n "${AFP_USER}" ]; then
cmd=""
if [ -n "${AFP_UID}" ]; then
cmd="$cmd --uid ${AFP_UID}"
fi
if [ -n "${AFP_GID}" ]; then
cmd="$cmd --gid ${AFP_GID}"
groupadd --gid "${AFP_GID}" "${AFP_USER}" || true
fi
# shellcheck disable=SC2086
adduser $cmd --no-create-home --disabled-password --gecos '' "${AFP_USER}" || true
if [ -n "${AFP_PASSWORD}" ]; then
echo "${AFP_USER}:${AFP_PASSWORD}" | chpasswd
fi
fi

mkdir -p /media/share /media/timemachine
chown "${AFP_USER:-root}" /media/share /media/timemachine

sed -i'' -e "s,%USER%,${AFP_USER:-},g" /etc/afp.conf

echo "---begin-afp.conf--"
cat /etc/afp.conf
echo "---end---afp.conf--"

# Clean up any stale runtime state from a previous (unclean) start.
mkdir -p /var/run/dbus
rm -f /var/run/dbus/pid /var/run/dbus/system_bus_socket
rm -f /var/run/lock/netatalk
18 changes: 18 additions & 0 deletions root/etc/services.d/avahi/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/command/with-contenv bash
# Bonjour/mDNS advertisement for the AFP shares. Opt-in via AVAHI=1.
if [ "${AVAHI}" != "1" ]; then
echo "avahi-daemon disabled (set AVAHI=1 to enable); idling."
exec sleep infinity
fi

# Wait for the system bus socket before starting.
for _ in $(seq 1 50); do
[ -S /var/run/dbus/system_bus_socket ] && break
sleep 0.2
done

# rlimit-nproc trips up avahi inside containers; drop it.
sed -i '/rlimit-nproc/d' /etc/avahi/avahi-daemon.conf
rm -f /var/run/avahi-daemon/pid

exec avahi-daemon -f /etc/avahi/avahi-daemon.conf
3 changes: 3 additions & 0 deletions root/etc/services.d/dbus/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/command/with-contenv bash
# System D-Bus broker. netatalk's Spotlight support and avahi-daemon talk to it.
exec dbus-daemon --system --nofork --nopidfile
11 changes: 11 additions & 0 deletions root/etc/services.d/netatalk/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/command/with-contenv bash
# The AFP file server itself. -d keeps it in the foreground so s6 can supervise.

# Wait for the system bus socket (netatalk connects to it for Spotlight).
for _ in $(seq 1 50); do
[ -S /var/run/dbus/system_bus_socket ] && break
sleep 0.2
done

rm -f /var/run/lock/netatalk
exec /usr/sbin/netatalk -F /etc/afp.conf -d
Loading