Introduce PUID and PGID env variables to syncserver Dockerfile (#3714)

PUID and PGID are optional env variables to specify the user and group id of
the user that the anki-sync-server process should run with.

This gives more flexibility for solving permission problems with volumes and is
a common pattern for Docker images (e.g. see here:
https://docs.linuxserver.io/general/understanding-puid-and-pgid/)

The anki-sync-server process will write any files with the permissions of the
user it's running with, which can be a problem when you need to access those
files from outside the container or when they are being written into a bind
mount that is owned by a particular user on the host system.

To be able to implement this the entrypoint.sh needs to run as root (since it
needs to create a user and change file permissions). anki-sync-server then
needs to be started with the user 'anki', which is why the new dependency
'su-exec' is required. The user 'anki' and group 'anki-group' can no longer be
created at image build time because then their ids would be fixed.

Also update the build instructions to require building the Docker image inside
the directory where the Dockerfile resides since the build now needs to copy
the entrypoint.sh and it seems wrong the specify the path
docs/syncserver/entrypoint.sh inside the Dockerfile.
This commit is contained in:
Omar Kohl 2025-01-25 08:19:38 +01:00 committed by GitHub
parent 6c37d5fc70
commit 71e2a6f782
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 10 deletions

View file

@ -13,16 +13,14 @@ FROM alpine:3.21.0
ARG SYNC_PORT=8080
RUN adduser -D -h /home/anki anki
RUN mkdir -p /anki_data && chown -R anki /anki_data
# Default PUID and PGID values (can be overridden at runtime). Use these to
# ensure the files on the volume have the permissions you need.
ENV PUID=1000
ENV PGID=1000
COPY --from=builder /anki-server/bin/anki-sync-server /usr/local/bin/anki-sync-server
RUN apk update && apk add --no-cache bash && rm -rf /var/cache/apk/*
USER anki
RUN apk update && apk add --no-cache bash su-exec && rm -rf /var/cache/apk/*
ENV SYNC_PORT=${SYNC_PORT}
@ -30,6 +28,10 @@ ENV SYNC_BASE=/anki_data
EXPOSE ${SYNC_PORT}
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["anki-sync-server"]
# This health check will work for Anki versions 24.08.x and newer.

View file

@ -22,14 +22,15 @@ the build products and runtime dependencies from the rest of your system.
| **Start-up Time** | ❌ Slower start-up time due to larger image size | ✅ Faster start-up time |
| **Tool Compatibility** | ✅ Compatible with more tools and libraries | ❌ Compatibility limitations with certain tools |
| **Maintenance** | ❌ Higher maintenance due to larger image and dependencies | ✅ Lower maintenance with minimal base image |
| **Custom uid/gid** | ✅ It's possible to pass in PUID and PGID | ❌ PUID and PGID are not supported |
# Building image
To proceed with building, you must specify the Anki version you want, by replacing `<version>` with something like `24.11` and `<Dockerfile>` with the chosen Dockerfile (e.g., `Dockerfile` or `Dockerfile.distroless`)
```bash
# Execute this command from the root directory of your project
docker build -f docs/syncserver/<Dockerfile> --no-cache --build-arg ANKI_VERSION=<version> -t anki-sync-server .
# Execute this command from this directory
docker build -f <Dockerfile> --no-cache --build-arg ANKI_VERSION=<version> -t anki-sync-server .
```
# Run container
@ -46,7 +47,17 @@ docker run -d \
anki-sync-server
```
However, if you want to have multiple users, you have to use the following approach:
If the image you are using was built with `Dockerfile` you can specify the
`PUID` and `PGID` env variables for the user and group id of the process that
will run the anki-sync-server process. This is valuable when you want the files
written and read from the `/anki_data` volume to belong to a particular
user/group e.g. to access it from the host or another container. Note the the
ids chosen for `PUID` and `PGID` must not already be in use inside the
container (1000 and above is fine). For example add `-e "PUID=1050"` and `-e
"PGID=1050"` to the above command.
If you want to have multiple Anki users that can sync their devices, you can
specify multiple `SYNC_USER` as follows:
```bash
# this will create anki server with multiple users

View file

@ -0,0 +1,25 @@
#!/bin/sh
set -o errexit
set -o nounset
set -o pipefail
# Default PUID and PGID if not provided
export PUID=${PUID:-1000}
export PGID=${PGID:-1000}
# Check if group exists, create if not
if ! getent group anki-group > /dev/null 2>&1; then
addgroup -g "$PGID" anki-group
fi
# Check if user exists, create if not
if ! id -u anki > /dev/null 2>&1; then
adduser -D -H -u "$PUID" -G anki-group anki
fi
# Fix ownership of mounted volumes
mkdir -p /anki_data
chown anki:anki-group /anki_data
# Run the provided command as the `anki` user
exec su-exec anki "$@"