Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2983477b7a | |||
| 105fb9f9cf | |||
| 7df1a4796f | |||
| 694480f2ae | |||
| e8d70fcef1 | |||
| 9501cca4cf | |||
| 8be9d96b27 | |||
| b773351c0c | |||
| e6d4313367 | |||
| 8a7347671e | |||
| 04bdfafabb | |||
| b55f06f662 | |||
| c8a03964a6 | |||
| a4b156778e | |||
| aae5948220 | |||
| 8dd6b61d4d | |||
| 245d253961 | |||
| 22e345f0cd | |||
| 6799a1c1f8 | |||
| d85fdc6f81 | |||
| d628ecda82 | |||
| be8360e035 | |||
| 1be30da4b9 | |||
| 268a113d77 | |||
| a40a27b702 | |||
| 5eae66198b | |||
| f2784d8661 |
Submodule
+1
Submodule .ci/common added at b0ca0dc3a3
+50
-4
@@ -1,11 +1,57 @@
|
||||
# 忽略所有 .git 相关
|
||||
.git
|
||||
.gitignore
|
||||
.gitmodules
|
||||
.gitattributes
|
||||
|
||||
./Makefile
|
||||
# 忽略 IDE 和编辑器文件
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
Thumbs.db
|
||||
|
||||
# 忽略本地依赖和构建缓存
|
||||
node_modules/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.env
|
||||
.env.*
|
||||
secrets/
|
||||
config/local.*
|
||||
|
||||
# 忽略日志和临时文件
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# 忽略测试报告(除非需要)
|
||||
coverage/
|
||||
htmlcov/
|
||||
.pytest_cache/
|
||||
|
||||
# 忽略 macOS 特有文件
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
# 忽略构建产物(如果 Docker 内部会重新构建)
|
||||
dist/
|
||||
build/
|
||||
out/
|
||||
target/
|
||||
|
||||
# 忽略项目特有文件及目录
|
||||
img
|
||||
build.sh
|
||||
LICENSE
|
||||
README.md
|
||||
*.yml
|
||||
*.yaml
|
||||
|
||||
./LICENSE
|
||||
./README.md
|
||||
./img
|
||||
# 忽略 AI 规则文件
|
||||
.lingma
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
# CI/CD 的阶段定义,按顺序执行各阶段;默认包含`.pre`(最先执行)/`.post`(最后执行)两个阶段,不用显示定义
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
# 全局变量定义
|
||||
variables:
|
||||
IMG_URL: "$HARBOR_HOST/$HARBOR_PROJECT/$CI_PROJECT_NAME"
|
||||
IMG_TAG: ":latest"
|
||||
|
||||
# 默认值信息配置
|
||||
default:
|
||||
# 各 stage 使用的默认镜像,如果不定义,则为 gitlab-runner 创建时指定的镜像;各 stage 可以覆盖该值以使用不同的镜像
|
||||
image: docker.colovu.com/library/docker:20.10.16
|
||||
# Gitlab-runner 配置的执行器为 Docker 时,需要 配置对应的 dind 服务
|
||||
services:
|
||||
- name: docker.colovu.com/library/docker:20.10.16-dind
|
||||
alias: docker
|
||||
# 流水线中,各阶段都会执行的脚本命令,包括`before_script`(在各阶段 script 前执行)/`after_script`(在各阶段 script 后执行)
|
||||
before_script:
|
||||
- |
|
||||
if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
|
||||
IMG_TAG=":latest"
|
||||
else
|
||||
IMG_TAG=":$CI_COMMIT_REF_NAME"
|
||||
fi
|
||||
- docker login -u "$HARBOR_USERNAME" -p "$HARBOR_PASSWORD" $HARBOR_URL
|
||||
|
||||
# 编译阶段任务
|
||||
build-arm64:
|
||||
stage: build
|
||||
tags:
|
||||
- arm64
|
||||
script:
|
||||
- export
|
||||
- env
|
||||
- docker buildx build --platform=linux/arm64 --pull -t "$IMG_URL$IMG_TAG-linux-arm64" . --push
|
||||
|
||||
build-amd64:
|
||||
stage: build
|
||||
tags:
|
||||
- amd64
|
||||
script:
|
||||
- docker buildx build --platform=linux/amd64 --pull -t "$IMG_URL$IMG_TAG-linux-amd64" . --push
|
||||
|
||||
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"
|
||||
|
||||
# 测试阶段任务
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- docker run --rm --platform=linux/arm64 "$IMG_URL$IMG_TAG" /bin/uname -a
|
||||
- docker run --rm --platform=linux/amd64 "$IMG_URL$IMG_TAG" /bin/uname -a
|
||||
|
||||
# 部署阶段任务
|
||||
deploy:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "deploy stage"
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule ".ci/common"]
|
||||
path = .ci/common
|
||||
url = https://git.colovu.com/docker/common.git
|
||||
@@ -0,0 +1,55 @@
|
||||
# 注意:
|
||||
# 1. git commit 信息中包含"[CI SKIP]"或"[SKIP CI]"则不触发工作流(注意大小写)
|
||||
# 2. 工作步骤中包含 volumes 挂载时,需在 Woodpecker 配置中添加 volumes 挂载信任(Trust)
|
||||
# 3. lables 配置项,可配置多个;如果存在,则必须完全符合 Runner 创建时设置的 Lables 配置项
|
||||
# 4. command 中,引用自定义变量不能使用`${VAR}`方式,需要使用`$VAR`方式;带花括号的变量,会在 Woodpecker 模板引擎解析阶段被替换(此时变量为空)
|
||||
# 5. 多架构编译后推送至 SWR 报错,或单架构编译后必须在推送时明确指定架构信息才能推送;可通过在编译命令中增加参数`--provenance=false --sbom=false`解决
|
||||
# 6. 使用 Git Submodule 管理通用脚本时,需手动更新 Submodule
|
||||
|
||||
when:
|
||||
# 匹配 main
|
||||
- event: push
|
||||
branch: main
|
||||
# 匹配 master
|
||||
- event: push
|
||||
branch: master
|
||||
# 匹配数字开头的分支,如 1.0, 2, 3.2.1
|
||||
- event: push
|
||||
branch: "[0-9]*"
|
||||
# 匹配 v 开头的版本分支,如 v1, v2.0
|
||||
- event: push
|
||||
branch: "v[0-9]*"
|
||||
# 匹配 tag 事件
|
||||
- event: tag
|
||||
ref: "refs/tags/(v?[0-9].*)"
|
||||
|
||||
labels:
|
||||
runtime: docker
|
||||
arch: amd64
|
||||
multiarch: "true"
|
||||
|
||||
steps:
|
||||
- name: 初始化子模块
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule update --init --recursive
|
||||
|
||||
- name: 编译并推送镜像
|
||||
image: docker:cli
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
SWR_REGISTRY: "swr.cn-north-4.myhuaweicloud.com"
|
||||
DOCKER_CLI_EXPERIMENTAL: enabled
|
||||
SWR_USERNAME:
|
||||
from_secret: swr_colovu_user
|
||||
SWR_PASSWORD:
|
||||
from_secret: swr_colovu_passwd
|
||||
commands:
|
||||
- |
|
||||
# 直接执行 Submodule .ci/common 下的构建推送脚本
|
||||
if [ ! -f ".ci/common/build_push.sh" ]; then
|
||||
echo "错误: 未找到 .ci/common/build_push.sh 脚本"
|
||||
exit 1
|
||||
fi
|
||||
- sh ./.ci/common/build_push.sh
|
||||
+115
-118
@@ -1,194 +1,191 @@
|
||||
# Ver: 1.9 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.12 by Endial Fang (endial@126.com)
|
||||
#
|
||||
|
||||
# 默认变量 ========================================================================
|
||||
# 系统默认变量 ====================================================================
|
||||
# 该部分变量为系统根据编译命令默认设置
|
||||
|
||||
# `TARGETPLATFORM`:构建后的目标平台信息。如 `linux/amd64`,`linux/arm/v7`,`windows/amd64`
|
||||
# `TARGETPLATFORM`:构建后的目标平台信息。如 `linux/amd64`,`linux/arm/v7`,`windows/amd64`
|
||||
# `TARGETOS`:目标平台信息(TARGETPLATFORM)中的操作系统部分,如:`linux`、`windows`
|
||||
# `TARGETARCH`:目标平台信息(TARGETPLATFORM)中的平台架构部分,如:`amd64`、`arm`
|
||||
# `TARGETVARIANT`:目标平台信息(TARGETPLATFORM)中的版本变体部分,如:`v7`
|
||||
# `BUILDPLATFORM`:用于构建的节点平台信息
|
||||
# `BUILDOS`:用于构建的节点平台信息(BUILDPLATFORM)中的操作系统部分
|
||||
# `BUILDARCH`用于构建的节点平台信息(BUILDPLATFORM)中的平台架构部分
|
||||
# `BUILDVARIANT`用于构建的节点平台信息(BUILDPLATFORM)中的版本变体部分
|
||||
# `BUILDARCH`:用于构建的节点平台信息(BUILDPLATFORM)中的平台架构部分
|
||||
# `BUILDVARIANT`:用于构建的节点平台信息(BUILDPLATFORM)中的版本变体部分
|
||||
|
||||
# 可变参数 ========================================================================
|
||||
# 该部分变量,在编译命令中通过 `--build-arg` 传入;如果未设置,则使用下面对应的默认值
|
||||
# 依赖镜像下载地址: docker.io (默认) / swr.cn-north-4.myhuaweicloud.com/colovu/
|
||||
# apt源: default / aliyun / ustc
|
||||
# 软件包本地服务器: http://pkgs.colovu.com/dist
|
||||
|
||||
# 设置当前应用名称及版本
|
||||
ARG APP_NAME=nginx
|
||||
ARG APP_VER=1.24.0
|
||||
|
||||
# 设置默认仓库地址,默认为本地仓库;定义时需要包含末尾的`/`
|
||||
ARG REGISTRY_URL="docker.colovu.com/"
|
||||
|
||||
# 设置 apt-get 源:default / ustc / aliyun
|
||||
ARG APP_VER=1.29.4
|
||||
ARG REGISTRY_URL="swr.cn-north-4.myhuaweicloud.com/colovu/"
|
||||
ARG APT_SOURCE=aliyun
|
||||
|
||||
# 编译镜像时指定用于加速的本地软件包存储服务器地址
|
||||
ARG LOCAL_URL=""
|
||||
|
||||
# 0. 预处理 ======================================================================
|
||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} ${REGISTRY_URL}colovu/dbuilder:11 as builder
|
||||
FROM ${REGISTRY_URL}debian-builder:v13 AS builder
|
||||
|
||||
# 声明需要使用的全局可变参数
|
||||
ARG APP_NAME
|
||||
ARG APP_VER
|
||||
ARG REGISTRY_URL
|
||||
ARG APT_SOURCE
|
||||
ARG LOCAL_URL
|
||||
ARG TARGETARCH
|
||||
|
||||
# 选择软件包源(Optional),以加速后续软件包安装
|
||||
RUN select_source ${APT_SOURCE};
|
||||
# 选择软件包源,加速后续软件包安装
|
||||
RUN /usr/local/sbin/select_source ${APT_SOURCE};
|
||||
|
||||
# 安装依赖的软件包及库(Optional)
|
||||
RUN install_pkg libpcre3 libpcre3-dev \
|
||||
zlib1g zlib1g-dev \
|
||||
libxslt1.1 libxslt1-dev \
|
||||
libgd3 libgd-dev \
|
||||
libxml2 libxml2-dev \
|
||||
geoip-bin geoip-database libgeoip-dev
|
||||
# 安装依赖的软件包及库
|
||||
RUN /usr/local/sbin/install_pkg libperl-dev \
|
||||
libpcre2-32-0 libpcre2-16-0 libpcre2-posix3 libpcre2-dev \
|
||||
zlib1g zlib1g-dev \
|
||||
libxslt1.1 libxslt1-dev \
|
||||
libgd3 libgd-dev \
|
||||
libxml2 libxml2-dev \
|
||||
geoip-bin geoip-database libgeoip-dev
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /tmp
|
||||
|
||||
# 下载并解压软件包 nginx
|
||||
# 下载并解压软件包 nginx: https://nginx.org/download/nginx-1.29.4.tar.gz
|
||||
RUN set -eux; \
|
||||
appName="${APP_NAME}-${APP_VER}.tar.gz"; \
|
||||
[ ! -z ${LOCAL_URL} ] && localURL=${LOCAL_URL}/nginx; \
|
||||
[ -n ${LOCAL_URL} ] && localURL=${LOCAL_URL}/${APP_NAME}; \
|
||||
appUrls="${localURL:-} \
|
||||
http://nginx.org/download \
|
||||
"; \
|
||||
download_pkg unpack ${appName} "${appUrls}";
|
||||
/usr/local/sbin/download_pkg unpack ${appName} "${appUrls}";
|
||||
|
||||
# 源码编译: 编译后将配置文件模板拷贝至 /usr/local/${app_name}/share/${app_name} 中
|
||||
RUN set -eux; \
|
||||
APP_ARCH=`arch` \
|
||||
APP_ARCH=${TARGETARCH:-$(dpkg --print-architecture)}; \
|
||||
APP_SRC="/tmp/${APP_NAME}-${APP_VER}"; \
|
||||
cd ${APP_SRC}; \
|
||||
LDFLAGS="-L/usr/local/lib -L/usr/lib/${APP_ARCH}-linux-gnu" ./configure \
|
||||
--prefix=/usr/local/nginx \
|
||||
--sbin-path=/usr/local/nginx/sbin/nginx \
|
||||
--conf-path=/etc/nginx/nginx.conf \
|
||||
--pid-path=/var/run/nginx/nginx.pid \
|
||||
--lock-path=/var/run/nginx/nginx.lock \
|
||||
--http-log-path=/var/log/nginx/access.log \
|
||||
--error-log-path=/var/log/nginx/error.log \
|
||||
--modules-path=/usr/local/nginx/modules \
|
||||
--http-client-body-temp-path=/var/cache/nginx/client_temp \
|
||||
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
|
||||
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
|
||||
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
|
||||
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
|
||||
LDFLAGS="-L/usr/local/lib -L/usr/lib/${APP_ARCH}-linux-gnu" \
|
||||
./configure \
|
||||
--prefix=/usr/local/${APP_NAME} \
|
||||
--sbin-path=/usr/local/${APP_NAME}/sbin/nginx \
|
||||
--conf-path=/usr/local/${APP_NAME}/etc/nginx/nginx.conf \
|
||||
--pid-path=/var/run/${APP_NAME}/nginx.pid \
|
||||
--lock-path=/var/run/${APP_NAME}/nginx.lock \
|
||||
--http-log-path=/var/log/${APP_NAME}/access.log \
|
||||
--error-log-path=/var/log/${APP_NAME}/error.log \
|
||||
--modules-path=/usr/local/${APP_NAME}/modules \
|
||||
--http-client-body-temp-path=/var/cache/${APP_NAME}/client_temp \
|
||||
--http-proxy-temp-path=/var/cache/${APP_NAME}/proxy_temp \
|
||||
--http-fastcgi-temp-path=/var/cache/${APP_NAME}/fastcgi_temp \
|
||||
--http-uwsgi-temp-path=/var/cache/${APP_NAME}/uwsgi_temp \
|
||||
--http-scgi-temp-path=/var/cache/${APP_NAME}/scgi_temp \
|
||||
\
|
||||
--with-pcre \
|
||||
--with-pcre-jit \
|
||||
--with-http_ssl_module \
|
||||
--with-http_v2_module \
|
||||
--with-http_v3_module \
|
||||
--with-http_realip_module \
|
||||
--with-http_xslt_module \
|
||||
--with-http_image_filter_module \
|
||||
--with-http_geoip_module \
|
||||
--with-http_sub_module \
|
||||
--with-http_dav_module \
|
||||
--with-http_mp4_module \
|
||||
--with-http_flv_module \
|
||||
--with-http_gunzip_module \
|
||||
--with-http_gzip_static_module \
|
||||
--with-http_auth_request_module \
|
||||
--with-http_addition_module \
|
||||
--with-http_slice_module \
|
||||
\
|
||||
--with-stream \
|
||||
--with-stream_geoip_module \
|
||||
--with-http_random_index_module \
|
||||
--with-http_secure_link_module \
|
||||
--with-http_stub_status_module \
|
||||
--with-mail_ssl_module \
|
||||
--with-pcre \
|
||||
--with-pcre-jit \
|
||||
--with-poll_module \
|
||||
--with-stream_realip_module \
|
||||
--with-stream_ssl_module \
|
||||
--with-threads \
|
||||
--with-poll_module \
|
||||
--with-mail \
|
||||
\
|
||||
--with-stream=dynamic \
|
||||
--with-stream_geoip_module=dynamic \
|
||||
--with-http_perl_module=dynamic \
|
||||
--with-http_geoip_module=dynamic \
|
||||
--with-http_xslt_module=dynamic \
|
||||
--with-http_image_filter_module=dynamic \
|
||||
--with-mail=dynamic \
|
||||
; \
|
||||
make -j "$(nproc)" && make install; \
|
||||
strip /usr/local/nginx/sbin/nginx;
|
||||
strip /usr/local/${APP_NAME}/sbin/nginx;
|
||||
|
||||
# 生成默认 PHP 首页文件
|
||||
RUN set -eux; \
|
||||
echo "<?php" >/usr/local/nginx/html/index.php; \
|
||||
echo "phpinfo();" >>/usr/local/nginx/html/index.php; \
|
||||
echo "?>" >>/usr/local/nginx/html/index.php;
|
||||
echo "<?php" >/usr/local/${APP_NAME}/html/index.php; \
|
||||
echo "phpinfo();" >>/usr/local/${APP_NAME}/html/index.php; \
|
||||
echo "?>" >>/usr/local/${APP_NAME}/html/index.php;
|
||||
|
||||
# 检测并生成依赖文件记录
|
||||
RUN set -eux; \
|
||||
find /usr/local/${APP_NAME} -type f -executable -exec ldd '{}' ';' | \
|
||||
awk '/=>/ { print $(NF-1) }' | \
|
||||
sort -u | \
|
||||
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:11
|
||||
FROM ${REGISTRY_URL}debian:v13
|
||||
|
||||
# 声明需要使用的全局可变参数
|
||||
# 声明需要使用的全局可变参数(ARG声明的变量仅编译打包阶段有效)
|
||||
ARG APP_NAME
|
||||
ARG APP_VER
|
||||
ARG REGISTRY_URL
|
||||
ARG APT_SOURCE
|
||||
ARG LOCAL_URL
|
||||
|
||||
# 镜像所包含应用的基础信息,定义环境变量,供后续脚本使用
|
||||
ENV APP_EXEC=${APP_NAME}
|
||||
# 定义应用的基础信息变量(ENV声明的变量实例化后容器内有效)
|
||||
ENV APP_NAME=${APP_NAME} \
|
||||
APP_VER=${APP_VER} \
|
||||
APP_EXEC=${APP_NAME} \
|
||||
APP_USER=${APP_NAME} \
|
||||
\
|
||||
PATH="${PATH}:/usr/local/${APP_NAME}/sbin"
|
||||
|
||||
ENV APP_HOME_DIR=/usr/local/${APP_NAME} \
|
||||
APP_DEF_DIR=/etc/${APP_NAME}
|
||||
# 镜像元数据标签 - 符合OCI镜像规范
|
||||
LABEL org.opencontainers.image.title="${APP_NAME}" \
|
||||
org.opencontainers.image.version="${APP_VER}" \
|
||||
org.opencontainers.image.description="Docker image for Nginx." \
|
||||
org.opencontainers.image.authors="Endial Fang <endial@126.com>" \
|
||||
org.opencontainers.image.url="https://gitee.com/colovu/docker-${APP_NAME}" \
|
||||
org.opencontainers.image.vendor="Endial Fang (colovu)" \
|
||||
org.opencontainers.image.licenses="Apache-2.0" \
|
||||
org.opencontainers.image.source="https://gitee.com/colovu/docker-${APP_NAME}" \
|
||||
org.opencontainers.image.documentation="https://gitee.com/colovu/docker-${APP_NAME}/blob/main/README.md" \
|
||||
maintainer="Endial Fang <endial@126.com>"
|
||||
|
||||
ENV PATH="${APP_HOME_DIR}/sbin:${APP_HOME_DIR}/bin:${PATH}" \
|
||||
LD_LIBRARY_PATH="${APP_HOME_DIR}/lib"
|
||||
|
||||
LABEL \
|
||||
"Version"="v${APP_VER}" \
|
||||
"Description"="Docker image for ${APP_NAME}." \
|
||||
"Github"="https://github.com/colovu/docker-${APP_NAME}" \
|
||||
"Vendor"="Endial Fang (endial@126.com)"
|
||||
|
||||
# 从预处理过程中拷贝软件包(Optional),可以使用阶段编号或阶段命名定义来源
|
||||
COPY --from=0 /usr/local/${APP_NAME} /usr/local/${APP_NAME}
|
||||
|
||||
# 拷贝应用使用的客制化脚本,并创建对应的用户及数据存储目录
|
||||
# 拷贝多阶段构建结果输出及客制化脚本
|
||||
COPY --from=builder /usr/local/${APP_NAME} /usr/local/${APP_NAME}
|
||||
COPY customer /
|
||||
|
||||
RUN set -eux; \
|
||||
prepare_env; \
|
||||
/bin/bash -c "ln -sf /usr/local/${APP_NAME}/etc/${APP_NAME} /etc/";
|
||||
|
||||
# 选择软件包源(Optional),以加速后续软件包安装
|
||||
RUN select_source ${APT_SOURCE}
|
||||
|
||||
# 安装依赖的软件包及库(Optional)
|
||||
RUN install_pkg `cat /usr/local/${APP_NAME}/runDeps`;
|
||||
|
||||
# 执行预处理脚本,并验证安装的软件包
|
||||
RUN set -eux; \
|
||||
override_file="/usr/local/overrides/overrides-${APP_VER}.sh"; \
|
||||
[ -e "${override_file}" ] && /bin/bash "${override_file}"; \
|
||||
\
|
||||
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/"; \
|
||||
\
|
||||
/usr/local/sbin/select_source ${APT_SOURCE}; \
|
||||
\
|
||||
/usr/local/sbin/install_pkg `cat /usr/local/${APP_NAME}/runDeps`; \
|
||||
\
|
||||
overrideShell="/usr/local/overrides/overrides-${APP_VER}.sh"; \
|
||||
[ -e "${overrideShell}" ] && /bin/bash "${overrideShell}"; \
|
||||
\
|
||||
${APP_EXEC} -V ;
|
||||
|
||||
# 默认提供的数据卷
|
||||
VOLUME ["/srv/conf", "/srv/data", "/srv/cert", "/var/log"]
|
||||
|
||||
# 默认non-root用户启动,必须保证端口在1024之上
|
||||
# 配置容器的数据卷、工作目录及服务端口(必须保证端口在1024之上)
|
||||
VOLUME ["/srv/${APP_NAME}/conf", "/srv/${APP_NAME}/data", "/srv/${APP_NAME}/cert", "/srv/${APP_NAME}/log"]
|
||||
WORKDIR /srv/${APP_NAME}
|
||||
EXPOSE 8080 8443
|
||||
|
||||
# 应用健康状态检查
|
||||
#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 8080
|
||||
#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 8080
|
||||
|
||||
# 使用 non-root 用户运行后续的命令
|
||||
USER 1001
|
||||
# 使用 dumb-init 启动入口 Shell,确保容器可以接收控制信号;并使用前台方式启动应用程序
|
||||
ENTRYPOINT ["dumb-init", "entry.sh"]
|
||||
CMD ["run.sh"]
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /srv/conf
|
||||
|
||||
# 容器初始化命令
|
||||
ENTRYPOINT ["/usr/local/bin/entry.sh"]
|
||||
|
||||
# 应用程序的启动命令,必须使用非守护进程方式运行
|
||||
CMD ["/usr/local/bin/run.sh"]
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# Ver: 1.11 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 当前 Docker 镜像的编译脚本
|
||||
|
||||
# 定义镜像名称
|
||||
image_name :=colovu/nginx
|
||||
|
||||
# 定义默认镜像仓库地址
|
||||
REGISTRY_URL :=docker.colovu.com
|
||||
|
||||
# 定义系统默认使用的源服务器,包含:default / ustc / aliyun
|
||||
APT_SOURCE :=aliyun
|
||||
|
||||
# 定义镜像TAG,类似:
|
||||
# <镜像名>:<分支名>-<7位Git ID> # 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)
|
||||
image_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)
|
||||
|
||||
build-arg:=--build-arg REGISTRY_URL=$(REGISTRY_URL)
|
||||
build-arg+=--build-arg APT_SOURCE=$(APT_SOURCE)
|
||||
|
||||
# 设置本地下载服务器路径,加速调试时的本地编译速度
|
||||
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 clean clearclean upgrade
|
||||
|
||||
build:
|
||||
@echo "Build $(image_name):$(image_tag)"
|
||||
@docker build --progress plain --force-rm $(build-arg) -t $(image_name):$(image_tag) .
|
||||
@echo "Add tag: $(image_name):latest"
|
||||
@docker tag $(image_name):$(image_tag) $(image_name):latest
|
||||
@echo "Build complete"
|
||||
|
||||
# 清理悬空的镜像(无TAG)及停止的容器
|
||||
clearclean: clean
|
||||
@echo "Clean untaged images and stoped containers..."
|
||||
@docker ps -a | grep "Exited" | awk '{print $$1}' | sort -u | xargs -L 1 docker rm
|
||||
@docker images | grep '<none>' | awk '{print $$3}' | sort -u | xargs -L 1 docker rmi -f
|
||||
|
||||
# 为了防止删除前缀名相同的镜像,在过滤条件中加入一个空格进行过滤
|
||||
clean:
|
||||
@echo "Clean all images for current application..."
|
||||
@docker images | grep "$(image_name) " | awk '{print $$3}' | sort -u | xargs -L 1 docker rmi -f
|
||||
|
||||
# 更新所有 colovu 仓库的镜像
|
||||
upgrade:
|
||||
@echo "Upgrade all images..."
|
||||
@docker images | grep 'colovu' | grep -v '<none>' | grep -v "latest-" | awk '{print $$1":"$$2}' | sort -u | xargs -L 1 docker pull
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
|
||||
**版本信息:**
|
||||
|
||||
- 1.24.0、latest
|
||||
- 1.29、latest
|
||||
- 1.28
|
||||
|
||||
**镜像信息:**
|
||||
|
||||
* 镜像地址:
|
||||
- 阿里云: registry.cn-shenzhen.aliyuncs.com/colovu/nginx:latest
|
||||
- DockerHub:colovu/nginx:latest
|
||||
- Colovu Registry: docker.colovu.com/colovu/nginx:latest
|
||||
- 依赖镜像:colovu/debian:11
|
||||
- 依赖镜像:colovu/debian:12
|
||||
|
||||
> 后续相关命令行默认使用`[Colovu Registry](https://docker.colovu.com)`镜像服务器做说明
|
||||
> 后续相关命令行默认使用 Aliyun ACR 镜像服务器做说明
|
||||
|
||||
## TL;DR
|
||||
|
||||
@@ -26,9 +26,11 @@ Docker 快速启动命令:
|
||||
|
||||
```shell
|
||||
# 从 Registry 服务器下载镜像并启动
|
||||
$ docker run -d -p 80:8080 docker.colovu.com/colovu/nginx:latest
|
||||
$ docker run -d -p 80:8080 registry.cn-shenzhen.aliyuncs.com/colovu/nginx:latest
|
||||
```
|
||||
|
||||
- `registry.cn-shenzhen.aliyuncs.com/colovu/imgname:<TAG>`:镜像名称及版本标签 TAG;标签不指定时默认使用最新版本
|
||||
|
||||
启动后,可以使用浏览器访问:`http://localhost/`,出现默认的 Nginx 首页。
|
||||
|
||||
Docker-Compose 快速启动命令:
|
||||
@@ -58,10 +60,11 @@ $ docker-compose up -d
|
||||
镜像默认提供以下数据卷定义,默认数据分别存储在自动生成的应用名对应`nginx`子目录中:
|
||||
|
||||
```shell
|
||||
/srv/conf # nginx 配置文件
|
||||
/srv/data # 站点源文件
|
||||
/var/log # 日志文件
|
||||
/var/run # 进程运行PID文件
|
||||
/srv/nginx/conf # 配置文件
|
||||
/srv/nginx/data # 数据文件,主要存放应用数据
|
||||
/srv/nginx/cert # 证书文件存放目录
|
||||
/srv/nginx/log # 日志文件
|
||||
/var/run/nginx # 进程运行PID文件
|
||||
```
|
||||
|
||||
如果需要持久化存储相应数据,需要**在宿主机建立本地目录**,并在使用镜像初始化容器时进行映射。宿主机相关的目录中如果不存在对应应用`nginx`的子目录或相应数据文件,则容器会在初始化时创建相应目录及文件。
|
||||
@@ -71,39 +74,46 @@ $ docker-compose up -d
|
||||
在初始化 `Nginx` 容器时,如果没有预置配置文件,可以在命令行中设置相应环境变量对默认参数进行修改。类似命令如下(配置环境变量`APP_ENV_KEY_NAME`的值为`key_value`):
|
||||
|
||||
```shell
|
||||
$ docker run -d -e "APP_ENV_KEY_NAME=key_value" docker.colovu.com/colovu/nginx:latest
|
||||
$ docker run -d -e "APP_ENV_KEY_NAME=key_value" registry.cn-shenzhen.aliyuncs.com/colovu/nginx:latest
|
||||
```
|
||||
|
||||
### 自动变量替换
|
||||
|
||||
针对配置文件中的配置项,支持环境变量名自动替换,该类环境变量定义规则为:`APP_CFG_*=<val>`
|
||||
针对应用配置文件中的配置项,支持由环境变量名自动替换生成,该类环境变量需要使用统一前缀,定义规则为:`APP_CFG_*=<val>`
|
||||
|
||||
- `APP_CFG_`:环境变量自动替换标识,具备该前缀的环境变量会被自动处理并更新至配置文件
|
||||
- `*`:配置文件中对应的配置项名,大小写需要符合实际参数名要求;特殊字符需要符合`特殊字符替换规则`
|
||||
- `<val>`:配置项对应值
|
||||
|
||||
**特殊字符替换规则**:
|
||||
|
||||
因为 Shell 变量只能以字母、数字和下划线组成,针对'xml'、'ini'等配置文件中使用的'.'、'-'等特殊字符,需要进行重定义及转换。预定义如下:
|
||||
|
||||
+ `_` ==> `_` : 应用配置属性中的`_`(下划线),与环境变量相同
|
||||
+ `__` ==> `.` : 应用配置属性中的`.`(半角点),在环境变量中由`__`(双下划线)表示
|
||||
+ `___` ==> `-` : 应用配置属性中的`-`(中划线),在环境变量中由`___`(三下划线)表示
|
||||
|
||||
例如:
|
||||
|
||||
```shell
|
||||
# 设置配置文件中配置项 max_wal_size,传入容器的变量为(两者都可以):
|
||||
APP_CFG_max_wal_size=400MB
|
||||
# 常用于`key-value`类型的配置
|
||||
APP_CFG_min_wal_size=100MB
|
||||
APP_CFG_max_wal_size="400MB"
|
||||
|
||||
# 容器启动后,应用配置文件中对应配置项生效,且设置为相应值:
|
||||
min_wal_size = '100MB'
|
||||
max_wal_size = '400MB'
|
||||
|
||||
|
||||
# 常用于`xml`类型的配置
|
||||
APP_CFG_fs__defaultFS=hdfs://namenode:8020
|
||||
APP_CFG_yarn__log___aggregation___enable=true
|
||||
|
||||
# 容器启动后,应用配置文件中对应配置项生效,且设置为相应值:
|
||||
<property><name>fs.defaultFS</name><value>hdfs://namenode:8020</value></property>
|
||||
<property><name>yarn.log-aggregation-enable</name><value>true</value></property>
|
||||
```
|
||||
|
||||
**特殊字符替换规则**:
|
||||
|
||||
- 针对使用`xml`格式的配置文件
|
||||
+ `_` ==> `.` : 环境变量中的`下划线`会被转义为设置属性中的`半角点`
|
||||
+ `__` ==> `_` : 环境变量中的`双下划线`会被转义为设置属性中的`单下划线`
|
||||
+ `___` ==> `-` : 环境变量中的`三下划线`会被转义为设置属性中的`中划线`
|
||||
- 针对使用`key-val`格式的配置文件
|
||||
+ `_` ==> `_` : 环境变量中的`下划线`不会被替换
|
||||
+ `__` ==> `.` : 环境变量中的`双下划线`会被转义为设置属性中的`半角点`
|
||||
+ `___` ==> `-` : 环境变量中的`三下划线`会被转义为设置属性中的`中划线`
|
||||
|
||||
### 常规配置参数
|
||||
|
||||
常规配置参数用来配置容器基本属性,一般情况下需要设置,主要包括:
|
||||
@@ -114,7 +124,8 @@ max_wal_size = '400MB'
|
||||
|
||||
如果没有必要,可选配置参数可以不用定义,直接使用对应的默认值,主要包括:
|
||||
|
||||
- `ENV_DEBUG`:默认值:**false**。设置是否输出容器调试信息。可选值:no、true、yes
|
||||
- `ENV_DEBUG`:默认值:**false**。设置是否输出容器调试信息。可选值:false、no、true、yes
|
||||
- `ALLOW_ANONYMOUS`:默认值:**no**。设置是否允许匿名链接。可选值:false、no、true、yes
|
||||
|
||||
### 集群配置参数
|
||||
|
||||
@@ -147,6 +158,7 @@ max_wal_size = '400MB'
|
||||
|
||||
## 更新记录
|
||||
|
||||
- 2026/1/21: 更新版本为 v1.29.3
|
||||
- 2023/8/3: 更新为 Nginx 1.24.0
|
||||
|
||||
----
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
1.28.1
|
||||
1.29.4
|
||||
|
||||
|
||||
Dynamic Modules
|
||||
Main nginx package is built with all modules that do not require additional libraries to avoid extra dependencies. Since version 1.9.11, nginx supports dynamic modules and the following modules are built as dynamic and shipped as separate packages:
|
||||
nginx-module-geoip
|
||||
nginx-module-image-filter
|
||||
nginx-module-njs
|
||||
nginx-module-perl
|
||||
nginx-module-xslt
|
||||
Additionally, since version 1.25.3, the following module is shipped as a separate package:
|
||||
nginx-module-otel
|
||||
Additionally, since version 1.29.1, the following module is shipped as a separate package:
|
||||
nginx-module-acme
|
||||
|
||||
原始 nginx.conf:
|
||||
|
||||
#user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
#error_log logs/error.log;
|
||||
#error_log logs/error.log notice;
|
||||
#error_log logs/error.log info;
|
||||
|
||||
#pid logs/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
# '$status $body_bytes_sent "$http_referer" '
|
||||
# '"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
#access_log logs/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
#keepalive_timeout 0;
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
#access_log logs/host.access.log main;
|
||||
|
||||
location / {
|
||||
root html;
|
||||
index index.html index.htm;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root html;
|
||||
}
|
||||
|
||||
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# proxy_pass http://127.0.0.1;
|
||||
#}
|
||||
|
||||
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# root html;
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
# fastcgi_index index.php;
|
||||
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
|
||||
# include fastcgi_params;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
|
||||
|
||||
# another virtual host using mix of IP-, name-, and port-based configuration
|
||||
#
|
||||
#server {
|
||||
# listen 8000;
|
||||
# listen somename:8080;
|
||||
# server_name somename alias another.alias;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
|
||||
# HTTPS server
|
||||
#
|
||||
#server {
|
||||
# listen 443 ssl;
|
||||
# server_name localhost;
|
||||
|
||||
# ssl_certificate cert.pem;
|
||||
# ssl_certificate_key cert.key;
|
||||
|
||||
# ssl_session_cache shared:SSL:1m;
|
||||
# ssl_session_timeout 5m;
|
||||
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
|
||||
# location / {
|
||||
# root html;
|
||||
# index index.html index.htm;
|
||||
# }
|
||||
#}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
# Ver: 3.0 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# Docker 镜像构建脚本 - 主入口
|
||||
|
||||
# 编译后镜像名称
|
||||
export IMAGE_NAME="nginx"
|
||||
# 依赖镜像的仓库地址
|
||||
export REGISTRY_URL="swr.cn-north-4.myhuaweicloud.com/colovu/"
|
||||
# 源仓库地址(本地编译时,使用阿里云源仓库)
|
||||
export APT_SOURCE="aliyun"
|
||||
# 针对无法直接下载到软件包,本地变异时,使用缓存的软件包
|
||||
export LOCAL_URL="http://pkgs.colovu.com/dist"
|
||||
|
||||
# 引入本地构建脚本
|
||||
if [ -f ".ci/common/build_local.sh" ]; then
|
||||
# 执行本地构建脚本并传递参数
|
||||
exec ".ci/common/build_local.sh" "$@"
|
||||
else
|
||||
echo "Error: .ci/common/build_local.sh script not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,435 +1,42 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.1 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用通用业务处理函数
|
||||
|
||||
# 加载依赖脚本
|
||||
. /usr/local/scripts/libcommon.sh # 通用函数库
|
||||
. /usr/local/lib/libcommon.sh # 通用函数库
|
||||
|
||||
. /usr/local/scripts/libfile.sh
|
||||
. /usr/local/scripts/libfs.sh
|
||||
. /usr/local/scripts/liblog.sh
|
||||
. /usr/local/scripts/libos.sh
|
||||
. /usr/local/scripts/libservice.sh
|
||||
. /usr/local/scripts/libvalidations.sh
|
||||
. /usr/local/lib/libfile.sh
|
||||
. /usr/local/lib/libfs.sh
|
||||
. /usr/local/lib/liblog.sh
|
||||
. /usr/local/lib/libos.sh
|
||||
. /usr/local/lib/libservice.sh
|
||||
. /usr/local/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=""
|
||||
|
||||
# 使用环境变量中以 "<PREFIX>" 开头的的全局变量更新指定配置文件中对应项(以"."分隔)
|
||||
# 如果需要全部转换为小写,可使用命令: tr '[:upper:]' '[:lower:]'
|
||||
# 全局变量:
|
||||
# <PREFIX>_* :
|
||||
# 替换规则(变量中字符 ==> 替换后全局变量中字符):
|
||||
# - "." ==> "_"
|
||||
# - "_" ==> "__"
|
||||
# - "-" ==> "___"
|
||||
#
|
||||
# 变量:
|
||||
# $1 - 配置文件
|
||||
# $2 - 前缀(不含结束的"_")
|
||||
#
|
||||
# 举例:
|
||||
# CORE_CONF_fs_defaultFS 对应配置文件中的配置项:fs.defaultFS
|
||||
nginx_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}"
|
||||
nginx_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
|
||||
}
|
||||
|
||||
# 将变量配置更新至配置文件
|
||||
# 参数:
|
||||
# $1 - 文件
|
||||
# $2 - 变量
|
||||
# $3 - 值(列表)
|
||||
nginx_common_conf_set() {
|
||||
local file="${1:?missing file}"
|
||||
local key="${2:?missing key}"
|
||||
shift
|
||||
shift
|
||||
local values=("$@")
|
||||
|
||||
if [[ "${#values[@]}" -eq 0 ]]; then
|
||||
LOG_E "missing value"
|
||||
return 1
|
||||
elif [[ "${#values[@]}" -ne 1 ]]; then
|
||||
for i in "${!values[@]}"; do
|
||||
nginx_common_conf_set "$file" "${key[$i]}" "${values[$i]}"
|
||||
done
|
||||
else
|
||||
value="${values[0]}"
|
||||
# Check if the value was set before
|
||||
if grep -q "^[#\\s]*$key\s*=.*" "$file"; then
|
||||
# Update the existing key
|
||||
replace_in_file "$file" "^[#\\s]*${key}\s*=.*" "${key}=${value}" false
|
||||
shift 2
|
||||
debug "List to check in ${base_path}: $@"
|
||||
while [ "$#" -gt 0 ]; do
|
||||
f="${1}"
|
||||
debug " Process \"${f}\""
|
||||
if [ -d "${base_path}/${f}" ]; then
|
||||
[[ ! -d "${dist_path}/${f}" ]] && debug " 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
|
||||
# 增加一个新的配置项;如果在其他位置有类似操作,需要注意换行
|
||||
printf "%s=%s" "$key" "$value" >>"$file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 更新 server.properties 配置文件中指定变量值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
# $2 - 值(列表)
|
||||
nginx_conf_set() {
|
||||
nginx_common_conf_set "${APP_CONF_DIR}/zoo.cfg" "$@"
|
||||
}
|
||||
|
||||
# 更新 log4j.properties 配置文件中指定变量值
|
||||
# 变量:
|
||||
# $1 - 变量
|
||||
# $2 - 值(列表)
|
||||
nginx_log4j_set() {
|
||||
nginx_common_conf_set "${APP_CONF_DIR}/log4j.properties" "$@"
|
||||
}
|
||||
|
||||
# 使用环境变量中配置,更新配置文件
|
||||
nginx_update_conf() {
|
||||
LOG_I "Update configure files..."
|
||||
|
||||
}
|
||||
|
||||
# 生成默认配置文件
|
||||
nginx_generate_conf() {
|
||||
# 准备原始默认配置文件或生成空文件
|
||||
cp "${APP_CONF_DIR}/zoo_sample.cfg" "$APP_CONF_FILE"
|
||||
|
||||
echo "">> "$APP_CONF_FILE"
|
||||
|
||||
# 根据容器参数,设置配置文件
|
||||
nginx_log4j_set "zookeeper.console.threshold" "${ZOO_LOG_LEVEL}"
|
||||
nginx_log4j_set "zookeeper.log.dir" "${APP_LOG_DIR}"
|
||||
|
||||
nginx_update_conf
|
||||
}
|
||||
|
||||
# 设置环境变量 JVMFLAGS
|
||||
# 参数:
|
||||
# $1 - value
|
||||
nginx_export_jvmflags() {
|
||||
local -r value="${1:?value is required}"
|
||||
|
||||
export JVMFLAGS="${JVMFLAGS} ${value}"
|
||||
echo "export JVMFLAGS=\"${JVMFLAGS}\"" > "${APP_CONF_DIR}/java.env"
|
||||
}
|
||||
|
||||
# 配置 HEAP 大小
|
||||
# 参数:
|
||||
# $1 - HEAP 大小
|
||||
nginx_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..."
|
||||
nginx_export_jvmflags "-Xmx${heap_size}m -Xms${heap_size}m"
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测用户参数信息是否满足条件; 针对部分权限过于开放情况,打印提示信息
|
||||
nginx_verify_minimum_env() {
|
||||
local error_code=0
|
||||
|
||||
LOG_D "Validating settings in NGINX_* env vars..."
|
||||
|
||||
print_validation_error() {
|
||||
LOG_E "$1"
|
||||
error_code=1
|
||||
}
|
||||
|
||||
# 检测认证设置。如果不允许匿名登录,检测登录用户名及密码是否设置
|
||||
# if is_boolean_yes "$ALLOW_ANONYMOUS_LOGIN"; then
|
||||
# LOG_W "You have set the environment variable ALLOW_ANONYMOUS_LOGIN=${ALLOW_ANONYMOUS_LOGIN}. For safety reasons, do not use this flag in a production environment."
|
||||
# elif ! is_boolean_yes "$ZOO_ENABLE_AUTH"; then
|
||||
# print_validation_error "The ZOO_ENABLE_AUTH environment variable does not configure authentication. Set the environment variable ALLOW_ANONYMOUS_LOGIN=yes to allow unauthenticated users to connect to ZooKeeper."
|
||||
# fi
|
||||
|
||||
# TODO: 其他参数检测
|
||||
|
||||
[[ "$error_code" -eq 0 ]] || exit "$error_code"
|
||||
}
|
||||
|
||||
# 更改默认监听地址为 "*" 或 "0.0.0.0",以对容器外提供服务;默认配置文件应当为仅监听 localhost(127.0.0.1)
|
||||
nginx_enable_remote_connections() {
|
||||
LOG_D "Modify default config to enable all IP access"
|
||||
|
||||
}
|
||||
|
||||
# 检测依赖的服务端口是否就绪;该脚本依赖系统工具 'netcat'
|
||||
# 参数:
|
||||
# $1 - host:port
|
||||
nginx_wait_service() {
|
||||
local serviceport=${1:?Missing server info}
|
||||
local service=${serviceport%%:*}
|
||||
local port=${serviceport#*:}
|
||||
local retry_seconds=5
|
||||
local max_try=100
|
||||
let i=1
|
||||
|
||||
if [[ -z "$(which nc)" ]]; then
|
||||
LOG_E "Nedd nc installed before, command: \"apt-get install netcat\"."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOG_I "[0/${max_try}] check for ${service}:${port}..."
|
||||
|
||||
set +e
|
||||
nc -z ${service} ${port}
|
||||
result=$?
|
||||
|
||||
until [ $result -eq 0 ]; do
|
||||
LOG_D " [$i/${max_try}] not available yet"
|
||||
if (( $i == ${max_try} )); then
|
||||
LOG_E "${service}:${port} is still not available; giving up after ${max_try} tries."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOG_I "[$i/${max_try}] try in ${retry_seconds}s once again ..."
|
||||
let "i++"
|
||||
sleep ${retry_seconds}
|
||||
|
||||
nc -z ${service} ${port}
|
||||
result=$?
|
||||
done
|
||||
|
||||
set -e
|
||||
LOG_I "[$i/${max_try}] ${service}:${port} is available."
|
||||
}
|
||||
|
||||
# 以后台方式启动应用服务,并等待启动就绪
|
||||
nginx_start_server_bg() {
|
||||
nginx_is_server_running && return
|
||||
|
||||
LOG_I "Starting ${APP_NAME} in background..."
|
||||
|
||||
# 使用内置脚本启动服务
|
||||
#local start_command="zkServer.sh start"
|
||||
#if is_boolean_yes "${ENV_DEBUG}"; then
|
||||
# $start_command &
|
||||
#else
|
||||
# $start_command >/dev/null 2>&1 &
|
||||
#fi
|
||||
|
||||
# 使用内置命令启动服务
|
||||
# if [[ "${ENV_DEBUG:-false}" = true ]]; then
|
||||
# debug_execute "rabbitmq-server" &
|
||||
#else
|
||||
# debug_execute "rabbitmq-server" >/dev/null 2>&1 &
|
||||
#fi
|
||||
|
||||
# 通过命令或特定端口检测应用是否就绪
|
||||
LOG_I "Checking ${APP_NAME} ready status..."
|
||||
# wait-for-port --timeout 60 "$ZOO_PORT_NUMBER"
|
||||
|
||||
LOG_D "${APP_NAME} is ready for service..."
|
||||
}
|
||||
|
||||
# 停止应用服务
|
||||
nginx_stop_server() {
|
||||
if nginx_is_server_running ; then
|
||||
LOG_I "Stopping ${APP_NAME}..."
|
||||
|
||||
# 使用 PID 文件 kill 进程
|
||||
stop_service_using_pid "$APP_PID_FILE"
|
||||
|
||||
# 使用内置命令停止服务
|
||||
#debug_execute "rabbitmqctl" stop
|
||||
|
||||
# 使用内置脚本关闭服务
|
||||
#if [[ "$ENV_DEBUG" = true ]]; then
|
||||
# "zkServer.sh" stop
|
||||
#else
|
||||
# "zkServer.sh" stop >/dev/null 2>&1
|
||||
#fi
|
||||
|
||||
# 检测停止是否完成
|
||||
local counter=10
|
||||
while [[ "$counter" -ne 0 ]] && nginx_is_server_running; do
|
||||
LOG_D "Waiting for ${APP_NAME} to stop..."
|
||||
sleep 1
|
||||
counter=$((counter - 1))
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# 检测应用服务是否在后台运行中
|
||||
nginx_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')"
|
||||
|
||||
if [[ -z "${pid}" ]]; then
|
||||
false
|
||||
else
|
||||
is_service_running "${pid}"
|
||||
fi
|
||||
}
|
||||
|
||||
# 清理初始化应用时生成的临时文件
|
||||
nginx_clean_tmp_file() {
|
||||
LOG_D "Clean ${APP_NAME} tmp files for init..."
|
||||
|
||||
}
|
||||
|
||||
# 在重新启动容器时,删除标志文件及必须删除的临时文件 (容器重新启动)
|
||||
nginx_clean_from_restart() {
|
||||
LOG_D "Clean ${APP_NAME} tmp files for restart..."
|
||||
local -r -a files=(
|
||||
"/var/run/${APP_NAME}/${APP_NAME}.pid"
|
||||
)
|
||||
|
||||
for file in ${files[@]}; do
|
||||
if [[ -f "$file" ]]; then
|
||||
LOG_I "Cleaning stale $file file"
|
||||
rm "$file"
|
||||
[[ ! -e "${dist_path}/${f}" ]] && debug " Copy: ${base_path}/${f} to ${dist_path}" && cp "${base_path}/${f}" "${dist_path}"
|
||||
fi
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# 应用默认初始化操作
|
||||
# 执行完毕后,生成文件 ${APP_CONF_DIR}/.app_init_flag 及 ${APP_DATA_DIR}/.data_init_flag 文件
|
||||
nginx_default_init() {
|
||||
nginx_clean_from_restart
|
||||
LOG_D "Check init status of ${APP_NAME}..."
|
||||
|
||||
# 检测配置文件是否存在
|
||||
if [[ ! -f "${APP_CONF_DIR}/.app_init_flag" ]]; then
|
||||
LOG_I "No injected configuration file found, creating default config files..."
|
||||
|
||||
# TODO: 生成配置文件,并按照容器运行参数进行相应修改
|
||||
|
||||
# 修改默认 index.html 文件,增加限制主机名信息,用于集群测试验证
|
||||
HostInfo="<h1>Welcome to nginx!</h1></br><p>Served by host: ${HOSTNAME}</p>"
|
||||
sed -i -e "s#^<h1>Welcome to nginx!</h1>*#<h1>Welcome to nginx!</h1></br><p>Served by host: ${HOSTNAME}</p>#g" "/usr/local/nginx/html/index.html"
|
||||
|
||||
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..."
|
||||
nginx_update_conf
|
||||
fi
|
||||
|
||||
if [[ ! -f "${APP_DATA_DIR}/.data_init_flag" ]]; then
|
||||
LOG_I "Deploying ${APP_NAME} from scratch..."
|
||||
|
||||
# 启动后台服务
|
||||
nginx_start_server_bg
|
||||
|
||||
# TODO: 根据需要生成相应初始化数据
|
||||
|
||||
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
|
||||
nginx_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
|
||||
# nginx_wait_service "${i}"
|
||||
#done
|
||||
}
|
||||
|
||||
# 用户自定义的应用初始化操作,依次执行目录initdb.d中的初始化脚本
|
||||
# 执行完毕后,生成文件 ${APP_DATA_DIR}/.custom_init_flag
|
||||
nginx_custom_init() {
|
||||
LOG_I "Check custom initdb status of ${APP_NAME}..."
|
||||
|
||||
# 检测用户配置文件目录是否存在 initdb.d 文件夹,如果存在,尝试执行目录中的初始化脚本
|
||||
if [ -d "/srv/conf/${APP_NAME}/initdb.d" ]; then
|
||||
# 检测数据存储目录是否存在已初始化标志文件;如果不存在,检索可执行脚本文件并进行初始化操作
|
||||
if [[ -n $(find "/srv/conf/${APP_NAME}/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..."
|
||||
|
||||
# 启动后台服务
|
||||
nginx_start_server_bg
|
||||
|
||||
# 检索所有可执行脚本,排序后执行
|
||||
find "/srv/conf/${APP_NAME}/initdb.d/" -type f -regex ".*\.\(sh\|sql\|sql.gz\)" | sort | while read -r f; do
|
||||
case "$f" in
|
||||
*.sh)
|
||||
if [[ -x "$f" ]]; then
|
||||
LOG_D "Executing $f"; "$f"
|
||||
else
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 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
|
||||
|
||||
. /usr/local/scripts/libcommon.sh # 加载通用函数库
|
||||
. /usr/local/lib/libcommon.sh # 加载通用函数库
|
||||
|
||||
LOG_I "** Processing entry.sh **"
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
|
||||
if [[ "$*" = "/usr/local/bin/run.sh" ]]; then
|
||||
print_image_welcome
|
||||
info "** Processing entry.sh **"
|
||||
|
||||
LOG_I "** Starting ${APP_NAME} setup **"
|
||||
# 优先处理'-'开始的版本信息、帮助信息显示命令,如果是该类命令,处理后退出容器
|
||||
[[ "${1:0:1}" == '-' ]] && set -- "${APP_EXEC:-/bin/bash}" "$@" && print_command_help "$@"
|
||||
|
||||
# 处理 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: $@"
|
||||
# 处理非以上情形的自定义命令
|
||||
info "Start container with command: $@"
|
||||
exec "$@"
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.0 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=(
|
||||
APP_PASSWORD
|
||||
@@ -21,26 +20,23 @@ 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}"
|
||||
|
||||
|
||||
# 应用配置参数
|
||||
export APP_CONF_FILE=${APP_CONF_DIR}/nginx.conf
|
||||
|
||||
# 内部变量
|
||||
export APP_PID_FILE="${APP_PID_FILE:-${APP_RUN_DIR}/${APP_NAME}.pid}"
|
||||
|
||||
export APP_DAEMON_USER="${APP_NAME}"
|
||||
export APP_DAEMON_GROUP="${APP_NAME}"
|
||||
export APP_PID_FILE="${APP_PID_FILE:-/var/run/${APP_NAME}/${APP_NAME}.pid}"
|
||||
|
||||
# 个性化变量
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.2 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用初始化脚本
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错; -u: 变量未定义则报错; -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
|
||||
LOG_I "** Processing init.sh **"
|
||||
|
||||
trap "${APP_NAME}_stop_server" EXIT
|
||||
|
||||
${APP_NAME}_verify_minimum_env
|
||||
|
||||
# 执行应用预初始化操作
|
||||
${APP_NAME}_custom_preinit
|
||||
|
||||
# 执行应用初始化操作
|
||||
${APP_NAME}_default_init
|
||||
|
||||
# 执行用户自定义初始化脚本
|
||||
${APP_NAME}_custom_init
|
||||
|
||||
LOG_I "** Processing init.sh finished! **"
|
||||
@@ -1,29 +1,24 @@
|
||||
#!/bin/bash
|
||||
# Ver: 1.3 by Endial Fang (endial@126.com)
|
||||
# Ver: 1.5 by Endial Fang (endial@126.com)
|
||||
#
|
||||
# 应用启动脚本
|
||||
# 应用启动脚本;组合默认的配置参数及容器启动时传入的 CMD 参数,启动应用
|
||||
|
||||
# 设置 shell 执行参数,可使用'-'(打开)'+'(关闭)控制。常用:
|
||||
# -e: 命令执行错误则报错(errexit); -u: 变量未定义则报错(nounset); -x: 打印实际待执行的命令行; -o pipefail: 设置管道中命令遇到失败则报错
|
||||
set -eu
|
||||
set -o pipefail
|
||||
set -euo pipefail
|
||||
|
||||
. /usr/local/lib/liblog.sh # 日志输出函数库
|
||||
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
|
||||
LOG_I "** Processing run.sh **"
|
||||
info "** Processing run.sh **"
|
||||
readonly START_COMMAND="$(command -v ${APP_EXEC:-${APP_NAME}})"
|
||||
|
||||
# 配置默认启动参数(应用配置文件、前台方式启动)
|
||||
flags=()
|
||||
[[ -n "${APP_CONF_FILE:-}" ]] && flags+=("-c" "${APP_CONF_FILE}")
|
||||
[[ -n "${APP_EXTRA_FLAGS:-}" ]] && flags+=("${APP_EXTRA_FLAGS[@]}")
|
||||
flags+=("$@")
|
||||
|
||||
readonly START_COMMAND="$(command -v ${APP_EXEC})"
|
||||
|
||||
# 确保应用运行在前台
|
||||
flags=("-c" "${APP_CONF_FILE:-}")
|
||||
[[ -z "${APP_EXTRA_FLAGS:-}" ]] || flags=("${flags[@]}" "${APP_EXTRA_FLAGS[@]}")
|
||||
# 增加 "@" 以使用用户在命令行添加的扩展标识
|
||||
flags=("${flags[@]}" "$@")
|
||||
|
||||
LOG_I "** Starting ${APP_NAME} **"
|
||||
#is_root && flags=("-u" "$APP_DAEMON_USER" "${flags[@]}")
|
||||
|
||||
LOG_I "Command: ${START_COMMAND[@]} ${flags[@]}"
|
||||
info "Start ${APP_NAME} with command: ${START_COMMAND[@]} ${flags[@]}"
|
||||
exec "${START_COMMAND[@]}" "${flags[@]}"
|
||||
|
||||
@@ -1,38 +1,45 @@
|
||||
#!/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
|
||||
|
||||
. /usr/local/scripts/libcommon.sh # 加载通用函数库
|
||||
. /usr/local/scripts/libfs.sh # 加载文件操作函数库
|
||||
. /usr/local/scripts/libos.sh # 加载系统管理函数库
|
||||
. /usr/local/lib/libcommon.sh # 加载通用函数库
|
||||
. /usr/local/lib/libfs.sh # 加载文件操作函数库
|
||||
. /usr/local/lib/libos.sh # 加载系统管理函数库
|
||||
|
||||
. /usr/local/bin/environment.sh # 设置环境变量
|
||||
. /usr/local/bin/common.sh # 应用专用函数库
|
||||
|
||||
LOG_I "** Processing setup.sh **"
|
||||
info "** 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
|
||||
info "Ensure directory exists: ${APP_DIRS[@]}"
|
||||
for dir in ${APP_DIRS[@]}; do
|
||||
ensure_dir_exists ${dir}
|
||||
done
|
||||
|
||||
# 动态权限处理
|
||||
current_uid=$(id -u)
|
||||
current_gid=$(id -g)
|
||||
# 确保当前用户对必要目录有访问权限
|
||||
for dir in ${APP_DIRS[@]}; do
|
||||
if [ -d "$dir" ]; then
|
||||
chown $current_uid:$current_gid $dir
|
||||
fi
|
||||
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}")
|
||||
info "Check config files in: ${APP_CONF_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"
|
||||
|
||||
# 解决使用non-root后,nginx: [emerg] open() "/dev/stdout" failed (13: Permission denied)
|
||||
LOG_D "Change permissions of stdout/stderr to 0622"
|
||||
# 解决使用non-root后,[emerg] open() "/dev/stdout" failed (13: Permission denied)
|
||||
debug "Change permissions of stdout/stderr to 0662"
|
||||
chmod 0662 /dev/stdout /dev/stderr
|
||||
|
||||
LOG_I "** Processing setup.sh finished! **"
|
||||
|
||||
@@ -2,13 +2,15 @@ server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
#access_log /var/log/nginx/default.access.log main;
|
||||
#error_log /var/log/nginx/default.access.log warn;
|
||||
charset utf-8;
|
||||
|
||||
access_log /srv/nginx/log/default.access.log main;
|
||||
error_log /srv/nginx/log/default.error.log warn;
|
||||
|
||||
location / {
|
||||
root /usr/local/nginx/html;
|
||||
index index.html index.htm index.php;
|
||||
autoindex on;
|
||||
autoindex on;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
# /etc/nginx/nginx.conf
|
||||
|
||||
# 针对当前已使用 nginx 用户的 Docker 镜像使用时,不需要定义用户
|
||||
#user nginx;
|
||||
# 针对 Docker 镜像使用时,使用预定义的用户
|
||||
# user nginx;
|
||||
|
||||
# 关闭守护进程模式。如果设置为后台守护进程模式,容器在启动应用后会退出
|
||||
daemon off;
|
||||
|
||||
# 根据 CPU 核心数设置进程数量
|
||||
# 根据 CPU 核心数设置进程数量并开启CPU亲和机制
|
||||
worker_processes auto;
|
||||
worker_cpu_affinity auto;
|
||||
|
||||
# 手动设置进程数量。子进程个数最好跟CPU的核心数一样
|
||||
#worker_processes 8;
|
||||
# worker_processes 8;
|
||||
# 手动绑定子进程与 CPU 核心,避免进程切换造成性能损失
|
||||
#worker_cpu_affinity 0001 0010 0100 1000 0011 0110 1100 1001;
|
||||
# worker_cpu_affinity 0001 0010 0100 1000 0011 0110 1100 1001;
|
||||
|
||||
# Enables the use of JIT for regular expressions to speed-up their processing.
|
||||
# 启用 JIT 以加速正则表达式处理
|
||||
pcre_jit on;
|
||||
|
||||
# 配置默认的日志输出方式。可以为日志文件或标准输出设备,日志文件路径固定不可修改
|
||||
# 输出级别:notice / info / warn / error / 为空
|
||||
#error_log /var/log/nginx/error.log warn;
|
||||
#error_log /dev/stdout warn;
|
||||
# error_log /srv/nginx/log/error.log warn;
|
||||
# error_log /srv/nginx/log/error.log info;
|
||||
# error_log /srv/nginx/log/error.log notice;
|
||||
# error_log /srv/nginx/log/error.log;
|
||||
|
||||
# 包含配置文件,以加载动态模块
|
||||
include /usr/local/nginx/modules/*.conf;
|
||||
@@ -28,54 +31,77 @@ include /usr/local/nginx/modules/*.conf;
|
||||
# 设置PID文件路径为对应的子目录
|
||||
pid /var/run/nginx/nginx.pid;
|
||||
|
||||
worker_rlimit_nofile 32767;
|
||||
# 增加文件描述符限制
|
||||
worker_rlimit_nofile 65535;
|
||||
|
||||
events {
|
||||
# 使用 epoll 模型
|
||||
use epoll;
|
||||
|
||||
# 设置一个进程可以打开的最大并发链接数量
|
||||
worker_connections 10240;
|
||||
worker_connections 4096;
|
||||
multi_accept on;
|
||||
}
|
||||
|
||||
http {
|
||||
# 如果启用Ruby支持,需要编译支持Ruby的版本,在这里配置启用对应版本的Passenger
|
||||
#passenger_root /usr/local/rvm/gems/ruby-2.1.3/gems/passenger-4.0.57;
|
||||
#passenger_ruby /usr/local/rvm/gems/ruby-2.1.3/wrappers/ruby;
|
||||
# passenger_root /usr/local/rvm/gems/ruby-2.1.3/gems/passenger-4.0.57;
|
||||
# passenger_ruby /usr/local/rvm/gems/ruby-2.1.3/wrappers/ruby;
|
||||
|
||||
# 包含扩展名与类型映射定义 MIME 文件,并定义默认使用的类型
|
||||
include /srv/conf/nginx/mime.types;
|
||||
include /srv/nginx/conf/mime.types;
|
||||
default_type application/octet-stream;
|
||||
charset UTF-8;
|
||||
|
||||
# Sendfile copies data between one FD and other from within the kernel,
|
||||
# which is more efficient than read() + write().
|
||||
# 开启零拷贝机制
|
||||
sendfile on;
|
||||
|
||||
# Don't buffer data-sends (disable Nagle algorithm).
|
||||
# Good for sending frequent small bursts of data in real time.
|
||||
# 不缓存直接发送(禁用Nagle算法),一般用于开启了长连接的情况下使用
|
||||
# 用于对响应速度要求较高的场景,如IM、金融等
|
||||
tcp_nodelay on;
|
||||
|
||||
# Causes nginx to attempt to send its HTTP response head in one packet,
|
||||
# instead of using partial frames.
|
||||
#tcp_nopush on;
|
||||
# 拼包后发送(一个MTU或超时),与 tcp_nodelay 互斥,且需要配合 sendfile 使用
|
||||
# 用于对吞吐量要求比较高的场景,如调度、报表等
|
||||
# tcp_nopush on;
|
||||
|
||||
# Don't tell nginx version to clients.
|
||||
# 对客户端隐藏服务器版本
|
||||
server_tokens off;
|
||||
|
||||
# 安全头部设置
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
|
||||
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
||||
|
||||
# Specifies the maximum accepted body size of a client request, as
|
||||
# indicated by the request header Content-Length. If the stated content
|
||||
# length is greater than this size, then the client receives the HTTP
|
||||
# error code 413. Set to 0 to disable.
|
||||
# 客户端上传文件大小限制,超出时返回错误代码 413。
|
||||
# 默认值:1m;设置为 0 时禁用该限制
|
||||
client_max_body_size 1024m;
|
||||
|
||||
# Name servers used to resolve names of upstream servers into addresses.
|
||||
# It's also needed when using tcpsocket and udpsocket in Lua modules.
|
||||
#resolver 208.67.222.222 208.67.220.220;
|
||||
# resolver 208.67.222.222 208.67.220.220;
|
||||
|
||||
# Timeout for keep-alive connections. Server will close connections after
|
||||
# this time.
|
||||
# 优化服务器域名散列表
|
||||
server_names_hash_bucket_size 64;
|
||||
server_names_hash_max_size 2048;
|
||||
|
||||
# 连接超时时间,默认值:65秒
|
||||
keepalive_timeout 65;
|
||||
|
||||
# 读取客户端请求头超时时间,默认值:60秒
|
||||
client_header_timeout 60;
|
||||
|
||||
# 读取客户端请求体超时时间,默认值:60秒
|
||||
client_body_timeout 60;
|
||||
|
||||
# 临时文件路径
|
||||
client_body_temp_path /tmp/client_body_temp;
|
||||
fastcgi_temp_path /tmp/fastcgi_temp;
|
||||
proxy_temp_path /tmp/proxy_temp;
|
||||
scgi_temp_path /tmp/scgi_temp;
|
||||
uwsgi_temp_path /tmp/uwsgi_temp;
|
||||
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffering on;
|
||||
proxy_buffers 4 64k;
|
||||
@@ -86,7 +112,7 @@ http {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
# Path of the file with Diffie-Hellman parameters for EDH ciphers.
|
||||
#ssl_dhparam /etc/ssl/nginx/dh2048.pem;
|
||||
# ssl_dhparam /etc/ssl/nginx/dh2048.pem;
|
||||
|
||||
# Specifies that our cipher suits should be preferred over client ciphers.
|
||||
ssl_prefer_server_ciphers on;
|
||||
@@ -96,24 +122,21 @@ http {
|
||||
ssl_session_timeout 5m;
|
||||
|
||||
# 启用或禁用应答信息的压缩传输
|
||||
gzip off;
|
||||
|
||||
# Set the Vary HTTP header as defined in the RFC 2616.
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
|
||||
gzip_disable "msie6";
|
||||
gzip_proxied any;
|
||||
gzip_min_length 1000;
|
||||
gzip_min_length 1024;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 8 16k;
|
||||
gzip_types text/plain text/css text/xml application/xml application/javascript text/javascript application/json application/x-javascript text/xml;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_types text/plain text/css text/xml application/javascript application/json application/rss+xml;
|
||||
gzip_proxied no-cache no-store private expired auth;
|
||||
gzip_disable "MSIE [1-6]\.";
|
||||
|
||||
# Enable checking the existence of precompressed files.
|
||||
#gzip_static on;
|
||||
# gzip_static on;
|
||||
|
||||
# 定义日志格式
|
||||
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
# '$status $body_bytes_sent "$http_referer" '
|
||||
# '"$http_user_agent" "$http_x_forwarded_for"';
|
||||
log_format main '{"time_local": "$time_local", '
|
||||
@@ -129,20 +152,16 @@ http {
|
||||
'"body_bytes_sent": "$body_bytes_sent", '
|
||||
'"request_time": "$request_time", '
|
||||
'"http_referrer": "$http_referer" }';
|
||||
|
||||
# 设置日志输出的路径、格式
|
||||
#access_log /var/log/nginx/access.log main;
|
||||
#error_log /var/log/nginx/error.log warn;
|
||||
access_log /dev/stdout main;
|
||||
#error_log /dev/stdout warn;
|
||||
|
||||
# 关闭日志输出,提升性能
|
||||
#access_log /dev/null;
|
||||
#error_log /dev/null;
|
||||
|
||||
# 设置日志输出的路径、格式
|
||||
# access_log /srv/nginx/log/access.log main;
|
||||
# error_log /srv/nginx/log/error.log warn;
|
||||
access_log /dev/stdout main;
|
||||
error_log /dev/stdout warn;
|
||||
|
||||
# 包含虚拟服务器定义配置文件
|
||||
include /srv/conf/nginx/conf.d/*.conf;
|
||||
include /srv/nginx/conf/conf.d/*.conf;
|
||||
}
|
||||
|
||||
# 包含其它类型服务配置文件,如 RTMP
|
||||
include /srv/conf/nginx/services/*.conf;
|
||||
include /srv/nginx/conf/services/*.conf;
|
||||
|
||||
@@ -1,2 +1,13 @@
|
||||
# 其他类型的服务定义文件
|
||||
# 文件名默认为:<service-name>.conf
|
||||
# 文件名默认为:<service-name>.conf
|
||||
|
||||
# 优化作为代理服务时的长连接配置,减少握手次数,降低服务器损耗
|
||||
|
||||
upstream xxx {
|
||||
# 长连接数
|
||||
keepalive 32;
|
||||
# 每个长连接提供的最大请求数
|
||||
keepalived_requests 100;
|
||||
# 每个长连接没有新的请求时,保持的最长时间
|
||||
keepalive_timeout 60s;
|
||||
}
|
||||
@@ -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,17 +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}
|
||||
+1
-1
@@ -4,6 +4,6 @@ version: '3.8'
|
||||
# 当前配置仅保证可以启动容器;更多配置参数请参考镜像 README.md 文档中说明
|
||||
services:
|
||||
nginx:
|
||||
image: 'registry.cn-shenzhen.aliyuncs.com/colovu/nginx:1.24'
|
||||
image: 'registry.cn-shenzhen.aliyuncs.com/colovu/nginx:latest'
|
||||
ports:
|
||||
- '80:8080'
|
||||
|
||||
@@ -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