Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 60c52d6384 | |||
| cf3391b75f | |||
| 1d9f485554 | |||
| dae3345630 | |||
| ad400ff278 | |||
| f02387eb1f | |||
| f9b3f5089b | |||
| 43f6b1a4b1 | |||
| 0a6c987724 | |||
| 20e440b8b5 | |||
| 340729facd | |||
| ddc276a1ca | |||
| 9a2aa2d0f2 | |||
| 45c7eb4f5c | |||
| 71d270572e |
+5
-6
@@ -50,22 +50,21 @@ build-amd64:
|
||||
- docker buildx build --platform=linux/amd64 --pull -t "$IMG_URL$IMG_TAG-linux-amd64" . --push
|
||||
- docker rmi "$IMG_URL$IMG_TAG-linux-amd64"
|
||||
|
||||
# 生成多架构制品,并在上传后删除本地文件
|
||||
build-artifact:
|
||||
stage: build
|
||||
needs: [build-amd64, build-arm64]
|
||||
script:
|
||||
- docker manifest create "$IMG_URL$IMG_TAG" "$IMG_URL$IMG_TAG-linux-arm64" "$IMG_URL$IMG_TAG-linux-amd64"
|
||||
- docker manifest push "$IMG_URL$IMG_TAG"
|
||||
- docker manifest rm "$IMG_URL$IMG_TAG"
|
||||
- docker manifest push -p "$IMG_URL$IMG_TAG"
|
||||
|
||||
# 测试阶段任务
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- docker run --rm --platform=linux/arm64 "$IMG_URL$IMG_TAG" --version
|
||||
- sleep 1 && docker rmi -f "$IMG_URL$IMG_TAG"
|
||||
- docker run --rm --platform=linux/amd64 "$IMG_URL$IMG_TAG" --version
|
||||
- sleep 1 && docker rmi -f "$IMG_URL$IMG_TAG"
|
||||
- docker run --pull always --rm --platform=linux/arm64 "$IMG_URL$IMG_TAG" --version
|
||||
- docker run --pull always --rm --platform=linux/amd64 "$IMG_URL$IMG_TAG" --version
|
||||
- docker images -q "$IMG_URL" | sort -u | xargs docker rmi -f
|
||||
|
||||
# 部署阶段任务
|
||||
deploy:
|
||||
|
||||
+60
-70
@@ -1,9 +1,8 @@
|
||||
# Ver: 1.9 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.11 by Endial Fang (endial@126.com)
|
||||
#
|
||||
|
||||
# 默认变量 ========================================================================
|
||||
# 系统默认变量 ====================================================================
|
||||
# 该部分变量为系统根据编译命令默认设置
|
||||
|
||||
# `TARGETPLATFORM`:构建后的目标平台信息。如 `linux/amd64`,`linux/arm/v7`,`windows/amd64`
|
||||
# `TARGETOS`:目标平台信息(TARGETPLATFORM)中的操作系统部分,如:`linux`、`windows`
|
||||
# `TARGETARCH`:目标平台信息(TARGETPLATFORM)中的平台架构部分,如:`amd64`、`arm`
|
||||
@@ -16,18 +15,11 @@
|
||||
# 可变参数 ========================================================================
|
||||
# 该部分变量,在编译命令中通过 `--build-arg` 传入;如果未设置,则使用下面对应的默认值
|
||||
|
||||
# 设置当前应用名称及版本
|
||||
ARG APP_NAME=redis
|
||||
ARG APP_VER=6.2.13
|
||||
|
||||
# 设置默认仓库地址,默认为本地仓库;定义时需要包含末尾的`/`
|
||||
ARG REGISTRY_URL="docker.colovu.com/"
|
||||
|
||||
# 设置 apt-get 源:default / ustc / aliyun
|
||||
ARG APT_SOURCE=aliyun
|
||||
|
||||
# 编译镜像时指定用于加速的本地软件包存储服务器地址
|
||||
ARG LOCAL_URL="http://local.colovu.com/dist"
|
||||
ARG APP_NAME=redis # 设置当前应用名称
|
||||
ARG APP_VER=6.2.13 # 设置当前应用版本
|
||||
ARG REGISTRY_URL="docker.colovu.com/" # 设置默认仓库地址,默认为本地仓库;定义时需要包含末尾的`/`
|
||||
ARG APT_SOURCE=aliyun # 设置 apt-get 源:default / ustc / aliyun
|
||||
ARG LOCAL_URL="http://local.colovu.com/dist" # 编译镜像时指定用于加速的本地软件包存储服务器地址
|
||||
|
||||
# 0. 预处理 ======================================================================
|
||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} ${REGISTRY_URL}colovu/dbuilder:12 as builder
|
||||
@@ -38,14 +30,11 @@ ARG APP_VER
|
||||
ARG APT_SOURCE
|
||||
ARG LOCAL_URL
|
||||
|
||||
# 选择软件包源(Optional),以加速后续软件包安装
|
||||
# 选择软件包源,加速后续软件包安装
|
||||
RUN select_source ${APT_SOURCE};
|
||||
|
||||
# 安装依赖的软件包及库(Optional)
|
||||
#RUN install_pkg xz-utils
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /tmp
|
||||
# 安装依赖的软件包及库
|
||||
RUN install_pkg libjemalloc2 libjemalloc-dev;
|
||||
|
||||
# 下载并解压软件包
|
||||
RUN set -eux; \
|
||||
@@ -61,17 +50,34 @@ RUN set -eux; \
|
||||
RUN set -eux; \
|
||||
APP_SRC="/tmp/${APP_NAME}-${APP_VER}"; \
|
||||
cd ${APP_SRC}; \
|
||||
# 禁用安全保护模式,在 Docker 中运行时不需要
|
||||
\
|
||||
# 禁用安全保护模式,在 Docker 中运行时不需要
|
||||
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; \
|
||||
\
|
||||
# 根据操作系统设置内存页大小
|
||||
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
|
||||
extraJemallocConfigureFlags="--build=$gnuArch"; \
|
||||
dpkgArch="$(dpkg --print-architecture)"; \
|
||||
case "${dpkgArch##*-}" in \
|
||||
amd64 | i386 | x32) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=12" ;; \
|
||||
*) extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-page=16" ;; \
|
||||
esac; \
|
||||
extraJemallocConfigureFlags="$extraJemallocConfigureFlags --with-lg-hugepage=21"; \
|
||||
grep -F 'cd jemalloc && ./configure ' ./deps/Makefile; \
|
||||
sed -ri 's!cd jemalloc && ./configure !&'"$extraJemallocConfigureFlags"' !' ./deps/Makefile; \
|
||||
grep -F "cd jemalloc && ./configure $extraJemallocConfigureFlags " ./deps/Makefile; \
|
||||
\
|
||||
make MALLOC=libjemalloc2 BUILD_TLS=yes \
|
||||
-j "$(nproc)" all; \
|
||||
make PREFIX=/usr/local/${APP_NAME} install; \
|
||||
# 将配置文件模板拷贝至应用安装目录的 etc/${APP_NAME} 目录下
|
||||
\
|
||||
# 将配置文件模板拷贝至应用安装目录的 etc/${APP_NAME} 目录下
|
||||
mkdir -p /usr/local/${APP_NAME}/etc/${APP_NAME}; \
|
||||
cp /tmp/${APP_NAME}-${APP_VER}/*.conf /usr/local/${APP_NAME}/etc/${APP_NAME}/; \
|
||||
# 删除重复的应用程序,并生成对应的连接
|
||||
\
|
||||
# 删除重复的应用程序,并生成对应的连接
|
||||
serverMd5="$(md5sum /usr/local/redis/bin/redis-server | cut -d' ' -f1)"; export serverMd5; \
|
||||
find /usr/local/redis/bin/redis* -maxdepth 0 \
|
||||
-type f -not -name redis-server \
|
||||
@@ -89,12 +95,9 @@ RUN set -eux; \
|
||||
# 检测并生成依赖文件记录
|
||||
RUN set -eux; \
|
||||
find /usr/local/${APP_NAME} -type f -executable -exec ldd '{}' ';' | \
|
||||
awk '/=>/ { print $(NF-1) }' | \
|
||||
sort -u | \
|
||||
xargs -r readlink -f | \
|
||||
xargs -r dpkg-query --search 2>/dev/null | \
|
||||
cut -d: -f1 | \
|
||||
sort -u >>/usr/local/${APP_NAME}/runDeps;
|
||||
awk '/=>/ { print $(NF-1) }' | xargs -r basename -a | sort -u | \
|
||||
xargs -r dpkg-query --search 2>/dev/null | cut -d: -f1 | sort -u \
|
||||
>>/usr/local/${APP_NAME}/runDeps;
|
||||
|
||||
# 1. 生成镜像 =====================================================================
|
||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} ${REGISTRY_URL}colovu/debian:12
|
||||
@@ -109,12 +112,8 @@ ENV APP_NAME=${APP_NAME} \
|
||||
APP_VER=${APP_VER} \
|
||||
APP_EXEC=redis-server \
|
||||
APP_USER=${APP_NAME} \
|
||||
APP_HOME_DIR=/usr/local/${APP_NAME} \
|
||||
APP_DEF_DIR=/etc/${APP_NAME}
|
||||
|
||||
# 增加应用可执行文件及库文件搜索路径
|
||||
ENV PATH="${APP_HOME_DIR}/sbin:${APP_HOME_DIR}/bin:${PATH}" \
|
||||
LD_LIBRARY_PATH="${APP_HOME_DIR}/lib"
|
||||
LD_LIBRARY_PATH="/usr/local/${APP_NAME}/lib" \
|
||||
PATH="${PATH}:/usr/local/${APP_NAME}/bin"
|
||||
|
||||
LABEL \
|
||||
"Version"="v${APP_VER}" \
|
||||
@@ -122,56 +121,47 @@ LABEL \
|
||||
"Github"="https://github.com/colovu/docker-${APP_NAME}" \
|
||||
"Vendor"="Endial Fang (endial@126.com)"
|
||||
|
||||
# 从预处理过程中拷贝软件包(Optional),可以使用阶段编号或阶段命名定义来源
|
||||
# 拷贝多阶段构建结果输出及客制化脚本
|
||||
COPY --from=builder /usr/local/${APP_NAME} /usr/local/${APP_NAME}
|
||||
|
||||
# 拷贝应用使用的客制化脚本
|
||||
COPY customer /
|
||||
|
||||
RUN set -eux; \
|
||||
\
|
||||
# 创建对应的用户及数据存储目录
|
||||
prepare_env; \
|
||||
useradd -U -u 996 -d /srv/${APP_NAME} -s /usr/sbin/nologin -r ${APP_USER}; \
|
||||
mkdir -p /var/log/${APP_NAME} /var/run/${APP_NAME} /var/cache/${APP_NAME}; \
|
||||
mkdir -p /srv/${APP_NAME}/conf /srv/${APP_NAME}/data /srv/${APP_NAME}/cert /srv/${APP_NAME}/log; \
|
||||
chown -R ${APP_USER}:${APP_USER} /var/log/${APP_NAME} /var/run/${APP_NAME} /var/cache/${APP_NAME}; \
|
||||
chown -R ${APP_USER}:${APP_USER} /usr/local/${APP_NAME} /srv/${APP_NAME}; \
|
||||
\
|
||||
/bin/bash -c "ln -sf /usr/local/${APP_NAME}/etc/${APP_NAME} /etc/"; \
|
||||
\
|
||||
# 选择软件包源(Optional),以加速后续软件包安装
|
||||
# 选择软件包源,以加速后续软件包安装
|
||||
select_source ${APT_SOURCE}; \
|
||||
\
|
||||
# 安装依赖的软件包及库(Optional)
|
||||
install_pkg `cat /usr/local/${APP_NAME}/runDeps`; \
|
||||
# 安装应用依赖的软件包及库
|
||||
install_pkg ncat; \
|
||||
install_pkg `cat /usr/local/${APP_NAME}/runDeps`; \
|
||||
\
|
||||
# 执行后处理脚本,并验证安装的应用
|
||||
override_file="/usr/local/overrides/overrides-${APP_VER}.sh"; \
|
||||
[ -e "${override_file}" ] && /bin/bash "${override_file}"; \
|
||||
# 执行后处理脚本
|
||||
overrideShell="/usr/local/overrides/overrides-${APP_VER}.sh"; \
|
||||
[ -e "${overrideShell}" ] && /bin/bash "${overrideShell}"; \
|
||||
\
|
||||
# 验证安装的应用
|
||||
redis-cli --version; \
|
||||
${APP_EXEC} --version;
|
||||
|
||||
# 默认提供的数据卷
|
||||
VOLUME ["/srv/conf", "/srv/data", "/srv/datalog", "/srv/cert", "/var/log"]
|
||||
|
||||
# 默认使用gosu切换为新建用户启动,必须保证端口在1024之上
|
||||
# 配置容器的数据卷、工作目录及服务端口(必须保证端口在1024之上)
|
||||
VOLUME ["/srv/${APP_NAME}/conf", "/srv/${APP_NAME}/data", "/srv/${APP_NAME}/cert", "/srv/${APP_NAME}/log"]
|
||||
WORKDIR /srv/${APP_NAME}/data
|
||||
EXPOSE 6379
|
||||
|
||||
# 关闭基础镜像的健康检查
|
||||
#HEALTHCHECK NONE
|
||||
#HEALTHCHECK --interval=30s --timeout=30s --retries=3 CMD curl -fs http://localhost:8080/ || exit 1
|
||||
HEALTHCHECK --interval=10s --timeout=10s --retries=3 CMD netstat -ltun | grep 6379
|
||||
|
||||
# 应用健康状态检查
|
||||
#HEALTHCHECK --interval=30s --timeout=30s --retries=3 \
|
||||
# CMD curl -fs http://localhost:8080/ || exit 1
|
||||
HEALTHCHECK --interval=10s --timeout=10s --retries=3 \
|
||||
CMD netstat -ltun | grep 6379
|
||||
# 使用 dumb-init 启动入口 Shell,确保容器可以接收控制信号;并使用前台方式启动应用程序
|
||||
ENTRYPOINT ["dumb-init", "entry.sh"]
|
||||
CMD ["run.sh"]
|
||||
|
||||
# 使用 non-root 用户运行后续的命令
|
||||
USER 1001
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /srv/data
|
||||
|
||||
# 容器入口命令脚本,'/usr/local/bin/entry.sh'
|
||||
ENTRYPOINT ["entry.sh"]
|
||||
|
||||
# 应用程序的启动命令,可为应用程序可执行命令或脚本
|
||||
# 必须使用非守护进程方式运行,'/usr/local/bin/run.sh'
|
||||
CMD ["run.sh"]
|
||||
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
**镜像信息:**
|
||||
|
||||
* 镜像地址:
|
||||
- 阿里云: registry.cn-shenzhen.aliyuncs.com/colovu/redis:latest
|
||||
- DockerHub:colovu/redis:latest
|
||||
- Colovu Registry: docker.colovu.com/colovu/redis:latest
|
||||
- 阿里云: registry.cn-shenzhen.aliyuncs.com/colovu/redis:6.2
|
||||
- Colovu Registry: docker.colovu.com/colovu/redis:6.2
|
||||
- 依赖镜像:colovu/debian:12
|
||||
|
||||
> 后续相关命令行默认使用`[Colovu Registry](https://docker.colovu.com)`镜像服务器做说明
|
||||
> 后续相关命令行默认使用 Aliyun ACR 镜像服务器做说明
|
||||
|
||||
## TL;DR
|
||||
|
||||
@@ -28,10 +27,10 @@ Docker 快速启动命令:
|
||||
|
||||
```shell
|
||||
# 从 Registry 服务器下载镜像并启动
|
||||
$ docker run -d -e ALLOW_ANONYMOUS_LOGIN=yes --name imgname docker.colovu.com/colovu/redis:latest
|
||||
$ docker run -d -e ALLOW_ANONYMOUS=yes --name imgname registry.cn-shenzhen.aliyuncs.com/colovu/redis:6.2
|
||||
```
|
||||
|
||||
- `docker.colovu.com/colovu/imgname:<TAG>`:镜像名称及版本标签 TAG;标签不指定时默认使用`latest`
|
||||
- `registry.cn-shenzhen.aliyuncs.com/colovu/imgname:<TAG>`:镜像名称及版本标签 TAG;标签不指定时默认使用`latest`
|
||||
|
||||
|
||||
Docker-Compose 快速启动命令:
|
||||
@@ -69,11 +68,11 @@ $ docker-compose -f docker-compose-cluster.yml up -d
|
||||
镜像默认提供以下数据卷定义,默认数据分别存储在自动生成的应用名对应`redis`子目录中:
|
||||
|
||||
```shell
|
||||
/srv/data # Redis 数据文件,主要存放Redis持久化数据;自动创建子目录redis
|
||||
/srv/datalog # Redis 数据操作日志文件;自动创建子目录redis
|
||||
/srv/conf # Redis 配置文件;自动创建子目录redis
|
||||
/var/log # 日志文件,日志文件名为:redis.log
|
||||
/var/run # 进程运行PID文件,PID文件名为:redis_6379.pid、redis_sentinel.pid
|
||||
/srv/redis/data # Redis 数据文件,主要存放 Redis 持久化数据
|
||||
/srv/redis/conf # Redis 配置文件
|
||||
/srv/redis/cert # TLS 通讯证书文件
|
||||
/srv/redis/log # 日志文件,日志文件名为:redis.log
|
||||
/var/run/redis # 进程运行 PID 文件,PID 文件名为:redis.pid、redis_sentinel.pid
|
||||
```
|
||||
|
||||
如果需要持久化存储相应数据,需要**在宿主机建立本地目录**,并在使用镜像初始化容器时进行映射。宿主机相关的目录中如果不存在对应应用 Redis 的子目录或相应数据文件,则容器会在初始化时创建相应目录及文件。
|
||||
@@ -83,26 +82,54 @@ $ docker-compose -f docker-compose-cluster.yml up -d
|
||||
在初始化 Redis 容器时,如果没有预置配置文件,可以在命令行中设置相应环境变量对默认参数进行修改。类似命令如下:
|
||||
|
||||
```shell
|
||||
$ docker run -d -e "APP_ENV_KEY_NAME=key_value" docker.colovu.com/colovu/redis:latest
|
||||
$ docker run -d -e "REDIS_CFG_KEYNAME=key_value" registry.cn-shenzhen.aliyuncs.com/colovu/redis:6.2
|
||||
```
|
||||
|
||||
### 自动变量替换
|
||||
|
||||
针对应用配置文件中的配置项,支持由环境变量名自动替换生成,该类环境变量需要使用统一前缀,定义规则为:`REDIS_CFG_*=<val>`
|
||||
|
||||
- `REDIS_CFG_`:环境变量自动替换标识,具备该前缀的环境变量会被自动处理并更新至配置文件
|
||||
- `*`:配置文件中对应的配置项名,大小写需要符合实际参数名要求;特殊字符需要符合`特殊字符替换规则`
|
||||
- `<val>`:配置项对应值
|
||||
|
||||
**特殊字符替换规则**:
|
||||
|
||||
因为 Shell 变量只能以字母、数字和下划线组成,针对'xml'、'ini'等配置文件中使用的'.'、'-'等特殊字符,需要进行重定义及转换。预定义如下:
|
||||
|
||||
+ "_" ==> "-" : 应用配置属性中的`-`(中划线),与环境变量中由`_`(单下划线)表示
|
||||
+ "__" ==> "_" : 应用配置属性中的`_`(下划线),在环境变量中由`__`(双下划线)表示
|
||||
+ "___" ==> "." : 应用配置属性中的`.`(半角点),在环境变量中由`___`(三下划线)表示
|
||||
|
||||
例如:
|
||||
|
||||
```shell
|
||||
# 用于`key-value`类型的配置
|
||||
REDIS_CFG_REQUIREPASS=colovu123
|
||||
REDIS_CFG_APPENDONLY=no
|
||||
|
||||
# 容器启动后,应用配置文件中对应配置项生效,且设置为相应值:
|
||||
requirepass colovu123
|
||||
appendonly no
|
||||
```
|
||||
|
||||
### 常规配置参数
|
||||
|
||||
常使用的环境变量主要包括:
|
||||
|
||||
- **ALLOW_ANONYMOUS_LOGIN**:默认值:**no**。设置是否允许无密码连接。如果没有设置`REDIS_PASSWORD`,则必须设置当前环境变量为 `yes`
|
||||
- **REDIS_PASSWORD**:默认值:**无**。客户端认证的密码
|
||||
- **REDIS_DISABLE_COMMANDS**:默认值:**无**。设置禁用的 Redis 命令
|
||||
- **REDIS_AOF_ENABLED**:默认值:**yes**。设置是否启用 Append Only File 存储
|
||||
- **ALLOW_ANONYMOUS**:默认值:**no**。设置是否允许无密码连接。如果没有设置`REDIS_CFG_REQUIREPASS`,则必须设置当前环境变量为 `yes`
|
||||
- **REDIS_CFG_REQUIREPASS**:默认值:**无**。客户端认证的密码
|
||||
- **REDIS_CFG_APPENDONLY**:默认值:**no**。设置是否启用 Append Only File 存储
|
||||
|
||||
### 可选配置参数
|
||||
### 常规可选参数
|
||||
|
||||
如果没有必要,可选配置参数可以不用定义,直接使用对应的默认值,主要包括:
|
||||
|
||||
- **ENV_DEBUG**:默认值:**false**。设置是否输出容器调试信息。可设置为:1、true、yes
|
||||
- **REDIS_PORT**:默认值:**6379**。设置应用的默认客户访问端口
|
||||
- **REDIS_PASSWORD_FILE**:默认值:**无**。以绝对地址指定的客户端认证用户密码存储文件。该路径指的是容器内的路径
|
||||
- **REDIS_MASTER_PASSWORD_FILE**:默认值:**无**。以绝对地址指定的服务器密码存储文件。该路径指的是容器内的路径
|
||||
- `ENV_DEBUG`:默认值:**false**。设置是否输出容器调试信息。可选值:false、no、true、yes
|
||||
- **DISABLE_COMMANDS**:默认值:**无**。设置禁用的 Redis 命令
|
||||
- **PASSWORD_FILE**:默认值:**无**。以绝对地址指定的客户端认证用户密码存储文件。该路径指的是容器内的路径
|
||||
- **MASTER_PASSWORD_FILE**:默认值:**无**。以绝对地址指定的服务器密码存储文件。该路径指的是容器内的路径
|
||||
- **REDIS_CFG_PORT**:默认值:**6379**。设置应用的默认客户访问端口
|
||||
|
||||
### Sentinel配置参数
|
||||
|
||||
@@ -110,28 +137,17 @@ $ docker run -d -e "APP_ENV_KEY_NAME=key_value" docker.colovu.com/colovu/redis:l
|
||||
- **REDIS_SENTINEL_MASTER_NAME**:默认值:**无**
|
||||
- **REDIS_SENTINEL_PORT_NUMBER**:默认值:**26379**。设置 Sentinel 默认端口
|
||||
|
||||
### 集群配置参数
|
||||
|
||||
使用 Redis 镜像,可以很容易的建立一个 [redis](https://redis.apache.org/doc/r3.1.2/redisAdmin.html) 集群。针对 redis 的集群模式(复制模式),有以下参数可以配置:
|
||||
|
||||
- **REDIS_REPLICATION_MOD**:默认值:**无**。当前主机在集群中的工作模式,可使用值为:`master`/`slave`/`replica`
|
||||
- **REDIS_MASTER_HOST**:默认值:**无**。作为`slave`/`replica`时,对应的 master 主机名或 IP 地址
|
||||
- **REDIS_MASTER_PORT_NUMBER**:默认值:**6379**。master 主机对应的端口
|
||||
- **REDIS_MASTER_PASSWORD**:默认值:**无**。master 主机对应的登录验证密码
|
||||
|
||||
### TLS配置参数
|
||||
|
||||
使用证书加密传输时,相关配置参数如下:
|
||||
|
||||
- **REDIS_TLS_ENABLED**:启用或禁用 TLS。默认值:**no**
|
||||
- **REDIS_TLS_PORT**:使用 TLS 加密传输的端口。默认值:**6379**
|
||||
- **REDIS_TLS_CERT_FILE**:TLS 证书文件。默认值:**无**
|
||||
- **REDIS_TLS_KEY_FILE**:TLS 私钥文件。默认值:**无**
|
||||
- **REDIS_TLS_CA_FILE**:TLS 根证书文件。默认值:**无**
|
||||
- **REDIS_TLS_DH_PARAMS_FILE**:包含 DH 参数的配置文件 (DH 加密方式时需要)。默认值:**无**
|
||||
- **REDIS_TLS_AUTH_CLIENTS**:配置客户端是否需要 TLS 认证。 默认值:**yes**
|
||||
- **REDIS_CFG_TLS_PORT**:使用 TLS 加密传输的端口。默认值:**6379**
|
||||
- **REDIS_CFG_TLS_CERT_FILE**:TLS 证书文件。默认值:**无**
|
||||
- **REDIS_CFG_TLS_KEY_FILE**:TLS 私钥文件。默认值:**无**
|
||||
- **REDIS_CFG_TLS_CA_CERT_FILE**:TLS 根证书文件。默认值:**无**
|
||||
- **REDIS_CFG_TLS_AUTH_CLIENTS**:配置客户端是否需要 TLS 认证。 默认值:**no**
|
||||
|
||||
当使用 TLS 时,则默认的 non-TLS 通讯被禁用。如果需要同时支持 TLS 与 non-TLS 通讯,可以使用参数`REDIS_TLS_PORT`配置容器使用不同的 TLS 端口。
|
||||
当使用 TLS 时,则默认的 non-TLS 通讯被禁用。如果需要同时支持 TLS 与 non-TLS 通讯,可以使用参数`REDIS_CFG_TLS_PORT`配置容器使用不同的 TLS 端口。
|
||||
|
||||
## 安全
|
||||
|
||||
@@ -140,13 +156,13 @@ $ docker run -d -e "APP_ENV_KEY_NAME=key_value" docker.colovu.com/colovu/redis:l
|
||||
Redis 镜像默认禁用了无密码访问功能,在实际生产环境中建议使用用户名及密码控制访问;如果为了测试需要,可以使用以下环境变量启用无密码访问功能:
|
||||
|
||||
```shell
|
||||
ALLOW_ANONYMOUS_LOGIN=yes
|
||||
ALLOW_ANONYMOUS=yes
|
||||
```
|
||||
|
||||
通过配置环境变量`REDIS_PASSWORD`,可以启用基于密码的用户认证功能。命令行使用参考:
|
||||
|
||||
```shell
|
||||
$ docker run -d -e APPNAME_PASSWORD=colovu docker.colovu.com/colovu/redis:latest
|
||||
$ docker run -d -e REDIS_PASSWORD=colovu registry.cn-shenzhen.aliyuncs.com/colovu/redis:6.2
|
||||
```
|
||||
|
||||
使用 Docker-Compose 时,`docker-compose.yml`应包含类似如下配置:
|
||||
@@ -156,7 +172,7 @@ services:
|
||||
redis:
|
||||
...
|
||||
environment:
|
||||
- REDIS_PASSWORD=colovu
|
||||
- REDIS_CFG_REQUIREPASS=colovu
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
+217
-343
@@ -1,9 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.4 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用通用业务处理函数
|
||||
|
||||
# 加载依赖脚本
|
||||
. /colovu/lib/libcommon.sh # 通用函数库
|
||||
|
||||
. /colovu/lib/libfile.sh
|
||||
@@ -13,17 +12,57 @@
|
||||
. /colovu/lib/libservice.sh
|
||||
. /colovu/lib/libvalidations.sh
|
||||
|
||||
# 函数列表
|
||||
# 检测应用相应的配置文件是否存在,如果不存在,则从默认配置文件目录拷贝一份
|
||||
# 默认配置文件路径:/etc/${APP_NAME}
|
||||
# 目标配置文件路径:/srv/conf/${APP_NAME}
|
||||
# 参数:
|
||||
# $1 - 目标路径
|
||||
# $2 - 源路径
|
||||
# $* - 基础路径下的文件及目录列表,以" "分割
|
||||
# 例子:
|
||||
# ensure_config_file_exist /etc/${APP_NAME} conf.d server.conf
|
||||
app_ensure_config_file_exist() {
|
||||
local -r dist_path="${1:?dist paths is missing}"
|
||||
local -r base_path="${2:?source paths is missing}"
|
||||
local f=""
|
||||
|
||||
# 使用环境变量中以 "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:]')"
|
||||
shift 2
|
||||
LOG_D "List to check in ${base_path}: $@"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
f="${1}"
|
||||
LOG_D " Process \"${f}\""
|
||||
if [ -d "${base_path}/${f}" ]; then
|
||||
[[ ! -d "${dist_path}/${f}" ]] && LOG_D " Create directory: ${dist_path}/${f}" && mkdir -p "${dist_path}/${f}"
|
||||
[[ ! -z $(ls -A "${base_path}/${f}") ]] && app_ensure_config_file_exist "${dist_path}/${f}" "${base_path}/${f}" $(ls -A "${base_path}/${f}")
|
||||
else
|
||||
[[ ! -e "${dist_path}/${f}" ]] && LOG_D " Copy: ${base_path}/${f} to ${dist_path}" && cp "${base_path}/${f}" "${dist_path}"
|
||||
fi
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# 检测以 "<PREFIX>" 开头的环境变量,并更新指定配置文件中对应配置项的值
|
||||
# 如果需要全部转换为小写,可使用命令: tr '[:upper:]' '[:lower:]'
|
||||
# 环境变量与配置项替换规则 : 环境变量中下划线 ==> 配置参数中特殊字符
|
||||
# - "_" ==> "-"(中划线)
|
||||
# - "__" ==> "_"(下划线)
|
||||
# - "___" ==> "."(半角点)
|
||||
#
|
||||
# 变量:
|
||||
# $1 - 配置文件
|
||||
# $2 - <PREFIX>前缀(不含结束的"_")
|
||||
app_configure_from_environment() {
|
||||
local confFile="${1:?missing file}"
|
||||
local envPrefix="${2:-APP_CFG}"
|
||||
|
||||
LOG_D "Configuration File: ${confFile}"
|
||||
|
||||
# 更新普通key-value配置文件,转换为小写后写入文件
|
||||
for var in $(eval echo \${!${envPrefix}_@}); do
|
||||
key="$(echo "$var" | sed -e 's/^'${envPrefix}'_//g' -e 's/___/./g' -e 's/__/--/g' -e 's/_/-/g' -e 's/--/_/g' | tr '[:upper:]' '[:lower:]')"
|
||||
value="${!var}"
|
||||
redis_conf_set "$key" "$value"
|
||||
LOG_D " ${key} ${value}"
|
||||
app_common_conf_set "$confFile" "$key" "$value"
|
||||
done
|
||||
}
|
||||
|
||||
@@ -32,7 +71,7 @@ redis_configure_from_env_variables() {
|
||||
# $1 - 文件
|
||||
# $2 - 变量
|
||||
# $3 - 值(列表)
|
||||
redis_common_conf_set() {
|
||||
app_common_conf_set() {
|
||||
local file="${1:?missing file}"
|
||||
local key="${2:?missing key}"
|
||||
shift
|
||||
@@ -44,7 +83,7 @@ redis_common_conf_set() {
|
||||
return 1
|
||||
elif [[ "${#values[@]}" -ne 1 ]]; then
|
||||
for i in "${!values[@]}"; do
|
||||
redis_common_conf_set "$file" "${key[$i]}" "${values[$i]}"
|
||||
app_common_conf_set "$file" "${key[$i]}" "${values[$i]}"
|
||||
done
|
||||
else
|
||||
value="${values[0]}"
|
||||
@@ -53,10 +92,30 @@ redis_common_conf_set() {
|
||||
value="${value//&/\\&}"
|
||||
value="${value//\?/\\?}"
|
||||
[[ "$value" = "" ]] && value="\"$value\""
|
||||
# Check if the value was set before
|
||||
if grep -q "^[# ]*${key} .*" "$file"; then
|
||||
# Update the existing key
|
||||
replace_in_file "$file" "^[# ]*${key} .*" "${key} ${value}" false
|
||||
# 检测配置文件中是否有相应的配置项(含以"#"起始的)
|
||||
if grep -q "^[#]*${key} .*" "$file"; then
|
||||
# 更新当前被注释掉的配置项(以“#”开始)
|
||||
case ${key} in
|
||||
include)
|
||||
if grep -q "^${key} ${value}.*" "$file"; then
|
||||
LOG_W "Duplicated include: ${value}"
|
||||
else
|
||||
LOG_D "Add new include: ${value}"
|
||||
replace_in_file "$file" "^#${key} .*" "#include /path/to/local.conf\n${key} ${value}" false
|
||||
fi
|
||||
;;
|
||||
loadmodule)
|
||||
if grep -q "^${key} ${value}.*" "$file"; then
|
||||
LOG_W "Duplicated loadmodule: ${value}"
|
||||
else
|
||||
LOG_D "Add new loadmodule: ${value}"
|
||||
replace_in_file "$file" "^#${key} .*" "#loadmodule /path/to/my_module.so\n${key} ${value}" false
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
replace_in_file "$file" "^[#]*${key} .*" "${key} ${value}" false
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# 增加一个新的配置项;如果在其他位置有类似操作,需要注意换行
|
||||
printf "\n%s %s" "$key" "$value" >>"$file"
|
||||
@@ -64,151 +123,21 @@ redis_common_conf_set() {
|
||||
fi
|
||||
}
|
||||
|
||||
# 获取配置文件中指定关键字对应的值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
redis_conf_get() {
|
||||
local key="${1:?missing key}"
|
||||
# 使用环境变量中配置,更新配置文件
|
||||
app_update_conf() {
|
||||
LOG_I "Update configure files..."
|
||||
app_configure_from_environment "${REDIS_CONF_FILE}" "REDIS_CFG"
|
||||
|
||||
grep -E "^\s*$key " "${REDIS_CONF_FILE}" | awk '{print $2}'
|
||||
}
|
||||
|
||||
# 更新 redis.conf 配置文件中指定变量值,设置关键字及对应值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
# $2 - 值(列表)
|
||||
redis_conf_set() {
|
||||
redis_common_conf_set "${REDIS_CONF_FILE}" "$@"
|
||||
}
|
||||
|
||||
# 更新 sentinel.conf 配置文件中指定变量值,设置关键字及对应值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
# $2 - 值(列表)
|
||||
redis_sentinel_conf_set() {
|
||||
redis_common_conf_set "${REDIS_SENTINEL_FILE}" "$@"
|
||||
}
|
||||
|
||||
# 更新 redis.conf 配置文件中指定变量值,取消关键字设置信息
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
redis_conf_unset() {
|
||||
local key="${1:?missing key}"
|
||||
remove_in_file "${REDIS_CONF_FILE}" "^\s*$key .*" false
|
||||
}
|
||||
|
||||
# 获取 Redis 版本信息
|
||||
redis_version() {
|
||||
redis-cli --version | grep -E -o "[0-9]+.[0-9]+.[0-9]+"
|
||||
}
|
||||
|
||||
# 获取 Redis 主版本号
|
||||
redis_major_version() {
|
||||
redis_version | grep -E -o "^[0-9]+"
|
||||
}
|
||||
|
||||
# 禁用 Redis 不安全的命令
|
||||
# 参数:
|
||||
# $1 - 待禁用的命令列表
|
||||
redis_disable_unsafe_commands() {
|
||||
# The current syntax gets a comma separated list of commands, we split them
|
||||
# before passing to redis_disable_unsafe_commands
|
||||
read -r -a disabledCommands <<< "$(tr ',' ' ' <<< "$REDIS_DISABLE_COMMANDS")"
|
||||
LOG_D "Disabling commands: ${disabledCommands[*]}"
|
||||
echo "" >> "${REDIS_CONF_FILE}"
|
||||
for cmd in "${disabledCommands[@]}"; do
|
||||
if grep -E -q "^\s*rename-command\s+$cmd\s+\"\"\s*$" "${REDIS_CONF_FILE}"; then
|
||||
LOG_D "$cmd was already disabled"
|
||||
continue
|
||||
fi
|
||||
echo "rename-command $cmd \"\"" >> "${REDIS_CONF_FILE}"
|
||||
done
|
||||
}
|
||||
|
||||
# 生成默认配置文件
|
||||
redis_generate_conf() {
|
||||
redis_conf_set port "$REDIS_PORT"
|
||||
redis_conf_set dir "${APP_DATA_DIR}"
|
||||
redis_conf_set logfile "${APP_LOG_DIR}/redis.log" # Log to stdout
|
||||
redis_conf_set pidfile "${REDIS_PID_FILE}"
|
||||
redis_conf_set daemonize no
|
||||
redis_conf_set bind 127.0.0.1 # disallow remote connections when init
|
||||
# Enable AOF https://redis.io/topics/persistence#append-only-file
|
||||
# Leave default fsync (every second)
|
||||
redis_conf_set appendonly "${REDIS_AOF_ENABLED}"
|
||||
# Disable RDB persistence, AOF persistence already enabled.
|
||||
# Ref: https://redis.io/topics/persistence#interactions-between-aof-and-rdb-persistence
|
||||
redis_conf_set save ""
|
||||
# TLS configuration
|
||||
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
|
||||
if [[ "$REDIS_PORT" == "6379" ]] && [[ "$REDIS_TLS_PORT" == "6379" ]]; then
|
||||
# If both ports are set to default values, enable TLS traffic only
|
||||
redis_conf_set port 0
|
||||
redis_conf_set tls-port "$REDIS_TLS_PORT"
|
||||
else
|
||||
# Different ports were specified
|
||||
redis_conf_set port "$REDIS_PORT"
|
||||
redis_conf_set tls-port "$REDIS_TLS_PORT"
|
||||
fi
|
||||
redis_conf_set tls-cert-file "$REDIS_TLS_CERT_FILE"
|
||||
redis_conf_set tls-key-file "$REDIS_TLS_KEY_FILE"
|
||||
redis_conf_set tls-ca-cert-file "$REDIS_TLS_CA_FILE"
|
||||
[[ -n "$REDIS_TLS_DH_PARAMS_FILE" ]] && redis_conf_set tls-dh-params-file "$REDIS_TLS_DH_PARAMS_FILE"
|
||||
redis_conf_set tls-auth-clients "$REDIS_TLS_AUTH_CLIENTS"
|
||||
fi
|
||||
|
||||
if [[ -n "$REDIS_PASSWORD" ]]; then
|
||||
redis_conf_set requirepass "$REDIS_PASSWORD"
|
||||
else
|
||||
redis_conf_unset requirepass
|
||||
fi
|
||||
if [[ -n "$REDIS_DISABLE_COMMANDS" ]]; then
|
||||
redis_disable_unsafe_commands
|
||||
fi
|
||||
}
|
||||
|
||||
# 配置 Redis 复制模式参数
|
||||
# 参数:
|
||||
# $1 - 复制模式
|
||||
redis_configure_replication() {
|
||||
LOG_I "Configuring replication mode..."
|
||||
|
||||
redis_conf_set replica-announce-ip "$(get_machine_ip)"
|
||||
redis_conf_set replica-announce-port "$REDIS_MASTER_PORT_NUMBER"
|
||||
if [[ "$REDIS_REPLICATION_MODE" = "master" ]]; then
|
||||
if [[ -n "$REDIS_PASSWORD" ]]; then
|
||||
redis_conf_set masterauth "$REDIS_PASSWORD"
|
||||
fi
|
||||
elif [[ "$REDIS_REPLICATION_MODE" =~ ^(slave|replica)$ ]]; then
|
||||
if [[ -n "$REDIS_SENTINEL_HOST" ]]; then
|
||||
local sentinel_info_command
|
||||
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
|
||||
sentinel_info_command="redis-cli -h ${REDIS_SENTINEL_HOST} -p ${REDIS_SENTINEL_PORT_NUMBER} --tls --cert ${REDIS_TLS_CERT_FILE} --key ${REDIS_TLS_KEY_FILE} --cacert ${REDIS_TLS_CA_FILE} sentinel get-master-addr-by-name ${REDIS_SENTINEL_MASTER_NAME}"
|
||||
else
|
||||
sentinel_info_command="redis-cli -h ${REDIS_SENTINEL_HOST} -p ${REDIS_SENTINEL_PORT_NUMBER} sentinel get-master-addr-by-name ${REDIS_SENTINEL_MASTER_NAME}"
|
||||
fi
|
||||
REDIS_SENTINEL_INFO=($($sentinel_info_command))
|
||||
REDIS_MASTER_HOST=${REDIS_SENTINEL_INFO[0]}
|
||||
REDIS_MASTER_PORT_NUMBER=${REDIS_SENTINEL_INFO[1]}
|
||||
fi
|
||||
LOG_I "Waitting for Redis Master ready..."
|
||||
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"
|
||||
[[ $(redis_major_version) -lt 5 ]] && parameter="slaveof"
|
||||
redis_conf_set "$parameter" "$REDIS_MASTER_HOST $REDIS_MASTER_PORT_NUMBER"
|
||||
# Configure replicas to use TLS for outgoing connections to the master
|
||||
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
|
||||
redis_conf_set tls-replication yes
|
||||
fi
|
||||
if [[ -n "$DISABLE_COMMANDS" ]]; then
|
||||
app_disable_unsafe_commands
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息
|
||||
redis_verify_minimum_env() {
|
||||
app_verify_minimum_env() {
|
||||
local error_code=0
|
||||
LOG_D "Validating settings in REDIS_* env vars..."
|
||||
|
||||
LOG_D "Validating settings in ENV vars..."
|
||||
|
||||
print_validation_error() {
|
||||
LOG_E "$1"
|
||||
@@ -216,77 +145,63 @@ redis_verify_minimum_env() {
|
||||
}
|
||||
|
||||
# Redis authentication validations
|
||||
if is_boolean_yes "$ALLOW_ANONYMOUS_LOGIN"; then
|
||||
LOG_W "You set the environment variable ALLOW_ANONYMOUS_LOGIN=${ALLOW_ANONYMOUS_LOGIN}. For safety reasons, do not use this flag in a production environment."
|
||||
elif [[ -z "$REDIS_PASSWORD" ]]; then
|
||||
print_validation_error "The REDIS_PASSWORD environment variable is empty or not set. Set the environment variable ALLOW_ANONYMOUS_LOGIN=yes to allow the container to be started with blank passwords. This is recommended only for development."
|
||||
if is_boolean_yes "$ALLOW_ANONYMOUS"; then
|
||||
LOG_W "You set the environment variable ALLOW_ANONYMOUS=${ALLOW_ANONYMOUS}. For safety reasons, do not use this flag in a production environment."
|
||||
elif [[ -z "$REDIS_CFG_REQUIREPASS" ]]; then
|
||||
print_validation_error "The REDIS_CFG_REQUIREPASS environment variable is empty or not set. Set the environment variable ALLOW_ANONYMOUS=yes to allow the container to be started with blank passwords. This is recommended only for development."
|
||||
fi
|
||||
|
||||
if [[ -n "$REDIS_REPLICATION_MODE" ]]; then
|
||||
if [[ "$REDIS_REPLICATION_MODE" =~ ^(slave|replica)$ ]]; then
|
||||
if [[ -n "$REDIS_MASTER_PORT_NUMBER" ]]; then
|
||||
if ! err=$(validate_port "$REDIS_MASTER_PORT_NUMBER"); then
|
||||
print_validation_error "An invalid port was specified in the environment variable REDIS_MASTER_PORT_NUMBER: $err"
|
||||
fi
|
||||
fi
|
||||
if ! is_boolean_yes "$ALLOW_ANONYMOUS_LOGIN" && [[ -z "$REDIS_MASTER_PASSWORD" ]]; then
|
||||
print_validation_error "The REDIS_MASTER_PASSWORD environment variable is empty or not set. Set the environment variable ALLOW_ANONYMOUS_LOGIN=yes to allow the container to be started with blank passwords. This is recommended only for development."
|
||||
fi
|
||||
elif [[ "$REDIS_REPLICATION_MODE" != "master" ]]; then
|
||||
print_validation_error "Invalid replication mode. Available options are 'master/replica'"
|
||||
fi
|
||||
fi
|
||||
|
||||
if is_boolean_yes "$REDIS_TLS_ENABLED"; then
|
||||
if [[ "$REDIS_PORT" == "$REDIS_TLS_PORT" ]] && [[ "$REDIS_PORT" != "6379" ]]; then
|
||||
# If both ports are assigned the same numbers and they are different to the default settings
|
||||
print_validation_error "Enviroment variables REDIS_PORT and REDIS_TLS_PORT point to the same port number (${REDIS_PORT}). Change one of them or disable non-TLS traffic by setting REDIS_PORT=0"
|
||||
fi
|
||||
if [[ -z "$REDIS_TLS_CERT_FILE" ]]; then
|
||||
if [[ -n "${REDIS_CFG_TLS_PORT:-}" ]]; then
|
||||
if [[ -z "${REDIS_CFG_TLS_CERT_FILE:-}" ]]; then
|
||||
print_validation_error "You must provide a X.509 certificate in order to use TLS"
|
||||
elif [[ ! -f "$REDIS_TLS_CERT_FILE" ]]; then
|
||||
print_validation_error "The X.509 certificate file in the specified path ${REDIS_TLS_CERT_FILE} does not exist"
|
||||
elif [[ ! -f "$REDIS_CFG_TLS_CERT_FILE" ]]; then
|
||||
print_validation_error "The X.509 certificate file in the specified path ${REDIS_CFG_TLS_CERT_FILE} does not exist"
|
||||
fi
|
||||
if [[ -z "$REDIS_TLS_KEY_FILE" ]]; then
|
||||
if [[ -z "${REDIS_CFG_TLS_KEY_FILE:-}" ]]; then
|
||||
print_validation_error "You must provide a private key in order to use TLS"
|
||||
elif [[ ! -f "$REDIS_TLS_KEY_FILE" ]]; then
|
||||
print_validation_error "The private key file in the specified path ${REDIS_TLS_KEY_FILE} does not exist"
|
||||
elif [[ ! -f "$REDIS_CFG_TLS_KEY_FILE" ]]; then
|
||||
print_validation_error "The private key file in the specified path ${REDIS_CFG_TLS_KEY_FILE} does not exist"
|
||||
fi
|
||||
if [[ -z "$REDIS_TLS_CA_FILE" ]]; then
|
||||
if [[ -z "${REDIS_CFG_TLS_CA_CERT_FILE:-}" ]]; then
|
||||
print_validation_error "You must provide a CA X.509 certificate in order to use TLS"
|
||||
elif [[ ! -f "$REDIS_TLS_CA_FILE" ]]; then
|
||||
print_validation_error "The CA X.509 certificate file in the specified path ${REDIS_TLS_CA_FILE} does not exist"
|
||||
elif [[ ! -f "$REDIS_CFG_TLS_CA_CERT_FILE" ]]; then
|
||||
print_validation_error "The CA X.509 certificate file in the specified path ${REDIS_CFG_TLS_CA_CERT_FILE} does not exist"
|
||||
fi
|
||||
if [[ -n "$REDIS_TLS_DH_PARAMS_FILE" ]] && [[ ! -f "$REDIS_TLS_DH_PARAMS_FILE" ]]; then
|
||||
print_validation_error "The DH param file in the specified path ${REDIS_TLS_DH_PARAMS_FILE} does not exist"
|
||||
if [[ -n "${REDIS_CFG_TLS_DH_PARAMS_FILE:-}" ]] && [[ ! -f "$REDIS_CFG_TLS_DH_PARAMS_FILE" ]]; then
|
||||
print_validation_error "The DH param file in the specified path ${REDIS_CFG_TLS_DH_PARAMS_FILE} does not exist"
|
||||
fi
|
||||
fi
|
||||
|
||||
[[ "$error_code" -eq 0 ]] || exit "$error_code"
|
||||
}
|
||||
|
||||
# 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1)
|
||||
redis_enable_remote_connections() {
|
||||
LOG_D "Modify default config to enable all IP access"
|
||||
# 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务
|
||||
app_enable_remote_connections() {
|
||||
LOG_I "Modify default config to ENABLE external IP access"
|
||||
|
||||
redis_conf_set daemonize no
|
||||
redis_conf_set bind 0.0.0.0 # Allow remote connections
|
||||
app_conf_set bind "* -::*"
|
||||
}
|
||||
|
||||
# 更改默认监听地址为 "localhost" 或 "127.0.0.1",以禁止对容器外提供服务
|
||||
app_disable_remote_connections() {
|
||||
LOG_I "Modify default config to DISABLE external IP access"
|
||||
|
||||
app_conf_set bind "127.0.0.1 -::1"
|
||||
}
|
||||
|
||||
# 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat'
|
||||
# 参数:
|
||||
# $1 - host:port
|
||||
redis_wait_service() {
|
||||
local serviceport=${1:?Missing server info}
|
||||
local service=${serviceport%%:*}
|
||||
local port=${serviceport#*:}
|
||||
app_wait_service() {
|
||||
local serviceInfo=${1:?Missing server info}
|
||||
local service=${serviceInfo%%:*}
|
||||
local port=${serviceInfo#*:}
|
||||
local retry_seconds=5
|
||||
local max_try=100
|
||||
local max_try=6
|
||||
let i=1
|
||||
|
||||
if [[ -z "$(which nc)" ]]; then
|
||||
LOG_E "Nedd nc installed before, command: \"apt-get install netcat\"."
|
||||
exit 1
|
||||
install_pkg ncat
|
||||
fi
|
||||
|
||||
LOG_I "[0/${max_try}] check for ${service}:${port}..."
|
||||
@@ -296,13 +211,12 @@ redis_wait_service() {
|
||||
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_D " [$i/${max_try}] not available yet, try in ${retry_seconds}'s latter ..."
|
||||
|
||||
LOG_I "[$i/${max_try}] try in ${retry_seconds}s once again ..."
|
||||
let "i++"
|
||||
sleep ${retry_seconds}
|
||||
|
||||
@@ -315,97 +229,89 @@ redis_wait_service() {
|
||||
}
|
||||
|
||||
# 以后台方式启动应用服务,并等待启动就绪
|
||||
redis_start_server_bg() {
|
||||
redis_is_server_running && return
|
||||
app_start_server_bg() {
|
||||
app_is_server_running && return
|
||||
|
||||
LOG_I "Starting ${APP_NAME} in background..."
|
||||
|
||||
local pass
|
||||
pass="$(cat /dev/urandom | head -n 24 | md5sum | head -c 24)"
|
||||
|
||||
export REDISCLI_AUTH="${pass}"
|
||||
|
||||
if is_boolean_yes "${ENV_DEBUG}"; then
|
||||
"redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes"
|
||||
"redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes" "--requirepass" "${pass}"
|
||||
else
|
||||
"redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes" >/dev/null 2>&1
|
||||
"redis-server" "${REDIS_CONF_FILE}" "--daemonize" "yes" "--requirepass" "${pass}" >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
local counter=3
|
||||
while ! redis_is_server_running ; do
|
||||
LOG_D "Checking ${APP_NAME} ready status..."
|
||||
local counter=10
|
||||
while ! app_is_server_running ; do
|
||||
LOG_D "Waiting for ${APP_NAME} to ready ... $counter"
|
||||
if [[ "$counter" -ne 0 ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 1;
|
||||
counter=$((counter - 1))
|
||||
done
|
||||
|
||||
# 通过命令或特定端口检测应用是否就绪
|
||||
LOG_I "Checking ${APP_NAME} ready status..."
|
||||
#wait-for-port --timeout 60 "$REDIS_PORT"
|
||||
|
||||
LOG_D "${APP_NAME} is ready for service..."
|
||||
}
|
||||
|
||||
# 停止应用服务
|
||||
redis_stop_server() {
|
||||
redis_is_server_running || return
|
||||
app_stop_server() {
|
||||
if app_is_server_running ; then
|
||||
LOG_I "Stopping ${APP_NAME}..."
|
||||
|
||||
local pass
|
||||
local port
|
||||
local args
|
||||
LOG_I "Stopping ${APP_NAME}..."
|
||||
# 已通过环境变量设置了 REDISCLI_AUTH
|
||||
if is_boolean_yes "${ENV_DEBUG}"; then
|
||||
"redis-cli" shutdown
|
||||
else
|
||||
"redis-cli" shutdown >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
pass="$(redis_conf_get "requirepass")"
|
||||
is_boolean_yes "$REDIS_TLS_ENABLED" && port="$(redis_conf_get "tls-port")" || port="$(redis_conf_get "port")"
|
||||
|
||||
[[ -n "$pass" ]] && args+=("-a" "\"$pass\"")
|
||||
[[ "$port" != "0" ]] && args+=("-p" "$port")
|
||||
#args+=("--daemonize" "yes")
|
||||
|
||||
if is_boolean_yes "${ENV_DEBUG}"; then
|
||||
"redis-cli" "${args[@]}" shutdown
|
||||
else
|
||||
"redis-cli" "${args[@]}" shutdown >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
# 检测停止是否完成
|
||||
local counter=5
|
||||
while [[ "$counter" -ne 0 ]] && is_app_server_running; do
|
||||
LOG_D "Waiting for ${APP_NAME} to stop..."
|
||||
sleep 1
|
||||
counter=$((counter - 1))
|
||||
done
|
||||
# 检测停止是否完成
|
||||
LOG_D "Checking ${APP_NAME} running status..."
|
||||
local counter=10
|
||||
while [[ "$counter" -ne 0 ]] && app_is_server_running; do
|
||||
LOG_D "Waiting for ${APP_NAME} to stop ... $counter"
|
||||
sleep 1
|
||||
counter=$((counter - 1))
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测应用服务是否在后台运行中
|
||||
redis_is_server_running() {
|
||||
app_is_server_running() {
|
||||
LOG_D "Check if ${APP_NAME} is running..."
|
||||
local pid
|
||||
pid="$(get_pid_from_file "${REDIS_PID_FILE}")"
|
||||
pid="$(get_pid_from_file '${REDIS_PID_FILE}')"
|
||||
LOG_D "${APP_NAME} PID: ${pid}"
|
||||
|
||||
if [[ -z "${pid}" ]]; then
|
||||
false
|
||||
else
|
||||
if [[ -n "${pid}" ]]; then
|
||||
is_service_running "${pid}"
|
||||
else
|
||||
false
|
||||
fi
|
||||
}
|
||||
|
||||
redis_is_server_not_running() {
|
||||
! redis_is_server_running
|
||||
app_is_server_not_running() {
|
||||
if [[ app_is_server_running == false ]]; then
|
||||
true
|
||||
else
|
||||
flse
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理初始化应用时生成的临时文件
|
||||
redis_clean_tmp_file() {
|
||||
app_clean_tmp_file() {
|
||||
LOG_D "Clean ${APP_NAME} tmp files for init..."
|
||||
|
||||
}
|
||||
|
||||
# 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动)
|
||||
redis_clean_from_restart() {
|
||||
LOG_D "Clean ${APP_NAME} tmp files for restart..."
|
||||
local -r -a files=(
|
||||
"${REDIS_PID_FILE}"
|
||||
)
|
||||
|
||||
for file in ${files[@]}; do
|
||||
if [[ -f "$file" ]]; then
|
||||
LOG_I "Cleaning stale $file file"
|
||||
LOG_D " Remove $file"
|
||||
rm "$file"
|
||||
fi
|
||||
done
|
||||
@@ -413,86 +319,31 @@ redis_clean_from_restart() {
|
||||
|
||||
# 应用默认初始化操作
|
||||
# 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件
|
||||
redis_default_init() {
|
||||
redis_clean_from_restart
|
||||
LOG_D "Check init status of ${APP_NAME}..."
|
||||
app_default_init() {
|
||||
LOG_I "Process default init for ${APP_NAME}..."
|
||||
|
||||
# 检测配置文件是否存在
|
||||
if [[ ! -f "${APP_CONF_DIR}/.app_init_flag" ]]; then
|
||||
LOG_I "No injected configuration file found, creating default config files..."
|
||||
redis_generate_conf
|
||||
|
||||
# Configure Replication mode
|
||||
if [[ -n "$REDIS_REPLICATION_MODE" ]]; then
|
||||
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"
|
||||
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..."
|
||||
|
||||
# 启动后台服务
|
||||
#redis_start_server_bg
|
||||
|
||||
|
||||
touch ${APP_DATA_DIR}/.data_init_flag
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') : Init success." >> ${APP_DATA_DIR}/.data_init_flag
|
||||
else
|
||||
LOG_I "Deploying ${APP_NAME} with persisted data..."
|
||||
fi
|
||||
}
|
||||
|
||||
# 用户自定义的前置初始化操作,依次执行目录 preinitdb.d 中的初始化脚本
|
||||
# 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_preinit_flag
|
||||
redis_custom_preinit() {
|
||||
LOG_I "Check custom pre-init status of ${APP_NAME}..."
|
||||
|
||||
# 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本
|
||||
if [ -d "/srv/conf/${APP_NAME}/preinitdb.d" ]; then
|
||||
# 检测数据存储目录是否存在已初始化标志文件;如果不存在,检索可执行脚本文件并进行初始化操作
|
||||
if [[ -n $(find "/srv/conf/${APP_NAME}/preinitdb.d/" -type f -regex ".*\.\(sh\)") ]] && \
|
||||
[[ ! -f "${APP_DATA_DIR}/.custom_preinit_flag" ]]; then
|
||||
LOG_I "Process custom pre-init scripts from /srv/conf/${APP_NAME}/preinitdb.d..."
|
||||
|
||||
# 检索所有可执行脚本,排序后执行
|
||||
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"
|
||||
LOG_I "Custom preinit for ${APP_NAME} complete."
|
||||
else
|
||||
LOG_I "Custom preinit for ${APP_NAME} already done before, skipping initialization."
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检测依赖的服务是否就绪
|
||||
#for i in ${SERVICE_PRECONDITION[@]}; do
|
||||
# redis_wait_service "${i}"
|
||||
#done
|
||||
app_update_conf
|
||||
app_enable_remote_connections
|
||||
}
|
||||
|
||||
# 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本
|
||||
# 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag
|
||||
redis_custom_init() {
|
||||
LOG_I "Check custom initdb status of ${APP_NAME}..."
|
||||
app_custom_init() {
|
||||
LOG_I "Process customer init ${APP_NAME}..."
|
||||
|
||||
# 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本
|
||||
if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then
|
||||
if [ -d "${APP_CONF_DIR}/initdb.d" ]; then
|
||||
# 检测数据存储目录是否存在已初始化标志文件;如果不存在,检索可执行脚本文件并进行初始化操作
|
||||
if [[ -n $(find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)") ]] && \
|
||||
if [[ -n $(find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)") ]] && \
|
||||
[[ ! -f "${APP_DATA_DIR}/.custom_init_flag" ]]; then
|
||||
LOG_I "Process custom init scripts from /srv/conf/${APP_NAME}/initdb.d..."
|
||||
LOG_I "Process custom init scripts from ${APP_CONF_DIR}/initdb.d..."
|
||||
|
||||
# 启动后台服务
|
||||
#redis_start_server_bg
|
||||
app_disable_remote_connections
|
||||
app_start_server_bg
|
||||
|
||||
# 检索所有可执行脚本,排序后执行
|
||||
find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do
|
||||
find "${APP_CONF_DIR}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do
|
||||
case "$f" in
|
||||
*.sh)
|
||||
if [[ -x "$f" ]]; then
|
||||
@@ -501,15 +352,7 @@ redis_custom_init() {
|
||||
LOG_D "Sourcing $f"; . "$f"
|
||||
fi
|
||||
;;
|
||||
*.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
|
||||
@@ -517,18 +360,49 @@ redis_custom_init() {
|
||||
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."
|
||||
|
||||
# 检测服务是否运行中;如果运行,则停止后台服务
|
||||
app_is_server_running && app_stop_server
|
||||
app_clean_tmp_file
|
||||
app_enable_remote_connections
|
||||
else
|
||||
LOG_I "Custom init for ${APP_NAME} already done before, skipping initialization."
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检测服务是否运行中;如果运行,则停止后台服务
|
||||
redis_is_server_running && redis_stop_server
|
||||
|
||||
# 删除第一次运行生成的临时文件
|
||||
redis_clean_tmp_file
|
||||
|
||||
# 绑定所有 IP ,启用远程访问
|
||||
redis_enable_remote_connections
|
||||
}
|
||||
|
||||
# 更新 redis.conf 配置文件中指定变量值,设置关键字及对应值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
# $2 - 值(列表)
|
||||
app_conf_set() {
|
||||
app_common_conf_set "${REDIS_CONF_FILE}" "$@"
|
||||
}
|
||||
|
||||
# 获取配置文件中指定关键字对应的值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
app_conf_get() {
|
||||
local key="${1:?missing key}"
|
||||
|
||||
grep -E "^$key " "${REDIS_CONF_FILE}" | awk '{print $2}'
|
||||
}
|
||||
|
||||
# 禁用 Redis 不安全的命令
|
||||
# 参数:
|
||||
# $1 - 待禁用的命令列表
|
||||
app_disable_unsafe_commands() {
|
||||
# The current syntax gets a comma(",") separated list of commands, we split them
|
||||
# before passing to redis_disable_unsafe_commands
|
||||
read -r -a disabledCommands <<< "$(tr ',' ' ' <<< "$DISABLE_COMMANDS")"
|
||||
LOG_D "Disabling commands: ${disabledCommands[*]}"
|
||||
echo "" >> "${REDIS_CONF_FILE}"
|
||||
for cmd in "${disabledCommands[@]}"; do
|
||||
if grep -E -q "^\s*rename-command\s+$cmd\s+\"\"\s*$" "${REDIS_CONF_FILE}"; then
|
||||
LOG_D "$cmd was already disabled"
|
||||
continue
|
||||
fi
|
||||
echo "rename-command $cmd \"\"" >> "${REDIS_CONF_FILE}"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +1,31 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
#!/usr/bin/dumb-init /bin/bash
|
||||
# Ver: 1.5 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 容器入口脚本
|
||||
# 容器入口脚本;当前脚本执行完毕时,使用默认用户执行镜像 CMD 定义的命令(默认为'/usr/local/bin/run.sh')
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错(errexit); -u: 变量未定义则报错(nounset); -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
. /colovu/lib/libcommon.sh # 加载通用函数库
|
||||
. /colovu/lib/libcommon.sh # 加载通用函数库
|
||||
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
|
||||
LOG_I "** Processing entry.sh **"
|
||||
|
||||
if [[ "$*" = "/usr/local/bin/run.sh" ]]; then
|
||||
print_image_welcome
|
||||
# 优先处理'-'开始的版本信息、帮助信息显示命令,如果是该类命令,处理后退出容器
|
||||
[[ "${1:0:1}" == '-' ]] && set -- "${APP_EXEC:-/bin/bash}" "$@" && print_command_help "$@"
|
||||
|
||||
LOG_I "** Starting ${APP_NAME} setup **"
|
||||
# 处理 root 用户**且**使用默认启动脚本时的初始化
|
||||
if [[ "$(id -u)" == '0' ]] && [[ "$1" == "run.sh" ]]; then
|
||||
print_welcome_info
|
||||
/usr/local/bin/setup.sh
|
||||
/usr/local/bin/init.sh
|
||||
LOG_I "** ${APP_NAME} setup finished! **"
|
||||
|
||||
# 执行应用启动脚本并替换当前进程
|
||||
exec gosu "${APP_USER}" "$@"
|
||||
fi
|
||||
|
||||
# 检测是否仅打印帮助信息
|
||||
[ "${1:0:1}" = '-' ] && set -- "${APP_EXEC:-/bin/bash}" "$@"
|
||||
print_command_help "$@"
|
||||
|
||||
# 处理非以上情形的自定义命令
|
||||
LOG_I "Start container with command: $@"
|
||||
exec "$@"
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.1 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用环境变量定义及初始化
|
||||
|
||||
# 通用设置
|
||||
export ENV_DEBUG=${ENV_DEBUG:-false}
|
||||
export ALLOW_ANONYMOUS_LOGIN="${ALLOW_ANONYMOUS_LOGIN:-no}"
|
||||
export ALLOW_ANONYMOUS="${ALLOW_ANONYMOUS:-no}"
|
||||
|
||||
# 通过读取变量名对应的 *_FILE 文件,获取变量值;如果对应文件存在,则通过传入参数设置的变量值会被文件中对应的值覆盖
|
||||
# 通过读取变量名对应的`*_FILE`文件,获取变量值
|
||||
# 变量优先级: *_FILE > 传入变量 > 默认值
|
||||
app_env_file_lists=(
|
||||
REDIS_PASSWORD
|
||||
REDIS_MASTER_PASSWORD
|
||||
PASSWORD
|
||||
MASTER_PASSWORD
|
||||
)
|
||||
for env_var in "${app_env_file_lists[@]}"; do
|
||||
file_env_var="${env_var}_FILE"
|
||||
@@ -22,59 +21,43 @@ for env_var in "${app_env_file_lists[@]}"; do
|
||||
done
|
||||
unset app_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}"
|
||||
# 应用路径参数(Dockerfile 已定义:APP_NAME、APP_VER,可能定义 APP_USER、APP_EXEC)
|
||||
export APP_EXEC="${APP_EXEC:-${APP_NAME}}"
|
||||
export APP_USER="${APP_USER:-${APP_NAME}}"
|
||||
export APP_GROUP="${APP_USER:-${APP_NAME}}"
|
||||
export APP_HOME="${APP_HOME:-/srv/${APP_NAME}}"
|
||||
export APP_BASE="${APP_BASE:-/usr/local/${APP_NAME}}"
|
||||
|
||||
export APP_DEF_DIR="${APP_BASE}/etc/${APP_NAME}"
|
||||
export APP_CONF_DIR="/srv/${APP_NAME}/conf"
|
||||
export APP_DATA_DIR="/srv/${APP_NAME}/data"
|
||||
export APP_CERT_DIR="/srv/${APP_NAME}/cert"
|
||||
export APP_LOG_DIR="/srv/${APP_NAME}/log"
|
||||
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"
|
||||
# Config files
|
||||
export REDIS_CONF_FILE="${REDIS_CONF_FILE:-${APP_CONF_DIR}/redis.conf}"
|
||||
export REDIS_SENTINEL_FILE="${REDIS_SENTINEL_FILE:-${APP_CONF_DIR}/sentinel.conf}"
|
||||
export REDIS_PID_FILE="${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 Settings
|
||||
export DISABLE_COMMANDS=${DISABLE_COMMANDS:-}
|
||||
|
||||
# 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:-}"
|
||||
if [[ -n "${REDIS_CFG_TLS_PORT:-}" ]]; then
|
||||
[[ "${REDIS_CFG_TLS_PORT}" == "${REDIS_CFG_PORT:-}" ]] && export REDIS_CFG_PORT=0
|
||||
fi
|
||||
|
||||
# 应用配置参数
|
||||
|
||||
# 内部变量
|
||||
export APP_PID_FILE="${REDIS_PID_FILE:-${APP_RUN_DIR}/${APP_NAME}.pid}"
|
||||
|
||||
export APP_DAEMON_USER="${APP_NAME}"
|
||||
export APP_DAEMON_GROUP="${APP_NAME}"
|
||||
# Sentinel configuration
|
||||
export REDIS_SENTINEL_HOST="${REDIS_SENTINEL_HOST:-}"
|
||||
export REDIS_SENTINEL_QUORUM="${REDIS_SENTINEL_QUORUM:-2}"
|
||||
export REDIS_SENTINEL_MASTER_NAME="${REDIS_SENTINEL_MASTER_NAME:-cvmaster}"
|
||||
export REDIS_SENTINEL_PORT_NUMBER="${REDIS_SENTINEL_PORT_NUMBER:-26379}"
|
||||
|
||||
# 个性化变量
|
||||
# 如果设置了用户密码,设置环境变量 REDISCLI_AUTH,用于 `redis-cli` 登录时使用;不显示输入,保证安全
|
||||
if [[ -n "${REDIS_PASSWORD}" ]]; then
|
||||
export REDISCLI_AUTH="${REDIS_PASSWORD:-}"
|
||||
if [[ -n "${REDIS_CFG_REQUIREPASS:-}" ]]; then
|
||||
export REDISCLI_AUTH="${REDIS_CFG_REQUIREPASS:-}"
|
||||
fi
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用初始化脚本
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错; -u: 变量未定义则报错; -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
|
||||
LOG_I "** Processing init.sh **"
|
||||
trap "app_stop_server" EXIT
|
||||
|
||||
trap "${APP_NAME}_stop_server" EXIT
|
||||
|
||||
${APP_NAME}_verify_minimum_env
|
||||
|
||||
# 执行应用预初始化操作
|
||||
${APP_NAME}_custom_preinit
|
||||
app_verify_minimum_env
|
||||
|
||||
# 执行应用初始化操作
|
||||
${APP_NAME}_default_init
|
||||
app_default_init
|
||||
|
||||
# 执行用户自定义初始化脚本
|
||||
${APP_NAME}_custom_init
|
||||
|
||||
LOG_I "** Processing init.sh finished! **"
|
||||
app_custom_init
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.5 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.6 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用启动脚本
|
||||
# 应用启动脚本;组合默认的配置参数及容器启动时传入的 CMD 参数,启动应用
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错(errexit); -u: 变量未定义则报错(nounset); -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
. /colovu/lib/liblog.sh # 日志输出函数库
|
||||
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
|
||||
LOG_I "** Processing run.sh **"
|
||||
|
||||
readonly START_COMMAND="$(command -v ${APP_EXEC})"
|
||||
readonly START_COMMAND="$(command -v ${APP_EXEC:-${APP_NAME}})"
|
||||
|
||||
# 配置默认启动参数(应用配置文件、前台方式启动)
|
||||
flags=("${REDIS_CONF_FILE:-}" "--daemonize" "no")
|
||||
# 将启动时使用 REDIS_EXTRA_FLAGS 指定的参数附加在启动参数中
|
||||
[[ -z "${REDIS_EXTRA_FLAGS:-}" ]] || flags+=("${REDIS_EXTRA_FLAGS[@]}")
|
||||
# 增加 "@" 以使用用户在命令行添加的扩展标识
|
||||
flags=("${REDIS_CONF_FILE}" "--daemonize" "no")
|
||||
[[ -n "${APP_EXTRA_FLAGS:-}" ]] && flags+=("${APP_EXTRA_FLAGS[@]}")
|
||||
flags+=("$@")
|
||||
|
||||
LOG_I "** Starting ${APP_NAME} **"
|
||||
#is_root && flags=("-u" "$APP_DAEMON_USER" "${flags[@]}")
|
||||
|
||||
LOG_I "Command: ${START_COMMAND[@]} ${flags[@]}"
|
||||
LOG_I "Start ${APP_NAME} with command: ${START_COMMAND[@]} ${flags[@]}"
|
||||
exec "${START_COMMAND[@]}" "${flags[@]}"
|
||||
|
||||
@@ -1,34 +1,35 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用环境及依赖文件设置脚本
|
||||
# 应用环境及依赖文件设置脚本;当前脚本以‘root’用户执行
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错(errexit); -u: 变量未定义则报错(nounset); -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
. /colovu/lib/libcommon.sh # 加载通用函数库
|
||||
. /colovu/lib/libfs.sh # 加载文件操作函数库
|
||||
. /colovu/lib/libos.sh # 加载系统管理函数库
|
||||
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
|
||||
LOG_I "** Processing setup.sh **"
|
||||
|
||||
APP_DIRS="${APP_CONF_DIR:-} ${APP_DATA_DIR:-} ${APP_LOG_DIR:-} ${APP_CERT_DIR:-} ${APP_DATA_LOG_DIR:-}"
|
||||
APP_DIRS=(/var/log/${APP_NAME} /var/run/${APP_NAME} /var/cache/${APP_NAME} ${APP_HOME})
|
||||
APP_DIRS+=(${APP_HOME}/conf ${APP_HOME}/data ${APP_HOME}/cert ${APP_HOME}/log)
|
||||
|
||||
LOG_I "Ensure directory exists: ${APP_DIRS}"
|
||||
for dir in ${APP_DIRS}; do
|
||||
LOG_I "Ensure directory exists: ${APP_DIRS[@]}"
|
||||
for dir in ${APP_DIRS[@]}; do
|
||||
ensure_dir_exists ${dir}
|
||||
done
|
||||
|
||||
# 检测指定文件是否在配置文件存储目录存在,如果不存在则拷贝(新挂载数据卷、手动删除都会导致不存在)
|
||||
LOG_I "Check config files in: ${APP_CONF_DIR}"
|
||||
if [[ ! -z "$(ls -A "${APP_DEF_DIR}")" ]]; then
|
||||
ensure_config_file_exist "${APP_DEF_DIR}" $(ls -A "${APP_DEF_DIR}")
|
||||
if [[ -z "$(ls -A "${APP_CONF_DIR}")" ]]; then
|
||||
app_ensure_config_file_exist "${APP_CONF_DIR}" "${APP_DEF_DIR}" $(ls -A "${APP_DEF_DIR}")
|
||||
fi
|
||||
|
||||
is_root && ensure_user_exists "$APP_DAEMON_USER" -g "$APP_DAEMON_GROUP"
|
||||
|
||||
LOG_I "** Processing setup.sh finished! **"
|
||||
# 解决使用non-root后,[emerg] open() "/dev/stdout" failed (13: Permission denied)
|
||||
LOG_D "Change permissions of stdout/stderr to 0662"
|
||||
chmod 0662 /dev/stdout /dev/stderr
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
# Ver: 1.0 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 在安装完应用后,使用该脚本修改默认配置文件中部分配置项; 如果相应的配置项已经定义为容器环境变量,则不需要在这里修改
|
||||
|
||||
# 定义要修改的文件
|
||||
CONF_FILE="${APP_DEF_DIR}/redis.conf"
|
||||
echo "Process overrides for: ${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/^#?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}"
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash -e
|
||||
# Ver: 1.0 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 在安装完应用后,使用该脚本修改默认配置文件中部分配置项; 如果相应的配置项已经定义为容器环境变量,则不需要在这里修改
|
||||
|
||||
# 定义要修改的文件
|
||||
CONF_FILE="/usr/local/${APP_NAME}/etc/${APP_NAME}/redis.conf"
|
||||
echo "Process overrides for: ${CONF_FILE}"
|
||||
# 修改默认配置信息
|
||||
sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis.pid/g' "${CONF_FILE}"
|
||||
sed -i -E 's/^#?logfile .*/logfile \"\/srv\/redis\/log\/redis.log\"/g' "${CONF_FILE}"
|
||||
sed -i -E 's/^#?protected-mode .*/protected-mode no/g' "${CONF_FILE}"
|
||||
sed -i -E 's/^#?daemonize .*/daemonize no/g' "${CONF_FILE}"
|
||||
sed -i -E 's/^#?dir .*/dir \/srv\/'${APP_NAME}'\/data/g' "${CONF_FILE}"
|
||||
|
||||
SENTINEL_FILE="/usr/local/${APP_NAME}/etc/${APP_NAME}/sentinel.conf"
|
||||
echo "Process overrides for: ${SENTINEL_FILE}"
|
||||
# 修改 Sentinel 默认配置信息
|
||||
sed -i -E 's/^#?pidfile .*/pidfile \/var\/run\/redis\/redis-sentinel.pid/g' "${SENTINEL_FILE}"
|
||||
sed -i -E 's/^#?logfile .*/logfile \"\/srv\/redis\/log\/redis-sentinel.log\"/g' "${SENTINEL_FILE}"
|
||||
sed -i -E 's/^#?protected-mode .*/protected-mode no/g' "${SENTINEL_FILE}"
|
||||
sed -i -E 's/^#?daemonize .*/daemonize no/g' "${SENTINEL_FILE}"
|
||||
sed -i -E 's/^#?dir .*/dir \/srv\/'${APP_NAME}'\/data/g' "${CONF_FILE}"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,342 @@
|
||||
# Example sentinel.conf
|
||||
# 本文件经过变更,删除了配置项前的前置空格(“#”与关键字之间),以便后续可以使用 sed 进行处理
|
||||
|
||||
# *** IMPORTANT ***
|
||||
#
|
||||
# By default Sentinel will not be reachable from interfaces different than
|
||||
# localhost, either use the 'bind' directive to bind to a list of network
|
||||
# interfaces, or disable protected mode with "protected-mode no" by
|
||||
# adding it to this configuration file.
|
||||
#
|
||||
# Before doing that MAKE SURE the instance is protected from the outside
|
||||
# world via firewalling or other means.
|
||||
#
|
||||
# For example you may use one of the following:
|
||||
#
|
||||
# bind 127.0.0.1 192.168.1.1
|
||||
#
|
||||
#protected-mode no
|
||||
|
||||
# port <sentinel-port>
|
||||
# The port that this sentinel instance will run on
|
||||
port 26379
|
||||
|
||||
# By default Redis Sentinel does not run as a daemon. Use 'yes' if you need it.
|
||||
# Note that Redis will write a pid file in /var/run/redis-sentinel.pid when
|
||||
# daemonized.
|
||||
daemonize no
|
||||
|
||||
# When running daemonized, Redis Sentinel writes a pid file in
|
||||
# /var/run/redis-sentinel.pid by default. You can specify a custom pid file
|
||||
# location here.
|
||||
pidfile /var/run/redis-sentinel.pid
|
||||
|
||||
# Specify the log file name. Also the empty string can be used to force
|
||||
# Sentinel to log on the standard output. Note that if you use standard
|
||||
# output for logging but daemonize, logs will be sent to /dev/null
|
||||
logfile ""
|
||||
|
||||
# sentinel announce-ip <ip>
|
||||
# sentinel announce-port <port>
|
||||
#
|
||||
# The above two configuration directives are useful in environments where,
|
||||
# because of NAT, Sentinel is reachable from outside via a non-local address.
|
||||
#
|
||||
# When announce-ip is provided, the Sentinel will claim the specified IP address
|
||||
# in HELLO messages used to gossip its presence, instead of auto-detecting the
|
||||
# local address as it usually does.
|
||||
#
|
||||
# Similarly when announce-port is provided and is valid and non-zero, Sentinel
|
||||
# will announce the specified TCP port.
|
||||
#
|
||||
# The two options don't need to be used together, if only announce-ip is
|
||||
# provided, the Sentinel will announce the specified IP and the server port
|
||||
# as specified by the "port" option. If only announce-port is provided, the
|
||||
# Sentinel will announce the auto-detected local IP and the specified port.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
#sentinel announce-ip 1.2.3.4
|
||||
|
||||
# dir <working-directory>
|
||||
# Every long running process should have a well-defined working directory.
|
||||
# For Redis Sentinel to chdir to /tmp at startup is the simplest thing
|
||||
# for the process to don't interfere with administrative tasks such as
|
||||
# unmounting filesystems.
|
||||
dir /tmp
|
||||
|
||||
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
|
||||
#
|
||||
# Tells Sentinel to monitor this master, and to consider it in O_DOWN
|
||||
# (Objectively Down) state only if at least <quorum> sentinels agree.
|
||||
#
|
||||
# Note that whatever is the ODOWN quorum, a Sentinel will require to
|
||||
# be elected by the majority of the known Sentinels in order to
|
||||
# start a failover, so no failover can be performed in minority.
|
||||
#
|
||||
# Replicas are auto-discovered, so you don't need to specify replicas in
|
||||
# any way. Sentinel itself will rewrite this configuration file adding
|
||||
# the replicas using additional configuration options.
|
||||
# Also note that the configuration file is rewritten when a
|
||||
# replica is promoted to master.
|
||||
#
|
||||
# Note: master name should not include special characters or spaces.
|
||||
# The valid charset is A-z 0-9 and the three characters ".-_".
|
||||
sentinel monitor mymaster 127.0.0.1 6379 2
|
||||
|
||||
# sentinel auth-pass <master-name> <password>
|
||||
#
|
||||
# Set the password to use to authenticate with the master and replicas.
|
||||
# Useful if there is a password set in the Redis instances to monitor.
|
||||
#
|
||||
# Note that the master password is also used for replicas, so it is not
|
||||
# possible to set a different password in masters and replicas instances
|
||||
# if you want to be able to monitor these instances with Sentinel.
|
||||
#
|
||||
# However you can have Redis instances without the authentication enabled
|
||||
# mixed with Redis instances requiring the authentication (as long as the
|
||||
# password set is the same for all the instances requiring the password) as
|
||||
# the AUTH command will have no effect in Redis instances with authentication
|
||||
# switched off.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
#sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
|
||||
|
||||
#sentinel auth-user <master-name> <username>
|
||||
#
|
||||
# This is useful in order to authenticate to instances having ACL capabilities,
|
||||
# that is, running Redis 6.0 or greater. When just auth-pass is provided the
|
||||
# Sentinel instance will authenticate to Redis using the old "AUTH <pass>"
|
||||
# method. When also an username is provided, it will use "AUTH <user> <pass>".
|
||||
# In the Redis servers side, the ACL to provide just minimal access to
|
||||
# Sentinel instances, should be configured along the following lines:
|
||||
#
|
||||
# user sentinel-user >somepassword +client +subscribe +publish \
|
||||
# +ping +info +multi +slaveof +config +client +exec on
|
||||
|
||||
# sentinel down-after-milliseconds <master-name> <milliseconds>
|
||||
#
|
||||
# Number of milliseconds the master (or any attached replica or sentinel) should
|
||||
# be unreachable (as in, not acceptable reply to PING, continuously, for the
|
||||
# specified period) in order to consider it in S_DOWN state (Subjectively
|
||||
# Down).
|
||||
#
|
||||
# Default is 30 seconds.
|
||||
sentinel down-after-milliseconds mymaster 30000
|
||||
|
||||
# IMPORTANT NOTE: starting with Redis 6.2 ACL capability is supported for
|
||||
# Sentinel mode, please refer to the Redis website https://redis.io/topics/acl
|
||||
# for more details.
|
||||
|
||||
# Sentinel's ACL users are defined in the following format:
|
||||
#
|
||||
# user <username> ... acl rules ...
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# user worker +@admin +@connection ~* on >ffa9203c493aa99
|
||||
#
|
||||
# For more information about ACL configuration please refer to the Redis
|
||||
# website at https://redis.io/topics/acl and redis server configuration
|
||||
# template redis.conf.
|
||||
|
||||
# ACL LOG
|
||||
#
|
||||
# The ACL Log tracks failed commands and authentication events associated
|
||||
# with ACLs. The ACL Log is useful to troubleshoot failed commands blocked
|
||||
# by ACLs. The ACL Log is stored in memory. You can reclaim memory with
|
||||
# ACL LOG RESET. Define the maximum entry length of the ACL Log below.
|
||||
acllog-max-len 128
|
||||
|
||||
# Using an external ACL file
|
||||
#
|
||||
# Instead of configuring users here in this file, it is possible to use
|
||||
# a stand-alone file just listing users. The two methods cannot be mixed:
|
||||
# if you configure users here and at the same time you activate the external
|
||||
# ACL file, the server will refuse to start.
|
||||
#
|
||||
# The format of the external ACL user file is exactly the same as the
|
||||
# format that is used inside redis.conf to describe users.
|
||||
#
|
||||
#aclfile /etc/redis/sentinel-users.acl
|
||||
|
||||
#requirepass <password>
|
||||
#
|
||||
# You can configure Sentinel itself to require a password, however when doing
|
||||
# so Sentinel will try to authenticate with the same password to all the
|
||||
# other Sentinels. So you need to configure all your Sentinels in a given
|
||||
# group with the same "requirepass" password. Check the following documentation
|
||||
# for more info: https://redis.io/topics/sentinel
|
||||
#
|
||||
# IMPORTANT NOTE: starting with Redis 6.2 "requirepass" is a compatibility
|
||||
# layer on top of the ACL system. The option effect will be just setting
|
||||
# the password for the default user. Clients will still authenticate using
|
||||
# AUTH <password> as usually, or more explicitly with AUTH default <password>
|
||||
# if they follow the new protocol: both will work.
|
||||
#
|
||||
# New config files are advised to use separate authentication control for
|
||||
# incoming connections (via ACL), and for outgoing connections (via
|
||||
# sentinel-user and sentinel-pass)
|
||||
#
|
||||
# The requirepass is not compatable with aclfile option and the ACL LOAD
|
||||
# command, these will cause requirepass to be ignored.
|
||||
|
||||
#sentinel sentinel-user <username>
|
||||
#
|
||||
# You can configure Sentinel to authenticate with other Sentinels with specific
|
||||
# user name.
|
||||
|
||||
#sentinel sentinel-pass <password>
|
||||
#
|
||||
# The password for Sentinel to authenticate with other Sentinels. If sentinel-user
|
||||
# is not configured, Sentinel will use 'default' user with sentinel-pass to authenticate.
|
||||
|
||||
# sentinel parallel-syncs <master-name> <numreplicas>
|
||||
#
|
||||
# How many replicas we can reconfigure to point to the new replica simultaneously
|
||||
# during the failover. Use a low number if you use the replicas to serve query
|
||||
# to avoid that all the replicas will be unreachable at about the same
|
||||
# time while performing the synchronization with the master.
|
||||
sentinel parallel-syncs mymaster 1
|
||||
|
||||
# sentinel failover-timeout <master-name> <milliseconds>
|
||||
#
|
||||
# Specifies the failover timeout in milliseconds. It is used in many ways:
|
||||
#
|
||||
# - The time needed to re-start a failover after a previous failover was
|
||||
# already tried against the same master by a given Sentinel, is two
|
||||
# times the failover timeout.
|
||||
#
|
||||
# - The time needed for a replica replicating to a wrong master according
|
||||
# to a Sentinel current configuration, to be forced to replicate
|
||||
# with the right master, is exactly the failover timeout (counting since
|
||||
# the moment a Sentinel detected the misconfiguration).
|
||||
#
|
||||
# - The time needed to cancel a failover that is already in progress but
|
||||
# did not produced any configuration change (SLAVEOF NO ONE yet not
|
||||
# acknowledged by the promoted replica).
|
||||
#
|
||||
# - The maximum time a failover in progress waits for all the replicas to be
|
||||
# reconfigured as replicas of the new master. However even after this time
|
||||
# the replicas will be reconfigured by the Sentinels anyway, but not with
|
||||
# the exact parallel-syncs progression as specified.
|
||||
#
|
||||
# Default is 3 minutes.
|
||||
sentinel failover-timeout mymaster 180000
|
||||
|
||||
# SCRIPTS EXECUTION
|
||||
#
|
||||
# sentinel notification-script and sentinel reconfig-script are used in order
|
||||
# to configure scripts that are called to notify the system administrator
|
||||
# or to reconfigure clients after a failover. The scripts are executed
|
||||
# with the following rules for error handling:
|
||||
#
|
||||
# If script exits with "1" the execution is retried later (up to a maximum
|
||||
# number of times currently set to 10).
|
||||
#
|
||||
# If script exits with "2" (or an higher value) the script execution is
|
||||
# not retried.
|
||||
#
|
||||
# If script terminates because it receives a signal the behavior is the same
|
||||
# as exit code 1.
|
||||
#
|
||||
# A script has a maximum running time of 60 seconds. After this limit is
|
||||
# reached the script is terminated with a SIGKILL and the execution retried.
|
||||
|
||||
# NOTIFICATION SCRIPT
|
||||
#
|
||||
# sentinel notification-script <master-name> <script-path>
|
||||
#
|
||||
# Call the specified notification script for any sentinel event that is
|
||||
# generated in the WARNING level (for instance -sdown, -odown, and so forth).
|
||||
# This script should notify the system administrator via email, SMS, or any
|
||||
# other messaging system, that there is something wrong with the monitored
|
||||
# Redis systems.
|
||||
#
|
||||
# The script is called with just two arguments: the first is the event type
|
||||
# and the second the event description.
|
||||
#
|
||||
# The script must exist and be executable in order for sentinel to start if
|
||||
# this option is provided.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
#sentinel notification-script mymaster /var/redis/notify.sh
|
||||
|
||||
# CLIENTS RECONFIGURATION SCRIPT
|
||||
#
|
||||
# sentinel client-reconfig-script <master-name> <script-path>
|
||||
#
|
||||
# When the master changed because of a failover a script can be called in
|
||||
# order to perform application-specific tasks to notify the clients that the
|
||||
# configuration has changed and the master is at a different address.
|
||||
#
|
||||
# The following arguments are passed to the script:
|
||||
#
|
||||
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
|
||||
#
|
||||
# <state> is currently always "failover"
|
||||
# <role> is either "leader" or "observer"
|
||||
#
|
||||
# The arguments from-ip, from-port, to-ip, to-port are used to communicate
|
||||
# the old address of the master and the new address of the elected replica
|
||||
# (now a master).
|
||||
#
|
||||
# This script should be resistant to multiple invocations.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
#sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
|
||||
|
||||
# SECURITY
|
||||
#
|
||||
# By default SENTINEL SET will not be able to change the notification-script
|
||||
# and client-reconfig-script at runtime. This avoids a trivial security issue
|
||||
# where clients can set the script to anything and trigger a failover in order
|
||||
# to get the program executed.
|
||||
|
||||
sentinel deny-scripts-reconfig yes
|
||||
|
||||
# REDIS COMMANDS RENAMING
|
||||
#
|
||||
# Sometimes the Redis server has certain commands, that are needed for Sentinel
|
||||
# to work correctly, renamed to unguessable strings. This is often the case
|
||||
# of CONFIG and SLAVEOF in the context of providers that provide Redis as
|
||||
# a service, and don't want the customers to reconfigure the instances outside
|
||||
# of the administration console.
|
||||
#
|
||||
# In such case it is possible to tell Sentinel to use different command names
|
||||
# instead of the normal ones. For example if the master "mymaster", and the
|
||||
# associated replicas, have "CONFIG" all renamed to "GUESSME", I could use:
|
||||
#
|
||||
# SENTINEL rename-command mymaster CONFIG GUESSME
|
||||
#
|
||||
# After such configuration is set, every time Sentinel would use CONFIG it will
|
||||
# use GUESSME instead. Note that there is no actual need to respect the command
|
||||
# case, so writing "config guessme" is the same in the example above.
|
||||
#
|
||||
# SENTINEL SET can also be used in order to perform this configuration at runtime.
|
||||
#
|
||||
# In order to set a command back to its original name (undo the renaming), it
|
||||
# is possible to just rename a command to itself:
|
||||
#
|
||||
#SENTINEL rename-command mymaster CONFIG CONFIG
|
||||
|
||||
# HOSTNAMES SUPPORT
|
||||
#
|
||||
# Normally Sentinel uses only IP addresses and requires SENTINEL MONITOR
|
||||
# to specify an IP address. Also, it requires the Redis replica-announce-ip
|
||||
# keyword to specify only IP addresses.
|
||||
#
|
||||
# You may enable hostnames support by enabling resolve-hostnames. Note
|
||||
# that you must make sure your DNS is configured properly and that DNS
|
||||
# resolution does not introduce very long delays.
|
||||
#
|
||||
SENTINEL resolve-hostnames no
|
||||
|
||||
# When resolve-hostnames is enabled, Sentinel still uses IP addresses
|
||||
# when exposing instances to users, configuration files, etc. If you want
|
||||
# to retain the hostnames when announced, enable announce-hostnames below.
|
||||
#
|
||||
SENTINEL announce-hostnames no
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行)
|
||||
set -eux
|
||||
groupadd --gid 1001 --system ${APP_USER}
|
||||
#useradd --gid 1001 --uid 1001 --shell /bin/bash --home /srv/data/${APP_NAME} --system ${APP_USER}
|
||||
useradd --gid 1001 --uid 1001 --shell /usr/sbin/nologin --home /srv/data/${APP_NAME} --system ${APP_USER}
|
||||
|
||||
# 如果需要 sudo 权限,需要在 Dockerfile 中安装 su 软件包:RUN install_pkg sudo
|
||||
#sed -i -e 's/^\sDefaults\s*secure_path\s*=/# Defaults secure_path=/' /etc/sudoers
|
||||
#echo "${APP_USER} ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行)
|
||||
set -eux
|
||||
|
||||
APP_DIRS=" \
|
||||
/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}
|
||||
chmod -R g+rwX ${APP_DIRS} /usr/local/${APP_NAME}
|
||||
|
||||
# 针对对用户有特殊要求的应用,创建对应的默认用户,并将相关目录赋予该用户操作权限
|
||||
#chown -Rf ${APP_USER}:${APP_USER} ${APP_DIRS}
|
||||
@@ -6,30 +6,27 @@ version: '3.8'
|
||||
# 当前配置仅保证可以启动容器;更多配置参数请参考镜像 README.md 文档中说明
|
||||
|
||||
services:
|
||||
redis:
|
||||
image: 'colovu/redis:latest'
|
||||
redis-master:
|
||||
image: 'registry.cn-shenzhen.aliyuncs.com/colovu/redis:latest'
|
||||
ports:
|
||||
- '6379'
|
||||
environment:
|
||||
- REDIS_REPLICATION_MODE=master
|
||||
- REDIS_PASSWORD=colovu
|
||||
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
- REDIS_CFG_REQUIREPASS=colovu
|
||||
- DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
volumes:
|
||||
- 'redis_data:/srv/data'
|
||||
|
||||
redis-replica:
|
||||
image: 'colovu/redis:latest'
|
||||
image: 'registry.cn-shenzhen.aliyuncs.com/colovu/redis:latest'
|
||||
ports:
|
||||
- '6379'
|
||||
environment:
|
||||
- REDIS_REPLICATION_MODE=slave
|
||||
- REDIS_MASTER_HOST=redis
|
||||
- REDIS_MASTER_PORT_NUMBER=6379
|
||||
- REDIS_MASTER_PASSWORD=colovu
|
||||
- REDIS_PASSWORD=colovu
|
||||
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
- REDIS_CFG_REPLICAOF="redis-master 6379"
|
||||
- REDIS_CFG_MASTERAUTH=colovu
|
||||
- REDIS_CFG_REQUIREPASS=colovu
|
||||
- DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
depends_on:
|
||||
- redis
|
||||
- redis-master
|
||||
|
||||
# 定义本地数据卷,由系统管理,需要手动删除
|
||||
volumes:
|
||||
|
||||
+4
-4
@@ -4,13 +4,13 @@ version: '3.8'
|
||||
# 当前配置仅保证可以启动容器;更多配置参数请参考镜像 README.md 文档中说明
|
||||
services:
|
||||
redis:
|
||||
image: 'colovu/redis:latest'
|
||||
image: 'registry.cn-shenzhen.aliyuncs.com/colovu/redis:latest'
|
||||
ports:
|
||||
- '6379:6379'
|
||||
environment:
|
||||
# ALLOW_ANONYMOUS_LOGIN is recommended only for development.
|
||||
- ALLOW_ANONYMOUS_LOGIN=yes
|
||||
- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
# ALLOW_ANONYMOUS is recommended only for development.
|
||||
- ALLOW_ANONYMOUS=yes
|
||||
- DISABLE_COMMANDS=FLUSHDB,FLUSHALL
|
||||
volumes:
|
||||
- 'redis_data:/srv/data'
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# 说明
|
||||
|
||||
## 用途
|
||||
|
||||
本目录下相关 Hooks 脚本主要用于 Docker Hub 服务器编译镜像时,获取用户设置的环境变量,并根据环境变量进行条件编译。相关脚本说明参照[官方文档](https://docs.docker.com/docker-hub/builds/advanced/)。
|
||||
|
||||
目录`hooks`必须与镜像编译文件 Dockerfile 同目录。
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
# v1.0 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 用户 docker.hub 的自动编译钩子文件,相应的变量在镜像库自动编译界面进行配置(如:registry_url、apt_source)
|
||||
# 参见: https://docs.docker.com/docker-hub/builds/advanced/
|
||||
|
||||
docker build --build-arg registry_url=${registry_url:-docker.io} --build-arg apt_source=${apt_source:-default} -f $DOCKERFILE_PATH -t $IMAGE_NAME .
|
||||
Reference in New Issue
Block a user