[upgrade] docker.yml workflow to new javascript version

This commit is contained in:
ElevenNotes
2025-03-11 07:19:31 +01:00
parent 8d0f5da8ca
commit 5cce7c6900
20 changed files with 573 additions and 464 deletions

View File

@@ -1,5 +1,7 @@
# default
.git*
*.md
LICENSE
maintain/
project*
LICENSE
*.md
img/
node_modules/

4
.gitattributes vendored
View File

@@ -1,2 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
* text=auto
*.sh eol=lf

325
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,325 @@
name: docker
run-name: ${{ inputs.run-name }}
on:
workflow_dispatch:
inputs:
run-name:
description: 'set run-name for workflow (multiple calls)'
type: string
required: false
default: 'docker'
release:
description: 'set WORKFLOW_GITHUB_RELEASE'
required: false
default: 'false'
readme:
description: 'set WORKFLOW_GITHUB_README'
required: false
default: 'false'
image:
description: 'set IMAGE'
required: false
uid:
description: 'set IMAGE_UID'
required: false
gid:
description: 'set IMAGE_GID'
required: false
semverprefix:
description: 'prefix for semver tags'
required: false
semversuffix:
description: 'suffix for semver tags'
required: false
jobs:
docker:
runs-on: ubuntu-22.04
services:
registry:
image: registry:2
ports:
- 5000:5000
permissions:
actions: read
contents: write
packages: write
security-events: write
steps:
- name: init / checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
ref: ${{ github.ref_name }}
fetch-depth: 0
- name: init / setup environment
uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
with:
script: |
const { existsSync, readFileSync } = require('node:fs');
const { resolve } = require('node:path');
const inputs = `${{ toJSON(github.event.inputs) }}`;
const opt = {input:{}, dot:{}};
try{
if(inputs.length > 0){
opt.input = JSON.parse(inputs);
}
}catch(e){
core.warning('could not parse github.event.inputs');
}
try{
const path = resolve('.json');
if(existsSync(path)){
try{
opt.dot = JSON.parse(readFileSync(path).toString());
}catch(e){
throw new Error('could not parse .json');
}
}else{
throw new Error('.json does not exist');
}
}catch(e){
core.setFailed(e);
}
const docker = {
image:{
name:(opt.input?.image || opt.dot.image),
arch:(opt.dot.arch || 'linux/amd64,linux/arm64'),
prefix:((opt.input?.semverprefix) ? `${opt.input?.semverprefix}-` : ''),
suffix:((opt.input?.semversuffix) ? `-${opt.input?.semversuffix}` : ''),
description:(opt.dot?.readme?.description || ''),
tags:[],
},
app:{
image:opt.dot.image,
name:opt.dot.name,
version:opt.dot.semver.version,
root:opt.dot.root,
UID:(opt.input?.uid || 1000),
GID:(opt.input?.gid || 1000),
no_cache:new Date().getTime(),
},
cache:{
registry:'localhost:5000/',
}
};
docker.cache.name = `${docker.image.name}:${docker.image.prefix}buildcache${docker.image.suffix}`;
docker.cache.grype = `${docker.cache.registry}${docker.image.name}:${docker.image.prefix}grype${docker.image.suffix}`;
docker.app.prefix = docker.image.prefix;
docker.app.suffix = docker.image.suffix;
// setup tags
const semver = opt.dot.semver.version.split('.');
docker.image.tags.push(`${context.sha.substring(0,7)}`);
if(Array.isArray(semver)){
if(semver.length >= 1) docker.image.tags.push(`${semver[0]}`);
if(semver.length >= 2) docker.image.tags.push(`${semver[0]}.${semver[1]}`);
if(semver.length >= 3) docker.image.tags.push(`${semver[0]}.${semver[1]}.${semver[2]}`);
}
if(opt.dot.semver?.stable && new RegExp(opt.dot.semver.stable, 'ig').test(docker.image.tags.join(','))) docker.image.tags.push('stable');
if(opt.dot.semver?.latest && new RegExp(opt.dot.semver.latest, 'ig').test(docker.image.tags.join(','))) docker.image.tags.push('latest');
for(let i=0; i<docker.image.tags.length; i++){
docker.image.tags[i] = `${docker.image.name}:${docker.image.prefix}${docker.image.tags[i]}${docker.image.suffix}`;
}
// setup build arguments
const arguments = [];
for(const argument in docker.app){
arguments.push(`APP_${argument.toUpperCase()}=${docker.app[argument]}`);
}
// export to environment
core.exportVariable('DOCKER_CACHE_REGISTRY', docker.cache.registry);
core.exportVariable('DOCKER_CACHE_NAME', docker.cache.name);
core.exportVariable('DOCKER_CACHE_GRYPE', docker.cache.grype);
core.exportVariable('DOCKER_IMAGE_NAME', docker.image.name);
core.exportVariable('DOCKER_IMAGE_ARCH', docker.image.arch);
core.exportVariable('DOCKER_IMAGE_TAGS', docker.image.tags.join(','));
core.exportVariable('DOCKER_IMAGE_DESCRIPTION', docker.image.description);
core.exportVariable('DOCKER_IMAGE_ARGUMENTS', arguments.join("\r\n"));
core.exportVariable('WORKFLOW_CREATE_RELEASE', (opt.input?.release || true));
core.exportVariable('WORKFLOW_CREATE_README', (opt.input?.readme || true));
core.exportVariable('WORKFLOW_GRYPE_FAIL_ON_SEVERITY', (opt.json?.grpye?.fail || true));
core.exportVariable('WORKFLOW_GRYPE_SEVERITY_CUTOFF', (opt.json?.grpye?.severity || 'high'));
# DOCKER
- name: docker / login to hub
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
with:
username: 11notes
password: ${{ secrets.DOCKER_TOKEN }}
- name: docker / setup qemu
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a
- name: docker / setup buildx
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5
with:
driver-opts: network=host
- name: docker / build & push & tag grype
id: docker-build
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d
with:
context: .
file: arch.dockerfile
push: true
platforms: ${{ env.DOCKER_IMAGE_ARCH }}
cache-from: type=registry,ref=${{ env.DOCKER_CACHE_NAME }}
cache-to: type=registry,ref=${{ env.DOCKER_CACHE_REGISTRY }}${{ env.DOCKER_CACHE_NAME }},mode=max,compression=zstd,force-compression=true
build-args: |
${{ env.DOCKER_IMAGE_ARGUMENTS }}
tags: |
${{ env.DOCKER_CACHE_GRYPE }}
- name: grype / scan
id: grype
uses: anchore/scan-action@abae793926ec39a78ab18002bc7fc45bbbd94342
with:
image: ${{ env.DOCKER_CACHE_GRYPE }}
fail-build: ${{ env.WORKFLOW_GRYPE_FAIL_ON_SEVERITY }}
severity-cutoff: ${{ env.WORKFLOW_GRYPE_SEVERITY_CUTOFF }}
output-format: 'sarif'
by-cve: true
cache-db: true
- name: grype / fail
if: failure() || steps.grype.outcome == 'failure'
uses: anchore/scan-action@abae793926ec39a78ab18002bc7fc45bbbd94342
with:
image: ${{ env.DOCKER_CACHE_GRYPE }}
fail-build: false
severity-cutoff: ${{ env.WORKFLOW_GRYPE_SEVERITY_CUTOFF }}
output-format: 'table'
by-cve: true
cache-db: true
- name: docker / build & push
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d
with:
context: .
file: arch.dockerfile
push: true
sbom: true
provenance: mode=max
platforms: ${{ env.DOCKER_IMAGE_ARCH }}
cache-from: type=registry,ref=${{ env.DOCKER_CACHE_REGISTRY }}${{ env.DOCKER_CACHE_NAME }}
cache-to: type=registry,ref=${{ env.DOCKER_CACHE_NAME }},mode=max,compression=zstd,force-compression=true
build-args: |
${{ env.DOCKER_IMAGE_ARGUMENTS }}
tags: |
${{ env.DOCKER_IMAGE_TAGS }}
# RELEASE
- name: github / release / log
continue-on-error: true
id: git-log
run: |
LOCAL_LAST_TAG=$(git describe --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1`)
echo "using last tag: ${LOCAL_LAST_TAG}"
LOCAL_COMMITS=$(git log ${LOCAL_LAST_TAG}..HEAD --oneline)
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
echo "commits<<${EOF}" >> ${GITHUB_OUTPUT}
echo "${LOCAL_COMMITS}" >> ${GITHUB_OUTPUT}
echo "${EOF}" >> ${GITHUB_OUTPUT}
- name: github / release / markdown
if: env.WORKFLOW_CREATE_RELEASE == 'true' && steps.git-log.outcome == 'success'
id: git-release
uses: 11notes/action-docker-release@v1
with:
git_log: ${{ steps.git-log.outputs.commits }}
- name: github / release / create
if: env.WORKFLOW_CREATE_RELEASE == 'true' && steps.git-release.outcome == 'success'
uses: actions/create-release@4c11c9fe1dcd9636620a16455165783b20fc7ea0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
body: ${{ steps.git-release.outputs.release }}
draft: false
prerelease: false
# README
- name: github / checkout master
continue-on-error: true
run: |
git checkout master
- name: github / create README.md
id: github-readme
continue-on-error: true
if: env.WORKFLOW_CREATE_README == 'true' && steps.docker-build.outcome == 'success'
uses: 11notes/action-docker-readme@v1
with:
sarif_file: ${{ steps.grype.outputs.sarif }}
build_output_metadata: ${{ steps.docker-build.outputs.metadata }}
- name: github / commit & push
continue-on-error: true
if: steps.github-readme.outcome == 'success' && hashFiles('README.md') != ''
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add README.md
git commit -m "auto update README.md"
git push
- name: docker / push README.md to docker hub
continue-on-error: true
if: steps.github-readme.outcome == 'success' && hashFiles('README.md') != ''
uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8
env:
DOCKER_USER: 11notes
DOCKER_PASS: ${{ secrets.DOCKER_TOKEN }}
with:
destination_container_repo: ${{ env.DOCKER_IMAGE_NAME }}
provider: dockerhub
short_description: ${{ env.DOCKER_IMAGE_DESCRIPTION }}
readme_file: 'README.md'
# REPOSITORY SETTINGS
- name: github / update description and set repo defaults
run: |
curl --request PATCH \
--url https://api.github.com/repos/${{ github.repository }} \
--header 'authorization: Bearer ${{ secrets.REPOSITORY_TOKEN }}' \
--header 'content-type: application/json' \
--data '{
"description":"${{ env.DOCKER_IMAGE_DESCRIPTION }}",
"homepage":"",
"has_issues":true,
"has_discussions":true,
"has_projects":false,
"has_wiki":false
}' \
--fail

View File

@@ -1,26 +0,0 @@
name: create release notes
on:
push:
tags:
- "*"
- "!amd64*"
- "!arm64*"
permissions:
contents: write
jobs:
release:
name: release
runs-on: ubuntu-latest
steps:
- name: create release notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref_name }}
run: |
gh release create "$tag" \
--repo="$GITHUB_REPOSITORY" \
--title="${tag#v}" \
--generate-notes

25
.github/workflows/tags.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: tags
on:
push:
tags:
- 'v*'
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: build docker image
uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
with:
workflow: docker.yml
token: "${{ secrets.REPOSITORY_TOKEN }}"
inputs: '{ "release":"true", "readme":"true" }'
docker-unraid:
runs-on: ubuntu-latest
steps:
- name: build docker image for unraid community
uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
with:
workflow: docker.yml
token: "${{ secrets.REPOSITORY_TOKEN }}"
inputs: '{ "release":"false", "readme":"false", "uid":"99", "gid":"100", "semversuffix":"unraid", "run-name":"docker-unraid" }'

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
# default
maintain/
project*
node_modules/

21
.json Normal file
View File

@@ -0,0 +1,21 @@
{
"image":"11notes/nginx",
"name":"nginx",
"root":"/nginx",
"semver":{
"version":"1.26.3",
"stable":"1.26.3",
"latest":"1.26.3"
},
"readme":{
"description":"Nginx with additional plugins and custom compiled",
"parent":{
"image":"11notes/alpine:stable"
},
"built":{
"nginx":"https://nginx.org"
}
}
}

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 11notes
Copyright (c) 2020 11notes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,68 +0,0 @@
![Banner](https://github.com/11notes/defaults/blob/main/static/img/banner.png?raw=true)
# 🏔️ Alpine - Nginx
![size](https://img.shields.io/docker/image-size/11notes/nginx/1.26.2?color=0eb305) ![version](https://img.shields.io/docker/v/11notes/nginx/1.26.2?color=eb7a09) ![pulls](https://img.shields.io/docker/pulls/11notes/nginx?color=2b75d6)
**Nginx base image with additional plugins and custom compiled**
# SYNOPSIS
What can I do with this? This image will serve as a base for nginx related images that need a high-performance webserver. It can also be used stand alone as a webserver or reverse proxy. It will automatically reload on config changes if configured.
# VOLUMES
* **/nginx/etc** - Directory of vHost config, must end in *.conf (set in /etc/nginx/nginx.conf)
* **/nginx/var** - Directory of webroot for vHost
* **/nginx/ssl** - Directory of SSL certificates
# COMPOSE
```yaml
services:
nginx:
image: "11notes/nginx:1.26.2"
container_name: "nginx"
environment:
TZ: "Europe/Zurich"
ports:
- "8443:8443/tcp"
volumes:
- "etc:/nginx/etc"
- "var:/nginx/var"
- "ssl:/nginx/ssl"
restart: "always"
volumes:
etc:
var:
ssl:
```
# DEFAULT SETTINGS
| Parameter | Value | Description |
| --- | --- | --- |
| `user` | docker | user docker |
| `uid` | 1000 | user id 1000 |
| `gid` | 1000 | group id 1000 |
| `home` | /nginx | home directory of user docker |
# ENVIRONMENT
| Parameter | Value | Default |
| --- | --- | --- |
| `TZ` | [Time Zone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | |
| `DEBUG` | Show debug information | |
| `NGINX_DYNAMIC_RELOAD` | Enable reload of nginx on configuration changes in /nginx/etc (only on successful configuration test!) | |
# SOURCE
* [11notes/nginx:1.26.2](https://github.com/11notes/docker-nginx/tree/1.26.2)
# PARENT IMAGE
* [11notes/alpine:stable](https://hub.docker.com/r/11notes/alpine)
# BUILT WITH
* [nginx](https://nginx.org)
* [alpine](https://alpinelinux.org)
# TIPS
* Use a reverse proxy like Traefik, Nginx to terminate TLS with a valid certificate
* Use Lets Encrypt certificates to protect your SSL endpoints
# ElevenNotes<sup>™️</sup>
This image is provided to you at your own risk. Always make backups before updating an image to a new version. Check the changelog for breaking changes. You can find all my repositories on [github](https://github.com/11notes).

View File

@@ -1,158 +0,0 @@
# :: Util
FROM alpine as util
RUN set -ex; \
apk add --no-cache \
git; \
git clone https://github.com/11notes/util.git;
# :: Build
FROM alpine:latest as build
ENV BUILD_VERSION=1.26.2
ENV MODULE_HEADERS_MORE_NGINX_VERSION=0.37
RUN set -ex; \
CONFIG="\
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/nginx/run/nginx.pid \
--lock-path=/nginx/run/nginx.lock \
--http-client-body-temp-path=/nginx/cache/client_temp \
--http-proxy-temp-path=/nginx/cache/proxy_temp \
--http-fastcgi-temp-path=/nginx/cache/fastcgi_temp \
--http-uwsgi-temp-path=/nginx/cache/uwsgi_temp \
--http-scgi-temp-path=/nginx/cache/scgi_temp \
--user=docker \
--group=docker \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-mail \
--with-mail_ssl_module \
--with-compat \
--with-file-aio \
--with-http_v2_module \
--add-module=/usr/lib/nginx/modules/headers-more-nginx-module-${MODULE_HEADERS_MORE_NGINX_VERSION} \
"; \
apk add --no-cache --update \
curl \
tar \
gcc \
libc-dev \
make \
openssl-dev \
pcre2-dev \
zlib-dev \
linux-headers \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
libedit-dev \
bash \
alpine-sdk \
findutils; \
apk upgrade; \
mkdir -p /usr/lib/nginx/modules; \
mkdir -p /usr/src; \
curl -SL https://github.com/openresty/headers-more-nginx-module/archive/v${MODULE_HEADERS_MORE_NGINX_VERSION}.tar.gz | tar -zxC /usr/lib/nginx/modules; \
curl -SL https://nginx.org/download/nginx-${BUILD_VERSION}.tar.gz | tar -zxC /usr/src; \
cd /usr/src/nginx-${BUILD_VERSION}; \
./configure $CONFIG --with-debug; \
make -j $(nproc); \
mv objs/nginx objs/nginx-debug; \
mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so; \
mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so; \
mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so; \
mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so; \
./configure $CONFIG; \
make -j $(nproc); \
make install; \
install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so; \
install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so; \
install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so; \
install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so; \
strip /usr/sbin/nginx*; \
strip /usr/lib/nginx/modules/*.so;
# :: Header
FROM 11notes/alpine:stable
COPY --from=util /util/linux/shell/elevenLogJSON /usr/local/bin
COPY --from=build /usr/sbin/nginx /usr/sbin
COPY --from=build /etc/nginx/ /etc/nginx
COPY --from=build /usr/lib/nginx/modules/ /etc/nginx/modules
ENV APP_NAME="nginx"
ENV APP_VERSION=1.26.2
ENV APP_ROOT=/nginx
# :: Run
USER root
# :: update image
RUN set -ex; \
apk add --no-cache \
inotify-tools \
openssl \
pcre2-dev; \
apk --no-cache upgrade;
# :: prepare image
RUN set -ex; \
mkdir -p ${APP_ROOT}; \
mkdir -p ${APP_ROOT}/etc; \
mkdir -p ${APP_ROOT}/var; \
mkdir -p ${APP_ROOT}/ssl; \
mkdir -p ${APP_ROOT}/cache; \
mkdir -p ${APP_ROOT}/run; \
mkdir -p /var/log/nginx; \
touch /var/log/nginx/access.log; \
touch /var/log/nginx/error.log; \
ln -sf /dev/stdout /var/log/nginx/access.log; \
ln -sf /dev/stderr /var/log/nginx/error.log;
# :: copy root filesystem changes and add execution rights to init scripts
COPY ./rootfs /
RUN set -ex; \
chmod +x -R /usr/local/bin
# :: change home path for existing user and set correct permission
RUN set -ex; \
usermod -d ${APP_ROOT} docker; \
chown -R 1000:1000 \
${APP_ROOT} \
/var/log/nginx;
# :: Volumes
VOLUME ["${APP_ROOT}/etc", "${APP_ROOT}/var", "${APP_ROOT}/ssl"]
# :: Monitor
HEALTHCHECK --interval=5s --timeout=2s CMD /usr/local/bin/healthcheck.sh || exit 1
# :: Start
USER docker
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

160
arch.dockerfile Normal file
View File

@@ -0,0 +1,160 @@
# :: Util
FROM 11notes/util AS util
# :: Build / nginx
FROM alpine/git AS build
ARG APP_VERSION
ARG APP_ROOT
ENV MODULE_HEADERS_MORE_NGINX_VERSION=0.37
RUN set -ex; \
CONFIG="\
--with-cc-opt=-O2 \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=${APP_ROOT}/run/nginx.pid \
--lock-path=${APP_ROOT}/run/nginx.lock \
--http-client-body-temp-path=${APP_ROOT}/cache/client_temp \
--http-proxy-temp-path=${APP_ROOT}/cache/proxy_temp \
--http-fastcgi-temp-path=${APP_ROOT}/cache/fastcgi_temp \
--http-uwsgi-temp-path=${APP_ROOT}/cache/uwsgi_temp \
--http-scgi-temp-path=${APP_ROOT}/cache/scgi_temp \
--user=docker \
--group=docker \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-compat \
--with-file-aio \
--with-http_v2_module \
--add-module=/usr/lib/nginx/modules/headers-more-nginx-module-${MODULE_HEADERS_MORE_NGINX_VERSION} \
"; \
apk add --no-cache --update \
curl \
tar \
gcc \
libc-dev \
make \
openssl-dev \
pcre2-dev \
zlib-dev \
linux-headers \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
libedit-dev \
bash \
alpine-sdk \
findutils; \
apk upgrade; \
mkdir -p /usr/lib/nginx/modules; \
mkdir -p /usr/src; \
curl -SL https://github.com/openresty/headers-more-nginx-module/archive/v${MODULE_HEADERS_MORE_NGINX_VERSION}.tar.gz | tar -zxC /usr/lib/nginx/modules; \
curl -SL https://nginx.org/download/nginx-${APP_VERSION}.tar.gz | tar -zxC /usr/src; \
cd /usr/src/nginx-${APP_VERSION}; \
./configure $CONFIG --with-debug; \
make -j $(nproc); \
mv objs/nginx objs/nginx-debug; \
mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so; \
mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so; \
mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so; \
mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so; \
./configure $CONFIG; \
make -j $(nproc); \
make install; \
install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so; \
install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so; \
install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so; \
install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so; \
strip /usr/sbin/nginx*; \
strip /usr/lib/nginx/modules/*.so;
# :: Header
FROM 11notes/alpine:stable
# :: arguments
ARG TARGETARCH
ARG APP_IMAGE
ARG APP_NAME
ARG APP_VERSION
ARG APP_ROOT
ARG APP_UID
ARG APP_GID
# :: environment
ENV APP_IMAGE=${APP_IMAGE}
ENV APP_NAME=${APP_NAME}
ENV APP_VERSION=${APP_VERSION}
ENV APP_ROOT=${APP_ROOT}
ENV NGINX_HEALTHCHECK_URL="https://localhost:8443/ping"
# :: multi-stage
COPY --from=util /usr/local/bin/ /usr/local/bin
COPY --from=build /usr/sbin/nginx /usr/sbin
COPY --from=build /etc/nginx/ /etc/nginx
COPY --from=build /usr/lib/nginx/modules/ /etc/nginx/modules
# :: Run
USER root
RUN eleven printenv;
# :: install application
RUN set -ex; \
apk --no-cache --update add \
inotify-tools \
openssl \
pcre2-dev;
RUN set -ex; \
eleven mkdir ${APP_ROOT}/{etc,var,ssl,cache,run}; \
mkdir -p /var/log/nginx; \
touch /var/log/nginx/access.log; \
touch /var/log/nginx/error.log; \
ln -sf /dev/stdout /var/log/nginx/access.log; \
ln -sf /dev/stderr /var/log/nginx/error.log;
# :: copy filesystem changes and set correct permissions
COPY ./rootfs /
RUN set -ex; \
chmod +x -R /usr/local/bin; \
chown -R 1000:1000 \
${APP_ROOT} \
/var/log/nginx;
# :: support unraid
RUN set -ex; \
eleven unraid;
# :: Volumes
VOLUME ["${APP_ROOT}/etc", "${APP_ROOT}/var"]
# :: Monitor
HEALTHCHECK --interval=5s --timeout=2s CMD curl -X GET -kILs --fail ${NGINX_HEALTHCHECK_URL} || exit 1
# :: Start
USER docker

View File

@@ -1,162 +0,0 @@
# :: QEMU
FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu
# :: Util
FROM alpine as util
RUN set -ex; \
apk add --no-cache \
git; \
git clone https://github.com/11notes/util.git;
# :: Build
FROM arm64v8/alpine as build
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
ENV BUILD_VERSION=1.26.2
ENV MODULE_HEADERS_MORE_NGINX_VERSION=0.37
RUN set -ex; \
CONFIG="\
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/nginx/run/nginx.pid \
--lock-path=/nginx/run/nginx.lock \
--http-client-body-temp-path=/nginx/cache/client_temp \
--http-proxy-temp-path=/nginx/cache/proxy_temp \
--http-fastcgi-temp-path=/nginx/cache/fastcgi_temp \
--http-uwsgi-temp-path=/nginx/cache/uwsgi_temp \
--http-scgi-temp-path=/nginx/cache/scgi_temp \
--user=docker \
--group=docker \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-mail \
--with-mail_ssl_module \
--with-compat \
--with-file-aio \
--with-http_v2_module \
--add-module=/usr/lib/nginx/modules/headers-more-nginx-module-${MODULE_HEADERS_MORE_NGINX_VERSION} \
"; \
apk add --no-cache --update \
curl \
tar \
gcc \
libc-dev \
make \
openssl-dev \
pcre2-dev \
zlib-dev \
linux-headers \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
libedit-dev \
bash \
alpine-sdk \
findutils; \
apk upgrade; \
mkdir -p /usr/lib/nginx/modules; \
mkdir -p /usr/src; \
curl -SL https://github.com/openresty/headers-more-nginx-module/archive/v${MODULE_HEADERS_MORE_NGINX_VERSION}.tar.gz | tar -zxC /usr/lib/nginx/modules; \
curl -SL https://nginx.org/download/nginx-${BUILD_VERSION}.tar.gz | tar -zxC /usr/src; \
cd /usr/src/nginx-${BUILD_VERSION}; \
./configure $CONFIG --with-debug; \
make -j $(nproc); \
mv objs/nginx objs/nginx-debug; \
mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so; \
mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so; \
mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so; \
mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so; \
./configure $CONFIG; \
make -j $(nproc); \
make install; \
install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so; \
install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so; \
install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so; \
install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so; \
strip /usr/sbin/nginx*; \
strip /usr/lib/nginx/modules/*.so;
# :: Header
FROM --platform=linux/arm64 11notes/alpine:stable
COPY --from=qemu /usr/bin/qemu-aarch64-static /usr/bin
COPY --from=util /util/linux/shell/elevenLogJSON /usr/local/bin
COPY --from=build /usr/sbin/nginx /usr/sbin
COPY --from=build /etc/nginx/ /etc/nginx
COPY --from=build /usr/lib/nginx/modules/ /etc/nginx/modules
ENV APP_NAME="nginx"
ENV APP_VERSION=1.26.2
ENV APP_ROOT=/nginx
# :: Run
USER root
# :: update image
RUN set -ex; \
apk add --no-cache \
inotify-tools \
openssl \
pcre2-dev; \
apk --no-cache upgrade;
# :: prepare image
RUN set -ex; \
mkdir -p ${APP_ROOT}; \
mkdir -p ${APP_ROOT}/etc; \
mkdir -p ${APP_ROOT}/var; \
mkdir -p ${APP_ROOT}/ssl; \
mkdir -p ${APP_ROOT}/cache; \
mkdir -p ${APP_ROOT}/run; \
mkdir -p /var/log/nginx; \
touch /var/log/nginx/access.log; \
touch /var/log/nginx/error.log; \
ln -sf /dev/stdout /var/log/nginx/access.log; \
ln -sf /dev/stderr /var/log/nginx/error.log;
# :: copy root filesystem changes and add execution rights to init scripts
COPY ./rootfs /
RUN set -ex; \
chmod +x -R /usr/local/bin
# :: change home path for existing user and set correct permission
RUN set -ex; \
usermod -d ${APP_ROOT} docker; \
chown -R 1000:1000 \
${APP_ROOT} \
/var/log/nginx;
# :: Volumes
VOLUME ["${APP_ROOT}/etc", "${APP_ROOT}/var", "${APP_ROOT}/ssl"]
# :: Monitor
HEALTHCHECK --interval=5s --timeout=2s CMD /usr/local/bin/healthcheck.sh || exit 1
# :: Start
USER docker
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

View File

@@ -1,5 +0,0 @@
#!/bin/bash
curl -Lo manifest-tool https://github.com/estesp/manifest-tool/releases/download/v0.9.0/manifest-tool-linux-amd64
chmod +x manifest-tool
./manifest-tool push from-spec multi-arch-manifest-version.yaml
./manifest-tool push from-spec multi-arch-manifest-stable.yaml

View File

@@ -1,2 +0,0 @@
#!/bin/bash
docker run --rm --privileged multiarch/qemu-user-static:register --reset

View File

@@ -1,11 +0,0 @@
image: 11notes/nginx:stable
manifests:
- image: 11notes/nginx:amd64-stable
platform:
architecture: amd64
os: linux
- image: 11notes/nginx:arm64v8-stable
platform:
architecture: arm64
os: linux
variant: v8

View File

@@ -1,11 +0,0 @@
image: 11notes/nginx:1.26.2
manifests:
- image: 11notes/nginx:1.26.2
platform:
architecture: amd64
os: linux
- image: 11notes/nginx:1.26.2
platform:
architecture: arm64
os: linux
variant: v8

21
project.md Normal file
View File

@@ -0,0 +1,21 @@
${{ content_synopsis }} What can I do with this? This image will serve as a base for nginx related images that need a high-performance webserver. It can also be used stand alone as a webserver or reverse proxy. It will automatically reload on config changes if configured.
${{ title_volumes }}
* **${{ json_root }}/etc** - Directory of vHost config, must end in *.conf (set in /etc/nginx/nginx.conf)
* **${{ json_root }}/var** - Directory of webroot for vHost
${{ content_compose }}
${{ content_defaults }}
${{ content_environment }}
| `NGINX_DYNAMIC_RELOAD` | Enable reload of nginx on configuration changes in /nginx/etc (only on successful configuration test!) | |
| `NGINX_HEALTHCHECK_URL` | URL to check if nginx is ready to accept connections | https://localhost:8443/ping |
${{ content_source }}
${{ content_parent }}
${{ content_built }}
${{ content_tips }}

View File

@@ -1,6 +1,6 @@
#!/bin/ash
if [ ! -f "${APP_ROOT}/ssl/default.crt" ]; then
elevenLogJSON debug "creating default certificate"
#!/bin/ash
if { [ ! -f "${APP_ROOT}/ssl/default.crt" ] && [ -f "${APP_ROOT}/etc/default.conf" ] && cat ${APP_ROOT}/etc/default.conf | grep -q "default.crt"; }; then
eleven log debug "creating default certificate"
openssl req -x509 -newkey rsa:4096 -subj "/C=XX/ST=XX/L=XX/O=XX/OU=DOCKER/CN=${APP_NAME}" \
-keyout "${APP_ROOT}/ssl/default.key" \
-out "${APP_ROOT}/ssl/default.crt" \
@@ -9,14 +9,14 @@
if [ -z "${1}" ]; then
if [ ! -z ${NGINX_DYNAMIC_RELOAD} ]; then
elevenLogJSON info "enable dynamic reload"
eleven log info "enable dynamic reload"
/sbin/inotifyd /usr/local/bin/reload.sh ${APP_ROOT}/etc:cdnym &
fi
elevenLogJSON info "starting ${APP_NAME} (${APP_VERSION})"
set -- "nginx" \
-g \
'daemon off;'
eleven log start
fi
exec "$@"

View File

@@ -1,3 +0,0 @@
#!/bin/ash
HEALTHCHECK_URL=${HEALTHCHECK_URL:-https://localhost:8443/ping}
curl --insecure --max-time 3 -kILs --fail ${HEALTHCHECK_URL}

View File

@@ -1,6 +1,6 @@
#!/bin/ash
elevenLogJSON debug "inotifyd event: ${1}"
elevenLogJSON info "reloading config"
eleven log debug "inotifyd event: ${1}"
eleven log info "reloading config"
NGINX_DYNAMIC_RELOAD_LOG=${APP_ROOT}/run/reload.log
nginx -t &> ${NGINX_DYNAMIC_RELOAD_LOG}
@@ -8,19 +8,19 @@
if echo "${LINE}" | grep -q "nginx: "; then
if echo "${LINE}" | grep -q "\[warn\]"; then
LINE=$(echo ${LINE} | sed 's/nginx: \[warn\] //')
elevenLogJSON warning "${LINE}"
eleven log warning "${LINE}"
fi
if echo "${LINE}" | grep -q "\[emerg\]"; then
LINE=$(echo ${LINE} | sed 's/nginx: \[emerg\] //')
elevenLogJSON error "${LINE}"
eleven log error "${LINE}"
fi
fi
done < ${NGINX_DYNAMIC_RELOAD_LOG}
if cat ${NGINX_DYNAMIC_RELOAD_LOG} | grep -q "test is successful"; then
nginx -s reload
elevenLogJSON info "config reloaded"
eleven log info "config reloaded"
else
elevenLogJSON error "config reload failed!"
eleven log error "config reload failed!"
fi