├── .dockerignore
├── .gitattributes
├── .github
└── workflows
│ ├── adguard-sync.yml
│ ├── adguard.yml
│ ├── base.yml
│ ├── cmd-socket.yml
│ ├── curl.yml
│ ├── dnslookup.yml
│ ├── docker.yml
│ ├── hysteria.yml
│ ├── lego.yml
│ ├── nginx.yml
│ ├── node.yml
│ ├── par2.yml
│ ├── readme.yml
│ ├── socket-proxy.yml
│ ├── tini-pm.yml
│ ├── traefik.yml
│ └── unrar.yml
├── .gitignore
├── .json
├── LICENSE
├── README.md
├── adguard-sync.dockerfile
├── adguard.dockerfile
├── arch.dockerfile
├── build.dockerfile
├── cmd-socket.dockerfile
├── curl.dockerfile
├── dnslookup.dockerfile
├── hysteria.dockerfile
├── lego.dockerfile
├── nginx.dockerfile
├── node.dockerfile
├── par2.dockerfile
├── project.md
├── socket-proxy.dockerfile
├── tini-pm.dockerfile
├── traefik.dockerfile
└── unrar.dockerfile
/.dockerignore:
--------------------------------------------------------------------------------
1 | # default
2 | .git*
3 | maintain/
4 | LICENSE
5 | *.md
6 | img/
7 | node_modules/
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # default
2 | * text=auto
3 | *.sh eol=lf
--------------------------------------------------------------------------------
/.github/workflows/adguard-sync.yml:
--------------------------------------------------------------------------------
1 | name: adguard-sync
2 | on:
3 | push:
4 | tags:
5 | - 'adguard-sync'
6 | jobs:
7 | adguard-sync:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-adguard-sync/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"adguard-sync.dockerfile",
21 | tag:"adguard-sync",
22 | version:dot.semver.version,
23 | };
24 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
25 | }catch(e){
26 | core.setFailed(`workflow failed: ${e}`);
27 | }
28 | })();
29 |
30 | - name: build docker image
31 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
32 | with:
33 | workflow: docker.yml
34 | token: "${{ secrets.REPOSITORY_TOKEN }}"
35 | inputs: '{ "release":"false", "readme":"false", "run-name":"adguard-sync", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/adguard.yml:
--------------------------------------------------------------------------------
1 | name: adguard
2 | on:
3 | push:
4 | tags:
5 | - 'adguard'
6 | jobs:
7 | adguard:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-adguard/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"adguard.dockerfile",
21 | tag:"adguard",
22 | version:dot.semver.version,
23 | };
24 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
25 | }catch(e){
26 | core.setFailed(`workflow failed: ${e}`);
27 | }
28 | })();
29 |
30 | - name: build docker image
31 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
32 | with:
33 | workflow: docker.yml
34 | token: "${{ secrets.REPOSITORY_TOKEN }}"
35 | inputs: '{ "release":"false", "readme":"false", "run-name":"adguard", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/base.yml:
--------------------------------------------------------------------------------
1 | name: tags
2 | on:
3 | push:
4 | tags:
5 | - 'v*'
6 | jobs:
7 | base:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | const etc = {
16 | version:"latest"
17 | };
18 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
19 |
20 | - name: build docker image
21 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
22 | with:
23 | workflow: docker.yml
24 | token: "${{ secrets.REPOSITORY_TOKEN }}"
25 | inputs: '{ "release":"true", "readme":"true", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/cmd-socket.yml:
--------------------------------------------------------------------------------
1 | name: cmd-socket
2 | on:
3 | push:
4 | tags:
5 | - 'cmd-socket'
6 | jobs:
7 | cmd-socket:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | const etc = {
16 | dockerfile:"cmd-socket.dockerfile",
17 | tag:"cmd-socket",
18 | version:"latest"
19 | };
20 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
21 |
22 | - name: build docker image
23 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
24 | with:
25 | workflow: docker.yml
26 | token: "${{ secrets.REPOSITORY_TOKEN }}"
27 | inputs: '{ "release":"false", "readme":"false", "run-name":"cmd-socket", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/curl.yml:
--------------------------------------------------------------------------------
1 | name: curl
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'curl'
9 | jobs:
10 | curl:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://api.github.com/repos/curl/curl/releases/latest | jq -r '.tag_name' | sed 's/_/./g' | sed 's/curl-//')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/curl-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"curl.dockerfile",
31 | tag:"curl",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"curl", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/dnslookup.yml:
--------------------------------------------------------------------------------
1 | name: dnslookup
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'dnslookup'
9 | jobs:
10 | dnslookup:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://api.github.com/repos/ameshkov/dnslookup/releases/latest | jq -r '.tag_name' | sed 's/v//')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/dnslookup-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"dnslookup.dockerfile",
31 | tag:"dnslookup",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"dnslookup", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/docker.yml:
--------------------------------------------------------------------------------
1 | name: docker
2 | run-name: ${{ inputs.run-name }}
3 |
4 | on:
5 | workflow_dispatch:
6 | inputs:
7 | run-name:
8 | description: 'set run-name for workflow (multiple calls)'
9 | type: string
10 | required: false
11 | default: 'docker'
12 |
13 | runs-on:
14 | description: 'set runs-on for workflow (github or selfhosted)'
15 | type: string
16 | required: false
17 | default: 'ubuntu-22.04'
18 |
19 | build:
20 | description: 'set WORKFLOW_BUILD'
21 | required: false
22 | default: 'true'
23 |
24 | release:
25 | description: 'set WORKFLOW_GITHUB_RELEASE'
26 | required: false
27 | default: 'false'
28 |
29 | readme:
30 | description: 'set WORKFLOW_GITHUB_README'
31 | required: false
32 | default: 'false'
33 |
34 | etc:
35 | description: 'base64 encoded json string'
36 | required: false
37 |
38 | jobs:
39 | docker:
40 | runs-on: ${{ inputs.runs-on }}
41 | timeout-minutes: 1440
42 |
43 | services:
44 | registry:
45 | image: registry:2
46 | ports:
47 | - 5000:5000
48 |
49 | permissions:
50 | actions: read
51 | contents: write
52 | packages: write
53 |
54 | steps:
55 | - name: init / checkout
56 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
57 | with:
58 | ref: ${{ github.ref_name }}
59 | fetch-depth: 0
60 |
61 | - name: init / setup environment
62 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
63 | with:
64 | script: |
65 | const { existsSync, readFileSync } = require('node:fs');
66 | const { resolve } = require('node:path');
67 | const { inspect } = require('node:util');
68 | const { Buffer } = require('node:buffer');
69 | const inputs = `${{ toJSON(github.event.inputs) }}`;
70 | const opt = {input:{}, dot:{}};
71 |
72 | try{
73 | if(inputs.length > 0){
74 | opt.input = JSON.parse(inputs);
75 | if(opt.input?.etc){
76 | opt.input.etc = JSON.parse(Buffer.from(opt.input.etc, 'base64').toString('ascii'));
77 | }
78 | }
79 | }catch(e){
80 | core.warning('could not parse github.event.inputs');
81 | }
82 |
83 | try{
84 | const path = resolve('.json');
85 | if(existsSync(path)){
86 | try{
87 | opt.dot = JSON.parse(readFileSync(path).toString());
88 | }catch(e){
89 | throw new Error('could not parse .json');
90 | }
91 | }else{
92 | throw new Error('.json does not exist');
93 | }
94 | }catch(e){
95 | core.setFailed(e);
96 | }
97 |
98 | core.info(inspect(opt, {showHidden:false, depth:null, colors:true}));
99 |
100 | const docker = {
101 | image:{
102 | name:opt.dot.image,
103 | arch:(opt.dot.arch || 'linux/amd64,linux/arm64'),
104 | prefix:((opt.input?.etc?.semverprefix) ? `${opt.input?.etc?.semverprefix}-` : ''),
105 | suffix:((opt.input?.etc?.semversuffix) ? `-${opt.input?.etc?.semversuffix}` : ''),
106 | description:(opt.dot?.readme?.description || ''),
107 | tags:[],
108 | },
109 | app:{
110 | image:opt.dot.image,
111 | name:opt.dot.name,
112 | version:(opt.input?.etc?.version || opt.dot?.semver?.version),
113 | root:opt.dot.root,
114 | UID:(opt.input?.etc?.uid || 1000),
115 | GID:(opt.input?.etc?.gid || 1000),
116 | no_cache:new Date().getTime(),
117 | },
118 | cache:{
119 | registry:'localhost:5000/',
120 | },
121 | tags:[],
122 | };
123 |
124 | docker.cache.name = `${docker.image.name}:${docker.image.prefix}buildcache${docker.image.suffix}`;
125 | docker.cache.grype = `${docker.cache.registry}${docker.image.name}:${docker.image.prefix}grype${docker.image.suffix}`;
126 | docker.app.prefix = docker.image.prefix;
127 | docker.app.suffix = docker.image.suffix;
128 |
129 | // setup tags
130 | if(!opt.dot?.semver?.disable?.rolling){
131 | docker.image.tags.push('rolling');
132 | }
133 | if(opt.input?.etc?.dockerfile !== 'arch.dockerfile' && opt.input?.etc?.tag){
134 | docker.image.tags.push(`${context.sha.substring(0,7)}`);
135 | docker.image.tags.push(opt.input.etc.tag);
136 | docker.image.tags.push(`${opt.input.etc.tag}-${docker.app.version}`);
137 | docker.cache.name = `${docker.image.name}:buildcache-${opt.input.etc.tag}`;
138 | }else if(docker.app.version !== 'latest'){
139 | const semver = docker.app.version.split('.');
140 | docker.image.tags.push(`${context.sha.substring(0,7)}`);
141 | if(Array.isArray(semver)){
142 | if(semver.length >= 1) docker.image.tags.push(`${semver[0]}`);
143 | if(semver.length >= 2) docker.image.tags.push(`${semver[0]}.${semver[1]}`);
144 | if(semver.length >= 3) docker.image.tags.push(`${semver[0]}.${semver[1]}.${semver[2]}`);
145 | }
146 | if(opt.dot?.semver?.stable && new RegExp(opt.dot?.semver.stable, 'ig').test(docker.image.tags.join(','))) docker.image.tags.push('stable');
147 | if(opt.dot?.semver?.latest && new RegExp(opt.dot?.semver.latest, 'ig').test(docker.image.tags.join(','))) docker.image.tags.push('latest');
148 | }else{
149 | docker.image.tags.push('latest');
150 | }
151 |
152 | for(const tag of docker.image.tags){
153 | docker.tags.push(`${docker.image.name}:${docker.image.prefix}${tag}${docker.image.suffix}`);
154 | docker.tags.push(`ghcr.io/${docker.image.name}:${docker.image.prefix}${tag}${docker.image.suffix}`);
155 | docker.tags.push(`quay.io/${docker.image.name}:${docker.image.prefix}${tag}${docker.image.suffix}`);
156 | }
157 |
158 | // setup build arguments
159 | if(opt.input?.etc?.build?.args){
160 | for(const arg in opt.input.etc.build.args){
161 | docker.app[arg] = opt.input.etc.build.args[arg];
162 | }
163 | }
164 | if(opt.dot?.build?.args){
165 | for(const arg in opt.dot.build.args){
166 | docker.app[arg] = opt.dot.build.args[arg];
167 | }
168 | }
169 | const arguments = [];
170 | for(const argument in docker.app){
171 | arguments.push(`APP_${argument.toUpperCase()}=${docker.app[argument]}`);
172 | }
173 |
174 | // export to environment
175 | core.exportVariable('DOCKER_CACHE_REGISTRY', docker.cache.registry);
176 | core.exportVariable('DOCKER_CACHE_NAME', docker.cache.name);
177 | core.exportVariable('DOCKER_CACHE_GRYPE', docker.cache.grype);
178 |
179 | core.exportVariable('DOCKER_IMAGE_NAME', docker.image.name);
180 | core.exportVariable('DOCKER_IMAGE_ARCH', docker.image.arch);
181 | core.exportVariable('DOCKER_IMAGE_TAGS', docker.tags.join(','));
182 | core.exportVariable('DOCKER_IMAGE_DESCRIPTION', docker.image.description);
183 | core.exportVariable('DOCKER_IMAGE_ARGUMENTS', arguments.join("\r\n"));
184 | core.exportVariable('DOCKER_IMAGE_DOCKERFILE', opt.input?.etc?.dockerfile || 'arch.dockerfile');
185 |
186 | core.exportVariable('WORKFLOW_BUILD', (opt.input?.build === undefined) ? false : opt.input.build);
187 | core.exportVariable('WORKFLOW_CREATE_RELEASE', (opt.input?.release === undefined) ? false : opt.input.release);
188 | core.exportVariable('WORKFLOW_CREATE_README', (opt.input?.readme === undefined) ? false : opt.input.readme);
189 | core.exportVariable('WORKFLOW_GRYPE_FAIL_ON_SEVERITY', (opt.dot?.grype?.fail === undefined) ? true : opt.dot.grype.fail);
190 | core.exportVariable('WORKFLOW_GRYPE_SEVERITY_CUTOFF', (opt.dot?.grype?.severity || 'high'));
191 | if(opt.dot?.readme?.comparison){
192 | core.exportVariable('WORKFLOW_CREATE_COMPARISON', true);
193 | core.exportVariable('WORKFLOW_CREATE_COMPARISON_FOREIGN_IMAGE', opt.dot.readme.comparison.image);
194 | core.exportVariable('WORKFLOW_CREATE_COMPARISON_IMAGE', `${docker.image.name}:${docker.app.version}`);
195 | }
196 |
197 |
198 |
199 | # DOCKER
200 | - name: docker / login to hub
201 | uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
202 | with:
203 | username: 11notes
204 | password: ${{ secrets.DOCKER_TOKEN }}
205 |
206 | - name: github / login to ghcr
207 | uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
208 | with:
209 | registry: ghcr.io
210 | username: 11notes
211 | password: ${{ secrets.GITHUB_TOKEN }}
212 |
213 | - name: quay / login to quay
214 | uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
215 | with:
216 | registry: quay.io
217 | username: 11notes+github
218 | password: ${{ secrets.QUAY_TOKEN }}
219 |
220 | - name: docker / setup qemu
221 | if: env.WORKFLOW_BUILD == 'true'
222 | uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a
223 |
224 | - name: docker / setup buildx
225 | if: env.WORKFLOW_BUILD == 'true'
226 | uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5
227 | with:
228 | driver-opts: network=host
229 |
230 | - name: docker / build & push & tag grype
231 | if: env.WORKFLOW_BUILD == 'true'
232 | id: docker-build
233 | uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d
234 | with:
235 | context: .
236 | file: ${{ env.DOCKER_IMAGE_DOCKERFILE }}
237 | push: true
238 | platforms: ${{ env.DOCKER_IMAGE_ARCH }}
239 | cache-from: type=registry,ref=${{ env.DOCKER_CACHE_NAME }}
240 | cache-to: type=registry,ref=${{ env.DOCKER_CACHE_REGISTRY }}${{ env.DOCKER_CACHE_NAME }},mode=max,compression=zstd,force-compression=true
241 | build-args: |
242 | ${{ env.DOCKER_IMAGE_ARGUMENTS }}
243 | tags: |
244 | ${{ env.DOCKER_CACHE_GRYPE }}
245 |
246 | - name: grype / scan
247 | if: env.WORKFLOW_BUILD == 'true'
248 | id: grype
249 | uses: anchore/scan-action@dc6246fcaf83ae86fcc6010b9824c30d7320729e
250 | with:
251 | image: ${{ env.DOCKER_CACHE_GRYPE }}
252 | fail-build: ${{ env.WORKFLOW_GRYPE_FAIL_ON_SEVERITY }}
253 | severity-cutoff: ${{ env.WORKFLOW_GRYPE_SEVERITY_CUTOFF }}
254 | output-format: 'sarif'
255 | by-cve: true
256 | cache-db: true
257 |
258 | - name: grype / fail
259 | if: env.WORKFLOW_BUILD == 'true' && (failure() || steps.grype.outcome == 'failure')
260 | uses: anchore/scan-action@dc6246fcaf83ae86fcc6010b9824c30d7320729e
261 | with:
262 | image: ${{ env.DOCKER_CACHE_GRYPE }}
263 | fail-build: false
264 | severity-cutoff: ${{ env.WORKFLOW_GRYPE_SEVERITY_CUTOFF }}
265 | output-format: 'table'
266 | by-cve: true
267 | cache-db: true
268 |
269 | - name: docker / build & push
270 | if: env.WORKFLOW_BUILD == 'true'
271 | uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d
272 | with:
273 | context: .
274 | file: ${{ env.DOCKER_IMAGE_DOCKERFILE }}
275 | push: true
276 | sbom: true
277 | provenance: mode=max
278 | platforms: ${{ env.DOCKER_IMAGE_ARCH }}
279 | cache-from: type=registry,ref=${{ env.DOCKER_CACHE_REGISTRY }}${{ env.DOCKER_CACHE_NAME }}
280 | cache-to: type=registry,ref=${{ env.DOCKER_CACHE_NAME }},mode=max,compression=zstd,force-compression=true
281 | build-args: |
282 | ${{ env.DOCKER_IMAGE_ARGUMENTS }}
283 | tags: |
284 | ${{ env.DOCKER_IMAGE_TAGS }}
285 |
286 |
287 |
288 | # RELEASE
289 | - name: github / release / log
290 | continue-on-error: true
291 | id: git-log
292 | run: |
293 | LOCAL_LAST_TAG=$(git describe --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1`)
294 | echo "using last tag: ${LOCAL_LAST_TAG}"
295 | LOCAL_COMMITS=$(git log ${LOCAL_LAST_TAG}..HEAD --oneline)
296 |
297 | EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
298 | echo "commits<<${EOF}" >> ${GITHUB_OUTPUT}
299 | echo "${LOCAL_COMMITS}" >> ${GITHUB_OUTPUT}
300 | echo "${EOF}" >> ${GITHUB_OUTPUT}
301 |
302 | - name: github / release / markdown
303 | if: env.WORKFLOW_CREATE_RELEASE == 'true' && steps.git-log.outcome == 'success'
304 | id: git-release
305 | uses: 11notes/action-docker-release@v1
306 | # WHY IS THIS ACTION NOT SHA256 PINNED? SECURITY MUCH?!?!?!
307 | # ---------------------------------------------------------------------------------
308 | # the next step "github / release / create" creates a new release based on the code
309 | # in the repo. This code is not modified and can't be modified by this action.
310 | # It does create the markdown for the release, which could be abused, but to what
311 | # extend? Adding a link to a malicious repo?
312 | with:
313 | git_log: ${{ steps.git-log.outputs.commits }}
314 |
315 | - name: github / release / create
316 | if: env.WORKFLOW_CREATE_RELEASE == 'true' && steps.git-release.outcome == 'success'
317 | uses: actions/create-release@4c11c9fe1dcd9636620a16455165783b20fc7ea0
318 | env:
319 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
320 | with:
321 | tag_name: ${{ github.ref }}
322 | release_name: ${{ github.ref }}
323 | body: ${{ steps.git-release.outputs.release }}
324 | draft: false
325 | prerelease: false
326 |
327 |
328 |
329 |
330 | # LICENSE
331 | - name: license / update year
332 | continue-on-error: true
333 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
334 | with:
335 | script: |
336 | const { existsSync, readFileSync, writeFileSync } = require('node:fs');
337 | const { resolve } = require('node:path');
338 | const file = 'LICENSE';
339 | const year = new Date().getFullYear();
340 | try{
341 | const path = resolve(file);
342 | if(existsSync(path)){
343 | let license = readFileSync(file).toString();
344 | if(!new RegExp(`Copyright \\(c\\) ${year} 11notes`, 'i').test(license)){
345 | license = license.replace(/Copyright \(c\) \d{4} /i, `Copyright (c) ${new Date().getFullYear()} `);
346 | writeFileSync(path, license);
347 | }
348 | }else{
349 | throw new Error(`file ${file} does not exist`);
350 | }
351 | }catch(e){
352 | core.setFailed(e);
353 | }
354 |
355 |
356 |
357 |
358 | # README
359 | - name: github / checkout HEAD
360 | continue-on-error: true
361 | run: |
362 | git checkout HEAD
363 |
364 | - name: docker / setup comparison images
365 | if: env.WORKFLOW_CREATE_COMPARISON == 'true'
366 | continue-on-error: true
367 | run: |
368 | docker image pull ${{ env.WORKFLOW_CREATE_COMPARISON_IMAGE }}
369 | docker image ls --filter "reference=${{ env.WORKFLOW_CREATE_COMPARISON_IMAGE }}" --format json | jq --raw-output '.Size' &> ./comparison.size0.log
370 |
371 | docker image pull ${{ env.WORKFLOW_CREATE_COMPARISON_FOREIGN_IMAGE }}
372 | docker image ls --filter "reference=${{ env.WORKFLOW_CREATE_COMPARISON_FOREIGN_IMAGE }}" --format json | jq --raw-output '.Size' &> ./comparison.size1.log
373 |
374 | docker run --entrypoint "/bin/sh" --rm ${{ env.WORKFLOW_CREATE_COMPARISON_FOREIGN_IMAGE }} -c id &> ./comparison.id.log
375 |
376 | - name: github / create README.md
377 | id: github-readme
378 | continue-on-error: true
379 | if: env.WORKFLOW_CREATE_README == 'true'
380 | uses: 11notes/action-docker-readme@v1
381 | # WHY IS THIS ACTION NOT SHA256 PINNED? SECURITY MUCH?!?!?!
382 | # ---------------------------------------------------------------------------------
383 | # the next step "github / commit & push" only adds the README and LICENSE as well as
384 | # compose.yaml to the repository. This does not pose a security risk if this action
385 | # would be compromised. The code of the app can't be changed by this action. Since
386 | # only the files mentioned are commited to the repo. Sure, someone could make a bad
387 | # compose.yaml, but since this serves only as an example I see no harm in that.
388 | with:
389 | sarif_file: ${{ steps.grype.outputs.sarif }}
390 | build_output_metadata: ${{ steps.docker-build.outputs.metadata }}
391 |
392 | - name: docker / push README.md to docker hub
393 | continue-on-error: true
394 | if: steps.github-readme.outcome == 'success' && hashFiles('README_NONGITHUB.md') != ''
395 | uses: christian-korneck/update-container-description-action@d36005551adeaba9698d8d67a296bd16fa91f8e8
396 | env:
397 | DOCKER_USER: 11notes
398 | DOCKER_PASS: ${{ secrets.DOCKER_TOKEN }}
399 | with:
400 | destination_container_repo: ${{ env.DOCKER_IMAGE_NAME }}
401 | provider: dockerhub
402 | short_description: ${{ env.DOCKER_IMAGE_DESCRIPTION }}
403 | readme_file: 'README_NONGITHUB.md'
404 |
405 | - name: github / commit & push
406 | continue-on-error: true
407 | if: steps.github-readme.outcome == 'success' && hashFiles('README.md') != ''
408 | run: |
409 | git config user.name "github-actions[bot]"
410 | git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
411 | git add README.md
412 | if [ -f compose.yaml ]; then
413 | git add compose.yaml
414 | fi
415 | if [ -f LICENSE ]; then
416 | git add LICENSE
417 | fi
418 | git commit -m "github-actions[bot]: update README.md"
419 | git push origin HEAD:master
420 |
421 |
422 |
423 |
424 | # REPOSITORY SETTINGS
425 | - name: github / update description and set repo defaults
426 | run: |
427 | curl --request PATCH \
428 | --url https://api.github.com/repos/${{ github.repository }} \
429 | --header 'authorization: Bearer ${{ secrets.REPOSITORY_TOKEN }}' \
430 | --header 'content-type: application/json' \
431 | --data '{
432 | "description":"${{ env.DOCKER_IMAGE_DESCRIPTION }}",
433 | "homepage":"",
434 | "has_issues":true,
435 | "has_discussions":true,
436 | "has_projects":false,
437 | "has_wiki":false
438 | }' \
439 | --fail
--------------------------------------------------------------------------------
/.github/workflows/hysteria.yml:
--------------------------------------------------------------------------------
1 | name: hysteria
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'hysteria'
9 | jobs:
10 | hysteria:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://api.github.com/repos/apernet/hysteria/releases/latest | jq -r '.tag_name' | sed 's/app\/v//')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/hysteria-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"hysteria.dockerfile",
31 | tag:"hysteria",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"hysteria", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/lego.yml:
--------------------------------------------------------------------------------
1 | name: lego
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'lego'
9 | jobs:
10 | lego:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://api.github.com/repos/go-acme/lego/releases/latest | jq -r '.tag_name' | sed 's/v//')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/lego-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"lego.dockerfile",
31 | tag:"lego",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"lego", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/nginx.yml:
--------------------------------------------------------------------------------
1 | name: nginx
2 | on:
3 | push:
4 | tags:
5 | - 'nginx'
6 | jobs:
7 | nginx:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-nginx/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"nginx.dockerfile",
21 | tag:"nginx",
22 | version:dot.semver.version,
23 | };
24 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
25 | }catch(e){
26 | core.setFailed(`workflow failed: ${e}`);
27 | }
28 | })();
29 |
30 | - name: build docker image
31 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
32 | with:
33 | workflow: docker.yml
34 | token: "${{ secrets.REPOSITORY_TOKEN }}"
35 | inputs: '{ "release":"false", "readme":"false", "run-name":"nginx", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/node.yml:
--------------------------------------------------------------------------------
1 | name: node
2 | on:
3 | push:
4 | tags:
5 | - 'node'
6 | jobs:
7 | node:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-node/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"node.dockerfile",
21 | tag:"node",
22 | version:dot.semver.version,
23 | };
24 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
25 | }catch(e){
26 | core.setFailed(`workflow failed: ${e}`);
27 | }
28 | })();
29 |
30 | - name: build docker image
31 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
32 | with:
33 | workflow: docker.yml
34 | token: "${{ secrets.REPOSITORY_TOKEN }}"
35 | inputs: '{ "release":"false", "readme":"false", "run-name":"node", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/par2.yml:
--------------------------------------------------------------------------------
1 | name: par2
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'par2'
9 | jobs:
10 | par2:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://api.github.com/repos/animetosho/par2cmdline-turbo/releases/latest | jq -r '.tag_name' | sed 's/v//')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/par2-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"par2.dockerfile",
31 | tag:"par2",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"par2", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/readme.yml:
--------------------------------------------------------------------------------
1 | name: readme
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | readme:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: update README.md
11 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
12 | with:
13 | wait-for-completion: false
14 | workflow: docker.yml
15 | token: "${{ secrets.REPOSITORY_TOKEN }}"
16 | inputs: '{ "build":"false", "release":"false", "readme":"true" }'
--------------------------------------------------------------------------------
/.github/workflows/socket-proxy.yml:
--------------------------------------------------------------------------------
1 | name: socket-proxy
2 | on:
3 | push:
4 | tags:
5 | - 'socket-proxy'
6 | jobs:
7 | socket-proxy:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-socket-proxy/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"socket-proxy.dockerfile",
21 | tag:"socket-proxy",
22 | version:dot.semver.version,
23 | uid:0,
24 | gid:0,
25 | };
26 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
27 | }catch(e){
28 | core.setFailed(`workflow failed: ${e}`);
29 | }
30 | })();
31 |
32 | - name: build docker image
33 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
34 | with:
35 | workflow: docker.yml
36 | token: "${{ secrets.REPOSITORY_TOKEN }}"
37 | inputs: '{ "release":"false", "readme":"false", "run-name":"socket-proxy", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/tini-pm.yml:
--------------------------------------------------------------------------------
1 | name: tini-pm
2 | on:
3 | push:
4 | tags:
5 | - 'tini-pm'
6 | jobs:
7 | tini-pm:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | const etc = {
16 | dockerfile:"tini-pm.dockerfile",
17 | tag:"tini-pm",
18 | version:"latest"
19 | };
20 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
21 |
22 | - name: build docker image
23 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
24 | with:
25 | workflow: docker.yml
26 | token: "${{ secrets.REPOSITORY_TOKEN }}"
27 | inputs: '{ "release":"false", "readme":"false", "run-name":"tini-pm", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/traefik.yml:
--------------------------------------------------------------------------------
1 | name: traefik
2 | on:
3 | push:
4 | tags:
5 | - 'traefik'
6 | jobs:
7 | traefik:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: init / base64 nested json
11 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
12 | with:
13 | script: |
14 | const { Buffer } = require('node:buffer');
15 | (async()=>{
16 | try{
17 | const master = await fetch('https://raw.githubusercontent.com/11notes/docker-traefik/refs/heads/master/.json');
18 | const dot = await master.json();
19 | const etc = {
20 | dockerfile:"traefik.dockerfile",
21 | tag:"traefik",
22 | version:dot.semver.version,
23 | };
24 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
25 | }catch(e){
26 | core.setFailed(`workflow failed: ${e}`);
27 | }
28 | })();
29 |
30 | - name: build docker image
31 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
32 | with:
33 | workflow: docker.yml
34 | token: "${{ secrets.REPOSITORY_TOKEN }}"
35 | inputs: '{ "release":"false", "readme":"false", "run-name":"traefik", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.github/workflows/unrar.yml:
--------------------------------------------------------------------------------
1 | name: unrar
2 | on:
3 | workflow_dispatch:
4 | schedule:
5 | - cron: "0 5 * * *"
6 | push:
7 | tags:
8 | - 'unrar'
9 | jobs:
10 | unrar:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: cron-update / get latest version
14 | run: |
15 | LATEST_VERSION=$(curl -s https://www.rarlab.com/rar_add.htm | grep -i '>UnRAR source' | grep -oEi '[0-9].[0-9].[0-9]')
16 | echo "LATEST_VERSION=${LATEST_VERSION}" >> "${GITHUB_ENV}"
17 | if curl -kILs --fail https://hub.docker.com/v2/repositories/11notes/distroless/tags/unrar-${LATEST_VERSION}; then
18 | echo "tag ${LATEST_VERSION} exists already!"
19 | else
20 | echo "WORKFLOW_AUTO_UPDATE=true" >> "${GITHUB_ENV}"
21 | fi
22 |
23 | - name: init / base64 nested json
24 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
25 | uses: actions/github-script@62c3794a3eb6788d9a2a72b219504732c0c9a298
26 | with:
27 | script: |
28 | const { Buffer } = require('node:buffer');
29 | const etc = {
30 | dockerfile:"unrar.dockerfile",
31 | tag:"unrar",
32 | version:"${{ env.LATEST_VERSION }}"
33 | };
34 | core.exportVariable('WORKFLOW_BASE64JSON', Buffer.from(JSON.stringify(etc)).toString('base64'));
35 |
36 | - name: build docker image
37 | if: env.WORKFLOW_AUTO_UPDATE == 'true'
38 | uses: the-actions-org/workflow-dispatch@3133c5d135c7dbe4be4f9793872b6ef331b53bc7
39 | with:
40 | workflow: docker.yml
41 | token: "${{ secrets.REPOSITORY_TOKEN }}"
42 | inputs: '{ "release":"false", "readme":"false", "run-name":"unrar", "etc":"${{ env.WORKFLOW_BASE64JSON }}" }'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # default
2 | maintain/
3 | node_modules/
--------------------------------------------------------------------------------
/.json:
--------------------------------------------------------------------------------
1 | {
2 | "image":"11notes/distroless",
3 | "name":"distroless",
4 | "root":"/distroless",
5 | "arch":"linux/amd64,linux/arm64,linux/arm/v7",
6 |
7 | "readme":{
8 | "description":"Build your own distroless images with this mini file system and some binaries",
9 | "parent":{
10 | "image":"scratch"
11 | },
12 | "distroless":true
13 | }
14 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 11notes
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # DISTROLESS
4 | [
](https://github.com/11notes/docker-DISTROLESS)[
](https://github.com/11notes/docker-DISTROLESS/issues)
5 |
6 | Build your own distroless images with this mini file system and some binaries
7 |
8 | # MAIN TAGS 🏷️
9 | These are the main tags for the image. There is also a tag for each commit and its shorthand sha256 value.
10 |
11 | * [latest](https://hub.docker.com/r/11notes/distroless/tags?name=latest)
12 |
13 | # REPOSITORIES ☁️
14 | ```
15 | docker pull 11notes/distroless:latest
16 | docker pull ghcr.io/11notes/distroless:latest
17 | docker pull quay.io/11notes/distroless:latest
18 | ```
19 |
20 | # SYNOPSIS 📖
21 | **What can I do with this?** This image and its different layers can be used to build a distroless boiler plate for your application. Simply add the base layer and any additional layers (tags) with the stuff you need to run your application. All binaries are statically compiled and do not depend on any OS libraries or clib. The base layer contains Root CA certificates as well as time zone data and the user configuration for root and docker. Additional layers (tags) with statically compiled binaries are:
22 |
23 | # STAND-ALONE BINARIES
24 | * [11notes/distroless:curl](https://github.com/11notes/docker-distroless/blob/master/curl.dockerfile) - curl
25 | * [11notes/distroless:dnslookup](https://github.com/11notes/docker-distroless/blob/master/dnslookup.dockerfile) - dnslookup
26 | * [11notes/distroless:lego](https://github.com/11notes/docker-distroless/blob/master/lego.dockerfile) - lego
27 | * [11notes/distroless:par2](https://github.com/11notes/docker-distroless/blob/master/par2.dockerfile) - par2
28 |
29 | # APPLICATION SUITES
30 | * [11notes/distroless:node](https://github.com/11notes/docker-node) - node
31 | * [11notes/distroless:adguard](https://github.com/11notes/docker-adguard) - adguard
32 | * [11notes/distroless:adguard-sync](https://github.com/11notes/docker-adguard-sync) - adguard-sync
33 | * [11notes/distroless:nginx](https://github.com/11notes/docker-nginx) - nginx
34 | * [11notes/distroless:traefik](https://github.com/11notes/docker-traefik) - traefik
35 |
36 | # CONTAINER BUILD HELPERS
37 | * [11notes/distroless:tini-pm](https://github.com/11notes/go-tini-pm) - tini-pm
38 | * [11notes/distroless:cmd-socket](https://github.com/11notes/go-cmd-socket) - cmd-socket
39 | * [11notes/distroless:socket-proxy](https://github.com/11notes/docker-socket-proxy) - socket-proxy
40 |
41 | Each tag has sub tags like latest, stable or semver, check the tags available for each binary. If you need more binaries, open a PR or feature request. Some of the images have their own dedicated container images to run the applications within, simply check the link for the source and explanation on how to use them.
42 |
43 | These images are meant as direct competition to very popular images which come with almost no security in mind!
44 |
45 | # BUILD 🚧
46 | ```yaml
47 | # this will create a distroless image that just contains the curl binary
48 | FROM 11notes/distroless AS distroless
49 | FROM 11notes/distroless:curl AS distroless-curl
50 | FROM scratch
51 | COPY --from=distroless --chown=1000:1000 / /
52 | COPY --from=distroless-curl --chown=1000:1000 / /
53 | USER docker
54 | ENTRYPOINT ["curl"]
55 | ```
56 |
57 | # SOURCE 💾
58 | * [11notes/distroless](https://github.com/11notes/docker-DISTROLESS)
59 |
60 | # ElevenNotes™️
61 | This image is provided to you at your own risk. Always make backups before updating an image to a different version. Check the [releases](https://github.com/11notes/docker-distroless/releases) for breaking changes. If you have any problems with using this image simply raise an [issue](https://github.com/11notes/docker-distroless/issues), thanks. If you have a question or inputs please create a new [discussion](https://github.com/11notes/docker-distroless/discussions) instead of an issue. You can find all my other repositories on [github](https://github.com/11notes?tab=repositories).
62 |
63 | *created 29.04.2025, 17:13:50 (CET)*
--------------------------------------------------------------------------------
/adguard-sync.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=1000
3 | ARG APP_GID=1000
4 |
5 | # :: Distroless
6 | FROM 11notes/distroless AS distroless
7 | FROM 11notes/adguard-sync:${APP_VERSION} AS adguard-sync
8 | FROM scratch
9 | ARG APP_UID
10 | ARG APP_GID
11 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
12 | COPY --from=adguard-sync --chown=${APP_UID}:${APP_GID} /usr/local/bin/adguardhome-sync /usr/local/bin/adguardhome-sync
13 |
14 | # :: Start
15 | USER ${APP_UID}:${APP_GID}
16 | ENTRYPOINT ["/usr/local/bin/adguardhome-sync"]
--------------------------------------------------------------------------------
/adguard.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=1000
3 | ARG APP_GID=1000
4 |
5 | # :: Distroless
6 | FROM 11notes/distroless AS distroless
7 | FROM 11notes/adguard:${APP_VERSION} AS adguard
8 | FROM scratch
9 | ARG APP_UID
10 | ARG APP_GID
11 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
12 | COPY --from=adguard --chown=${APP_UID}:${APP_GID} /usr/local/bin/AdGuardHome /usr/local/bin/AdGuardHome
13 |
14 | # :: Start
15 | USER ${APP_UID}:${APP_GID}
16 | ENTRYPOINT ["/usr/local/bin/AdGuardHome"]
--------------------------------------------------------------------------------
/arch.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Header
5 | FROM alpine AS distroless
6 | ARG TARGETARCH
7 | ARG APP_ROOT
8 | ARG APP_VERSION
9 | USER root
10 |
11 | # :: create base folders
12 | RUN set -ex; \
13 | mkdir -p ${APP_ROOT}/etc; \
14 | mkdir -p ${APP_ROOT}/run;
15 |
16 | # :: create users
17 | RUN set -ex; \
18 | echo "root:x:0:0:root:/root:/sbin/nologin" > ${APP_ROOT}/etc/passwd; \
19 | echo "root:x:0:root" > ${APP_ROOT}/etc/group; \
20 | echo "docker:x:1000:1000:docker:/:/sbin/nologin" >> ${APP_ROOT}/etc/passwd; \
21 | echo "docker:x:1000:docker" >> ${APP_ROOT}/etc/group;
22 |
23 | # :: add ca-certificates
24 | RUN set -ex; \
25 | apk --update --no-cache add \
26 | ca-certificates \
27 | tzdata; \
28 | mkdir -p ${APP_ROOT}/usr/share/ca-certificates; \
29 | mkdir -p ${APP_ROOT}/etc/ssl/certs; \
30 | cp -R /usr/share/ca-certificates/* ${APP_ROOT}/usr/share/ca-certificates; \
31 | cp -R /etc/ssl/certs/* ${APP_ROOT}/etc/ssl/certs;
32 |
33 | # :: add timezones
34 | RUN set -ex; \
35 | apk --update --no-cache add \
36 | tzdata; \
37 | mkdir -p ${APP_ROOT}/usr/share/zoneinfo; \
38 | cp -R /usr/share/zoneinfo/* ${APP_ROOT}/usr/share/zoneinfo;
39 |
40 | # :: Distroless
41 | FROM scratch
42 | ARG APP_ROOT
43 | ARG APP_UID
44 | ARG APP_GID
45 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
46 |
47 | # :: Start
48 | USER ${APP_UID}:${APP_GID}
49 | ENTRYPOINT ["/"]
--------------------------------------------------------------------------------
/build.dockerfile:
--------------------------------------------------------------------------------
1 | # this will create a distroless image that just contains the curl binary
2 | FROM 11notes/distroless AS distroless
3 | FROM 11notes/distroless:curl AS distroless-curl
4 | FROM scratch
5 | COPY --from=distroless --chown=1000:1000 / /
6 | COPY --from=distroless-curl --chown=1000:1000 / /
7 | USER docker
8 | ENTRYPOINT ["curl"]
--------------------------------------------------------------------------------
/cmd-socket.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM golang:1.24-alpine AS build
9 | ARG APP_ROOT
10 | ARG APP_NO_CACHE
11 | ENV BUILD_ROOT=/go/go-cmd-socket
12 | ENV BUILD_BIN=${BUILD_ROOT}/cmd-socket
13 | ENV CGO_ENABLED=0
14 | USER root
15 |
16 | COPY --from=util /usr/local/bin/ /usr/local/bin
17 |
18 | RUN set -ex; \
19 | apk --update add \
20 | build-base \
21 | upx \
22 | git; \
23 | git clone https://github.com/11notes/go-cmd-socket.git;
24 |
25 | RUN set -ex; \
26 | eleven printenv;
27 |
28 | RUN set -ex; \
29 | cd ${BUILD_ROOT}; \
30 | mkdir -p ${APP_ROOT}/usr/local/bin; \
31 | mkdir -p ${APP_ROOT}/run/cmd; \
32 | go mod tidy; \
33 | go build -ldflags="-extldflags=-static" -o ${BUILD_BIN} main.go;
34 |
35 | RUN set -ex; \
36 | eleven checkStatic ${BUILD_BIN}; \
37 | eleven strip ${BUILD_BIN}; \
38 | mkdir -p ${APP_ROOT}/usr/local/bin; \
39 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
40 |
41 | # :: Distroless
42 | FROM scratch
43 | ARG APP_ROOT
44 | ARG APP_UID
45 | ARG APP_GID
46 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
47 |
48 | # :: Start
49 | USER ${APP_UID}:${APP_GID}
50 | ENTRYPOINT ["/usr/local/bin/cmd-socket"]
--------------------------------------------------------------------------------
/curl.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM alpine AS build
9 | ARG TARGETARCH
10 | ARG APP_ROOT
11 | ARG APP_VERSION
12 | ENV BUILD_ROOT=/curl-${APP_VERSION}
13 | ENV BUILD_BIN=/curl-${APP_VERSION}/src/curl
14 | ENV CC=clang
15 | USER root
16 | COPY --from=util /usr/local/bin/ /usr/local/bin
17 |
18 | # :: Build
19 | RUN set -ex; \
20 | apk --update --no-cache add \
21 | build-base \
22 | clang \
23 | openssl-dev \
24 | nghttp2-dev \
25 | nghttp2-static \
26 | libssh2-dev \
27 | libssh2-static \
28 | perl \
29 | openssl-libs-static \
30 | zlib-static \
31 | tar \
32 | upx \
33 | wget;
34 |
35 | RUN set -ex; \
36 | wget https://curl.se/download/curl-${APP_VERSION}.tar.gz; \
37 | tar xzf curl-${APP_VERSION}.tar.gz;
38 |
39 | RUN set -ex; \
40 | cd ${BUILD_ROOT}; \
41 | LDFLAGS="-static" PKG_CONFIG="pkg-config --static" \
42 | ./configure \
43 | --disable-shared \
44 | --enable-static \
45 | --disable-ldap \
46 | --disable-ipv6 \
47 | --enable-unix-sockets \
48 | --with-ssl \
49 | --disable-docs \
50 | --disable-manual \
51 | --without-libpsl; \
52 | make -s -j $(nproc) V=1 LDFLAGS="-static -all-static";
53 |
54 | RUN set -ex; \
55 | eleven checkStatic ${BUILD_BIN}; \
56 | eleven strip ${BUILD_BIN}; \
57 | mkdir -p ${APP_ROOT}/usr/local/bin; \
58 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
59 |
60 | # :: Distroless
61 | FROM 11notes/distroless AS distroless
62 | FROM scratch
63 | ARG APP_ROOT
64 | ARG APP_UID
65 | ARG APP_GID
66 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
67 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
68 |
69 | # :: Start
70 | USER ${APP_UID}:${APP_GID}
71 | ENTRYPOINT ["/usr/local/bin/curl"]
--------------------------------------------------------------------------------
/dnslookup.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM golang:1.24-alpine AS distroless
9 | ARG APP_ROOT
10 | ARG APP_VERSION
11 | ENV BUILD_ROOT=/go/dnslookup
12 | ENV BUILD_BIN=${BUILD_ROOT}/dnslookup
13 | ENV CGO_ENABLED=0
14 | COPY --from=util /usr/local/bin/ /usr/local/bin
15 | USER root
16 |
17 | # :: Build
18 | RUN set -ex; \
19 | apk --update --no-cache add \
20 | build-base \
21 | upx \
22 | git; \
23 | git clone https://github.com/ameshkov/dnslookup.git -b v${APP_VERSION}; \
24 | cd ${BUILD_ROOT}; \
25 | eleven patchGoMod go.mod "golang.org/x/crypto|v0.31.0|CVE-2024-45337"; \
26 | eleven patchGoMod go.mod "github.com/quic-go/quic-go|v0.48.2|CVE-2024-53259"; \
27 | eleven patchGoMod go.mod "golang.org/x/net|v0.36.0|CVE-2025-22870"; \
28 | go mod tidy; \
29 | go build -ldflags="-extldflags=-static";
30 |
31 | RUN set -ex; \
32 | eleven checkStatic ${BUILD_BIN}; \
33 | eleven strip ${BUILD_BIN}; \
34 | mkdir -p ${APP_ROOT}/usr/local/bin; \
35 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
36 |
37 | # :: Distroless
38 | FROM scratch
39 | ARG APP_ROOT
40 | ARG APP_UID
41 | ARG APP_GID
42 | COPY --from=distroless ${APP_ROOT}/ /
43 |
44 | # :: Start
45 | USER ${APP_UID}:${APP_GID}
46 | ENTRYPOINT ["/usr/local/bin/dnslookup"]
--------------------------------------------------------------------------------
/hysteria.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM golang:1.24-alpine AS build
9 | ARG TARGETARCH
10 | ARG APP_ROOT
11 | ARG APP_VERSION
12 | ENV BUILD_ROOT=/go/hysteria
13 | ENV BUILD_BIN=${BUILD_ROOT}/build/hysteria-linux-${TARGETARCH}
14 | ENV CGO_ENABLED=0
15 | COPY --from=util /usr/local/bin/ /usr/local/bin
16 | USER root
17 |
18 | # :: Build
19 | RUN set -ex; \
20 | apk --update add \
21 | python3 \
22 | build-base \
23 | upx \
24 | git; \
25 | git clone https://github.com/apernet/hysteria.git -b app/v${APP_VERSION}; \
26 | cd ${BUILD_ROOT}; \
27 | python3 hyperbole.py build -r;
28 |
29 | RUN set -ex; \
30 | eleven checkStatic ${BUILD_BIN}; \
31 | eleven strip ${BUILD_BIN}; \
32 | mkdir -p ${APP_ROOT}/usr/local/bin; \
33 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin/hysteria;
34 |
35 | # :: Distroless
36 | FROM 11notes/distroless AS distroless
37 | FROM scratch
38 | ARG APP_ROOT
39 | ARG APP_UID
40 | ARG APP_GID
41 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
42 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
43 |
44 | # :: Start
45 | USER ${APP_UID}:${APP_GID}
46 | ENTRYPOINT ["/usr/local/bin/hysteria"]
--------------------------------------------------------------------------------
/lego.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM golang:1.24-alpine AS build
9 | ARG TARGETARCH
10 | ARG APP_ROOT
11 | ARG APP_VERSION
12 | ENV BUILD_ROOT=/go/lego
13 | ENV BUILD_BIN=${BUILD_ROOT}/dist/lego
14 | ENV CGO_ENABLED=0
15 | COPY --from=util /usr/local/bin/ /usr/local/bin
16 | USER root
17 |
18 | # :: Build
19 | RUN set -ex; \
20 | apk --update --no-cache add \
21 | build-base \
22 | upx \
23 | git; \
24 | git clone https://github.com/go-acme/lego.git -b v${APP_VERSION};
25 |
26 | RUN set -ex; \
27 | cd ${BUILD_ROOT}; \
28 | go build -trimpath -ldflags '-X "main.version='${APP_VERSION}'" -extldflags=-static' -o dist/lego ./cmd/lego/;
29 |
30 | RUN set -ex; \
31 | cd ${BUILD_ROOT}; \
32 | mkdir -p ${APP_ROOT}/usr/local/bin; \
33 | eleven strip ${BUILD_BIN}; \
34 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
35 |
36 | # :: Distroless
37 | FROM 11notes/distroless AS distroless
38 | FROM scratch
39 | ARG APP_ROOT
40 | ARG APP_UID
41 | ARG APP_GID
42 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
43 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
44 |
45 | # :: Start
46 | USER ${APP_UID}:${APP_GID}
47 | ENTRYPOINT ["/usr/local/bin/lego"]
--------------------------------------------------------------------------------
/nginx.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=1000
3 | ARG APP_GID=1000
4 |
5 | # :: Distroless
6 | FROM 11notes/nginx:${APP_VERSION} AS nginx
7 | FROM scratch
8 | ARG APP_UID
9 | ARG APP_GID
10 | COPY --from=nginx --chown=${APP_UID}:${APP_GID} /usr/local/bin/nginx /usr/local/bin
11 | COPY --from=nginx --chown=${APP_UID}:${APP_GID} /nginx /
12 | COPY --from=nginx --chown=${APP_UID}:${APP_GID} /etc/nginx /etc
13 |
14 | # :: Start
15 | USER ${APP_UID}:${APP_GID}
16 | ENTRYPOINT ["/usr/local/bin/nginx"]
--------------------------------------------------------------------------------
/node.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=1000
3 | ARG APP_GID=1000
4 |
5 | # :: Distroless
6 | FROM 11notes/node:${APP_VERSION} AS node
7 | FROM scratch
8 | ARG APP_UID
9 | ARG APP_GID
10 | COPY --from=node --chown=${APP_UID}:${APP_GID} /usr/local/bin/node /usr/local/bin
11 |
12 | # :: Start
13 | USER ${APP_UID}:${APP_GID}
14 | ENTRYPOINT ["/usr/local/bin/node"]
--------------------------------------------------------------------------------
/par2.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM alpine AS build
9 | ARG TARGETARCH
10 | ARG APP_ROOT
11 | ARG APP_VERSION
12 | ENV BUILD_ROOT=/par2cmdline-turbo
13 | ENV BUILD_BIN=${BUILD_ROOT}/par2
14 | USER root
15 | COPY --from=util /usr/local/bin/ /usr/local/bin
16 |
17 | # :: Build
18 | RUN set -ex; \
19 | apk --no-cache --update add \
20 | autoconf \
21 | automake \
22 | build-base \
23 | libffi-dev \
24 | openssl-dev \
25 | python3-dev \
26 | git;
27 |
28 | RUN set -ex; \
29 | git clone https://github.com/animetosho/par2cmdline-turbo -b v${APP_VERSION};
30 |
31 | RUN set -ex; \
32 | cd ${BUILD_ROOT}; \
33 | ./automake.sh; \
34 | ./configure \
35 | --prefix="/usr"; \
36 | make -s -j $(nproc) V=1 LDFLAGS="--static";
37 |
38 | RUN set -ex; \
39 | eleven checkStatic ${BUILD_BIN}; \
40 | eleven strip ${BUILD_BIN}; \
41 | mkdir -p ${APP_ROOT}/usr/local/bin; \
42 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
43 |
44 | # :: Distroless
45 | FROM scratch
46 | ARG APP_ROOT
47 | ARG APP_UID
48 | ARG APP_GID
49 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
50 |
51 | # :: Start
52 | USER ${APP_UID}:${APP_GID}
53 | ENTRYPOINT ["/usr/local/bin/par2"]
--------------------------------------------------------------------------------
/project.md:
--------------------------------------------------------------------------------
1 | ${{ content_synopsis }} This image and its different layers can be used to build a distroless boiler plate for your application. Simply add the base layer and any additional layers (tags) with the stuff you need to run your application. All binaries are statically compiled and do not depend on any OS libraries or clib. The base layer contains Root CA certificates as well as time zone data and the user configuration for root and docker. Additional layers (tags) with statically compiled binaries are:
2 |
3 | # STAND-ALONE BINARIES
4 | * [11notes/distroless:curl](https://github.com/11notes/docker-distroless/blob/master/curl.dockerfile) - curl
5 | * [11notes/distroless:dnslookup](https://github.com/11notes/docker-distroless/blob/master/dnslookup.dockerfile) - dnslookup
6 | * [11notes/distroless:lego](https://github.com/11notes/docker-distroless/blob/master/lego.dockerfile) - lego
7 | * [11notes/distroless:par2](https://github.com/11notes/docker-distroless/blob/master/par2.dockerfile) - par2
8 | * [11notes/distroless:unrar](https://github.com/11notes/docker-distroless/blob/master/unrar.dockerfile) - unrar
9 |
10 | # APPLICATION SUITES
11 | * [11notes/distroless:node](https://github.com/11notes/docker-node) - node
12 | * [11notes/distroless:adguard](https://github.com/11notes/docker-adguard) - adguard
13 | * [11notes/distroless:adguard-sync](https://github.com/11notes/docker-adguard-sync) - adguard-sync
14 | * [11notes/distroless:nginx](https://github.com/11notes/docker-nginx) - nginx
15 | * [11notes/distroless:traefik](https://github.com/11notes/docker-traefik) - traefik
16 | * [11notes/distroless:hysteria](https://github.com/11notes/docker-hysteria) - hysteria
17 |
18 | # CONTAINER ENTRYPOINTS
19 | * [11notes/distroless:tini-pm](https://github.com/11notes/go-tini-pm) - tini-pm
20 |
21 | # CONTAINER HELPERS
22 | * [11notes/distroless:socket-proxy](https://github.com/11notes/docker-socket-proxy) - socket-proxy
23 | * [11notes/distroless:cmd-socket](https://github.com/11notes/go-cmd-socket) - cmd-socket
24 |
25 | Each tag has sub tags like latest, stable or semver, check the tags available for each binary. If you need more binaries, open a PR or feature request. Some of the images have their own dedicated container images to run the applications within, simply check the link for the source and explanation on how to use them.
26 |
27 | These images are meant as direct competition to very popular images which come with almost no security in mind!
28 |
29 | ${{ content_build }}
30 |
31 | ${{ content_source }}
--------------------------------------------------------------------------------
/socket-proxy.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=0
3 | ARG APP_GID=0
4 |
5 | # :: Distroless
6 | FROM 11notes/distroless AS distroless
7 | FROM 11notes/socket-proxy:${APP_VERSION} AS socket-proxy
8 | FROM scratch
9 | ARG APP_UID
10 | ARG APP_GID
11 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
12 | COPY --from=socket-proxy --chown=${APP_UID}:${APP_GID} /usr/local/bin/socket-proxy /usr/local/bin/socket-proxy
13 |
14 | # :: Start
15 | USER ${APP_UID}:${APP_GID}
16 | ENTRYPOINT ["/usr/local/bin/socket-proxy"]
--------------------------------------------------------------------------------
/tini-pm.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM golang:1.24-alpine AS build
9 | ARG APP_ROOT
10 | ARG APP_NO_CACHE
11 | ENV BUILD_ROOT=/go/go-tini-pm
12 | ENV BUILD_BIN=${BUILD_ROOT}/tini-pm
13 | ENV CGO_ENABLED=0
14 | USER root
15 |
16 | COPY --from=util /usr/local/bin/ /usr/local/bin
17 |
18 | RUN set -ex; \
19 | apk --update add \
20 | build-base \
21 | upx \
22 | git; \
23 | git clone https://github.com/11notes/go-tini-pm.git;
24 |
25 | RUN set -ex; \
26 | eleven printenv;
27 |
28 | RUN set -ex; \
29 | cd ${BUILD_ROOT}; \
30 | mkdir -p ${APP_ROOT}/usr/local/bin; \
31 | go mod tidy; \
32 | go build -ldflags="-extldflags=-static" -o ${BUILD_BIN} main.go;
33 |
34 | RUN set -ex; \
35 | eleven checkStatic ${BUILD_BIN}; \
36 | eleven strip ${BUILD_BIN}; \
37 | mkdir -p ${APP_ROOT}/usr/local/bin; \
38 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
39 |
40 | # :: Distroless
41 | FROM 11notes/distroless:cmd-socket AS distroless-cmd-socket
42 | FROM scratch
43 | ARG APP_ROOT
44 | ARG APP_UID
45 | ARG APP_GID
46 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
47 | COPY --from=distroless-cmd-socket --chown=${APP_UID}:${APP_GID} / /
48 |
49 | # :: Start
50 | USER ${APP_UID}:${APP_GID}
51 | ENTRYPOINT ["/usr/local/bin/tini-pm"]
--------------------------------------------------------------------------------
/traefik.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_VERSION=stable
2 | ARG APP_UID=1000
3 | ARG APP_GID=1000
4 |
5 | # :: Distroless
6 | FROM 11notes/distroless AS distroless
7 | FROM 11notes/traefik:${APP_VERSION} AS traefik
8 | FROM scratch
9 | ARG APP_UID
10 | ARG APP_GID
11 | COPY --from=distroless --chown=${APP_UID}:${APP_GID} / /
12 | COPY --from=traefik --chown=${APP_UID}:${APP_GID} /usr/local/bin/traefik /usr/local/bin
13 | COPY --from=traefik --chown=${APP_UID}:${APP_GID} /traefik /
14 |
15 | # :: Start
16 | USER ${APP_UID}:${APP_GID}
17 | ENTRYPOINT ["/usr/local/bin/traefik"]
--------------------------------------------------------------------------------
/unrar.dockerfile:
--------------------------------------------------------------------------------
1 | ARG APP_UID=1000
2 | ARG APP_GID=1000
3 |
4 | # :: Util
5 | FROM 11notes/util AS util
6 |
7 | # :: Header
8 | FROM alpine AS build
9 | ARG TARGETARCH
10 | ARG APP_ROOT
11 | ARG APP_VERSION
12 | ENV BUILD_ROOT=/unrar
13 | ENV BUILD_BIN=${BUILD_ROOT}/unrar
14 | USER root
15 | COPY --from=util /usr/local/bin/ /usr/local/bin
16 |
17 | # :: Build
18 | RUN set -ex; \
19 | apk --update --no-cache add \
20 | build-base \
21 | gcc \
22 | clang \
23 | g++ \
24 | make \
25 | cmake \
26 | git \
27 | curl \
28 | tar \
29 | xz;
30 |
31 | RUN set -ex; \
32 | curl -SL https://www.rarlab.com/rar/unrarsrc-${APP_VERSION}.tar.gz | tar -zxC /;
33 |
34 | RUN set -ex; \
35 | cd ${BUILD_ROOT}; \
36 | make -s -j $(nproc) V=1 LDFLAGS="--static";
37 |
38 | RUN set -ex; \
39 | eleven checkStatic ${BUILD_BIN}; \
40 | eleven strip ${BUILD_BIN}; \
41 | mkdir -p ${APP_ROOT}/usr/local/bin; \
42 | cp ${BUILD_BIN} ${APP_ROOT}/usr/local/bin;
43 |
44 | # :: Distroless
45 | FROM scratch
46 | ARG APP_ROOT
47 | ARG APP_UID
48 | ARG APP_GID
49 | COPY --from=build --chown=${APP_UID}:${APP_GID} ${APP_ROOT}/ /
50 |
51 | # :: Start
52 | USER ${APP_UID}:${APP_GID}
53 | ENTRYPOINT ["/usr/local/bin/unrar"]
--------------------------------------------------------------------------------