fix: named volume permissions in docker (#3518)

Fixes #2917

The problem is described in this "working as intended" issue https://github.com/moby/moby/issues/3124
So the advised approach of using "USER dfly" directive does not really work because it requires
that the host will also define 'dfly' user with the same id. It's unrealistic expectation.

Therefore, we revert the fix done in #1775 and follow valkey approach:
https://github.com/valkey-io/valkey-container/blob/mainline/docker-entrypoint.sh#L12

1. we run the entrypoint in the container as root which later spawns the dragonfly process
2. if we run as root:
   a. we chmod files under /data to dfly.
   b. use setpriv to exec ourselves as dfly.
3. if we do not run as root we execute the docker command.

So even though the process starts as root, the server runs as dfly and only the bootstrap
part has elevated permissions is used to fix the volume access.

While we are at it, we also switched to setpriv following the change of https://github.com/valkey-io/valkey-container/pull/24/files

Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
Roman Gershman 2024-08-22 11:33:29 +03:00 committed by GitHub
parent 1bf6d73aa3
commit cec3659b51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 13 additions and 20 deletions

View File

@ -11,12 +11,21 @@ set -e
# first arg is `-some-option` # first arg is `-some-option`
if [ "${1#-}" != "$1" ]; then if [ "${1#-}" != "$1" ]; then
# override arguments by prepending "dragonfly --logtostderr" to them. # override arguments by prepending "dragonfly --logtostderr" to them.
set -- dragonfly --logtostderr "$@" set -- dragonfly --logtostderr "$@"
fi fi
# allow the docker container to be started with `--user` # allow the docker container to be started with `--user`
if [ "$1" = 'dragonfly' -a "$(id -u)" = '0' ]; then if [ "$1" = 'dragonfly' -a "$(id -u)" = '0' ]; then
exec su-exec dfly "$0" "$@" # runs this script under user dfly # find all the files in the WORKDIR including the dir itself that do not
# have dfly user on them and chmod them to dfly.
find . \! -user dfly -exec chown dfly '{}' +
# runs this script under user dfly
exec setpriv --reuid=dfly --regid=dfly --clear-groups -- "$0" "$@"
fi
um="$(umask)"
if [ "$um" = '0022' ]; then
umask 0077 # restrict access permissions only to the owner
fi fi
exec "$@" exec "$@"

View File

@ -30,7 +30,7 @@ COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh
COPY --from=builder /build/build-release/dragonfly /usr/local/bin/ COPY --from=builder /build/build-release/dragonfly /usr/local/bin/
RUN apk --no-cache add libgcc libstdc++ \ RUN apk --no-cache add libgcc libstdc++ \
su-exec netcat-openbsd boost-context && ldd /usr/local/bin/dragonfly setpriv netcat-openbsd boost-context && ldd /usr/local/bin/dragonfly
RUN addgroup -S -g 1000 dfly && adduser -S -G dfly -u 999 dfly RUN addgroup -S -g 1000 dfly && adduser -S -G dfly -u 999 dfly
RUN mkdir /data && chown dfly:dfly /data RUN mkdir /data && chown dfly:dfly /data
@ -43,6 +43,4 @@ ENTRYPOINT ["entrypoint.sh"]
EXPOSE 6379 EXPOSE 6379
USER dfly
CMD ["dragonfly", "--logtostderr"] CMD ["dragonfly", "--logtostderr"]

View File

@ -12,10 +12,7 @@ RUN make release
RUN build-release/dragonfly --version RUN build-release/dragonfly --version
RUN curl -O https://raw.githubusercontent.com/ncopa/su-exec/212b75144bbc06722fbd7661f651390dc47a43d1/su-exec.c && \ FROM ubuntu:22.04
gcc -Wall -O2 su-exec.c -o su-exec
FROM debian:12-slim
RUN --mount=type=tmpfs,target=/var/cache/apt \ RUN --mount=type=tmpfs,target=/var/cache/apt \
--mount=type=tmpfs,target=/var/lib/apt/lists \ --mount=type=tmpfs,target=/var/lib/apt/lists \
@ -30,7 +27,6 @@ WORKDIR /data
COPY tools/docker/entrypoint.sh /usr/local/bin/entrypoint.sh COPY tools/docker/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh
COPY --from=builder /build/su-exec /usr/local/bin/
COPY --from=builder /build/build-release/dragonfly /usr/local/bin/ COPY --from=builder /build/build-release/dragonfly /usr/local/bin/
HEALTHCHECK CMD /usr/local/bin/healthcheck.sh HEALTHCHECK CMD /usr/local/bin/healthcheck.sh
@ -39,6 +35,4 @@ ENTRYPOINT ["entrypoint.sh"]
# For inter-container communication. # For inter-container communication.
EXPOSE 6379 EXPOSE 6379
USER dfly
CMD ["dragonfly", "--logtostderr"] CMD ["dragonfly", "--logtostderr"]

View File

@ -7,11 +7,6 @@ WORKDIR /build
COPY tools/docker/fetch_release.sh /tmp/ COPY tools/docker/fetch_release.sh /tmp/
COPY releases/dragonfly-* /tmp/ COPY releases/dragonfly-* /tmp/
ARG SUEXEC_HASH=d6c40440609a23483f12eb6295b5191e94baf08298a856bab6e15b10c3b82891
RUN curl -O https://raw.githubusercontent.com/ncopa/su-exec/212b75144bbc06722fbd7661f651390dc47a43d1/su-exec.c && \
if [ "$SUEXEC_HASH" != $(sha256sum su-exec.c | awk '{print $1}') ]; then echo "Wrong hash!" && exit 1; fi && \
gcc -Wall -O2 su-exec.c -o su-exec
RUN /tmp/fetch_release.sh ${TARGETPLATFORM} RUN /tmp/fetch_release.sh ${TARGETPLATFORM}
# Now prod image # Now prod image
@ -35,7 +30,6 @@ WORKDIR /data
COPY tools/docker/entrypoint.sh /usr/local/bin/entrypoint.sh COPY tools/docker/entrypoint.sh /usr/local/bin/entrypoint.sh
COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh COPY tools/docker/healthcheck.sh /usr/local/bin/healthcheck.sh
COPY --from=builder /build/su-exec /usr/local/bin/
COPY --from=builder /build/dragonfly /usr/local/bin/ COPY --from=builder /build/dragonfly /usr/local/bin/
HEALTHCHECK CMD /usr/local/bin/healthcheck.sh HEALTHCHECK CMD /usr/local/bin/healthcheck.sh
@ -44,6 +38,4 @@ ENTRYPOINT ["entrypoint.sh"]
# For inter-container communication. # For inter-container communication.
EXPOSE 6379 EXPOSE 6379
USER dfly
CMD ["dragonfly", "--logtostderr"] CMD ["dragonfly", "--logtostderr"]