diff --git a/4.0/32bit/Dockerfile b/4.0/32bit/Dockerfile index 00bd1da05..b1f28ad14 100644 --- a/4.0/32bit/Dockerfile +++ b/4.0/32bit/Dockerfile @@ -39,15 +39,15 @@ RUN set -eux; \ gosu --version; \ gosu nobody true -ENV REDIS_VERSION 4.0.14 -ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-4.0.14.tar.gz -ENV REDIS_DOWNLOAD_SHA 1e1e18420a86cfb285933123b04a82e1ebda20bfb0a289472745a087587e93a7 - RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends libc6-i386; \ rm -rf /var/lib/apt/lists/* +ENV REDIS_VERSION 4.0.14 +ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-4.0.14.tar.gz +ENV REDIS_DOWNLOAD_SHA 1e1e18420a86cfb285933123b04a82e1ebda20bfb0a289472745a087587e93a7 + RUN set -eux; \ \ savedAptMark="$(apt-mark showmanual)"; \ diff --git a/5.0/32bit/Dockerfile b/5.0/32bit/Dockerfile index b8bc2543a..15c935aad 100644 --- a/5.0/32bit/Dockerfile +++ b/5.0/32bit/Dockerfile @@ -39,15 +39,15 @@ RUN set -eux; \ gosu --version; \ gosu nobody true -ENV REDIS_VERSION 5.0.7 -ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.7.tar.gz -ENV REDIS_DOWNLOAD_SHA 61db74eabf6801f057fd24b590232f2f337d422280fd19486eca03be87d3a82b - RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends libc6-i386; \ rm -rf /var/lib/apt/lists/* +ENV REDIS_VERSION 5.0.7 +ENV REDIS_DOWNLOAD_URL http://download.redis.io/releases/redis-5.0.7.tar.gz +ENV REDIS_DOWNLOAD_SHA 61db74eabf6801f057fd24b590232f2f337d422280fd19486eca03be87d3a82b + RUN set -eux; \ \ savedAptMark="$(apt-mark showmanual)"; \ diff --git a/6.0-rc/32bit/Dockerfile b/6.0-rc/32bit/Dockerfile index e4855644f..c05038d59 100644 --- a/6.0-rc/32bit/Dockerfile +++ b/6.0-rc/32bit/Dockerfile @@ -39,15 +39,15 @@ RUN set -eux; \ gosu --version; \ gosu nobody true -ENV REDIS_VERSION 6.0-rc1 -ENV REDIS_DOWNLOAD_URL https://github.com/antirez/redis/archive/6.0-rc1.tar.gz -ENV REDIS_DOWNLOAD_SHA 2676012e2fcfe8d41e594b2ae8a05d0a050d2d84c38a0471ae5fe0143e4b0eca - RUN set -eux; \ apt-get update; \ apt-get install -y --no-install-recommends libc6-i386; \ rm -rf /var/lib/apt/lists/* +ENV REDIS_VERSION 6.0-rc1 +ENV REDIS_DOWNLOAD_URL https://github.com/antirez/redis/archive/6.0-rc1.tar.gz +ENV REDIS_DOWNLOAD_SHA 2676012e2fcfe8d41e594b2ae8a05d0a050d2d84c38a0471ae5fe0143e4b0eca + RUN set -eux; \ \ savedAptMark="$(apt-mark showmanual)"; \ diff --git a/Dockerfile-32bit.template b/Dockerfile-32bit.template new file mode 100644 index 000000000..d909ddd6c --- /dev/null +++ b/Dockerfile-32bit.template @@ -0,0 +1,115 @@ +FROM debian:buster-slim + +# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added +RUN groupadd -r -g 999 redis && useradd -r -g redis -u 999 redis + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.11 +RUN set -eux; \ +# save list of currently installed packages for later so we can clean up + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + dirmngr \ + gnupg \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + \ +# verify the signature + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + \ +# clean up fetch dependencies + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ + chmod +x /usr/local/bin/gosu; \ +# verify that the binary works + gosu --version; \ + gosu nobody true + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends libc6-i386; \ + rm -rf /var/lib/apt/lists/* + +ENV REDIS_VERSION placeholder +ENV REDIS_DOWNLOAD_URL placeholder +ENV REDIS_DOWNLOAD_SHA placeholder + +RUN set -eux; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + wget \ + \ + gcc \ + gcc-multilib \ + libc6-dev-i386 \ + make \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \ + echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ + mkdir -p /usr/src/redis; \ + tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ + rm redis.tar.gz; \ + \ +# disable Redis protected mode [1] as it is unnecessary in context of Docker +# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P) +# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da +#### + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/src/redis/src/config.c; \ + sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/src/redis/src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/src/redis/src/config.c; \ +#### +# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" +# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 +# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) + \ + make -C /usr/src/redis -j "$(nproc)" 32bit; \ + make -C /usr/src/redis install; \ + \ +# TODO https://github.com/antirez/redis/pull/3494 (deduplicate "redis-server" copies) + serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ + find /usr/local/bin/redis* -maxdepth 0 \ + -type f -not -name redis-server \ + -exec sh -eux -c ' \ + md5="$(md5sum "$1" | cut -d" " -f1)"; \ + test "$md5" = "$serverMd5"; \ + ' -- '{}' ';' \ + -exec ln -svfT 'redis-server' '{}' ';' \ + ; \ + \ + rm -r /usr/src/redis; \ + \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ + redis-cli --version; \ + redis-server --version + +RUN mkdir /data && chown redis:redis /data +VOLUME /data +WORKDIR /data + +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 6379 +CMD ["redis-server"] diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template new file mode 100644 index 000000000..966d9008a --- /dev/null +++ b/Dockerfile-alpine.template @@ -0,0 +1,81 @@ +FROM alpine:3.11 + +# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added +RUN addgroup -S -g 1000 redis && adduser -S -G redis -u 999 redis +# alpine already has a gid 999, so we'll use the next id + +RUN apk add --no-cache \ +# grab su-exec for easy step-down from root + 'su-exec>=0.2' \ +# add tzdata for https://github.com/docker-library/redis/issues/138 + tzdata + +ENV REDIS_VERSION placeholder +ENV REDIS_DOWNLOAD_URL placeholder +ENV REDIS_DOWNLOAD_SHA placeholder + +RUN set -eux; \ + \ + apk add --no-cache --virtual .build-deps \ + coreutils \ + gcc \ + linux-headers \ + make \ + musl-dev \ + ; \ + \ + wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \ + echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ + mkdir -p /usr/src/redis; \ + tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ + rm redis.tar.gz; \ + \ +# disable Redis protected mode [1] as it is unnecessary in context of Docker +# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P) +# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da +#### + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/src/redis/src/config.c; \ + sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/src/redis/src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/src/redis/src/config.c; \ +#### +# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" +# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 +# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) + \ + make -C /usr/src/redis -j "$(nproc)"; \ + make -C /usr/src/redis install; \ + \ +# TODO https://github.com/antirez/redis/pull/3494 (deduplicate "redis-server" copies) + serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ + find /usr/local/bin/redis* -maxdepth 0 \ + -type f -not -name redis-server \ + -exec sh -eux -c ' \ + md5="$(md5sum "$1" | cut -d" " -f1)"; \ + test "$md5" = "$serverMd5"; \ + ' -- '{}' ';' \ + -exec ln -svfT 'redis-server' '{}' ';' \ + ; \ + \ + rm -r /usr/src/redis; \ + \ + runDeps="$( \ + scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ + | tr ',' '\n' \ + | sort -u \ + | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-network --virtual .redis-rundeps $runDeps; \ + apk del --no-network .build-deps; \ + \ + redis-cli --version; \ + redis-server --version + +RUN mkdir /data && chown redis:redis /data +VOLUME /data +WORKDIR /data + +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 6379 +CMD ["redis-server"] diff --git a/Dockerfile.template b/Dockerfile.template new file mode 100644 index 000000000..a4d8384d2 --- /dev/null +++ b/Dockerfile.template @@ -0,0 +1,109 @@ +FROM debian:buster-slim + +# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added +RUN groupadd -r -g 999 redis && useradd -r -g redis -u 999 redis + +# grab gosu for easy step-down from root +# https://github.com/tianon/gosu/releases +ENV GOSU_VERSION 1.11 +RUN set -eux; \ +# save list of currently installed packages for later so we can clean up + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + dirmngr \ + gnupg \ + wget \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ + wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ + wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ + \ +# verify the signature + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ + gpgconf --kill all; \ + rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ + \ +# clean up fetch dependencies + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ + chmod +x /usr/local/bin/gosu; \ +# verify that the binary works + gosu --version; \ + gosu nobody true + +ENV REDIS_VERSION placeholder +ENV REDIS_DOWNLOAD_URL placeholder +ENV REDIS_DOWNLOAD_SHA placeholder + +RUN set -eux; \ + \ + savedAptMark="$(apt-mark showmanual)"; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + ca-certificates \ + wget \ + \ + gcc \ + libc6-dev \ + make \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + wget -O redis.tar.gz "$REDIS_DOWNLOAD_URL"; \ + echo "$REDIS_DOWNLOAD_SHA *redis.tar.gz" | sha256sum -c -; \ + mkdir -p /usr/src/redis; \ + tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1; \ + rm redis.tar.gz; \ + \ +# disable Redis protected mode [1] as it is unnecessary in context of Docker +# (ports are not automatically exposed when running inside Docker, but rather explicitly by specifying -p / -P) +# [1]: https://github.com/antirez/redis/commit/edd4d555df57dc84265fdfb4ef59a4678832f6da +#### + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/src/redis/src/config.c; \ + sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/src/redis/src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/src/redis/src/config.c; \ +#### +# for future reference, we modify this directly in the source instead of just supplying a default configuration flag because apparently "if you specify any argument to redis-server, [it assumes] you are going to specify everything" +# see also https://github.com/docker-library/redis/issues/4#issuecomment-50780840 +# (more exactly, this makes sure the default behavior of "save on SIGTERM" stays functional by default) + \ + make -C /usr/src/redis -j "$(nproc)"; \ + make -C /usr/src/redis install; \ + \ +# TODO https://github.com/antirez/redis/pull/3494 (deduplicate "redis-server" copies) + serverMd5="$(md5sum /usr/local/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ + find /usr/local/bin/redis* -maxdepth 0 \ + -type f -not -name redis-server \ + -exec sh -eux -c ' \ + md5="$(md5sum "$1" | cut -d" " -f1)"; \ + test "$md5" = "$serverMd5"; \ + ' -- '{}' ';' \ + -exec ln -svfT 'redis-server' '{}' ';' \ + ; \ + \ + rm -r /usr/src/redis; \ + \ + apt-mark auto '.*' > /dev/null; \ + [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ + apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ + \ + redis-cli --version; \ + redis-server --version + +RUN mkdir /data && chown redis:redis /data +VOLUME /data +WORKDIR /data + +COPY docker-entrypoint.sh /usr/local/bin/ +ENTRYPOINT ["docker-entrypoint.sh"] + +EXPOSE 6379 +CMD ["redis-server"] diff --git a/old-protected-mode-sed.template b/old-protected-mode-sed.template new file mode 100644 index 000000000..418b07a99 --- /dev/null +++ b/old-protected-mode-sed.template @@ -0,0 +1,4 @@ +# this changes in Redis 6.0+: https://github.com/docker-library/redis/pull/212#issuecomment-567705694 (see "update.sh" for where this template gets injected) + grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 1$' /usr/src/redis/src/server.h; \ + sed -ri 's!^(#define CONFIG_DEFAULT_PROTECTED_MODE) 1$!\1 0!' /usr/src/redis/src/server.h; \ + grep -q '^#define CONFIG_DEFAULT_PROTECTED_MODE 0$' /usr/src/redis/src/server.h; \ diff --git a/update.sh b/update.sh index 339509d06..b233d270a 100755 --- a/update.sh +++ b/update.sh @@ -1,5 +1,5 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -Eeuo pipefail cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" @@ -11,7 +11,8 @@ versions=( "${versions[@]%/}" ) packagesUrl='https://raw.githubusercontent.com/antirez/redis-hashes/master/README' packages="$(echo "$packagesUrl" | sed -r 's/[^a-zA-Z.-]+/-/g')" -curl -fsSL "$packagesUrl" > "$packages" +trap "$(printf 'rm -f %q' "$packages")" EXIT +curl -fsSL "$packagesUrl" -o "$packages" travisEnv= for version in "${versions[@]}"; do @@ -47,23 +48,38 @@ for version in "${versions[@]}"; do fi [ "$shaType" = 'sha256' ] || [ "$shaType" = 'sha1' ] - ( - set -x - sed -ri \ + echo "$version: $fullVersion" + + for variant in \ + alpine 32bit '' \ + ; do + dir="$version${variant:+/$variant}" + [ -d "$dir" ] || continue + template="Dockerfile${variant:+-$variant}.template" + + sed -r \ -e 's/^(ENV REDIS_VERSION) .*/\1 '"$fullVersion"'/' \ -e 's!^(ENV REDIS_DOWNLOAD_URL) .*!\1 '"$downloadUrl"'!' \ -e 's/^(ENV REDIS_DOWNLOAD_SHA) .*/\1 '"$shaHash"'/' \ -e 's!sha[0-9]+sum!'"$shaType"'sum!g' \ - "$version"/{,*/}Dockerfile - ) - for variant in alpine 32bit; do - [ -d "$version/$variant" ] || continue + "$template" > "$dir/Dockerfile" + + case "$version" in + 4.0 | 5.0) + gawk -i inplace ' + $1 == "####" { ia = 0 } + !ia { print } + $1 == "####" { ia = 1; ac = 0 } + ia { ac++ } + ia && ac == 1 { system("grep -vE \"^#\" old-protected-mode-sed.template") } + ' "$dir/Dockerfile" + ;; + esac + sed -ri -e '/protected-mode-sed/d' "$dir/Dockerfile" + travisEnv='\n - VERSION='"$version VARIANT=$variant$travisEnv" done - travisEnv='\n - VERSION='"$version VARIANT=$travisEnv" done travis="$(awk -v 'RS=\n\n' '$1 == "env:" { $0 = "env:'"$travisEnv"'" } { printf "%s%s", $0, RS }' .travis.yml)" echo "$travis" > .travis.yml - -rm "$packages"