diff --git a/Dockerfile b/Dockerfile index 23c66ab..adef175 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# Ver: 1.2 by Endial Fang (endial@126.com) +# Ver: 1.3 by Endial Fang (endial@126.com) # # 预处理 ========================================================================= @@ -10,7 +10,8 @@ ARG apt_source=default # 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" -WORKDIR /usr/local +ENV APP_NAME=redis \ + APP_VERSION=6.0.8 RUN select_source ${apt_source}; #RUN install_pkg xz-utils @@ -26,25 +27,27 @@ RUN set -eux; \ download_pkg unpack ${appName} "${appUrls}"; \ chmod +x /usr/local/wait-for-port-1.0.0-1-linux-amd64-debian-10/files/common/bin/wait-for-port; +# 下载并解压软件包 RUN set -eux; \ - appVersion=6.0.8; \ - appName="redis-${appVersion}.tar.gz"; \ + appName="${APP_NAME}-${APP_VERSION}.tar.gz"; \ sha256="04fa1fddc39bd1aecb6739dd5dd73858a3515b427acd1e2947a66dadce868d68"; \ - [ ! -z ${local_url} ] && localURL=${local_url}/redis; \ + [ ! -z ${local_url} ] && localURL=${local_url}/${APP_NAME}; \ appUrls="${localURL:-} \ http://download.redis.io/releases \ "; \ - download_pkg unpack ${appName} "${appUrls}" -s "${sha256}"; \ - mkdir -p /usr/local/redis; \ - cd /usr/local/redis-${appVersion}; \ + download_pkg unpack ${appName} "${appUrls}" -s "${sha256}"; + +# 源码编译: 编译后将配置文件模板拷贝至 /usr/local/${APP_NAME}/share/${APP_NAME} 中 +RUN set -eux; \ + APP_SRC="/usr/local/${APP_NAME}-${APP_VERSION}"; \ + cd ${APP_SRC}; \ # 禁用安全保护模式,在 Docker 中运行时不需要 - grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/local/redis-${appVersion}/src/config.c; \ - sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/local/redis-${appVersion}/src/config.c; \ - grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/local/redis-${appVersion}/src/config.c; \ - make BUILD_TLS=yes MALLOC=libc \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.c; \ + sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.c; \ + make MALLOC=libc BUILD_TLS=yes \ -j "$(nproc)" all; \ - make PREFIX=/usr/local/redis install; \ - \ + make PREFIX=/usr/local/${APP_NAME} install; \ # 删除重复的应用程序,并生成对应的连接 serverMd5="$(md5sum /usr/local/redis/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ find /usr/local/redis/bin/redis* -maxdepth 0 \ @@ -55,8 +58,19 @@ RUN set -eux; \ ' -- '{}' ';' \ -exec ln -svfT 'redis-server' '{}' ';' ; +# 删除编译生成的多余文件 +RUN set -eux; \ + find /usr/local -name '*.a' -delete; \ + rm -rf /usr/local/${APP_NAME}/include; -#find /usr/local/redis/bin -type f -executable -exec ldd '{}' ';' | awk '/=>/ { print $(NF-1) }' | sort -u | xargs -r dpkg-query --search | cut -d: -f1 | sort -u +# 检测并生成依赖文件记录 +RUN set -eux; \ + find /usr/local/${APP_NAME} -type f -executable -exec ldd '{}' ';' | \ + awk '/=>/ { print $(NF-1) }' | \ + sort -u | \ + xargs -r dpkg-query --search | \ + cut -d: -f1 | \ + sort -u >/usr/local/${APP_NAME}/runDeps; # 镜像生成 ======================================================================== FROM colovu/debian:10 @@ -70,17 +84,10 @@ ENV APP_NAME=redis \ APP_VERSION=6.0.8 ENV APP_HOME_DIR=/usr/local/${APP_NAME} \ - APP_DEF_DIR=/etc/${APP_NAME} \ - APP_CONF_DIR=/srv/conf/${APP_NAME} \ - APP_DATA_DIR=/srv/data/${APP_NAME} \ - APP_DATA_LOG_DIR=/srv/datalog/${APP_NAME} \ - APP_CACHE_DIR=/var/cache/${APP_NAME} \ - APP_RUN_DIR=/var/run/${APP_NAME} \ - APP_LOG_DIR=/var/log/${APP_NAME} \ - APP_CERT_DIR=/srv/cert/${APP_NAME} + APP_DEF_DIR=/etc/${APP_NAME} -ENV \ - PATH="${APP_HOME_DIR}/bin:${PATH}" +ENV PATH="${APP_HOME_DIR}/bin:${PATH}" \ + LD_LIBRARY_PATH="${APP_HOME_DIR}/lib" LABEL \ "Version"="v${APP_VERSION}" \ @@ -88,18 +95,19 @@ LABEL \ "Dockerfile"="https://github.com/colovu/docker-${APP_NAME}" \ "Vendor"="Endial Fang (endial@126.com)" -COPY customer / - -# 以包管理方式安装软件包(Optional) +# 选择软件包源 RUN select_source ${apt_source} -RUN install_pkg libssl1.1 +COPY customer / RUN create_user && prepare_env # 从预处理过程中拷贝软件包(Optional) COPY --from=builder /usr/local/wait-for-port-1.0.0-1-linux-amd64-debian-10/files/common/bin/ /usr/local/bin/ -COPY --from=builder /usr/local/redis /usr/local/redis -COPY --from=builder /usr/local/redis-${APP_VERSION}/*.conf ${APP_DEF_DIR}/ +COPY --from=builder /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} +COPY --from=builder /usr/local/${APP_NAME}-${APP_VERSION}/*.conf /etc/${APP_NAME}/ + +# 安装依赖的软件包及库(Optional) +RUN install_pkg `cat /usr/local/${APP_NAME}/runDeps`; # 执行预处理脚本,并验证安装的软件包 RUN set -eux; \ @@ -107,7 +115,7 @@ RUN set -eux; \ [ -e "${override_file}" ] && /bin/bash "${override_file}"; \ gosu ${APP_USER} redis-cli --version; \ gosu ${APP_USER} redis-server --version; \ - :; + gosu --version; # 默认提供的数据卷 VOLUME ["/srv/conf", "/srv/data", "/srv/datalog", "/srv/cert", "/var/log"] diff --git a/Makefile b/Makefile index e499415..626d12b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# Ver: 1.4 by Endial Fang (endial@126.com) +# Ver: 1.6 by Endial Fang (endial@126.com) # # 当前 Docker 镜像的编译脚本 @@ -8,14 +8,14 @@ app_name :=colovu/redis # <镜像名>:<分支名>- # Git 仓库且无文件修改直接编译 # <镜像名>:<分支名>-<年月日>-<时分秒> # Git 仓库有文件修改后的编译 # <镜像名>:latest-<年月日>-<时分秒> # 非 Git 仓库编译 -current_subversion:=$(shell if [[ -d .git ]]; then git rev-parse --short HEAD; else date +%y%m%d-%H%M%S; fi) -current_tag:=$(shell if [[ -d .git ]]; then git rev-parse --abbrev-ref HEAD | sed -e 's/master/latest/'; else echo "latest"; fi)-$(current_subversion) +current_subversion:=$(shell if [ ! `git status >/dev/null 2>&1` ]; then git rev-parse --short HEAD; else date +%y%m%d-%H%M%S; fi) +current_tag:=local-$(shell if [ ! `git status >/dev/null 2>&1` ]; then git rev-parse --abbrev-ref HEAD | sed -e 's/master/latest/'; else echo "latest"; fi)-$(current_subversion) # Sources List: default / tencent / ustc / aliyun / huawei build-arg:=--build-arg apt_source=tencent # 设置本地下载服务器路径,加速调试时的本地编译速度 -local_ip:=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $$2}'|tr -d "addr:"` +local_ip:=`echo "en0 eth0" |xargs -n1 ip addr show 2>/dev/null|grep inet|grep -v 127.0.0.1|grep -v inet6|tr "/" " "|awk '{print $$2}'` build-arg+=--build-arg local_url=http://$(local_ip)/dist-files .PHONY: build build-debian build-alpine clean clearclean upgrade @@ -26,14 +26,14 @@ build: build-alpine build-debian build-debian: @echo "Build $(app_name):$(current_tag)" @docker build --force-rm $(build-arg) -t $(app_name):$(current_tag) . - @echo "Add tag: $(app_name):latest" - @docker tag $(app_name):$(current_tag) $(app_name):latest + @echo "Add tag: $(app_name):local-latest" + @docker tag $(app_name):$(current_tag) $(app_name):local-latest build-alpine: @echo "Build $(app_name):$(current_tag)-alpine" @docker build --force-rm $(build-arg) -t $(app_name):$(current_tag)-alpine ./alpine - @echo "Add tag: $(app_name):latest-alpine" - @docker tag $(app_name):$(current_tag)-alpine $(app_name):latest-alpine + @echo "Add tag: $(app_name):local-latest-alpine" + @docker tag $(app_name):$(current_tag)-alpine $(app_name):local-latest-alpine # 清理悬空的镜像(无TAG)及停止的容器 clearclean: clean diff --git a/alpine/Dockerfile b/alpine/Dockerfile index 6ca392e..3bc645e 100644 --- a/alpine/Dockerfile +++ b/alpine/Dockerfile @@ -1,4 +1,4 @@ -# Ver: 1.2 by Endial Fang (endial@126.com) +# Ver: 1.3 by Endial Fang (endial@126.com) # # 预处理 ========================================================================= @@ -10,7 +10,8 @@ ARG apt_source=default # 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" -WORKDIR /usr/local +ENV APP_NAME=redis \ + APP_VERSION=6.0.8 RUN select_source ${apt_source}; #RUN install_pkg xz-utils @@ -26,25 +27,27 @@ RUN set -eux; \ download_pkg unpack ${appName} "${appUrls}"; \ chmod +x /usr/local/wait-for-port-1.0.0-1-linux-amd64-debian-10/files/common/bin/wait-for-port; +# 下载并解压软件包 RUN set -eux; \ - appVersion=6.0.8; \ - appName="redis-${appVersion}.tar.gz"; \ + appName="${APP_NAME}-${APP_VERSION}.tar.gz"; \ sha256="04fa1fddc39bd1aecb6739dd5dd73858a3515b427acd1e2947a66dadce868d68"; \ - [ ! -z ${local_url} ] && localURL=${local_url}/redis; \ + [ ! -z ${local_url} ] && localURL=${local_url}/${APP_NAME}; \ appUrls="${localURL:-} \ http://download.redis.io/releases \ "; \ - download_pkg unpack ${appName} "${appUrls}" -s "${sha256}"; \ - mkdir -p /usr/local/redis; \ - cd /usr/local/redis-${appVersion}; \ + download_pkg unpack ${appName} "${appUrls}" -s "${sha256}"; + +# 源码编译: 编译后将配置文件模板拷贝至 /usr/local/${APP_NAME}/share/${APP_NAME} 中 +RUN set -eux; \ + APP_SRC="/usr/local/${APP_NAME}-${APP_VERSION}"; \ + cd ${APP_SRC}; \ # 禁用安全保护模式,在 Docker 中运行时不需要 - grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' /usr/local/redis-${appVersion}/src/config.c; \ - sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' /usr/local/redis-${appVersion}/src/config.c; \ - grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' /usr/local/redis-${appVersion}/src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *1 *,.*[)],$' ./src/config.c; \ + sed -ri 's!^( *createBoolConfig[(]"protected-mode",.*, *)1( *,.*[)],)$!\10\2!' ./src/config.c; \ + grep -E '^ *createBoolConfig[(]"protected-mode",.*, *0 *,.*[)],$' ./src/config.c; \ make MALLOC=libc BUILD_TLS=yes \ -j "$(nproc)" all; \ - make PREFIX=/usr/local/redis install; \ - \ + make PREFIX=/usr/local/${APP_NAME} install; \ # 删除重复的应用程序,并生成对应的连接 serverMd5="$(md5sum /usr/local/redis/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \ find /usr/local/redis/bin/redis* -maxdepth 0 \ @@ -55,9 +58,18 @@ RUN set -eux; \ ' -- '{}' ';' \ -exec ln -svfT 'redis-server' '{}' ';' ; +# 删除编译生成的多余文件 +RUN set -eux; \ + find /usr/local -name '*.a' -delete; \ + rm -rf /usr/local/${APP_NAME}/include; - -#find /usr/local/redis/bin -type f -executable -exec ldd '{}' ';' | awk '/=>/ { print $(NF-1) }' | sort -u | xargs -r dpkg-query --search | cut -d: -f1 | sort -u +# 检测并生成依赖文件记录 +RUN set -eux; \ + scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/${APP_NAME} | \ + tr ',' '\n' | \ + sort -u | \ + awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } \ + { print "so:" $1 }' >/usr/local/${APP_NAME}/runDeps; # 镜像生成 ======================================================================== FROM colovu/alpine:3.12 @@ -71,17 +83,10 @@ ENV APP_NAME=redis \ APP_VERSION=6.0.8 ENV APP_HOME_DIR=/usr/local/${APP_NAME} \ - APP_DEF_DIR=/etc/${APP_NAME} \ - APP_CONF_DIR=/srv/conf/${APP_NAME} \ - APP_DATA_DIR=/srv/data/${APP_NAME} \ - APP_DATA_LOG_DIR=/srv/datalog/${APP_NAME} \ - APP_CACHE_DIR=/var/cache/${APP_NAME} \ - APP_RUN_DIR=/var/run/${APP_NAME} \ - APP_LOG_DIR=/var/log/${APP_NAME} \ - APP_CERT_DIR=/srv/cert/${APP_NAME} + APP_DEF_DIR=/etc/${APP_NAME} -ENV \ - PATH="${APP_HOME_DIR}/bin:${PATH}" +ENV PATH="${APP_HOME_DIR}/bin:${PATH}" \ + LD_LIBRARY_PATH="${APP_HOME_DIR}/lib" LABEL \ "Version"="v${APP_VERSION}" \ @@ -89,18 +94,19 @@ LABEL \ "Dockerfile"="https://github.com/colovu/docker-${APP_NAME}" \ "Vendor"="Endial Fang (endial@126.com)" -COPY customer / - -# 以包管理方式安装软件包(Optional) +# 选择软件包源 RUN select_source ${apt_source} -#RUN install_pkg libssl1.1 +COPY customer / RUN create_user && prepare_env # 从预处理过程中拷贝软件包(Optional) COPY --from=builder /usr/local/wait-for-port-1.0.0-1-linux-amd64-debian-10/files/common/bin/ /usr/local/bin/ -COPY --from=builder /usr/local/redis /usr/local/redis -COPY --from=builder /usr/local/redis-${APP_VERSION}/*.conf ${APP_DEF_DIR}/ +COPY --from=builder /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} +COPY --from=builder /usr/local/${APP_NAME}-${APP_VERSION}/*.conf /etc/${APP_NAME}/ + +# 安装依赖的软件包及库(Optional) +RUN install_pkg `cat /usr/local/${APP_NAME}/runDeps`; # 执行预处理脚本,并验证安装的软件包 RUN set -eux; \ @@ -108,7 +114,7 @@ RUN set -eux; \ [ -e "${override_file}" ] && /bin/bash "${override_file}"; \ gosu ${APP_USER} redis-cli --version; \ gosu ${APP_USER} redis-server --version; \ - :; + gosu --version; # 默认提供的数据卷 VOLUME ["/srv/conf", "/srv/data", "/srv/datalog", "/srv/cert", "/var/log"] diff --git a/alpine/customer/usr/local/bin/comm-env.sh b/alpine/customer/usr/local/bin/comm-env.sh new file mode 100644 index 0000000..1b77484 --- /dev/null +++ b/alpine/customer/usr/local/bin/comm-env.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Ver: 1.0 by Endial Fang (endial@126.com) +# +# 应用环境变量定义及初始化 + +# 通用设置 +export ENV_DEBUG=${ENV_DEBUG:-false} +export ALLOW_ANONYMOUS_LOGIN="${ALLOW_ANONYMOUS_LOGIN:-no}" + +# 通过读取变量名对应的 *_FILE 文件,获取变量值;如果对应文件存在,则通过传入参数设置的变量值会被文件中对应的值覆盖 +# 变量优先级: *_FILE > 传入变量 > 默认值 +redis_env_file_lists=( + REDIS_PASSWORD + REDIS_MASTER_PASSWORD +) +for env_var in "${redis_env_file_lists[@]}"; do + file_env_var="${env_var}_FILE" + if [[ -n "${!file_env_var:-}" ]]; then + export "${env_var}=$(< "${!file_env_var}")" + unset "${file_env_var}" + fi +done +unset redis_env_file_lists + +# 应用路径参数 +export APP_HOME_DIR="/usr/local/${APP_NAME}" +export APP_DEF_DIR="/etc/${APP_NAME}" +export APP_CONF_DIR="/srv/conf/${APP_NAME}" +export APP_DATA_DIR="/srv/data/${APP_NAME}" +export APP_DATA_LOG_DIR="/srv/datalog/${APP_NAME}" +export APP_CACHE_DIR="/var/cache/${APP_NAME}" +export APP_RUN_DIR="/var/run/${APP_NAME}" +export APP_LOG_DIR="/var/log/${APP_NAME}" +export APP_CERT_DIR="/srv/cert/${APP_NAME}" + +# Paths +export REDIS_CONF_FILE="${APP_CONF_DIR}/redis.conf" +export REDIS_SENTINEL_FILE="${APP_CONF_DIR}/sentinel.conf" +export REDIS_PID_FILE="${APP_RUN_DIR}/redis.pid" + +# Redis settings +export REDIS_PORT="${REDIS_PORT:-6379}" +export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" +export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" + +# Cluster configuration +export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}" +export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-}" +export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}" + +export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" +export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" +export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" +export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" + +# Redis TLS Settings +export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" +export REDIS_TLS_PORT="${REDIS_TLS_PORT:-6379}" +export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" +export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" +export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" +export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" +export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" + +# Authentication +export REDIS_PASSWORD="${REDIS_PASSWORD:-}" + +# 应用配置参数 + +# 内部变量 + +# 个性化变量 +# 如果设置了用户密码,设置环境变量 REDISCLI_AUTH,用于 `redis-cli` 登录时使用;不显示输入,保证安全 +if [[ -n "${REDIS_PASSWORD}" ]]; then + export REDISCLI_AUTH="${REDIS_PASSWORD:-}" +fi diff --git a/alpine/customer/usr/local/bin/appcommon.sh b/alpine/customer/usr/local/bin/comm-redis.sh similarity index 82% rename from alpine/customer/usr/local/bin/appcommon.sh rename to alpine/customer/usr/local/bin/comm-redis.sh index 14cc856..281b5fe 100644 --- a/alpine/customer/usr/local/bin/appcommon.sh +++ b/alpine/customer/usr/local/bin/comm-redis.sh @@ -9,78 +9,22 @@ . /usr/local/scripts/libfile.sh . /usr/local/scripts/libfs.sh . /usr/local/scripts/libos.sh +. /usr/local/scripts/libnet.sh . /usr/local/scripts/libservice.sh . /usr/local/scripts/libvalidations.sh # 函数列表 -# 加载应用使用的环境变量初始值,该函数在相关脚本中以 eval 方式调用 -# 全局变量: -# ENV_* : 容器使用的全局变量 -# APP_* : 在镜像创建时定义的全局变量 -# *_* : 应用配置文件使用的全局变量,变量名根据配置项定义 -# 返回值: -# 可以被 'eval' 使用的序列化输出 -app_env() { - cat <<-'EOF' -# Common Settings -export ENV_DEBUG=${ENV_DEBUG:-false} -export ALLOW_ANONYMOUS_LOGIN="${ALLOW_ANONYMOUS_LOGIN:-no}" - -# Paths -export REDIS_CONF_FILE="${APP_CONF_DIR}/redis.conf" -export REDIS_SENTINEL_FILE="${APP_CONF_DIR}/sentinel.conf" -export REDIS_PID_FILE="${APP_RUN_DIR}/redis.pid" - -# Users - -# Redis settings -export REDIS_PORT="${REDIS_PORT:-6379}" -export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" -export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" - -# Cluster configuration -export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}" -export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-}" -export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}" - -export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" -export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" -export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" -export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" - -# Redis TLS Settings -export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" -export REDIS_TLS_PORT="${REDIS_TLS_PORT:-6379}" -export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" -export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" -export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" -export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" -export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" - -# Authentication -export REDIS_PASSWORD="${REDIS_PASSWORD:-}" -EOF - - # 利用 *_FILE 设置密码,不在配置命令中设置密码,增强安全性 - if [[ -f "${REDIS_PASSWORD_FILE:-}" ]]; then - cat <<"EOF" -export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" -EOF - fi - - if [[ -f "${REDIS_MASTER_PASSWORD_FILE:-}" ]]; then - cat <<"EOF" -export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" -EOF - fi - - # 如果设置了用户密码,设置环境变量 REDISCLI_AUTH,用于 `redis-cli` 登录时使用;不显示输入,保证安全 - if [[ -n "${REDIS_PASSWORD}" ]]; then - cat <<"EOF" -export REDISCLI_AUTH=${REDIS_PASSWORD} -EOF - fi +# 使用环境变量中以 "APP_CFG_" 开头的的全局变量更新配置文件中对应项(全小写,以"."分隔) +# 举例: +# APP_CFG_LOG_DIRS 对应配置文件中的配置项:log.dirs +redis_configure_from_env_variables() { + # Map environment variables to config properties + for var in "${!APP_CFG_@}"; do + key="$(echo "$var" | sed -e 's/^APP_CFG_//g' -e 's/_/\./g' | tr '[:upper:]' '[:lower:]')" + value="${!var}" + redis_conf_set "$key" "$value" + done } # 将变量配置更新至配置文件 @@ -248,7 +192,7 @@ redis_configure_replication() { REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} fi LOG_I "Waitting for Redis Master ready..." - wait-for-port --host "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" + redis_wait_service "${REDIS_MASTER_HOST}:${REDIS_MASTER_PORT_NUMBER}" [[ -n "$REDIS_MASTER_PASSWORD" ]] && redis_conf_set masterauth "$REDIS_MASTER_PASSWORD" # Starting with Redis 5, use 'replicaof' instead of 'slaveof'. Maintaining both for backward compatibility local parameter="replicaof" @@ -262,11 +206,10 @@ redis_configure_replication() { } # 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息 -app_verify_minimum_env() { +redis_verify_minimum_env() { local error_code=0 LOG_D "Validating settings in REDIS_* env vars..." - # Auxiliary functions print_validation_error() { LOG_E "$1" error_code=1 @@ -323,16 +266,57 @@ app_verify_minimum_env() { } # 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1) -app_enable_remote_connections() { +redis_enable_remote_connections() { LOG_D "Modify default config to enable all IP access" redis_conf_set daemonize no redis_conf_set bind 0.0.0.0 # Allow remote connections } +# 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat' +# 参数: +# $1 - host:port +redis_wait_service() { + local serviceport=${1:?Missing server info} + local service=${serviceport%%:*} + local port=${serviceport#*:} + local retry_seconds=5 + local max_try=100 + let i=1 + + if [[ -z "$(which nc)" ]]; then + LOG_E "Nedd nc installed before, command: \"apt-get install netcat\"." + exit 1 + fi + + LOG_I "[0/${max_try}] check for ${service}:${port}..." + + set +e + nc -z ${service} ${port} + result=$? + + until [ $result -eq 0 ]; do + LOG_D " [$i/${max_try}] not available yet" + if (( $i == ${max_try} )); then + LOG_E "${service}:${port} is still not available; giving up after ${max_try} tries." + exit 1 + fi + + LOG_I "[$i/${max_try}] try in ${retry_seconds}s once again ..." + let "i++" + sleep ${retry_seconds} + + nc -z ${service} ${port} + result=$? + done + + set -e + LOG_I "[$i/${max_try}] ${service}:${port} is available." +} + # 以后台方式启动应用服务,并等待启动就绪 -app_start_server_bg() { - is_app_server_running && return +redis_start_server_bg() { + redis_is_server_running && return LOG_I "Starting ${APP_NAME} in background..." @@ -343,7 +327,7 @@ app_start_server_bg() { fi local counter=3 - while ! is_app_server_running ; do + while ! redis_is_server_running ; do if [[ "$counter" -ne 0 ]]; then break fi @@ -359,8 +343,8 @@ app_start_server_bg() { } # 停止应用服务 -app_stop_server() { - is_app_server_running || return +redis_stop_server() { + redis_is_server_running || return local pass local port @@ -390,7 +374,7 @@ app_stop_server() { } # 检测应用服务是否在后台运行中 -is_app_server_running() { +redis_is_server_running() { LOG_D "Check if ${APP_NAME} is running..." local pid pid="$(get_pid_from_file "${REDIS_PID_FILE}")" @@ -403,13 +387,13 @@ is_app_server_running() { } # 清理初始化应用时生成的临时文件 -app_clean_tmp_file() { +redis_clean_tmp_file() { LOG_D "Clean ${APP_NAME} tmp files for init..." } # 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动) -app_clean_from_restart() { +redis_clean_from_restart() { LOG_D "Clean ${APP_NAME} tmp files for restart..." local -r -a files=( "${REDIS_PID_FILE}" @@ -425,8 +409,8 @@ app_clean_from_restart() { # 应用默认初始化操作 # 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件 -app_default_init() { - app_clean_from_restart +redis_default_init() { + redis_clean_from_restart LOG_D "Check init status of ${APP_NAME}..." # 检测配置文件是否存在 @@ -439,15 +423,17 @@ app_default_init() { redis_configure_replication fi - touch ${APP_CONF_DIR}/.app_init_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_CONF_DIR}/.app_init_flag + touch "${APP_CONF_DIR}/.app_init_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_CONF_DIR}/.app_init_flag" else LOG_I "User injected custom configuration detected!" fi if [[ ! -f "${APP_DATA_DIR}/.data_init_flag" ]]; then LOG_I "Deploying ${APP_NAME} from scratch..." - #app_start_server_bg + + # 启动后台服务 + #redis_start_server_bg touch ${APP_DATA_DIR}/.data_init_flag @@ -459,8 +445,8 @@ app_default_init() { # 用户自定义的前置初始化操作,依次执行目录 preinitdb.d 中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_preinit_flag -app_custom_preinit() { - LOG_D "Check custom pre-init status of ${APP_NAME}..." +redis_custom_preinit() { + LOG_I "Check custom pre-init status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/preinitdb.d" ]; then @@ -472,8 +458,8 @@ app_custom_preinit() { # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/preinitdb.d/" -type f -regex ".*\.\(sh\)" | sort | process_init_files - touch ${APP_DATA_DIR}/.custom_preinit_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_DATA_DIR}/.custom_preinit_flag + touch "${APP_DATA_DIR}/.custom_preinit_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_preinit_flag" LOG_I "Custom preinit for ${APP_NAME} complete." else LOG_I "Custom preinit for ${APP_NAME} already done before, skipping initialization." @@ -482,14 +468,14 @@ app_custom_preinit() { # 检测依赖的服务是否就绪 #for i in ${SERVICE_PRECONDITION[@]}; do - # app_wait_service "${i}" + # redis_wait_service "${i}" #done } # 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag -app_custom_init() { - LOG_D "Check custom init status of ${APP_NAME}..." +redis_custom_init() { + LOG_I "Check custom initdb status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then @@ -498,7 +484,8 @@ app_custom_init() { [[ ! -f "${APP_DATA_DIR}/.custom_init_flag" ]]; then LOG_I "Process custom init scripts from /srv/conf/${APP_NAME}/initdb.d..." - #app_start_server_bg + # 启动后台服务 + #redis_start_server_bg # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do @@ -510,12 +497,21 @@ app_custom_init() { LOG_D "Sourcing $f"; . "$f" fi ;; - *) LOG_D "Ignoring $f" ;; + *.sql) + LOG_D "Executing $f"; + postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" < "$f" + ;; + *.sql.gz) + LOG_D "Executing $f"; + gunzip -c "$f" | postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" + ;; + *) + LOG_D "Ignoring $f" ;; esac done - touch ${APP_DATA_DIR}/.custom_init_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_DATA_DIR}/.custom_init_flag + touch "${APP_DATA_DIR}/.custom_init_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_init_flag" LOG_I "Custom init for ${APP_NAME} complete." else LOG_I "Custom init for ${APP_NAME} already done before, skipping initialization." @@ -523,11 +519,12 @@ app_custom_init() { fi # 检测服务是否运行中;如果运行,则停止后台服务 - is_app_server_running && app_stop_server + redis_is_server_running && redis_stop_server # 删除第一次运行生成的临时文件 - app_clean_tmp_file + redis_clean_tmp_file # 绑定所有 IP ,启用远程访问 - app_enable_remote_connections + redis_enable_remote_connections } + diff --git a/alpine/customer/usr/local/bin/entry.sh b/alpine/customer/usr/local/bin/entry.sh index f3728ea..9c531c0 100755 --- a/alpine/customer/usr/local/bin/entry.sh +++ b/alpine/customer/usr/local/bin/entry.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 容器入口脚本 @@ -8,9 +8,10 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing entry.sh **" if ! is_sourced; then @@ -25,8 +26,8 @@ if ! is_sourced; then if [ "$1" = "${APP_EXEC}" ] && is_root; then /usr/local/bin/setup.sh - LOG_I "Restart with non-root user: ${APP_USER:-APP_NAME}\n" - exec gosu "${APP_USER:-APP_NAME}" "$0" "$@" + LOG_I "Restart with non-root user: ${APP_USER}\n" + exec gosu "${APP_USER}" "$0" "$@" fi [ "$1" = "${APP_EXEC}" ] && /usr/local/bin/init.sh diff --git a/alpine/customer/usr/local/bin/init.sh b/alpine/customer/usr/local/bin/init.sh index 727d9fa..1151b4f 100755 --- a/alpine/customer/usr/local/bin/init.sh +++ b/alpine/customer/usr/local/bin/init.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用初始化脚本 @@ -8,18 +8,21 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing init.sh **" +trap "${APP_NAME}_stop_server" EXIT + # 执行应用预初始化操作 -app_custom_preinit +${APP_NAME}_custom_preinit # 执行应用初始化操作 -app_default_init +${APP_NAME}_default_init # 执行用户自定义初始化脚本 -app_custom_init +${APP_NAME}_custom_init LOG_I "** Processing init.sh finished! **" diff --git a/alpine/customer/usr/local/bin/run.sh b/alpine/customer/usr/local/bin/run.sh index 73dc478..475b117 100755 --- a/alpine/customer/usr/local/bin/run.sh +++ b/alpine/customer/usr/local/bin/run.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用启动脚本 @@ -8,18 +8,20 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing run.sh **" flags=("${APP_CONF_FILE:-}") [[ -z "${APP_EXTRA_FLAGS:-}" ]] || flags=("${flags[@]}" "${APP_EXTRA_FLAGS[@]}") -START_COMMAND=("${APP_EXEC:-/bin/bash}" "${flags[@]}") +START_COMMAND=("${APP_EXEC:-/bin/bash}") LOG_I "** Starting ${APP_NAME} **" if is_root; then - exec gosu "${APP_USER:-APP_NAME}" tini -s -- "${START_COMMAND[@]}" + exec gosu "${APP_USER}" tini -s -- "${START_COMMAND[@]}" "${flags[@]}" else - exec tini -s -- "${START_COMMAND[@]}" + exec tini -s -- "${START_COMMAND[@]}" "${flags[@]}" fi + diff --git a/alpine/customer/usr/local/bin/setup.sh b/alpine/customer/usr/local/bin/setup.sh index ae59c47..ac154ca 100755 --- a/alpine/customer/usr/local/bin/setup.sh +++ b/alpine/customer/usr/local/bin/setup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用环境及依赖文件设置脚本 @@ -8,17 +8,19 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing setup.sh **" APP_DIRS="${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_DATA_LOG_DIR:-}" +LOG_I "Ensure directory exists: ${APP_DIRS}" for dir in ${APP_DIRS}; do ensure_dir_exists ${dir} done -app_verify_minimum_env +${APP_NAME}_verify_minimum_env # 检测指定文件是否在配置文件存储目录存在,如果不存在则拷贝(新挂载数据卷、手动删除都会导致不存在) LOG_I "Check config files in: ${APP_CONF_DIR}" @@ -26,6 +28,7 @@ if [[ ! -z "$(ls -A "${APP_DEF_DIR}")" ]]; then ensure_config_file_exist "${APP_DEF_DIR}" $(ls -A "${APP_DEF_DIR}") fi +LOG_I "Ensure directory ownership: ${APP_USER}" for dir in ${APP_DIRS}; do configure_permissions_ownership "$dir" -u "${APP_USER}" -g "${APP_USER}" done diff --git a/alpine/customer/usr/local/overrides/overrides-6.0.8.sh b/alpine/customer/usr/local/overrides/overrides-6.0.8.sh index 7861c99..e89e34b 100644 --- a/alpine/customer/usr/local/overrides/overrides-6.0.8.sh +++ b/alpine/customer/usr/local/overrides/overrides-6.0.8.sh @@ -1,4 +1,5 @@ #!/bin/bash -e +# Ver: 1.0 by Endial Fang (endial@126.com) # # 在安装完应用后,使用该脚本修改默认配置文件中部分配置项; 如果相应的配置项已经定义为容器环境变量,则不需要在这里修改 @@ -6,14 +7,14 @@ CONF_FILE="${APP_DEF_DIR}/redis.conf" echo "Process overrides for: ${CONF_FILE}" # 修改默认配置信息 -sed -i -E 's/^bind .*/bind 127.0.0.1/g' "${CONF_FILE}" -sed -i -E 's/^daemonize .*/daemonize yes/g' "${CONF_FILE}" -sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis.pid/g' "${CONF_FILE}" -sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis.log\"/g' "${CONF_FILE}" +sed -i -E 's/^#?bind .*/bind 127.0.0.1/g' "${CONF_FILE}" +sed -i -E 's/^#?daemonize .*/daemonize yes/g' "${CONF_FILE}" +sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis.pid/g' "${CONF_FILE}" +sed -i -E 's/^#?logfile .*/logfile \"\/var\/log\/redis\/redis.log\"/g' "${CONF_FILE}" SENTINEL_FILE="${APP_DEF_DIR}/sentinel.conf" echo "Process overrides for: ${SENTINEL_FILE}" # 修改 Sentinel 默认配置信息 -sed -i -E 's/^daemonize .*/daemonize yes/g' "${SENTINEL_FILE}" -sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "${SENTINEL_FILE}" -sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis-sentinel.log\"/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?daemonize .*/daemonize yes/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?logfile .*/logfile \"\/var\/log\/redis\/redis-sentinel.log\"/g' "${SENTINEL_FILE}" diff --git a/alpine/customer/usr/sbin/create_user b/alpine/customer/usr/sbin/create_user index c01a650..ff2dba0 100755 --- a/alpine/customer/usr/sbin/create_user +++ b/alpine/customer/usr/sbin/create_user @@ -2,7 +2,8 @@ # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux addgroup -g 998 -S ${APP_USER} -adduser -G ${APP_USER} -u 999 -s /usr/sbin/nologin -h ${APP_DATA_DIR} -D -S ${APP_USER} +#adduser -G ${APP_USER} -u 999 -s /bin/bash -h /srv/data/${APP_NAME} -D -S ${APP_USER} +adduser -G ${APP_USER} -u 999 -s /usr/sbin/nologin -h /srv/data/${APP_NAME} -D -S ${APP_USER} # 如果需要 sudo 权限,需要安装 su 软件包:apk add sudo #sed -i -e 's/^\sDefaults\s*secure_path\s*=/# Defaults secure_path=/' /etc/sudoers diff --git a/alpine/customer/usr/sbin/prepare_env b/alpine/customer/usr/sbin/prepare_env index cb7b34b..05ce3b1 100755 --- a/alpine/customer/usr/sbin/prepare_env +++ b/alpine/customer/usr/sbin/prepare_env @@ -2,7 +2,16 @@ # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux -APP_DIRS="${APP_DEF_DIR:-} ${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_DATA_LOG_DIR:-} ${APP_CACHE_DIR:-} ${APP_RUN_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_HOME_DIR:-}" +APP_DIRS=" \ + /usr/local/${APP_NAME} \ + /etc/${APP_NAME} \ + /srv/conf/${APP_NAME} \ + /srv/data/${APP_NAME} \ + /srv/datalog/${APP_NAME} \ + /var/cache/${APP_NAME} \ + /var/run/${APP_NAME} \ + /var/log/${APP_NAME} \ + /srv/cert/${APP_NAME}" mkdir -p ${APP_DIRS} chown -Rf ${APP_USER}:${APP_USER} ${APP_DIRS}; diff --git a/customer/usr/local/bin/comm-env.sh b/customer/usr/local/bin/comm-env.sh new file mode 100644 index 0000000..1b77484 --- /dev/null +++ b/customer/usr/local/bin/comm-env.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Ver: 1.0 by Endial Fang (endial@126.com) +# +# 应用环境变量定义及初始化 + +# 通用设置 +export ENV_DEBUG=${ENV_DEBUG:-false} +export ALLOW_ANONYMOUS_LOGIN="${ALLOW_ANONYMOUS_LOGIN:-no}" + +# 通过读取变量名对应的 *_FILE 文件,获取变量值;如果对应文件存在,则通过传入参数设置的变量值会被文件中对应的值覆盖 +# 变量优先级: *_FILE > 传入变量 > 默认值 +redis_env_file_lists=( + REDIS_PASSWORD + REDIS_MASTER_PASSWORD +) +for env_var in "${redis_env_file_lists[@]}"; do + file_env_var="${env_var}_FILE" + if [[ -n "${!file_env_var:-}" ]]; then + export "${env_var}=$(< "${!file_env_var}")" + unset "${file_env_var}" + fi +done +unset redis_env_file_lists + +# 应用路径参数 +export APP_HOME_DIR="/usr/local/${APP_NAME}" +export APP_DEF_DIR="/etc/${APP_NAME}" +export APP_CONF_DIR="/srv/conf/${APP_NAME}" +export APP_DATA_DIR="/srv/data/${APP_NAME}" +export APP_DATA_LOG_DIR="/srv/datalog/${APP_NAME}" +export APP_CACHE_DIR="/var/cache/${APP_NAME}" +export APP_RUN_DIR="/var/run/${APP_NAME}" +export APP_LOG_DIR="/var/log/${APP_NAME}" +export APP_CERT_DIR="/srv/cert/${APP_NAME}" + +# Paths +export REDIS_CONF_FILE="${APP_CONF_DIR}/redis.conf" +export REDIS_SENTINEL_FILE="${APP_CONF_DIR}/sentinel.conf" +export REDIS_PID_FILE="${APP_RUN_DIR}/redis.pid" + +# Redis settings +export REDIS_PORT="${REDIS_PORT:-6379}" +export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" +export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" + +# Cluster configuration +export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}" +export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-}" +export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}" + +export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" +export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" +export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" +export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" + +# Redis TLS Settings +export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" +export REDIS_TLS_PORT="${REDIS_TLS_PORT:-6379}" +export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" +export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" +export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" +export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" +export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" + +# Authentication +export REDIS_PASSWORD="${REDIS_PASSWORD:-}" + +# 应用配置参数 + +# 内部变量 + +# 个性化变量 +# 如果设置了用户密码,设置环境变量 REDISCLI_AUTH,用于 `redis-cli` 登录时使用;不显示输入,保证安全 +if [[ -n "${REDIS_PASSWORD}" ]]; then + export REDISCLI_AUTH="${REDIS_PASSWORD:-}" +fi diff --git a/customer/usr/local/bin/appcommon.sh b/customer/usr/local/bin/comm-redis.sh similarity index 82% rename from customer/usr/local/bin/appcommon.sh rename to customer/usr/local/bin/comm-redis.sh index 14cc856..281b5fe 100644 --- a/customer/usr/local/bin/appcommon.sh +++ b/customer/usr/local/bin/comm-redis.sh @@ -9,78 +9,22 @@ . /usr/local/scripts/libfile.sh . /usr/local/scripts/libfs.sh . /usr/local/scripts/libos.sh +. /usr/local/scripts/libnet.sh . /usr/local/scripts/libservice.sh . /usr/local/scripts/libvalidations.sh # 函数列表 -# 加载应用使用的环境变量初始值,该函数在相关脚本中以 eval 方式调用 -# 全局变量: -# ENV_* : 容器使用的全局变量 -# APP_* : 在镜像创建时定义的全局变量 -# *_* : 应用配置文件使用的全局变量,变量名根据配置项定义 -# 返回值: -# 可以被 'eval' 使用的序列化输出 -app_env() { - cat <<-'EOF' -# Common Settings -export ENV_DEBUG=${ENV_DEBUG:-false} -export ALLOW_ANONYMOUS_LOGIN="${ALLOW_ANONYMOUS_LOGIN:-no}" - -# Paths -export REDIS_CONF_FILE="${APP_CONF_DIR}/redis.conf" -export REDIS_SENTINEL_FILE="${APP_CONF_DIR}/sentinel.conf" -export REDIS_PID_FILE="${APP_RUN_DIR}/redis.pid" - -# Users - -# Redis settings -export REDIS_PORT="${REDIS_PORT:-6379}" -export REDIS_DISABLE_COMMANDS="${REDIS_DISABLE_COMMANDS:-}" -export REDIS_AOF_ENABLED="${REDIS_AOF_ENABLED:-yes}" - -# Cluster configuration -export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}" -export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-}" -export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}" - -export REDIS_MASTER_HOST="${REDIS_MASTER_HOST:-}" -export REDIS_MASTER_PORT_NUMBER="${REDIS_MASTER_PORT_NUMBER:-6379}" -export REDIS_MASTER_PASSWORD="${REDIS_MASTER_PASSWORD:-}" -export REDIS_REPLICATION_MODE="${REDIS_REPLICATION_MODE:-}" - -# Redis TLS Settings -export REDIS_TLS_ENABLED="${REDIS_TLS_ENABLED:-no}" -export REDIS_TLS_PORT="${REDIS_TLS_PORT:-6379}" -export REDIS_TLS_CERT_FILE="${REDIS_TLS_CERT_FILE:-}" -export REDIS_TLS_KEY_FILE="${REDIS_TLS_KEY_FILE:-}" -export REDIS_TLS_CA_FILE="${REDIS_TLS_CA_FILE:-}" -export REDIS_TLS_DH_PARAMS_FILE="${REDIS_TLS_DH_PARAMS_FILE:-}" -export REDIS_TLS_AUTH_CLIENTS="${REDIS_TLS_AUTH_CLIENTS:-yes}" - -# Authentication -export REDIS_PASSWORD="${REDIS_PASSWORD:-}" -EOF - - # 利用 *_FILE 设置密码,不在配置命令中设置密码,增强安全性 - if [[ -f "${REDIS_PASSWORD_FILE:-}" ]]; then - cat <<"EOF" -export REDIS_PASSWORD="$(< "${REDIS_PASSWORD_FILE}")" -EOF - fi - - if [[ -f "${REDIS_MASTER_PASSWORD_FILE:-}" ]]; then - cat <<"EOF" -export REDIS_MASTER_PASSWORD="$(< "${REDIS_MASTER_PASSWORD_FILE}")" -EOF - fi - - # 如果设置了用户密码,设置环境变量 REDISCLI_AUTH,用于 `redis-cli` 登录时使用;不显示输入,保证安全 - if [[ -n "${REDIS_PASSWORD}" ]]; then - cat <<"EOF" -export REDISCLI_AUTH=${REDIS_PASSWORD} -EOF - fi +# 使用环境变量中以 "APP_CFG_" 开头的的全局变量更新配置文件中对应项(全小写,以"."分隔) +# 举例: +# APP_CFG_LOG_DIRS 对应配置文件中的配置项:log.dirs +redis_configure_from_env_variables() { + # Map environment variables to config properties + for var in "${!APP_CFG_@}"; do + key="$(echo "$var" | sed -e 's/^APP_CFG_//g' -e 's/_/\./g' | tr '[:upper:]' '[:lower:]')" + value="${!var}" + redis_conf_set "$key" "$value" + done } # 将变量配置更新至配置文件 @@ -248,7 +192,7 @@ redis_configure_replication() { REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]} fi LOG_I "Waitting for Redis Master ready..." - wait-for-port --host "$REDIS_MASTER_HOST" "$REDIS_MASTER_PORT_NUMBER" + redis_wait_service "${REDIS_MASTER_HOST}:${REDIS_MASTER_PORT_NUMBER}" [[ -n "$REDIS_MASTER_PASSWORD" ]] && redis_conf_set masterauth "$REDIS_MASTER_PASSWORD" # Starting with Redis 5, use 'replicaof' instead of 'slaveof'. Maintaining both for backward compatibility local parameter="replicaof" @@ -262,11 +206,10 @@ redis_configure_replication() { } # 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息 -app_verify_minimum_env() { +redis_verify_minimum_env() { local error_code=0 LOG_D "Validating settings in REDIS_* env vars..." - # Auxiliary functions print_validation_error() { LOG_E "$1" error_code=1 @@ -323,16 +266,57 @@ app_verify_minimum_env() { } # 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1) -app_enable_remote_connections() { +redis_enable_remote_connections() { LOG_D "Modify default config to enable all IP access" redis_conf_set daemonize no redis_conf_set bind 0.0.0.0 # Allow remote connections } +# 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat' +# 参数: +# $1 - host:port +redis_wait_service() { + local serviceport=${1:?Missing server info} + local service=${serviceport%%:*} + local port=${serviceport#*:} + local retry_seconds=5 + local max_try=100 + let i=1 + + if [[ -z "$(which nc)" ]]; then + LOG_E "Nedd nc installed before, command: \"apt-get install netcat\"." + exit 1 + fi + + LOG_I "[0/${max_try}] check for ${service}:${port}..." + + set +e + nc -z ${service} ${port} + result=$? + + until [ $result -eq 0 ]; do + LOG_D " [$i/${max_try}] not available yet" + if (( $i == ${max_try} )); then + LOG_E "${service}:${port} is still not available; giving up after ${max_try} tries." + exit 1 + fi + + LOG_I "[$i/${max_try}] try in ${retry_seconds}s once again ..." + let "i++" + sleep ${retry_seconds} + + nc -z ${service} ${port} + result=$? + done + + set -e + LOG_I "[$i/${max_try}] ${service}:${port} is available." +} + # 以后台方式启动应用服务,并等待启动就绪 -app_start_server_bg() { - is_app_server_running && return +redis_start_server_bg() { + redis_is_server_running && return LOG_I "Starting ${APP_NAME} in background..." @@ -343,7 +327,7 @@ app_start_server_bg() { fi local counter=3 - while ! is_app_server_running ; do + while ! redis_is_server_running ; do if [[ "$counter" -ne 0 ]]; then break fi @@ -359,8 +343,8 @@ app_start_server_bg() { } # 停止应用服务 -app_stop_server() { - is_app_server_running || return +redis_stop_server() { + redis_is_server_running || return local pass local port @@ -390,7 +374,7 @@ app_stop_server() { } # 检测应用服务是否在后台运行中 -is_app_server_running() { +redis_is_server_running() { LOG_D "Check if ${APP_NAME} is running..." local pid pid="$(get_pid_from_file "${REDIS_PID_FILE}")" @@ -403,13 +387,13 @@ is_app_server_running() { } # 清理初始化应用时生成的临时文件 -app_clean_tmp_file() { +redis_clean_tmp_file() { LOG_D "Clean ${APP_NAME} tmp files for init..." } # 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动) -app_clean_from_restart() { +redis_clean_from_restart() { LOG_D "Clean ${APP_NAME} tmp files for restart..." local -r -a files=( "${REDIS_PID_FILE}" @@ -425,8 +409,8 @@ app_clean_from_restart() { # 应用默认初始化操作 # 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件 -app_default_init() { - app_clean_from_restart +redis_default_init() { + redis_clean_from_restart LOG_D "Check init status of ${APP_NAME}..." # 检测配置文件是否存在 @@ -439,15 +423,17 @@ app_default_init() { redis_configure_replication fi - touch ${APP_CONF_DIR}/.app_init_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_CONF_DIR}/.app_init_flag + touch "${APP_CONF_DIR}/.app_init_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_CONF_DIR}/.app_init_flag" else LOG_I "User injected custom configuration detected!" fi if [[ ! -f "${APP_DATA_DIR}/.data_init_flag" ]]; then LOG_I "Deploying ${APP_NAME} from scratch..." - #app_start_server_bg + + # 启动后台服务 + #redis_start_server_bg touch ${APP_DATA_DIR}/.data_init_flag @@ -459,8 +445,8 @@ app_default_init() { # 用户自定义的前置初始化操作,依次执行目录 preinitdb.d 中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_preinit_flag -app_custom_preinit() { - LOG_D "Check custom pre-init status of ${APP_NAME}..." +redis_custom_preinit() { + LOG_I "Check custom pre-init status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/preinitdb.d" ]; then @@ -472,8 +458,8 @@ app_custom_preinit() { # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/preinitdb.d/" -type f -regex ".*\.\(sh\)" | sort | process_init_files - touch ${APP_DATA_DIR}/.custom_preinit_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_DATA_DIR}/.custom_preinit_flag + touch "${APP_DATA_DIR}/.custom_preinit_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_preinit_flag" LOG_I "Custom preinit for ${APP_NAME} complete." else LOG_I "Custom preinit for ${APP_NAME} already done before, skipping initialization." @@ -482,14 +468,14 @@ app_custom_preinit() { # 检测依赖的服务是否就绪 #for i in ${SERVICE_PRECONDITION[@]}; do - # app_wait_service "${i}" + # redis_wait_service "${i}" #done } # 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag -app_custom_init() { - LOG_D "Check custom init status of ${APP_NAME}..." +redis_custom_init() { + LOG_I "Check custom initdb status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then @@ -498,7 +484,8 @@ app_custom_init() { [[ ! -f "${APP_DATA_DIR}/.custom_init_flag" ]]; then LOG_I "Process custom init scripts from /srv/conf/${APP_NAME}/initdb.d..." - #app_start_server_bg + # 启动后台服务 + #redis_start_server_bg # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do @@ -510,12 +497,21 @@ app_custom_init() { LOG_D "Sourcing $f"; . "$f" fi ;; - *) LOG_D "Ignoring $f" ;; + *.sql) + LOG_D "Executing $f"; + postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" < "$f" + ;; + *.sql.gz) + LOG_D "Executing $f"; + gunzip -c "$f" | postgresql_execute "${PG_DATABASE}" "${PG_INITSCRIPTS_USERNAME}" "${PG_INITSCRIPTS_PASSWORD}" + ;; + *) + LOG_D "Ignoring $f" ;; esac done - touch ${APP_DATA_DIR}/.custom_init_flag - echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_DATA_DIR}/.custom_init_flag + touch "${APP_DATA_DIR}/.custom_init_flag" + echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> "${APP_DATA_DIR}/.custom_init_flag" LOG_I "Custom init for ${APP_NAME} complete." else LOG_I "Custom init for ${APP_NAME} already done before, skipping initialization." @@ -523,11 +519,12 @@ app_custom_init() { fi # 检测服务是否运行中;如果运行,则停止后台服务 - is_app_server_running && app_stop_server + redis_is_server_running && redis_stop_server # 删除第一次运行生成的临时文件 - app_clean_tmp_file + redis_clean_tmp_file # 绑定所有 IP ,启用远程访问 - app_enable_remote_connections + redis_enable_remote_connections } + diff --git a/customer/usr/local/bin/entry.sh b/customer/usr/local/bin/entry.sh index f3728ea..9c531c0 100755 --- a/customer/usr/local/bin/entry.sh +++ b/customer/usr/local/bin/entry.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 容器入口脚本 @@ -8,9 +8,10 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing entry.sh **" if ! is_sourced; then @@ -25,8 +26,8 @@ if ! is_sourced; then if [ "$1" = "${APP_EXEC}" ] && is_root; then /usr/local/bin/setup.sh - LOG_I "Restart with non-root user: ${APP_USER:-APP_NAME}\n" - exec gosu "${APP_USER:-APP_NAME}" "$0" "$@" + LOG_I "Restart with non-root user: ${APP_USER}\n" + exec gosu "${APP_USER}" "$0" "$@" fi [ "$1" = "${APP_EXEC}" ] && /usr/local/bin/init.sh diff --git a/customer/usr/local/bin/init.sh b/customer/usr/local/bin/init.sh index 727d9fa..1151b4f 100755 --- a/customer/usr/local/bin/init.sh +++ b/customer/usr/local/bin/init.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用初始化脚本 @@ -8,18 +8,21 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing init.sh **" +trap "${APP_NAME}_stop_server" EXIT + # 执行应用预初始化操作 -app_custom_preinit +${APP_NAME}_custom_preinit # 执行应用初始化操作 -app_default_init +${APP_NAME}_default_init # 执行用户自定义初始化脚本 -app_custom_init +${APP_NAME}_custom_init LOG_I "** Processing init.sh finished! **" diff --git a/customer/usr/local/bin/run.sh b/customer/usr/local/bin/run.sh index 73dc478..475b117 100755 --- a/customer/usr/local/bin/run.sh +++ b/customer/usr/local/bin/run.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用启动脚本 @@ -8,18 +8,20 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing run.sh **" flags=("${APP_CONF_FILE:-}") [[ -z "${APP_EXTRA_FLAGS:-}" ]] || flags=("${flags[@]}" "${APP_EXTRA_FLAGS[@]}") -START_COMMAND=("${APP_EXEC:-/bin/bash}" "${flags[@]}") +START_COMMAND=("${APP_EXEC:-/bin/bash}") LOG_I "** Starting ${APP_NAME} **" if is_root; then - exec gosu "${APP_USER:-APP_NAME}" tini -s -- "${START_COMMAND[@]}" + exec gosu "${APP_USER}" tini -s -- "${START_COMMAND[@]}" "${flags[@]}" else - exec tini -s -- "${START_COMMAND[@]}" + exec tini -s -- "${START_COMMAND[@]}" "${flags[@]}" fi + diff --git a/customer/usr/local/bin/setup.sh b/customer/usr/local/bin/setup.sh index ae59c47..ac154ca 100755 --- a/customer/usr/local/bin/setup.sh +++ b/customer/usr/local/bin/setup.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Ver: 1.0 by Endial Fang (endial@126.com) +# Ver: 1.1 by Endial Fang (endial@126.com) # # 应用环境及依赖文件设置脚本 @@ -8,17 +8,19 @@ set -eu set -o pipefail -. /usr/local/bin/appcommon.sh # 应用专用函数库 +. /usr/local/bin/comm-${APP_NAME}.sh # 应用专用函数库 + +. /usr/local/bin/comm-env.sh # 设置环境变量 -eval "$(app_env)" LOG_I "** Processing setup.sh **" APP_DIRS="${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_DATA_LOG_DIR:-}" +LOG_I "Ensure directory exists: ${APP_DIRS}" for dir in ${APP_DIRS}; do ensure_dir_exists ${dir} done -app_verify_minimum_env +${APP_NAME}_verify_minimum_env # 检测指定文件是否在配置文件存储目录存在,如果不存在则拷贝(新挂载数据卷、手动删除都会导致不存在) LOG_I "Check config files in: ${APP_CONF_DIR}" @@ -26,6 +28,7 @@ if [[ ! -z "$(ls -A "${APP_DEF_DIR}")" ]]; then ensure_config_file_exist "${APP_DEF_DIR}" $(ls -A "${APP_DEF_DIR}") fi +LOG_I "Ensure directory ownership: ${APP_USER}" for dir in ${APP_DIRS}; do configure_permissions_ownership "$dir" -u "${APP_USER}" -g "${APP_USER}" done diff --git a/customer/usr/local/overrides/overrides-6.0.8.sh b/customer/usr/local/overrides/overrides-6.0.8.sh index 7861c99..e89e34b 100644 --- a/customer/usr/local/overrides/overrides-6.0.8.sh +++ b/customer/usr/local/overrides/overrides-6.0.8.sh @@ -1,4 +1,5 @@ #!/bin/bash -e +# Ver: 1.0 by Endial Fang (endial@126.com) # # 在安装完应用后,使用该脚本修改默认配置文件中部分配置项; 如果相应的配置项已经定义为容器环境变量,则不需要在这里修改 @@ -6,14 +7,14 @@ CONF_FILE="${APP_DEF_DIR}/redis.conf" echo "Process overrides for: ${CONF_FILE}" # 修改默认配置信息 -sed -i -E 's/^bind .*/bind 127.0.0.1/g' "${CONF_FILE}" -sed -i -E 's/^daemonize .*/daemonize yes/g' "${CONF_FILE}" -sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis.pid/g' "${CONF_FILE}" -sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis.log\"/g' "${CONF_FILE}" +sed -i -E 's/^#?bind .*/bind 127.0.0.1/g' "${CONF_FILE}" +sed -i -E 's/^#?daemonize .*/daemonize yes/g' "${CONF_FILE}" +sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis.pid/g' "${CONF_FILE}" +sed -i -E 's/^#?logfile .*/logfile \"\/var\/log\/redis\/redis.log\"/g' "${CONF_FILE}" SENTINEL_FILE="${APP_DEF_DIR}/sentinel.conf" echo "Process overrides for: ${SENTINEL_FILE}" # 修改 Sentinel 默认配置信息 -sed -i -E 's/^daemonize .*/daemonize yes/g' "${SENTINEL_FILE}" -sed -i -E 's/^pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "${SENTINEL_FILE}" -sed -i -E 's/^logfile .*/logfile \"\/var\/log\/redis\/redis-sentinel.log\"/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?daemonize .*/daemonize yes/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "${SENTINEL_FILE}" +sed -i -E 's/^#?logfile .*/logfile \"\/var\/log\/redis\/redis-sentinel.log\"/g' "${SENTINEL_FILE}" diff --git a/customer/usr/sbin/create_user b/customer/usr/sbin/create_user index 78c4251..4f86e9c 100755 --- a/customer/usr/sbin/create_user +++ b/customer/usr/sbin/create_user @@ -2,7 +2,8 @@ # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux groupadd --gid 998 --system ${APP_USER} -useradd --gid 998 --uid 999 --shell /usr/sbin/nologin --home ${APP_DATA_DIR} --system ${APP_USER} +#useradd --gid 998 --uid 999 --shell /bin/bash --home /srv/data/${APP_NAME} --system ${APP_USER} +useradd --gid 998 --uid 999 --shell /usr/sbin/nologin --home /srv/data/${APP_NAME} --system ${APP_USER} # 如果需要 sudo 权限,需要安装 su 软件包:apk add sudo #sed -i -e 's/^\sDefaults\s*secure_path\s*=/# Defaults secure_path=/' /etc/sudoers diff --git a/customer/usr/sbin/prepare_env b/customer/usr/sbin/prepare_env index cb7b34b..05ce3b1 100755 --- a/customer/usr/sbin/prepare_env +++ b/customer/usr/sbin/prepare_env @@ -2,7 +2,16 @@ # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux -APP_DIRS="${APP_DEF_DIR:-} ${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_DATA_LOG_DIR:-} ${APP_CACHE_DIR:-} ${APP_RUN_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_HOME_DIR:-}" +APP_DIRS=" \ + /usr/local/${APP_NAME} \ + /etc/${APP_NAME} \ + /srv/conf/${APP_NAME} \ + /srv/data/${APP_NAME} \ + /srv/datalog/${APP_NAME} \ + /var/cache/${APP_NAME} \ + /var/run/${APP_NAME} \ + /var/log/${APP_NAME} \ + /srv/cert/${APP_NAME}" mkdir -p ${APP_DIRS} chown -Rf ${APP_USER}:${APP_USER} ${APP_DIRS}; diff --git a/docker-compose-cluster.yml b/docker-compose-replicate.yml similarity index 87% rename from docker-compose-cluster.yml rename to docker-compose-replicate.yml index 9107849..70f044b 100644 --- a/docker-compose-cluster.yml +++ b/docker-compose-replicate.yml @@ -3,10 +3,10 @@ version: '3.8' # 可以使用 scale 动态扩容容器:docker-compose scale redis-replica=3 services: - redis-primary: + redis: image: 'colovu/redis' ports: - - '6379:6379' + - '6379' environment: - REDIS_REPLICATION_MODE=master - REDIS_PASSWORD=colovu @@ -20,13 +20,13 @@ services: - '6379' environment: - REDIS_REPLICATION_MODE=slave - - REDIS_MASTER_HOST=redis-primary + - REDIS_MASTER_HOST=redis - REDIS_MASTER_PORT_NUMBER=6379 - REDIS_MASTER_PASSWORD=colovu - REDIS_PASSWORD=colovu - REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL depends_on: - - redis-primary + - redis # 定义本地数据卷,由系统管理,需要手动删除 volumes: diff --git a/docker-compose-sentinel.yml b/docker-compose-sentinel.yml deleted file mode 100644 index 9069d45..0000000 --- a/docker-compose-sentinel.yml +++ /dev/null @@ -1,2 +0,0 @@ -version: '3.8' -