diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 6a297faf..5fdda0da 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -51,6 +51,10 @@ jobs: done test "$READY" = 1 + # a NAS panel's terminal opens bash or sh, with magpie on PATH + docker exec smoke /bin/bash -c 'magpie healthcheck && ls /config >/dev/null' + docker exec smoke /bin/sh -c 'echo sh works' + CODE=$(curl -s -o /tmp/body.json -w '%{http_code}' \ -H 'Authorization: Bearer magpie' -H 'Content-Type: application/json' \ -d '{"model":"ci-unknown-model","messages":[{"role":"user","content":"hi"}]}' \ diff --git a/Dockerfile b/Dockerfile index d3b7b14f..1daa2a71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,12 +12,32 @@ RUN CGO_ENABLED=0 go build -tags nogui -trimpath \ -ldflags "-s -w -X main.version=${VERSION}" -o /out/magpie . \ && mkdir -p /config/home /config/cache /config/data /config/state +# A shell for the container's terminal: NAS panels (Synology, 1Panel, +# Portainer) open /bin/bash or /bin/sh, and distroless has neither, so a +# terminal there failed with "stat /bin/bash: no such file or directory". +# Debian 12's bash (with the libtinfo it links), which runs on the glibc of +# distroless's own Debian 12, and busybox for ls, cat and the like. +FROM debian:12-slim AS shell +RUN mkdir -p /out/bin /out/lib \ + && cp /bin/bash /out/bin/bash \ + && cp -L "$(ldd /bin/bash | awk '/libtinfo/ {print $3}')" /out/lib/ + +FROM busybox:1.37-uclibc AS busybox + # cc, not static: plugins run on Bun, which magpie downloads on first use # and which needs glibc (static has no libc at all, and Bun's musl build # would need musl). cc is static plus glibc, libgcc and libstdc++. FROM gcr.io/distroless/cc-debian12:nonroot COPY --from=build /out/magpie /magpie +COPY --from=busybox /bin/busybox /bin/busybox +COPY --from=shell /out/bin/bash /bin/bash +COPY --from=shell /out/lib/ /usr/lib/ +# busybox's commands, and magpie on PATH, so `magpie accounts add …` works +# in that terminal +USER root +RUN ["/bin/busybox", "sh", "-c", "/bin/busybox --install -s /bin && mkdir -p /usr/local/bin && ln -s /magpie /usr/local/bin/magpie"] +USER nonroot COPY --from=build --chown=65532:65532 /config /config # Everything magpie and the sign-ins it manages write goes into the volume: diff --git a/README.md b/README.md index 30810f9b..6f5189e0 100644 --- a/README.md +++ b/README.md @@ -788,7 +788,9 @@ Termux uses the Android terminal build: the installer puts it in ### Docker `docker build` makes a server image: the terminal-only binary on -distroless (`cc`, for the glibc the plugins' Bun needs), run as nonroot, +distroless (`cc`, for the glibc the plugins' Bun needs) with bash and +busybox for a terminal in the container (`docker exec -it magpie bash`, or a +NAS panel's terminal; `magpie` is on its PATH), run as nonroot, with everything it keeps in a volume at `/config`: magpie's own files (`/config/magpie`), the sign-ins kept where their agent keeps them (HOME is `/config/home`, so `~/.codex`, `~/.claude`… are in it) and the cache with the