chore: remove Node.js tooling, update maintenance docs

Remove package.json, build.js, tests/*.mjs, .nvmrc, and the old
website template. Update MAINTENANCE.md with Go CLI commands.
Switch dependabot from npm to gomod.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julien Bisconti
2026-02-27 23:33:06 +01:00
parent 0816049273
commit 8956f1d292
12 changed files with 22 additions and 1474 deletions

View File

@@ -30,7 +30,7 @@ This guide helps maintainers keep the awesome-docker list up-to-date and high-qu
4. Remove projects that are truly abandoned/broken 4. Remove projects that are truly abandoned/broken
### Quarterly Deep Dive (Every 3 months) ### Quarterly Deep Dive (Every 3 months)
1. Run: `npm run health-check` for detailed report 1. Run: `./awesome-docker health` then `./awesome-docker report` for detailed report
2. Review project categories - are they still relevant? 2. Review project categories - are they still relevant?
3. Check for popular new Docker tools to add 3. Check for popular new Docker tools to add
4. Update documentation links if newer versions exist 4. Update documentation links if newer versions exist
@@ -39,25 +39,34 @@ This guide helps maintainers keep the awesome-docker list up-to-date and high-qu
1. Remove all `:skull:` projects older than 1 year 1. Remove all `:skull:` projects older than 1 year
2. Review CONTRIBUTING.md guidelines 2. Review CONTRIBUTING.md guidelines
3. Update year references in documentation 3. Update year references in documentation
4. Check Node.js version requirements
## 🛠️ Maintenance Commands ## 🛠️ Maintenance Commands
```bash ```bash
# Test all links (requires GITHUB_TOKEN) # Build the CLI
npm test go build -o awesome-docker ./cmd/awesome-docker
# Test PR changes only # Lint README formatting (add --fix to auto-fix)
npm run test-pr ./awesome-docker lint
./awesome-docker lint --fix
# Generate health report (requires GITHUB_TOKEN) # Check all links (requires GITHUB_TOKEN for GitHub repos)
npm run health-check ./awesome-docker check
# PR validation (lint + external link check)
./awesome-docker validate
# Score repository health (requires GITHUB_TOKEN)
./awesome-docker health
# Generate health report from cache
./awesome-docker report
# Build the website # Build the website
npm run build ./awesome-docker build
# Update dependencies # Run tests
npm update go test ./...
``` ```
## 📊 Quality Standards ## 📊 Quality Standards

View File

@@ -1,17 +1,13 @@
version: 2 version: 2
updates: updates:
# Enable version updates for npm # Enable version updates for Go modules
- package-ecosystem: "npm" - package-ecosystem: "gomod"
# Look for `package.json` and `lock` files in the `root` directory
directory: "/" directory: "/"
# Check the npm registry for updates every day (weekdays)
schedule: schedule:
interval: "weekly" interval: "weekly"
# Enable version updates for GitHub Actions # Enable version updates for GitHub Actions
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
# Workflow files stored in the default location of `.github/workflows`
# You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"

1
.nvmrc
View File

@@ -1 +0,0 @@
lts/*

View File

@@ -1,51 +0,0 @@
const fs = require('fs-extra');
const cheerio = require('cheerio');
const showdown = require('showdown');
process.env.NODE_ENV = 'production';
const LOG = {
error: (...args) => console.error('❌ ERROR', { ...args }),
debug: (...args) => {
if (process.env.DEBUG) console.log('💡 DEBUG: ', { ...args });
},
};
const handleFailure = (err) => {
LOG.error(err);
process.exit(1);
};
process.on('unhandledRejection', handleFailure);
// --- FILES
const README = 'README.md';
const WEBSITE_FOLDER = 'website';
const indexTemplate = `${WEBSITE_FOLDER}/index.tmpl.html`;
const indexDestination = `${WEBSITE_FOLDER}/index.html`;
async function processIndex() {
const converter = new showdown.Converter();
converter.setFlavor('github');
try {
LOG.debug('Loading files...', { indexTemplate, README });
const template = await fs.readFile(indexTemplate, 'utf8');
const markdown = await fs.readFile(README, 'utf8');
LOG.debug('Merging files...');
const $ = cheerio.load(template);
$('#md').append(converter.makeHtml(markdown));
LOG.debug('Writing index.html');
await fs.outputFile(indexDestination, $.html(), 'utf8');
LOG.debug('DONE 👍');
} catch (err) {
handleFailure(err);
}
}
async function main() {
await processIndex();
}
main();

619
package-lock.json generated
View File

@@ -1,619 +0,0 @@
{
"name": "awesome-docker-website",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "awesome-docker-website",
"version": "1.0.0",
"license": "Apache-2.0",
"dependencies": {
"cheerio": "1.2.0",
"draftlog": "1.0.13",
"fs-extra": "11.3.3",
"node-fetch": "3.3.2",
"rimraf": "6.1.3",
"showdown": "^2.1.0"
}
},
"node_modules/@isaacs/cliui": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
"integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
"license": "BlueOak-1.0.0",
"engines": {
"node": ">=18"
}
},
"node_modules/balanced-match": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz",
"integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==",
"license": "MIT",
"dependencies": {
"jackspeak": "^4.2.3"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"license": "ISC"
},
"node_modules/brace-expansion": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz",
"integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "20 || >=22"
}
},
"node_modules/cheerio": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
"license": "MIT",
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"encoding-sniffer": "^0.2.1",
"htmlparser2": "^10.1.0",
"parse5": "^7.3.0",
"parse5-htmlparser2-tree-adapter": "^7.1.0",
"parse5-parser-stream": "^7.1.2",
"undici": "^7.19.0",
"whatwg-mimetype": "^4.0.0"
},
"engines": {
"node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/cheerio-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
"css-what": "^6.1.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"license": "MIT",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/css-select": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"license": "MIT",
"engines": {
"node": ">= 12"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/draftlog": {
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/draftlog/-/draftlog-1.0.13.tgz",
"integrity": "sha512-GeMWOpXERBpfVDK6v7m0x1hPg8+g8ZsZWqJl2T17wHqrm4h8fnjiZmXcnCrmwogAc6R3YTxFXax15wezfuyCUw==",
"license": "MIT"
},
"node_modules/encoding-sniffer": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
"license": "MIT",
"dependencies": {
"iconv-lite": "^0.6.3",
"whatwg-encoding": "^3.1.1"
},
"funding": {
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"license": "MIT",
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/fs-extra": {
"version": "11.3.3",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
"integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"node_modules/glob": {
"version": "13.0.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.3.tgz",
"integrity": "sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"minimatch": "^10.2.0",
"minipass": "^7.1.2",
"path-scurry": "^2.0.0"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/htmlparser2": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
"entities": "^7.0.1"
}
},
"node_modules/htmlparser2/node_modules/entities": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/jackspeak": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
"integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/cliui": "^9.0.0"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/jsonfile": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/lru-cache": {
"version": "11.2.6",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/minimatch": {
"version": "10.2.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz",
"integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==",
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"deprecated": "Use your platform's native DOMException instead",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"license": "MIT",
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
"license": "MIT",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.0"
},
"node_modules/parse5": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
"license": "MIT",
"dependencies": {
"domhandler": "^5.0.3",
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-parser-stream": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
"license": "MIT",
"dependencies": {
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5/node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/path-scurry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz",
"integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==",
"license": "BlueOak-1.0.0",
"dependencies": {
"glob": "^13.0.3",
"package-json-from-dist": "^1.0.1"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"engines": {
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/showdown": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
"integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
"license": "MIT",
"dependencies": {
"commander": "^9.0.0"
},
"bin": {
"showdown": "bin/showdown.js"
},
"funding": {
"type": "individual",
"url": "https://www.paypal.me/tiviesantos"
}
},
"node_modules/undici": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz",
"integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/whatwg-encoding": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
"license": "MIT",
"dependencies": {
"iconv-lite": "0.6.3"
},
"engines": {
"node": ">=18"
}
},
"node_modules/whatwg-mimetype": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
"license": "MIT",
"engines": {
"node": ">=18"
}
}
}
}

View File

@@ -1,30 +0,0 @@
{
"name": "awesome-docker-website",
"version": "1.0.0",
"description": "A curated list of Docker resources and projects Inspired by @sindresorhus and improved by amazing contributors",
"main": "build.js",
"scripts": {
"build": "rimraf ./dist/ && node build.js",
"test-pr": "node tests/pull_request.mjs",
"test": "node tests/test_all.mjs",
"health-check": "node tests/health_check.mjs"
},
"repository": {
"type": "git",
"url": "git+https://github.com/veggiemonk/awesome-docker.git"
},
"author": "Julien Bisconti <julien.bisconti at hotmail dot com>",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/veggiemonk/awesome-docker/issues"
},
"homepage": "https://github.com/veggiemonk/awesome-docker#readme",
"dependencies": {
"cheerio": "1.2.0",
"draftlog": "1.0.13",
"fs-extra": "11.3.3",
"node-fetch": "3.3.2",
"rimraf": "6.1.3",
"showdown": "^2.1.0"
}
}

View File

@@ -1,108 +0,0 @@
import fetch from 'node-fetch';
import { isRedirect } from 'node-fetch';
import {readFileSync} from 'fs';
const LINKS_OPTIONS = {
redirect: 'manual',
headers: {
'Content-Type': 'application/json',
'user-agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
},
timeout: 60000, // 1m
signal: AbortSignal.timeout(60000),
};
const LOG = {
error: (...args) => console.error('❌ ERROR', args),
error_string: (...args) =>
console.error('❌ ERROR', JSON.stringify({ ...args }, null, ' ')),
debug: (...args) => {
if (process.env.DEBUG) console.log('>>> DEBUG: ', { ...args });
},
debug_string: (...args) => {
if (process.env.DEBUG)
console.log('>>> DEBUG: ', JSON.stringify({ ...args }, null, ' '));
},
};
const handleFailure = (error) => {
console.error(`${error.message}: ${error.stack}`, { error });
process.exit(1);
};
process.on('unhandledRejection', handleFailure);
const extract_all_links = (markdown) => {
// if you have a problem and you try to solve it with a regex,
// now you have two problems
// TODO: replace this mess with a mardown parser ?
const re = /(((https:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w\-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/@\-\\\w]*))?)/g;
return markdown.match(re);
};
const find_duplicates = (arr) => {
const hm = {};
const dup = [];
arr.forEach((e) => {
if (hm[e]) dup.push(e);
else hm[e] = true;
});
return dup;
};
const partition = (arr, func) => {
const ap = [[], []];
arr.forEach((e) => (func(e) ? ap[0].push(e) : ap[1].push(e)));
return ap;
};
async function fetch_link(url) {
try {
const { headers, ok, status, statusText } = await fetch(url, LINKS_OPTIONS);
const redirect = isRedirect(status) ? { redirect: { src: url, dst: headers.get("location") } } : {};
return [url, { ok, status: statusText, ...redirect }];
} catch (error) {
return [url, { ok: false, status: error.message }];
}
}
async function batch_fetch({ arr, get, post_filter_func, BATCH_SIZE = 8 }) {
const result = [];
/* eslint-disable no-await-in-loop */
for (let i = 0; i < arr.length; i += BATCH_SIZE) {
const batch = arr.slice(i, i + BATCH_SIZE);
LOG.debug_string({ batch });
let res = await Promise.all(batch.map(get));
console.log(`batch fetched...${i + BATCH_SIZE}`);
res = post_filter_func ? res.filter(post_filter_func) : res;
LOG.debug_string({ res });
result.push(...res);
}
return result;
}
const data = readFileSync('./tests/exclude_in_test.json')
const exclude = JSON.parse(data)
const exclude_length = exclude.length;
const exclude_from_list = (link) => {
let is_excluded = false;
for (let i = 0; i < exclude_length; i += 1) {
if (link.startsWith(exclude[i])) {
is_excluded = true;
break;
}
}
return is_excluded;
};
export default {
LOG,
handleFailure,
extract_all_links,
find_duplicates,
partition,
fetch_link,
batch_fetch,
exclude_from_list,
};

View File

@@ -1,17 +0,0 @@
[
"https://vimeo.com",
"https://travis-ci.org/veggiemonk/awesome-docker.svg",
"https://github.com/apps/",
"https://twitter.com",
"https://www.meetup.com/",
"https://cycle.io/",
"https://www.manning.com/",
"https://deepfence.io",
"https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg",
"https://www.se-radio.net/2017/05/se-radio-episode-290-diogo-monica-on-docker-security",
"https://www.reddit.com/r/docker/",
"https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615",
"https://www.youtube.com/playlist",
"https://www.aquasec.com",
"https://cloudsmith.com"
]

View File

@@ -1,206 +0,0 @@
import fs from 'fs-extra';
import fetch from 'node-fetch';
import helper from './common.mjs';
const README = 'README.md';
const GITHUB_GQL_API = 'https://api.github.com/graphql';
const TOKEN = process.env.GITHUB_TOKEN || '';
if (!TOKEN) {
console.error('GITHUB_TOKEN environment variable is required');
process.exit(1);
}
const Authorization = `token ${TOKEN}`;
const LOG = {
info: (...args) => console.log(' ', ...args),
warn: (...args) => console.warn('⚠️ ', ...args),
error: (...args) => console.error('❌', ...args),
};
// Extract GitHub repos from links
const extract_repos = (arr) =>
arr
.map((e) => e.substr('https://github.com/'.length).split('/'))
.filter((r) => r.length === 2 && r[1] !== '');
// Generate GraphQL query to check repo health
const generate_health_query = (repos) => {
const repoQueries = repos.map(([owner, name]) => {
const safeName = `repo_${owner.replace(/(-|\.)/g, '_')}_${name.replace(/(-|\.)/g, '_')}`;
return `${safeName}: repository(owner: "${owner}", name:"${name}"){
nameWithOwner
isArchived
pushedAt
createdAt
stargazerCount
forkCount
isDisabled
isFork
isLocked
isPrivate
}`;
}).join('\n');
return `query REPO_HEALTH { ${repoQueries} }`;
};
// Batch repos into smaller chunks for GraphQL
function* batchRepos(repos, size = 50) {
for (let i = 0; i < repos.length; i += size) {
yield repos.slice(i, i + size);
}
}
async function checkRepoHealth(repos) {
const results = {
archived: [],
stale: [], // No commits in 2+ years
inactive: [], // No commits in 1-2 years
healthy: [],
disabled: [],
total: repos.length,
};
const twoYearsAgo = new Date();
twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2);
const oneYearAgo = new Date();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
LOG.info(`Checking health of ${repos.length} repositories...`);
for (const batch of batchRepos(repos)) {
const query = generate_health_query(batch);
const options = {
method: 'POST',
headers: {
Authorization,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query }),
};
try {
const response = await fetch(GITHUB_GQL_API, options);
const data = await response.json();
if (data.errors) {
LOG.error('GraphQL errors:', data.errors);
continue;
}
for (const [key, repo] of Object.entries(data.data)) {
if (!repo) continue;
const pushedAt = new Date(repo.pushedAt);
const repoInfo = {
name: repo.nameWithOwner,
pushedAt: repo.pushedAt,
stars: repo.stargazerCount,
url: `https://github.com/${repo.nameWithOwner}`,
};
if (repo.isArchived) {
results.archived.push(repoInfo);
} else if (repo.isDisabled) {
results.disabled.push(repoInfo);
} else if (pushedAt < twoYearsAgo) {
results.stale.push(repoInfo);
} else if (pushedAt < oneYearAgo) {
results.inactive.push(repoInfo);
} else {
results.healthy.push(repoInfo);
}
}
} catch (error) {
LOG.error('Batch fetch error:', error.message);
}
// Rate limiting - wait a bit between batches
await new Promise(resolve => setTimeout(resolve, 1000));
}
return results;
}
function generateReport(results) {
const report = [];
report.push('# 🏥 Awesome Docker - Health Check Report\n');
report.push(`**Generated:** ${new Date().toISOString()}\n`);
report.push(`**Total Repositories:** ${results.total}\n`);
report.push('\n## 📊 Summary\n');
report.push(`- ✅ Healthy (updated in last year): ${results.healthy.length}`);
report.push(`- ⚠️ Inactive (1-2 years): ${results.inactive.length}`);
report.push(`- 🪦 Stale (2+ years): ${results.stale.length}`);
report.push(`- 📦 Archived: ${results.archived.length}`);
report.push(`- 🚫 Disabled: ${results.disabled.length}\n`);
if (results.archived.length > 0) {
report.push('\n## 📦 Archived Repositories (Should mark as :skull:)\n');
results.archived.forEach(repo => {
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
});
}
if (results.stale.length > 0) {
report.push('\n## 🪦 Stale Repositories (No activity in 2+ years)\n');
results.stale.slice(0, 50).forEach(repo => {
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
});
if (results.stale.length > 50) {
report.push(`\n... and ${results.stale.length - 50} more`);
}
}
if (results.inactive.length > 0) {
report.push('\n## ⚠️ Inactive Repositories (No activity in 1-2 years)\n');
report.push('_These may still be stable/complete projects - review individually_\n');
results.inactive.slice(0, 30).forEach(repo => {
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
});
if (results.inactive.length > 30) {
report.push(`\n... and ${results.inactive.length - 30} more`);
}
}
return report.join('\n');
}
async function main() {
const markdown = await fs.readFile(README, 'utf8');
let links = helper.extract_all_links(markdown);
const github_links = links.filter(link =>
link.startsWith('https://github.com') &&
!helper.exclude_from_list(link) &&
!link.includes('/issues') &&
!link.includes('/pull') &&
!link.includes('/wiki') &&
!link.includes('#')
);
const repos = extract_repos(github_links);
const results = await checkRepoHealth(repos);
const report = generateReport(results);
// Save report
await fs.writeFile('HEALTH_REPORT.md', report);
LOG.info('Health report saved to HEALTH_REPORT.md');
// Also print summary to console
console.log('\n' + report);
// Exit with error if there are actionable items
if (results.archived.length > 0 || results.stale.length > 10) {
LOG.warn(`Found ${results.archived.length} archived and ${results.stale.length} stale repos`);
process.exit(1);
}
}
console.log('Starting health check...');
main();

View File

@@ -1,69 +0,0 @@
import fs from 'fs-extra';
import helper from './common.mjs';
console.log({
DEBUG: process.env.DEBUG || false,
});
const README = 'README.md';
async function main() {
const has_error = {
show: false,
duplicates: '',
other_links_error: '',
};
const markdown = await fs.readFile(README, 'utf8');
let links = helper.extract_all_links(markdown);
links = links.filter((l) => !helper.exclude_from_list(l)); // exclude websites
helper.LOG.debug_string({ links });
console.log(`total links to check ${links.length}`);
console.log('checking for duplicates links...');
const duplicates = helper.find_duplicates(links);
if (duplicates.length > 0) {
has_error.show = true;
has_error.duplicates = duplicates;
}
helper.LOG.debug_string({ duplicates });
const [github_links, external_links] = helper.partition(links, (link) =>
link.startsWith('https://github.com'),
);
console.log(`checking ${external_links.length} external links...`);
const external_links_error = await helper.batch_fetch({
arr: external_links,
get: helper.fetch_link,
post_filter_func: (x) => !x[1].ok,
BATCH_SIZE: 8,
});
if (external_links_error.length > 0) {
has_error.show = true;
has_error.other_links_error = external_links_error;
}
console.log(`checking ${github_links.length} GitHub repositories...`);
console.log(
`skipping GitHub repository check. Run "npm run test" to execute them manually.`,
);
console.log({
TEST_PASSED: !has_error.show,
EXTERNAL_LINKS: external_links.length,
});
if (has_error.show) {
helper.LOG.error_string(has_error);
process.exit(1);
}
}
console.log('starting...');
main().catch((error) => {
console.error('Fatal error:', error);
process.exit(1);
});

View File

@@ -1,127 +0,0 @@
import fs from 'fs-extra';
import fetch from 'node-fetch';
import helper from './common.mjs';
function envvar_undefined(variable_name) {
throw new Error(`${variable_name} must be defined`);
}
console.log({
DEBUG: process.env.DEBUG || false,
});
const README = 'README.md';
const GITHUB_GQL_API = 'https://api.github.com/graphql';
const TOKEN = process.env.GITHUB_TOKEN || envvar_undefined('GITHUB_TOKEN');
const Authorization = `token ${TOKEN}`;
const make_GQL_options = (query) => ({
method: 'POST',
headers: {
Authorization,
'Content-Type': 'application/json',
'user-agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
},
body: JSON.stringify({ query }),
});
const extract_repos = (arr) =>
arr
.map((e) => e.substr('https://github.com/'.length).split('/'))
.filter((r) => r.length === 2 && r[1] !== '');
const generate_GQL_query = (arr) =>
`query AWESOME_REPOS{ ${arr
.map(
([owner, name]) =>
`repo_${owner.replace(/(-|\.)/g, '_')}_${name.replace(
/(-|\.)/g,
'_',
)}: repository(owner: "${owner}", name:"${name}"){ nameWithOwner isArchived } `,
)
.join('')} }`;
async function main() {
const has_error = {
show: false,
duplicates: '',
other_links_error: '',
github_repos: '',
};
const markdown = await fs.readFile(README, 'utf8');
let links = helper.extract_all_links(markdown);
links = links.filter((l) => !helper.exclude_from_list(l)); // exclude websites
helper.LOG.debug_string({ links });
console.log(`total links to check ${links.length}`);
console.log('checking for duplicates links...');
const duplicates = helper.find_duplicates(links);
if (duplicates.length > 0) {
has_error.show = true;
has_error.duplicates = duplicates;
}
helper.LOG.debug_string({ duplicates });
const [github_links, external_links] = helper.partition(links, (link) =>
link.startsWith('https://github.com'),
);
console.log(`checking ${external_links.length} external links...`);
const external_links_error = await helper.batch_fetch({
arr: external_links,
get: helper.fetch_link,
post_filter_func: (x) => !x[1].ok,
BATCH_SIZE: 8,
});
if (external_links_error.length > 0) {
has_error.show = true;
has_error.other_links_error = external_links_error;
}
console.log(`checking ${github_links.length} GitHub repositories...`);
const repos = extract_repos(github_links);
const query = generate_GQL_query(repos);
const options = make_GQL_options(query);
const gql_response = await fetch(GITHUB_GQL_API, options).then((r) =>
r.json(),
);
if (gql_response.errors) {
has_error.show = true;
has_error.github_repos = gql_response.errors;
}
// Check for archived repositories
console.log('checking for archived repositories...');
const archived_repos = [];
if (gql_response.data) {
for (const [key, repo] of Object.entries(gql_response.data)) {
if (repo && repo.isArchived) {
archived_repos.push(repo.nameWithOwner);
}
}
}
if (archived_repos.length > 0) {
console.warn(`⚠️ Found ${archived_repos.length} archived repositories that should be marked with :skull:`);
console.warn('Archived repos:', archived_repos);
// Don't fail the build, just warn
}
console.log({
TEST_PASSED: has_error.show,
GITHUB_REPOSITORY: github_links.length,
EXTERNAL_LINKS: external_links.length,
});
if (has_error.show) {
helper.LOG.error_string(has_error);
process.exit(1);
}
}
console.log('starting...');
main();

View File

@@ -1,229 +0,0 @@
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Cache-control" content="public" />
<meta charset="UTF-8" />
<title>Awesome-docker</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#5DBCD2" />
<meta
name="description"
content="A curated list of Docker resources and projects."
/>
<meta
name="keywords"
content="free and open-source open source projects for docker moby kubernetes linux awesome awesome-list container tools dockerfile list moby docker-container docker-image docker-environment docker-deployment docker-swarm docker-api docker-monitoring docker-machine docker-security docker-registry"
/>
<meta
name="google-site-verification"
content="_yiugvz0gCtfsBLyLl1LnkALXb6D4ofiwCyV1XOlYBM"
/>
<link rel="icon" type="image/png" href="favicon.png" />
<style>
* {
box-sizing: border-box;
}
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
body {
padding: 0;
margin: 0;
font-family: Open Sans, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
color: #606c71;
}
section {
display: block;
}
a {
background-color: transparent;
color: #5dbcd2;
text-decoration: none;
}
strong {
font-weight: 700;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
img {
border: 0;
}
svg:not(:root) {
overflow: hidden;
}
.btn {
display: inline-block;
margin-bottom: 1rem;
color: hsla(0, 0%, 100%, 0.7);
background-color: hsla(0, 0%, 100%, 0.08);
border: 1px solid hsla(0, 0%, 100%, 0.2);
border-radius: 0.3rem;
}
.page-header {
color: #fff;
text-align: center;
background-color: #5dbcd2;
background-image: linear-gradient(120deg, #155799, #5dbcd2);
}
.project-name {
margin-top: 0;
margin-bottom: 0.1rem;
}
.project-tagline {
margin-bottom: 2rem;
font-weight: 400;
opacity: 0.7;
}
.main-content {
word-wrap: break-word;
}
.main-content :first-child {
margin-top: 0;
}
.main-content h1,
.main-content h4 {
margin-top: 2rem;
margin-bottom: 1rem;
font-weight: 400;
color: #5dbcd2;
}
.main-content p {
margin-bottom: 1em;
}
.main-content blockquote {
padding: 0 1rem;
margin-left: 0;
color: #819198;
border-left: 0.3rem solid #dce6f0;
}
.main-content blockquote > :first-child {
margin-top: 0;
}
.main-content blockquote > :last-child {
margin-bottom: 0;
}
.main-content img {
max-width: 100%;
}
@media screen and (min-width: 64em) {
.btn {
padding: 0.75rem 1rem;
}
.page-header {
padding: 5rem 6rem;
}
.project-name {
font-size: 3.25rem;
}
.project-tagline {
font-size: 1.25rem;
}
.main-content {
max-width: 64rem;
padding: 2rem 6rem;
margin: 0 auto;
font-size: 1.1rem;
}
}
@media screen and (min-width: 42em) and (max-width: 64em) {
.btn {
padding: 0.6rem 0.9rem;
font-size: 0.9rem;
}
.page-header {
padding: 3rem 4rem;
}
.project-name {
font-size: 2.25rem;
}
.project-tagline {
font-size: 1.15rem;
}
.main-content {
padding: 2rem 4rem;
font-size: 1.1rem;
}
}
@media screen and (max-width: 42em) {
.btn {
display: block;
width: 100%;
padding: 0.75rem;
font-size: 0.9rem;
}
.page-header {
padding: 2rem 1rem;
}
.project-name {
font-size: 1.75rem;
}
.project-tagline {
font-size: 1rem;
}
.main-content {
padding: 2rem 1rem;
font-size: 1rem;
}
}
</style>
</head>
<body>
<section class="page-header">
<h1 class="project-name">Awesome-docker</h1>
<h2 class="project-tagline">
A curated list of Docker resources and projects
</h2>
<a href="https://github.com/veggiemonk/awesome-docker" class="btn"
>View on GitHub</a
>
<br />
<!-- Place this tag where you want the button to render. -->
<a
class="github-button"
href="https://github.com/veggiemonk/awesome-docker#readme"
data-icon="octicon-star"
data-size="large"
data-count-href="/veggiemonk/awesome-docker/stargazers"
data-show-count="true"
data-count-aria-label="# stargazers on GitHub"
aria-label="Star veggiemonk/awesome-docker on GitHub"
>Star</a
>
</section>
<section id="md" class="main-content"></section>
<!--<script src="index.js"></script> -->
<!--Place this tag in your head or just before your close body tag. -->
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>