diff --git a/Dockerfile b/Dockerfile index cafda1b..6bb6f52 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,19 +4,19 @@ FROM redis@sha256:e422889e156ebea83856b6ff973bfe0c86bce867d80def228044eeecf92559 LABEL maintainer="Johan Andersson " # Some Environment Variables -ENV HOME /root -ENV DEBIAN_FRONTEND noninteractive +ENV HOME=/root +ENV DEBIAN_FRONTEND=noninteractive # Install system dependencies RUN apt-get update -qq && \ apt-get install --no-install-recommends -yqq \ - net-tools supervisor ruby rubygems locales gettext-base wget gcc make g++ build-essential libc6-dev tcl && \ + net-tools supervisor ruby rubygems locales locales-all gettext-base wget gcc make g++ build-essential libc6-dev tcl && \ apt-get clean -yqq # # Ensure UTF-8 lang and locale +ENV LANG=en_US.UTF-8 +ENV LC_ALL=en_US.UTF-8 RUN locale-gen en_US.UTF-8 -ENV LANG en_US.UTF-8 -ENV LC_ALL en_US.UTF-8 # Necessary for gem installs due to SHA1 being weak and old cert being revoked ENV SSL_CERT_FILE=/usr/local/etc/openssl/cert.pem diff --git a/README.md b/README.md index 3dcea6a..b51033a 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,38 @@ Unfortunately Docker does not handle IPv6 NAT so, when acceptable, `--network ho # Example using plain docker docker run -e "IP=::1" -e "BIND_ADDRESS=::" --network host grokzen/redis-cluster:latest +## Enable authentication +By default, authentication using a password is disabled. +This is configurable by an enviroment variable that specifies which a password string is required to authenticate itself using the AUTH command. + +| Environment variable | Default | +| -------------------- | ------------------------------------------ | +| `PASSWORD` | "" (requirepass/masterauth not configured) | + +## Announced hostname +By default, no announced hostname is set. +This is configurable by an enviroment variable that specifies which show hostname as additional metadata in the CLUSTER SLOTS command. This valus is communicated along the clusterbus to all nodes, setting it to an empty string will remove the hostname and also propagate the removal. + +| Environment variable | Default | +| -------------------- | ------------------------------------------ | +| `CLUSTER_ANNOUNCE_HOSTNAME` | "" (empty announced hostname) | + +## Protected mode +By default, Protected mode is enabled. +This is configurable by an enviroment variable that specifies which the system administator can still ignore the error given by Redis and just disable protected mode or manually bind all the interfaces. + +| Environment variable | Default | +| -------------------- | ------------------------------------------ | +| `PROTECTED_MODE` | "" (protected-mode is yes) | + +## Clean redis-data before start redis +By default, All file in folder redis-data will be remove before start redis. +This is configurable by an enviroment variable that specifies which the system administator can handle remove/keep all file in redis-data before start redis. + +| Environment variable | Default | +| -------------------- | ------------------------------------------ | +| `RESET_DATA` | "" (redis-data will be clean) | + ## Build alternative redis versions diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 0b2e67f..696be88 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -42,24 +42,51 @@ if [ "$1" = 'redis-cluster' ]; then for port in $(seq $INITIAL_PORT $max_port); do mkdir -p /redis-conf/${port} mkdir -p /redis-data/${port} - - if [ -e /redis-data/${port}/nodes.conf ]; then - rm /redis-data/${port}/nodes.conf + if [ -n "$RESET_DATA" -a "$RESET_DATA" = "false" ]; then + if [ ! -e /redis-data/${port}/nodes.conf ]; then + RESET_DATA="true" + fi fi + done - if [ -e /redis-data/${port}/dump.rdb ]; then - rm /redis-data/${port}/dump.rdb + for port in $(seq $INITIAL_PORT $max_port); do + if [ -z "$RESET_DATA" -o "$RESET_DATA" = "true" ]; then + if [ -e /redis-data/${port}/nodes.conf ]; then + rm /redis-data/${port}/nodes.conf + fi + + if [ -e /redis-data/${port}/dump.rdb ]; then + rm /redis-data/${port}/dump.rdb + fi + + if [ -e /redis-data/${port}/appendonly.aof ]; then + rm /redis-data/${port}/appendonly.aof + fi fi + if [ -z "$PROTECTED_MODE" -o "$PROTECTED_MODE" = "true" ]; then + protectedmode="protected-mode yes" + elif [ "$PROTECTED_MODE" = "false" ]; then + protectedmode="protected-mode no" + fi + - if [ -e /redis-data/${port}/appendonly.aof ]; then - rm /redis-data/${port}/appendonly.aof + if [ -n "$CLUSTER_ANNOUNCE_HOSTNAME" ]; then + clusterannouncehostname="cluster-announce-hostname '${CLUSTER_ANNOUNCE_HOSTNAME}'" + clusterpreferedendpointtype="cluster-preferred-endpoint-type hostname" fi if [ "$port" -lt "$first_standalone" ]; then - PORT=${port} BIND_ADDRESS=${BIND_ADDRESS} envsubst < /redis-conf/redis-cluster.tmpl > /redis-conf/${port}/redis.conf + if [ -n "$PASSWORD" ]; then + requirepass="requirepass '${PASSWORD}'" + masterauth="masterauth '${PASSWORD}'" + fi + PORT=${port} BIND_ADDRESS=${BIND_ADDRESS} REQUIREPASS=${requirepass} MASTERAUTH=${masterauth} PROTECTED_MODE=${protectedmode} CLUSTER_ANNOUNCE_HOSTNAME=${clusterannouncehostname} CLUSTER_PREFERED_ENDPOINT_TYPE=${clusterpreferedendpointtype} envsubst < /redis-conf/redis-cluster.tmpl > /redis-conf/${port}/redis.conf nodes="$nodes $IP:$port" else - PORT=${port} BIND_ADDRESS=${BIND_ADDRESS} envsubst < /redis-conf/redis.tmpl > /redis-conf/${port}/redis.conf + if [ -n "$PASSWORD" ]; then + requirepass="requirepass '${PASSWORD}'" + fi + PORT=${port} BIND_ADDRESS=${BIND_ADDRESS} REQUIREPASS=${requirepass} PROTECTED_MODE=${protectedmode} envsubst < /redis-conf/redis.tmpl > /redis-conf/${port}/redis.conf fi if [ "$port" -lt $(($INITIAL_PORT + $MASTERS)) ]; then @@ -80,21 +107,27 @@ if [ "$1" = 'redis-cluster' ]; then ## Check the version of redis-cli and if we run on a redis server below 5.0 ## If it is below 5.0 then we use the redis-trib.rb to build the cluster # - /redis/src/redis-cli --version | grep -E "redis-cli 3.0|redis-cli 3.2|redis-cli 4.0" - - if [ $? -eq 0 ] - then - echo "Using old redis-trib.rb to create the cluster" - echo "yes" | eval ruby /redis/src/redis-trib.rb create --replicas "$SLAVES_PER_MASTER" "$nodes" - else - echo "Using redis-cli to create the cluster" - echo "yes" | eval /redis/src/redis-cli --cluster create --cluster-replicas "$SLAVES_PER_MASTER" "$nodes" - fi + if [ -z "$RESET_DATA" -o "$RESET_DATA" = "true" ]; then + /redis/src/redis-cli --version | grep -E "redis-cli 3.0|redis-cli 3.2|redis-cli 4.0" + if [ $? -eq 0 ] + then + echo "Using old redis-trib.rb to create the cluster" + echo "yes" | eval ruby /redis/src/redis-trib.rb create --replicas "$SLAVES_PER_MASTER" "$nodes" + else + echo "Using redis-cli to create the cluster" + if [ -z "$PASSWORD" ]; then + echo "yes" | eval /redis/src/redis-cli --cluster create --cluster-replicas "$SLAVES_PER_MASTER" "$nodes" + password_arg="-a $PASSWORD" + else + echo "yes" | eval /redis/src/redis-cli --cluster create --cluster-replicas "$SLAVES_PER_MASTER" -a "$PASSWORD" "$nodes" + fi + fi - if [ "$SENTINEL" = "true" ]; then - for port in $(seq $INITIAL_PORT $(($INITIAL_PORT + $MASTERS))); do - redis-sentinel /redis-conf/sentinel-${port}.conf & - done + if [ "$SENTINEL" = "true" ]; then + for port in $(seq $INITIAL_PORT $(($INITIAL_PORT + $MASTERS))); do + redis-sentinel /redis-conf/sentinel-${port}.conf & + done + fi fi tail -f /var/log/supervisor/redis*.log diff --git a/redis-cluster.tmpl b/redis-cluster.tmpl index ebc9ce7..6dc58a4 100644 --- a/redis-cluster.tmpl +++ b/redis-cluster.tmpl @@ -5,4 +5,8 @@ cluster-config-file nodes.conf cluster-node-timeout 5000 appendonly yes dir /redis-data/${PORT} -protected-mode no +${REQUIREPASS} +${MASTERAUTH} +${PROTECTED_MODE} +${CLUSTER_ANNOUNCE_HOSTNAME} +${CLUSTER_PREFERED_ENDPOINT_TYPE} \ No newline at end of file diff --git a/redis.tmpl b/redis.tmpl index 2081848..64628f6 100644 --- a/redis.tmpl +++ b/redis.tmpl @@ -2,4 +2,5 @@ bind ${BIND_ADDRESS} port ${PORT} appendonly yes dir /redis-data/${PORT} -protected-mode no +${REQUIREPASS} +${PROTECTED_MODE} \ No newline at end of file