diff --git a/Dockerfile b/Dockerfile index aabea20..5a9f458 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,23 @@ -# Ver: 1.2 by Endial Fang (endial@126.com) +# Ver: 1.4 by Endial Fang (endial@126.com) # # 预处理 ========================================================================= -FROM colovu/dbuilder as builder +ARG registry_url="registry.cn-shenzhen.aliyuncs.com" +FROM ${registry_url}/colovu/dbuilder as builder # sources.list 可使用版本:default / tencent / ustc / aliyun / huawei -ARG apt_source=default +ARG apt_source=aliyun # 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" -WORKDIR /usr/local +ENV APP_NAME=test \ + APP_VERSION=1.0.0 +# 选择软件包源(Optional),以加速后续软件包安装 RUN select_source ${apt_source}; + +# 安装依赖的软件包及库(Optional) #RUN install_pkg xz-utils # 下载并解压软件包 @@ -21,7 +26,7 @@ RUN select_source ${apt_source}; # appName=gosu-"$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ # appKeys="0xB42F6819007F00F88E364FD4036A9C25BF357DD4"; \ # sha256="04fa1fddc39bd1aecb6739dd5dd73858a3515b427acd1e2947a66dadce868d68"; \ -# [ ! -z ${local_url} ] && localURL=${local_url}/gosu; \ +# [ ! -z ${local_url} ] && localURL=${local_url}/${APP_NAME}; \ # appUrls="${localURL:-} \ # https://github.com/tianon/gosu/releases/download/${appVersion} \ # "; \ @@ -29,42 +34,51 @@ RUN select_source ${apt_source}; # download_pkg unpack ${appName} "${appUrls}"; \ # chmod +x /usr/local/bin/${appName}; -# 源码编译软件包 +# 源码编译: 编译后将配置文件模板拷贝至 /usr/local/${APP_NAME}/share/${APP_NAME} 中 #RUN set -eux; \ -# 源码编译方式安装: 编译后将原始配置文件拷贝至 ${APP_DEF_DIR} 中 -# mkdir -p /usr/local/${APP_NAME}; \ # APP_SRC="/usr/local/${APP_NAME}-${APP_VERSION}"; \ # cd ${APP_SRC}; \ -# ./configure ; \ +# ./configure \ +# --prefix=/usr/local/${APP_NAME} \ +# ; \ # make -j "$(nproc)"; \ -# make PREFIX=/usr/local/${APP_NAME} install; \ -# cp -rf ./conf/* ${APP_DEF_DIR}/; +# make PREFIX=/usr/local/${APP_NAME} install; + +# 删除编译生成的多余文件 +RUN set -eux; \ + find /usr/local -name '*.a' -delete; \ + rm -rf /usr/local/${APP_NAME}/include; + +# 检测并生成依赖文件记录 +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; -#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 # 镜像生成 ======================================================================== -FROM colovu/debian:10 +FROM ${registry_url}/colovu/debian:10 -ARG apt_source=default +# sources.list 可使用版本:default / tencent / ustc / aliyun / huawei +ARG apt_source=aliyun + +# 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" +# 镜像所包含应用的基础信息 ENV APP_NAME=test \ APP_USER=builder \ - APP_EXEC=/bin/bash \ + APP_EXEC=run.sh \ APP_VERSION=1.0.0 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:${APP_HOME_DIR}/sbin:${PATH}" \ + LD_LIBRARY_PATH="${APP_HOME_DIR}/lib" LABEL \ "Version"="v${APP_VERSION}" \ @@ -72,25 +86,27 @@ 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 bash tini sudo libssl1.1 - RUN create_user && prepare_env -# 从预处理过程中拷贝软件包(Optional) -#COPY --from=0 /usr/local/bin/gosu-amd64 /usr/local/bin/gosu -#COPY --from=builder /usr/local/redis /usr/local/redis -#COPY --from=builder /usr/local/bin/gosu-amd64 /usr/local/bin/gosu +# 从预处理过程中拷贝软件包(Optional),可以使用阶段编号或阶段命名定义来源 +#COPY --from=0 /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} +#COPY --from=builder /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} + +# 选择软件包源(Optional),以加速后续软件包安装 +RUN select_source ${apt_source} + +# 安装依赖的软件包及库(Optional) +#RUN install_pkg `cat /usr/local/${APP_NAME}/runDeps`; +#RUN install_pkg bash tini sudo libssl1.1 # 执行预处理脚本,并验证安装的软件包 RUN set -eux; \ override_file="/usr/local/overrides/overrides-${APP_VERSION}.sh"; \ [ -e "${override_file}" ] && /bin/bash "${override_file}"; \ gosu ${APP_USER} ${APP_EXEC} --version ; \ - :; + gosu --version; # 默认提供的数据卷 VOLUME ["/srv/conf", "/srv/data", "/srv/datalog", "/srv/cert", "/var/log"] @@ -101,8 +117,6 @@ EXPOSE 8080 # 容器初始化命令,默认存放在:/usr/local/bin/entry.sh ENTRYPOINT ["entry.sh"] -WORKDIR /srv/data - # 应用程序的服务命令,必须使用非守护进程方式运行。如果使用变量,则该变量必须在运行环境中存在(ENV可以获取) CMD ["${APP_EXEC}"] diff --git a/Makefile b/Makefile index 20f1d0e..737fb47 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,40 @@ -# Ver: 1.4 by Endial Fang (endial@126.com) +# Ver: 1.7 by Endial Fang (endial@126.com) # # 当前 Docker 镜像的编译脚本 -app_name :=colovu/test +registry_url :=registry.cn-shenzhen.aliyuncs.com +app_name :=colovu/template # 生成镜像TAG,类似: # <镜像名>:<分支名>- # Git 仓库且无文件修改直接编译 # <镜像名>:<分支名>-<年月日>-<时分秒> # Git 仓库有文件修改后的编译 # <镜像名>:latest-<年月日>-<时分秒> # 非 Git 仓库编译 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:=$(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) +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 -build: build-debian build-alpine +build: build-alpine build-debian @echo "Build complete" build-debian: - @echo "Build $(app_name):$(current_tag)-deb" - @docker build --force-rm $(build-arg) -t $(app_name):$(current_tag)-deb . - @echo "Add tag: $(app_name):latest-deb" - @docker tag $(app_name):$(current_tag)-deb $(app_name):latest-deb + @echo "Build $(app_name):$(current_tag)" + @docker build --force-rm $(build-arg) -t $(app_name):$(current_tag) . + @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)" - @docker build --force-rm $(build-arg) -t $(app_name):$(current_tag) ./alpine - @echo "Add tag: $(app_name):latest" - @docker tag $(app_name):$(current_tag) $(app_name):latest + @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):local-latest-alpine" + @docker tag $(app_name):$(current_tag)-alpine $(app_name):local-latest-alpine # 清理悬空的镜像(无TAG)及停止的容器 clearclean: clean @@ -46,16 +47,6 @@ clean: @echo "Clean all images for current application..." @docker images | grep "$(app_name) " | awk '{print $$3}' | sort -u | xargs -L 1 docker rmi -f -tag: - @echo "Add tag: $(local_registory)/$(app_name):latest" - @docker tag $(app_name):latest $(local_registory)/$(app_name):latest - -push: tag - @echo "Push: $(local_registory)/$(app_name):latest" - @docker push $(local_registory)/$(app_name):latest - @echo "Push: $(app_name):latest" - @docker push $(app_name):latest - # 更新所有 colovu 仓库的镜像 upgrade: @echo "Upgrade all images..." diff --git a/README.md b/README.md index 9859440..1b88195 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 使用说明可参照:[官方说明]() - +AppName-logo **版本信息:** @@ -12,7 +12,7 @@ **镜像信息:** -* 镜像地址:colovu/imgname:latest +* 镜像地址:registry.cn-shenzhen.aliyuncs.com/colovu/imgname @@ -21,7 +21,7 @@ Docker 快速启动命令: ```shell -$ docker run -d colovu/imgname +$ docker run -d -e ALLOW_ANONYMOUS_LOGIN=yes colovu/imgname ``` Docker-Compose 快速启动命令: @@ -71,6 +71,37 @@ $ docker run -d -e "APP_ENV_KEY_NAME=key_value" colovu/imgname +### 自动变量替换 + +针对配置文件中的配置项,支持环境变量名自动替换,该类环境变量定义规则为:`APP_CFG_*=` + +- `APP_CFG_`:环境变量自动替换标识,具备该前缀的环境变量会被自动处理并更新至配置文件 +- `*`:配置文件中对应的配置项名,特殊字符替换规则 +- ``:配置项对应值 + +例如: + +```shell +# 设置配置文件中配置项 max_wal_size,传入容器的变量为(两者都可以): +PG_CFG_max_wal_size=400MB +PG_CFG_max_wal_size="400MB" + +# 容器启动后,应用配置文件中对应配置项生效,且设置为相应值: +max_wal_size = '400MB' +``` + +**特殊字符替换规则**: + +- 针对使用`xml`格式的配置文件 + + `_` ==> `.` : 环境变量中的`下划线`会被转义为设置属性中的`半角点` + + `__` ==> `_` : 环境变量中的`双下划线`会被转义为设置属性中的`单下划线` + + `___` ==> `-` : 环境变量中的`三下划线`会被转义为设置属性中的`中划线` +- 针对使用`key-val`格式的配置文件 + + `_` ==> `_` : 环境变量中的`下划线`不会被替换 + + `__` ==> `.` : 环境变量中的`双下划线`会被转义为设置属性中的`半角点` + + `___` ==> `-` : 环境变量中的`三下划线`会被转义为设置属性中的`中划线` + + ### 常规配置参数 常规配置参数用来配置容器基本属性,一般情况下需要设置,主要包括: @@ -104,7 +135,7 @@ $ docker run -d -e "APP_ENV_KEY_NAME=key_value" colovu/imgname `AppName`镜像默认禁用了无密码访问功能,在实际生产环境中建议使用用户名及密码控制访问;如果为了测试需要,可以使用以下环境变量启用无密码访问功能: ```shell -ALLOW_EMPTY_PASSWORD=yes +ALLOW_ANONYMOUS_LOGIN=yes ``` 通过配置环境变量`APPNAME_PASSWORD`,可以启用基于密码的用户认证功能。命令行使用参考: diff --git a/alpine/Dockerfile b/alpine/Dockerfile index 771d71a..d768d26 100644 --- a/alpine/Dockerfile +++ b/alpine/Dockerfile @@ -1,18 +1,23 @@ -# Ver: 1.2 by Endial Fang (endial@126.com) +# Ver: 1.4 by Endial Fang (endial@126.com) # # 预处理 ========================================================================= -FROM colovu/abuilder as builder +ARG registry_url="registry.cn-shenzhen.aliyuncs.com" +FROM ${registry_url}/colovu/abuilder as builder # sources.list 可使用版本:default / tencent / ustc / aliyun / huawei -ARG apt_source=default +ARG apt_source=aliyun # 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" -WORKDIR /usr/local +ENV APP_NAME=test \ + APP_VERSION=1.0.0 +# 选择软件包源(Optional),以加速后续软件包安装 RUN select_source ${apt_source}; + +# 安装依赖的软件包及库(Optional) #RUN install_pkg xz-utils # 下载并解压软件包 @@ -21,7 +26,7 @@ RUN select_source ${apt_source}; # appName=gosu-"$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ # appKeys="0xB42F6819007F00F88E364FD4036A9C25BF357DD4"; \ # sha256="04fa1fddc39bd1aecb6739dd5dd73858a3515b427acd1e2947a66dadce868d68"; \ -# [ ! -z ${local_url} ] && localURL=${local_url}/gosu; \ +# [ ! -z ${local_url} ] && localURL=${local_url}/${APP_NAME}; \ # appUrls="${localURL:-} \ # https://github.com/tianon/gosu/releases/download/${appVersion} \ # "; \ @@ -29,53 +34,50 @@ RUN select_source ${apt_source}; # download_pkg unpack ${appName} "${appUrls}"; \ # chmod +x /usr/local/bin/${appName}; -# 源码编译软件包 +# 源码编译: 编译后将配置文件模板拷贝至 /usr/local/${APP_NAME}/share/${APP_NAME} 中 #RUN set -eux; \ -# 源码编译方式安装: 编译后将原始配置文件拷贝至 ${APP_DEF_DIR} 中 # APP_SRC="/usr/local/${APP_NAME}-${APP_VERSION}"; \ -# mkdir -p /usr/local/${APP_NAME}; \ # cd ${APP_SRC}; \ -# ./configure --prefix=/usr/local/${APP_NAME} \ +# ./configure \ +# --prefix=/usr/local/${APP_NAME} \ # ; \ # make -j "$(nproc)"; \ -# make PREFIX=/usr/local/${APP_NAME} install; \ -# runDeps="$( \ -# scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ -# | tr ',' '\n' \ -# | sort -u \ -# | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ -# )"; \ -# echo "${runDeps}" >/usr/local/${APP_NAME}/runDeps; \ -# find /usr/local -name '*.a' -delete; \ -# cp -rf ./conf/* ${APP_DEF_DIR}/; +# make PREFIX=/usr/local/${APP_NAME} install; + +# 删除编译生成的多余文件 +RUN set -eux; \ + find /usr/local -name '*.a' -delete; \ + rm -rf /usr/local/${APP_NAME}/include; + +# 检测并生成依赖文件记录 +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; -# Alpine:scanelf --needed --nobanner --format '%n#p' --recursive /usr/local | tr ',' '\n' | sort -u | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' -# Debian: 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 # 镜像生成 ======================================================================== -FROM colovu/alpine:3.12 +FROM ${registry_url}/colovu/alpine:3.12 -ARG apt_source=default +# sources.list 可使用版本:default / tencent / ustc / aliyun / huawei +ARG apt_source=aliyun + +# 编译镜像时指定用于加速的本地服务器地址 ARG local_url="" +# 镜像所包含应用的基础信息 ENV APP_NAME=test \ APP_USER=builder \ - APP_EXEC=/bin/bash \ + APP_EXEC=run.sh \ APP_VERSION=1.0.0 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}" \ - LD_LIBRARY_PATH=${APP_HOME_DIR}/lib +ENV PATH="${APP_HOME_DIR}/bin:${APP_HOME_DIR}/sbin:${PATH}" \ + LD_LIBRARY_PATH="${APP_HOME_DIR}/lib" LABEL \ "Version"="v${APP_VERSION}" \ @@ -83,28 +85,27 @@ LABEL \ "Dockerfile"="https://github.com/colovu/docker-${APP_NAME}" \ "Vendor"="Endial Fang (endial@126.com)" +# 拷贝应用使用的客制化脚本,并创建对应的用户及数据存储目录 COPY customer / +RUN create_user && prepare_env -# 以包管理方式安装软件包(Optional) +# 从预处理过程中拷贝软件包(Optional),可以使用阶段编号或阶段命名定义来源 +#COPY --from=0 /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} +#COPY --from=builder /usr/local/${APP_NAME}/ /usr/local/${APP_NAME} + +# 选择软件包源(Optional),以加速后续软件包安装 RUN select_source ${apt_source} + +# 安装依赖的软件包及库(Optional) +#RUN install_pkg `cat /usr/local/${APP_NAME}/runDeps`; #RUN install_pkg bash tini sudo libssl1.1 -RUN create_user && prepare_env && mkdir -p ${APP_HOME_DIR}/bin ${APP_HOME_DIR}/lib - -# 从预处理过程中拷贝软件包(Optional) -#COPY --from=0 /usr/local/bin/gosu-amd64 /usr/local/bin/gosu -#COPY --from=builder /usr/local/redis /usr/local/redis -#COPY --from=builder /usr/local/bin/gosu-amd64 /usr/local/bin/gosu - -RUN install_pkg `cat /usr/local/${APP_NAME}/lib/runDeps`; - # 执行预处理脚本,并验证安装的软件包 RUN set -eux; \ override_file="/usr/local/overrides/overrides-${APP_VERSION}.sh"; \ [ -e "${override_file}" ] && /bin/bash "${override_file}"; \ - export LD_LIBRARY_PATH=/usr/local/${APP_NAME}/lib; \ gosu ${APP_USER} ${APP_EXEC} --version ; \ - :; + gosu --version; # 默认提供的数据卷 VOLUME ["/srv/conf", "/srv/data", "/srv/datalog", "/srv/cert", "/var/log"] diff --git a/alpine/customer/usr/local/bin/appcommon.sh b/alpine/customer/usr/local/bin/comm-appname.sh similarity index 67% rename from alpine/customer/usr/local/bin/appcommon.sh rename to alpine/customer/usr/local/bin/comm-appname.sh index 5290c82..37324c1 100644 --- a/alpine/customer/usr/local/bin/appcommon.sh +++ b/alpine/customer/usr/local/bin/comm-appname.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) # # 应用通用业务处理函数 @@ -14,42 +14,52 @@ # 函数列表 -# 加载应用使用的环境变量初始值,该函数在相关脚本中以 eval 方式调用 +# 使用环境变量中以 "" 开头的的全局变量更新指定配置文件中对应项(以"."分隔) +# 如果需要全部转换为小写,可使用命令: tr '[:upper:]' '[:lower:]' # 全局变量: -# ENV_* : 容器使用的全局变量 -# APP_* : 在镜像创建时定义的全局变量 -# *_* : 应用配置文件使用的全局变量,变量名根据配置项定义 -# 返回值: -# 可以被 'eval' 使用的序列化输出 -app_env() { - cat <<-'EOF' - # Common Settings - export ENV_DEBUG=${ENV_DEBUG:-false} - # Paths configuration - # Application settings - # Cluster configuration - # TLS Settings - # JVM settings - # Authentication -EOF - - # 利用 *_FILE 设置密码,不在配置命令中设置密码,增强安全性 - if [[ -f "${APP_CLIENT_PASSWORD_FILE:-}" ]]; then - cat <<-'EOF' - export APP_CLIENT_PASSWORD="$(< "${APP_CLIENT_PASSWORD_FILE}")" -EOF - fi -} - -# 使用环境变量中以 "APP_CFG_" 开头的的全局变量更新配置文件中对应项(全小写,以"."分隔) +# _* : +# 替换规则(变量中字符 ==> 替换后全局变量中字符): +# - "." ==> "_" +# - "_" ==> "__" +# - "-" ==> "___" +# +# 变量: +# $1 - 配置文件 +# $2 - 前缀(不含结束的"_") +# # 举例: -# APP_CFG_LOG_DIRS 对应配置文件中的配置项:log.dirs -app_configure_from_env_variables() { +# CORE_CONF_fs_defaultFS 对应配置文件中的配置项:fs.defaultFS +appname_configure_from_environment() { # 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}" - app_conf_set "$key" "$value" + appname_conf_set "$key" "$value" + done + + local path="${1:?missing file}" + local envPrefix="${2:?missing parameters}" + + LOG_D " File: ${path}" + # Map environment variables to config properties + #for var in `printenv | grep ${envPrefix} | "${!${envPrefix}_@}"`; do + # LOG_D " Process: ${var}" + # key="$(echo "${var}" | sed -e 's/^${envPrefix}_//g' -e 's/___/-/g' -e 's/__/_/g' -e 's/_/\./g')" + # value="${!var}" + # hadoop_common_xml_set "${path}" "${key}" "${value}" + #done + #for var in $(printenv | grep ${envPrefix}); do + # LOG_D " Process: ${var}" + # key="$(echo "${var}" | sed -e 's/^${envPrefix}_//g' -e 's/___/-/g' -e 's/__/_/g' -e 's/_/\./g' )" + # value="${!var}" + # hadoop_common_xml_set "${path}" "${key}" "${value}" + #done + for c in `printenv | perl -sne 'print "$1 " if m/^${envPrefix}_(.+?)=.*/' -- -envPrefix=${envPrefix}`; do + name=`echo ${c} | perl -pe 's/___/-/g; s/__/_/g; s/_/./g;'` + key="${envPrefix}_${c}" + #LOG_D " Process: ${key} => ${!key}" + value="${!key}" + hadoop_common_xml_set "${path}" "${name}" "${value}" done } @@ -58,7 +68,7 @@ app_configure_from_env_variables() { # $1 - 文件 # $2 - 变量 # $3 - 值(列表) -app_common_conf_set() { +appname_common_conf_set() { local file="${1:?missing file}" local key="${2:?missing key}" shift @@ -70,7 +80,7 @@ app_common_conf_set() { return 1 elif [[ "${#values[@]}" -ne 1 ]]; then for i in "${!values[@]}"; do - app_common_conf_set "$file" "${key[$i]}" "${values[$i]}" + appname_common_conf_set "$file" "${key[$i]}" "${values[$i]}" done else value="${values[0]}" @@ -89,34 +99,42 @@ app_common_conf_set() { # 变量: # $1 - 变量 # $2 - 值(列表) -app_conf_set() { - app_common_conf_set "${APP_CONF_DIR}/zoo.cfg" "$@" +appname_conf_set() { + appname_common_conf_set "${APP_CONF_DIR}/zoo.cfg" "$@" } # 更新 log4j.properties 配置文件中指定变量值 # 变量: # $1 - 变量 # $2 - 值(列表) -app_log4j_set() { - app_common_conf_set "${APP_CONF_DIR}/log4j.properties" "$@" +appname_log4j_set() { + appname_common_conf_set "${APP_CONF_DIR}/log4j.properties" "$@" +} + +# 使用环境变量中配置,更新配置文件 +appname_update_conf() { + LOG_I "Update configure files..." + } # 生成默认配置文件 -app_generate_conf() { +appname_generate_conf() { # 准备原始默认配置文件或生成空文件 cp "${APP_CONF_DIR}/app_sample.cfg" "${APP_CONF_FILE}" echo "">> "${APP_CONF_FILE}" # 根据容器参数,设置配置文件 - app_log4j_set "zookeeper.console.threshold" "${ZOO_LOG_LEVEL}" - app_log4j_set "zookeeper.log.dir" "${APP_LOG_DIR}" + appname_log4j_set "zookeeper.console.threshold" "${ZOO_LOG_LEVEL}" + appname_log4j_set "zookeeper.log.dir" "${APP_LOG_DIR}" + + appname_update_conf } # 设置环境变量 JVMFLAGS # 参数: # $1 - value -app_export_jvmflags() { +appname_export_jvmflags() { local -r value="${1:?value is required}" export JVMFLAGS="${JVMFLAGS} ${value}" @@ -126,19 +144,19 @@ app_export_jvmflags() { # 配置 HEAP 大小 # 参数: # $1 - HEAP 大小 -app_configure_heap_size() { +appname_configure_heap_size() { local -r heap_size="${1:?heap_size is required}" if [[ "${JVMFLAGS}" =~ -Xm[xs].*-Xm[xs] ]]; then LOG_D "Using specified values (JVMFLAGS=${JVMFLAGS})" else LOG_D "Setting '-Xmx${heap_size}m -Xms${heap_size}m' heap options..." - app_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" + appname_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" fi } # 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息 -app_verify_minimum_env() { +appname_verify_minimum_env() { local error_code=0 LOG_D "Validating settings in APP_* env vars..." @@ -161,7 +179,7 @@ app_verify_minimum_env() { } # 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1) -app_enable_remote_connections() { +appname_enable_remote_connections() { LOG_D "Modify default config to enable all IP access" } @@ -169,7 +187,7 @@ app_enable_remote_connections() { # 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat' # 参数: # $1 - host:port -app_wait_service() { +appname_wait_service() { local serviceport=${1:?Missing server info} local service=${serviceport%%:*} local port=${serviceport#*:} @@ -208,8 +226,9 @@ app_wait_service() { } # 以后台方式启动应用服务,并等待启动就绪 -app_start_server_bg() { - is_app_server_running && return +appname_start_server_bg() { + appname_is_server_running && return + LOG_I "Starting ${APP_NAME} in background..." # 使用内置脚本启动服务 @@ -235,34 +254,35 @@ app_start_server_bg() { } # 停止应用服务 -app_stop_server() { - is_app_server_running || return - LOG_I "Stopping ${APP_NAME}..." +appname_stop_server() { + if appname_is_server_running ; then + LOG_I "Stopping ${APP_NAME}..." - # 使用 PID 文件 kill 进程 - stop_service_using_pid "$APP_PID_FILE" + # 使用 PID 文件 kill 进程 + stop_service_using_pid "$APP_PID_FILE" - # 使用内置命令停止服务 - #debug_execute "rabbitmqctl" stop + # 使用内置命令停止服务 + #debug_execute "rabbitmqctl" stop - # 使用内置脚本关闭服务 - #if [[ "$ENV_DEBUG" = true ]]; then - # "zkServer.sh" stop - #else - # "zkServer.sh" stop >/dev/null 2>&1 - #fi + # 使用内置脚本关闭服务 + #if [[ "$ENV_DEBUG" = true ]]; then + # "zkServer.sh" stop + #else + # "zkServer.sh" stop >/dev/null 2>&1 + #fi - # 检测停止是否完成 - local counter=10 - while [[ "$counter" -ne 0 ]] && is_app_server_running; do - LOG_D "Waiting for ${APP_NAME} to stop..." - sleep 1 - counter=$((counter - 1)) - done + # 检测停止是否完成 + local counter=10 + while [[ "$counter" -ne 0 ]] && appname_is_server_running; do + LOG_D "Waiting for ${APP_NAME} to stop..." + sleep 1 + counter=$((counter - 1)) + done + fi } # 检测应用服务是否在后台运行中 -is_app_server_running() { +appname_is_server_running() { LOG_D "Check if ${APP_NAME} is running..." local pid pid="$(get_pid_from_file '/var/run/${APP_NAME}/${APP_NAME}.pid')" @@ -275,13 +295,13 @@ is_app_server_running() { } # 清理初始化应用时生成的临时文件 -app_clean_tmp_file() { +appname_clean_tmp_file() { LOG_D "Clean ${APP_NAME} tmp files for init..." } # 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动) -app_clean_from_restart() { +appname_clean_from_restart() { LOG_D "Clean ${APP_NAME} tmp files for restart..." local -r -a files=( "/var/run/${APP_NAME}/${APP_NAME}.pid" @@ -297,8 +317,8 @@ app_clean_from_restart() { # 应用默认初始化操作 # 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件 -app_default_init() { - app_clean_from_restart +appname_default_init() { + appname_clean_from_restart LOG_D "Check init status of ${APP_NAME}..." # 检测配置文件是否存在 @@ -307,17 +327,20 @@ app_default_init() { # TODO: 生成配置文件,并按照容器运行参数进行相应修改 - 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!" + + LOG_D "Update configure files from environment..." + appname_update_conf fi if [[ ! -f "${APP_DATA_DIR}/.data_init_flag" ]]; then LOG_I "Deploying ${APP_NAME} from scratch..." - # 检测服务是否运行中如果未运行,则启动后台服务 - is_app_server_running || app_start_server_bg + # 启动后台服务 + appname_start_server_bg # TODO: 根据需要生成相应初始化数据 @@ -330,8 +353,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}..." +appname_custom_preinit() { + LOG_I "Check custom pre-init status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/preinitdb.d" ]; then @@ -343,8 +366,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." @@ -353,14 +376,14 @@ app_custom_preinit() { # 检测依赖的服务是否就绪 #for i in ${SERVICE_PRECONDITION[@]}; do - # app_wait_service "${i}" + # appname_wait_service "${i}" #done } # 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag -app_custom_init() { - LOG_D "Check custom init status of ${APP_NAME}..." +appname_custom_init() { + LOG_I "Check custom initdb status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then @@ -369,8 +392,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..." - # 检测服务是否运行中;如果未运行,则启动后台服务 - is_app_server_running || app_start_server_bg + # 启动后台服务 + appname_start_server_bg # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do @@ -382,26 +405,26 @@ app_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" ;; + *.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." fi fi - # 检测服务是否运行中;如果运行,则停止后台服务 - is_app_server_running && app_stop_server - - # 删除第一次运行生成的临时文件 - app_clean_tmp_file - - # 绑定所有 IP ,启用远程访问 - app_enable_remote_connections } + 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..c92b32a --- /dev/null +++ b/alpine/customer/usr/local/bin/comm-env.sh @@ -0,0 +1,41 @@ +#!/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 > 传入变量 > 默认值 +app_env_file_lists=( + APP_PASSWORD +) +for env_var in "${app_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 postgresql_env_vars + +# 应用路径参数 +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}" + + +# 应用配置参数 + +# 内部变量 + +# 个性化变量 + 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-x.x.x.sh b/alpine/customer/usr/local/overrides/overrides-x.x.x.sh index 939603d..10401c9 100644 --- a/alpine/customer/usr/local/overrides/overrides-x.x.x.sh +++ b/alpine/customer/usr/local/overrides/overrides-x.x.x.sh @@ -7,5 +7,6 @@ CONF_FILE="${APP_DEF_DIR}/config/server.properties" echo "Process overrides for: ${CONF_FILE}" -#sed -i -E 's/^listeners=/d' "${CONF_FILE}" -#sed -i -E 's/^log.dirs=\/tmp\/kafka-logs*/log.dirs=\/var\/log\/kafka/g' "${CONF_FILE}" +#sed -i -E 's/^#?listeners=/d' "${CONF_FILE}" +#sed -i -E 's/^#?log.dirs=\/tmp\/kafka-logs*/log.dirs=\/var\/log\/kafka/g' "${CONF_FILE}" + diff --git a/alpine/customer/usr/sbin/create_user b/alpine/customer/usr/sbin/create_user index 3ae221f..3958797 100755 --- a/alpine/customer/usr/sbin/create_user +++ b/alpine/customer/usr/sbin/create_user @@ -1,9 +1,11 @@ #!/bin/bash +# Ver: 1.1 by Endial Fang (endial@126.com) +# # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux addgroup -g 998 -S ${APP_USER} -#adduser -G ${APP_USER} -u 999 -s /bin/bash -h ${APP_DATA_DIR} -D -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..1b92faa 100755 --- a/alpine/customer/usr/sbin/prepare_env +++ b/alpine/customer/usr/sbin/prepare_env @@ -1,8 +1,19 @@ #!/bin/bash +# Ver: 1.1 by Endial Fang (endial@126.com) +# # 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/appcommon.sh b/customer/usr/local/bin/comm-appname.sh similarity index 67% rename from customer/usr/local/bin/appcommon.sh rename to customer/usr/local/bin/comm-appname.sh index d63d3be..4470dac 100644 --- a/customer/usr/local/bin/appcommon.sh +++ b/customer/usr/local/bin/comm-appname.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) # # 应用通用业务处理函数 @@ -14,42 +14,52 @@ # 函数列表 -# 加载应用使用的环境变量初始值,该函数在相关脚本中以 eval 方式调用 +# 使用环境变量中以 "" 开头的的全局变量更新指定配置文件中对应项(以"."分隔) +# 如果需要全部转换为小写,可使用命令: tr '[:upper:]' '[:lower:]' # 全局变量: -# ENV_* : 容器使用的全局变量 -# APP_* : 在镜像创建时定义的全局变量 -# *_* : 应用配置文件使用的全局变量,变量名根据配置项定义 -# 返回值: -# 可以被 'eval' 使用的序列化输出 -app_env() { - cat <<-'EOF' - # Common Settings - export ENV_DEBUG=${ENV_DEBUG:-false} - # Paths configuration - # Application settings - # Cluster configuration - # TLS Settings - # JVM settings - # Authentication -EOF - - # 利用 *_FILE 设置密码,不在配置命令中设置密码,增强安全性 - if [[ -f "${APP_CLIENT_PASSWORD_FILE:-}" ]]; then - cat <<-'EOF' - export APP_CLIENT_PASSWORD="$(< "${APP_CLIENT_PASSWORD_FILE}")" -EOF - fi -} - -# 使用环境变量中以 "APP_CFG_" 开头的的全局变量更新配置文件中对应项(全小写,以"."分隔) +# _* : +# 替换规则(变量中字符 ==> 替换后全局变量中字符): +# - "." ==> "_" +# - "_" ==> "__" +# - "-" ==> "___" +# +# 变量: +# $1 - 配置文件 +# $2 - 前缀(不含结束的"_") +# # 举例: -# APP_CFG_LOG_DIRS 对应配置文件中的配置项:log.dirs -app_configure_from_env_variables() { +# CORE_CONF_fs_defaultFS 对应配置文件中的配置项:fs.defaultFS +appname_configure_from_environment() { # 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}" - app_conf_set "$key" "$value" + appname_conf_set "$key" "$value" + done + + local path="${1:?missing file}" + local envPrefix="${2:?missing parameters}" + + LOG_D " File: ${path}" + # Map environment variables to config properties + #for var in `printenv | grep ${envPrefix} | "${!${envPrefix}_@}"`; do + # LOG_D " Process: ${var}" + # key="$(echo "${var}" | sed -e 's/^${envPrefix}_//g' -e 's/___/-/g' -e 's/__/_/g' -e 's/_/\./g')" + # value="${!var}" + # hadoop_common_xml_set "${path}" "${key}" "${value}" + #done + #for var in $(printenv | grep ${envPrefix}); do + # LOG_D " Process: ${var}" + # key="$(echo "${var}" | sed -e 's/^${envPrefix}_//g' -e 's/___/-/g' -e 's/__/_/g' -e 's/_/\./g' )" + # value="${!var}" + # hadoop_common_xml_set "${path}" "${key}" "${value}" + #done + for c in `printenv | perl -sne 'print "$1 " if m/^${envPrefix}_(.+?)=.*/' -- -envPrefix=${envPrefix}`; do + name=`echo ${c} | perl -pe 's/___/-/g; s/__/_/g; s/_/./g;'` + key="${envPrefix}_${c}" + #LOG_D " Process: ${key} => ${!key}" + value="${!key}" + hadoop_common_xml_set "${path}" "${name}" "${value}" done } @@ -58,7 +68,7 @@ app_configure_from_env_variables() { # $1 - 文件 # $2 - 变量 # $3 - 值(列表) -app_common_conf_set() { +appname_common_conf_set() { local file="${1:?missing file}" local key="${2:?missing key}" shift @@ -70,7 +80,7 @@ app_common_conf_set() { return 1 elif [[ "${#values[@]}" -ne 1 ]]; then for i in "${!values[@]}"; do - app_common_conf_set "$file" "${key[$i]}" "${values[$i]}" + appname_common_conf_set "$file" "${key[$i]}" "${values[$i]}" done else value="${values[0]}" @@ -89,34 +99,42 @@ app_common_conf_set() { # 变量: # $1 - 变量 # $2 - 值(列表) -app_conf_set() { - app_common_conf_set "${APP_CONF_DIR}/zoo.cfg" "$@" +appname_conf_set() { + appname_common_conf_set "${APP_CONF_DIR}/zoo.cfg" "$@" } # 更新 log4j.properties 配置文件中指定变量值 # 变量: # $1 - 变量 # $2 - 值(列表) -app_log4j_set() { - app_common_conf_set "${APP_CONF_DIR}/log4j.properties" "$@" +appname_log4j_set() { + appname_common_conf_set "${APP_CONF_DIR}/log4j.properties" "$@" +} + +# 使用环境变量中配置,更新配置文件 +appname_update_conf() { + LOG_I "Update configure files..." + } # 生成默认配置文件 -app_generate_conf() { +appname_generate_conf() { # 准备原始默认配置文件或生成空文件 cp "${APP_CONF_DIR}/app_sample.cfg" "${APP_CONF_FILE}" echo "">> "${APP_CONF_FILE}" # 根据容器参数,设置配置文件 - app_log4j_set "zookeeper.console.threshold" "${ZOO_LOG_LEVEL}" - app_log4j_set "zookeeper.log.dir" "${APP_LOG_DIR}" + appname_log4j_set "zookeeper.console.threshold" "${ZOO_LOG_LEVEL}" + appname_log4j_set "zookeeper.log.dir" "${APP_LOG_DIR}" + + appname_update_conf } # 设置环境变量 JVMFLAGS # 参数: # $1 - value -app_export_jvmflags() { +appname_export_jvmflags() { local -r value="${1:?value is required}" export JVMFLAGS="${JVMFLAGS} ${value}" @@ -126,19 +144,19 @@ app_export_jvmflags() { # 配置 HEAP 大小 # 参数: # $1 - HEAP 大小 -app_configure_heap_size() { +appname_configure_heap_size() { local -r heap_size="${1:?heap_size is required}" if [[ "${JVMFLAGS}" =~ -Xm[xs].*-Xm[xs] ]]; then LOG_D "Using specified values (JVMFLAGS=${JVMFLAGS})" else LOG_D "Setting '-Xmx${heap_size}m -Xms${heap_size}m' heap options..." - app_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" + appname_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m" fi } # 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息 -app_verify_minimum_env() { +appname_verify_minimum_env() { local error_code=0 LOG_D "Validating settings in APP_* env vars..." @@ -161,7 +179,7 @@ app_verify_minimum_env() { } # 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1) -app_enable_remote_connections() { +appname_enable_remote_connections() { LOG_D "Modify default config to enable all IP access" } @@ -169,7 +187,7 @@ app_enable_remote_connections() { # 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat' # 参数: # $1 - host:port -app_wait_service() { +appname_wait_service() { local serviceport=${1:?Missing server info} local service=${serviceport%%:*} local port=${serviceport#*:} @@ -208,8 +226,8 @@ app_wait_service() { } # 以后台方式启动应用服务,并等待启动就绪 -app_start_server_bg() { - is_app_server_running && return +appname_start_server_bg() { + appname_is_server_running && return LOG_I "Starting ${APP_NAME} in background..." @@ -236,34 +254,35 @@ app_start_server_bg() { } # 停止应用服务 -app_stop_server() { - is_app_server_running || return - LOG_I "Stopping ${APP_NAME}..." +appname_stop_server() { + if appname_is_server_running ; then + LOG_I "Stopping ${APP_NAME}..." - # 使用 PID 文件 kill 进程 - stop_service_using_pid "$APP_PID_FILE" + # 使用 PID 文件 kill 进程 + stop_service_using_pid "$APP_PID_FILE" - # 使用内置命令停止服务 - #debug_execute "rabbitmqctl" stop + # 使用内置命令停止服务 + #debug_execute "rabbitmqctl" stop - # 使用内置脚本关闭服务 - #if [[ "$ENV_DEBUG" = true ]]; then - # "zkServer.sh" stop - #else - # "zkServer.sh" stop >/dev/null 2>&1 - #fi + # 使用内置脚本关闭服务 + #if [[ "$ENV_DEBUG" = true ]]; then + # "zkServer.sh" stop + #else + # "zkServer.sh" stop >/dev/null 2>&1 + #fi - # 检测停止是否完成 - local counter=10 - while [[ "$counter" -ne 0 ]] && is_app_server_running; do - LOG_D "Waiting for ${APP_NAME} to stop..." - sleep 1 - counter=$((counter - 1)) - done + # 检测停止是否完成 + local counter=10 + while [[ "$counter" -ne 0 ]] && appname_is_server_running; do + LOG_D "Waiting for ${APP_NAME} to stop..." + sleep 1 + counter=$((counter - 1)) + done + fi } # 检测应用服务是否在后台运行中 -is_app_server_running() { +appname_is_server_running() { LOG_D "Check if ${APP_NAME} is running..." local pid pid="$(get_pid_from_file '/var/run/${APP_NAME}/${APP_NAME}.pid')" @@ -276,13 +295,13 @@ is_app_server_running() { } # 清理初始化应用时生成的临时文件 -app_clean_tmp_file() { +appname_clean_tmp_file() { LOG_D "Clean ${APP_NAME} tmp files for init..." } # 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动) -app_clean_from_restart() { +appname_clean_from_restart() { LOG_D "Clean ${APP_NAME} tmp files for restart..." local -r -a files=( "/var/run/${APP_NAME}/${APP_NAME}.pid" @@ -298,8 +317,8 @@ app_clean_from_restart() { # 应用默认初始化操作 # 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件 -app_default_init() { - app_clean_from_restart +appname_default_init() { + appname_clean_from_restart LOG_D "Check init status of ${APP_NAME}..." # 检测配置文件是否存在 @@ -308,17 +327,20 @@ app_default_init() { # TODO: 生成配置文件,并按照容器运行参数进行相应修改 - 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!" + + LOG_D "Update configure files from environment..." + appname_update_conf fi if [[ ! -f "${APP_DATA_DIR}/.data_init_flag" ]]; then LOG_I "Deploying ${APP_NAME} from scratch..." - # 检测服务是否运行中如果未运行,则启动后台服务 - is_app_server_running || app_start_server_bg + # 启动后台服务 + appname_start_server_bg # TODO: 根据需要生成相应初始化数据 @@ -331,8 +353,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}..." +appname_custom_preinit() { + LOG_I "Check custom pre-init status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 preinitdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/preinitdb.d" ]; then @@ -344,8 +366,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." @@ -354,14 +376,14 @@ app_custom_preinit() { # 检测依赖的服务是否就绪 #for i in ${SERVICE_PRECONDITION[@]}; do - # app_wait_service "${i}" + # appname_wait_service "${i}" #done } # 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本 # 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag -app_custom_init() { - LOG_D "Check custom init status of ${APP_NAME}..." +appname_custom_init() { + LOG_I "Check custom initdb status of ${APP_NAME}..." # 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本 if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then @@ -370,8 +392,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..." - # 检测服务是否运行中;如果未运行,则启动后台服务 - is_app_server_running || app_start_server_bg + # 启动后台服务 + appname_start_server_bg # 检索所有可执行脚本,排序后执行 find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do @@ -383,27 +405,26 @@ app_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" ;; + *.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." fi fi - # 检测服务是否运行中;如果运行,则停止后台服务 - is_app_server_running && app_stop_server - - # 删除第一次运行生成的临时文件 - app_clean_tmp_file - - # 绑定所有 IP ,启用远程访问 - app_enable_remote_connections } diff --git a/customer/usr/local/bin/comm-env.sh b/customer/usr/local/bin/comm-env.sh new file mode 100644 index 0000000..e26a810 --- /dev/null +++ b/customer/usr/local/bin/comm-env.sh @@ -0,0 +1,41 @@ +#!/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 > 传入变量 > 默认值 +app_env_file_lists=( + APP_PASSWORD +) +for env_var in "${app_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 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}" +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}" + + +# 应用配置参数 + +# 内部变量 + +# 个性化变量 + 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..f1f10e8 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,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 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 +29,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-x.x.x.sh b/customer/usr/local/overrides/overrides-x.x.x.sh index 939603d..10401c9 100644 --- a/customer/usr/local/overrides/overrides-x.x.x.sh +++ b/customer/usr/local/overrides/overrides-x.x.x.sh @@ -7,5 +7,6 @@ CONF_FILE="${APP_DEF_DIR}/config/server.properties" echo "Process overrides for: ${CONF_FILE}" -#sed -i -E 's/^listeners=/d' "${CONF_FILE}" -#sed -i -E 's/^log.dirs=\/tmp\/kafka-logs*/log.dirs=\/var\/log\/kafka/g' "${CONF_FILE}" +#sed -i -E 's/^#?listeners=/d' "${CONF_FILE}" +#sed -i -E 's/^#?log.dirs=\/tmp\/kafka-logs*/log.dirs=\/var\/log\/kafka/g' "${CONF_FILE}" + diff --git a/customer/usr/sbin/create_user b/customer/usr/sbin/create_user index 34a474d..7b69b93 100755 --- a/customer/usr/sbin/create_user +++ b/customer/usr/sbin/create_user @@ -1,9 +1,11 @@ #!/bin/bash +# Ver: 1.1 by Endial Fang (endial@126.com) +# # shell 执行参数,分别为 -e(命令执行错误则退出脚本) -u(变量未定义则报错) -x(打印实际待执行的命令行) set -eux groupadd --gid 998 --system ${APP_USER} -#useradd --gid 998 --uid 999 --shell /bin/bash --home ${APP_DATA_DIR} --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..1b92faa 100755 --- a/customer/usr/sbin/prepare_env +++ b/customer/usr/sbin/prepare_env @@ -1,8 +1,19 @@ #!/bin/bash +# Ver: 1.1 by Endial Fang (endial@126.com) +# # 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-cluster.yml index 4970728..a9a5523 100644 --- a/docker-compose-cluster.yml +++ b/docker-compose-cluster.yml @@ -35,5 +35,5 @@ volumes: driver: local app_data: driver: local - app_datalog: + var_log: driver: local \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 451a4ad..4d1dae3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ version: '3.8' # 更多配置参数请参考镜像 README.md 文档中说明 services: app-name: - image: 'colovu/app-name' + image: 'registry.cn-shenzhen.aliyuncs.com/colovu/app-name' ports: - '8000:8000' volumes: @@ -12,6 +12,7 @@ services: environment: # ALLOW_ANONYMOUS_LOGIN is recommended only for development. - ALLOW_ANONYMOUS_LOGIN=yes + - ENV_DEBUG=yes # 定义本地数据卷,由系统管理,需要手动删除 volumes: @@ -19,5 +20,5 @@ volumes: driver: local app_data: driver: local - app_datalog: + var_log: driver: local