Compare commits

..
138 Commits
Author SHA1 Message Date
yeasy 48e86b7bec fix(appendix): correct .dockerignore typo in image-slimming FAQ 2026-05-28 11:38:28 -07:00
yeasy 9230b49b6b fix(04): replace deprecated openjdk base image with eclipse-temurin and fix 地 typo 2026-05-28 11:38:28 -07:00
yeasy 2185211041 fix(07): note FROM uses pre-FROM ARG, not ENV, for variable substitution 2026-05-28 11:38:27 -07:00
yeasy f09e800020 fix(content): harden copy-paste safety examples 2026-05-27 18:17:24 -07:00
yeasy 3a9ee19d22 docs(content): refresh Kubernetes helper versions 2026-05-26 00:45:20 -07:00
yeasy ea26f96297 fix(content): remove demo registry credential 2026-05-25 01:13:10 -07:00
yeasy 30f26d9195 chore(17): remove obsolete coreos_README.md leftover
This 7-line file was never in SUMMARY.md and its content is a strict
subset of the current 17.1_coreos_intro.md. It looks like a draft
that survived the chapter rename to NN.M_topic.md convention.
Removed so the directory only contains files reachable from the ToC.
2026-05-24 12:56:55 -07:00
yeasy fb361bb1f0 fix(appendix): use H2 for 附录七 to match sibling appendix files
The other appendix entries (附录四 best_practices, 附录五 debug,
附录六 resources, 附录八 learning_roadmap) all use H2. glossary.md
was the lone H1, which broke the table-of-contents nesting in
GitBook. Demoted to H2 to align.
2026-05-24 01:03:34 -07:00
yeasy 036f0486db fix(content): tighten safety guidance 2026-05-24 00:57:03 -07:00
yeasy 28c23d003e fix(content): harden Docker examples 2026-05-23 21:28:59 -07:00
yeasy 6a55219310 fix(11.3): use COPY (not ADD) in Flask/Redis intro Dockerfile
§7.3 of this book explicitly recommends COPY over ADD for simple
file copies ("在大多数情况下,你应该使用 COPY,而不是 ADD"). The intro
Compose example showed ADD without needing tar extraction or URL
download, contradicting the canonical guidance. Switched to COPY
so the first Dockerfile readers see matches the rule the book
teaches a few chapters later.
2026-05-23 21:27:01 -07:00
yeasy 8f4d88e350 docs: refine Buildx guidance 2026-05-22 07:58:38 -07:00
yeasy 7f83abc53b fix(content): correct Docker Engine 29.0.0 date and align login-action version
Docker Engine 29.0.0 was released 2025-11-10 per docs.docker.com release
notes, not 2025-11-11 (off by one day). Also bring docker/login-action
reference in 18.6 up to v4 to match the 21.2 example (v4 has been current
since 2026-03-04).
2026-05-22 03:19:37 -07:00
yeasy ec0fa15835 docs(content): harden Kubernetes and supply-chain examples 2026-05-22 00:53:38 -07:00
yeasy 8b9e4518c8 docs(content): add Mac alternatives, K8s transition guide, CI/CD registry push example
- Add OrbStack/Colima comparison table to Mac install chapter (3.7.4)
- Add Docker→K8s concept mapping paragraph to Ch13 intro
- Add KubeKey/RKE2 deployment tool notes to Ch14
- Add production image checklist to Dockerfile chapter summary
- Add build-and-push-to-registry workflow example to GitHub Actions section
- Expand Ch18 security summary with dimension table
2026-05-21 21:33:58 -07:00
yeasy dae0af9ae7 fix(content): DCT expiry tense + bundle buildx --check additions 2026-05-21 20:49:42 -07:00
yeasy 10b09f35eb fix(content): update DCT expiry tense and prefer named multistage COPY 2026-05-21 20:49:19 -07:00
yeasy e17bef96d2 docs(content): update Compose and safety guidance 2026-05-21 20:13:39 -07:00
yeasy a3567ff6a0 docs: use digest-based cosign signing 2026-05-21 19:14:33 -07:00
yeasy 9ef842ebb3 docs: update distro caveats 2026-05-21 18:25:54 -07:00
yeasy 2e625a3cdf fix(content): harden install and security guidance 2026-05-21 01:23:44 -07:00
yeasy d47afa7e75 docs: harden Docker practice security examples 2026-05-20 15:58:46 -07:00
yeasy 1b651e5f8c fix(content): refresh Docker and Kubernetes guidance 2026-05-20 09:16:36 -07:00
yeasy e91fe87822 fix(content): harden kubernetes and signing examples 2026-05-20 08:49:28 -07:00
yeasy bb97d5a46a fix(13.2): remove incorrect "Node lifecycle" (Pending/Running/Terminated)
The "节点周期" subsection listed `Pending`/`Running`/`Terminated` as
node phases, but those are **Pod** phases (pod.status.phase). Kubernetes
nodes use Conditions (Ready/MemoryPressure/DiskPressure/PIDPressure)
not phases; there is no "Terminated" node state. Removed the
misleading subsection and clarified the surviving "节点状态" section
with an explicit note distinguishing Pod phases from node conditions,
and added the eviction behavior when a node becomes Unknown.
2026-05-20 08:37:43 -07:00
yeasy 1f69884c8f Fix Chinese quote formatting 2026-05-20 08:02:42 -07:00
yeasy 4f92b3aa70 fix(19.3): add security trade-off note for cAdvisor privileged: true
The cAdvisor compose examples in 19.3.3 use `privileged: true`, which
contradicts the minimum-privilege / cap_drop=all guidance in chapter 18.
Add an explicit trade-off note before the first cAdvisor snippet
explaining the inconsistency and pointing to 18.4 for capability-based
hardening alternatives (cap_add: [SYS_ADMIN] + device_cgroup_rules
instead of full privileged mode).

This addresses the Round 1 review finding about pedagogical conflict
between the monitoring and security chapters.
2026-05-20 00:18:37 -07:00
yeasy 58504e9316 fix(review-fixes): surgical content corrections from web-verified library deep review 2026-05-19 19:45:02 -07:00
yeasy 4075330dba Fix architecture mermaid and MySQL version 2026-05-19 18:43:11 -07:00
yeasy e6bf228066 docs: update image signing and login guidance 2026-05-19 15:29:26 -07:00
yeasy 1b15b65bc5 Clarify AKS pricing tiers 2026-05-19 08:20:49 -07:00
yeasy 26da467052 docs: link deployment engineering guide 2026-05-18 22:37:02 -07:00
yeasy 7abaff237a test: add project rules check 2026-05-18 22:37:02 -07:00
yeasy 1c4e0538d8 Fix CI PDF order 2026-05-18 08:06:51 -07:00
yeasy 0b8f6e9b60 Refresh metadata and workflows 2026-05-18 07:38:58 -07:00
yeasy 5650315cb4 Remove demo TLS key 2026-05-17 20:28:01 -07:00
yeasy e21794ebde Fix stale image facts 2026-05-17 20:28:01 -07:00
yeasy 78ca8f6d19 Refresh Docker ecosystem 2026-05-16 14:09:31 -07:00
yeasy 1ba904a9ff Fix markdown format issues 2026-05-15 09:58:19 -07:00
yeasy 705d162f05 Fix image docs typos 2026-05-15 09:16:33 -07:00
yeasy 92be0050fd Fix docker debug note, Go modules, Compose V2, CentOS Quay migration 2026-05-15 08:11:38 +00:00
yeasy a20d1b19c4 Fix 3 broken external links in appendix 2026-05-14 02:27:32 +00:00
yeasy 9f481e88ca Fix go mod, Docker Hub rate limit, Compose verbose, docker debug, htpasswd security 2026-05-13 08:30:20 +00:00
yeasy ef5a97fa09 Fix VirtioFS note, cri-socket, componentstatuses, ES version and typo 2026-05-13 08:26:24 +00:00
yeasy 3c5c5911b0 Fix nginx version, IPVS removal, cgroups v2 and Redis config 2026-05-13 08:22:20 +00:00
yeasy e2742313f2 Fix typo in Fedora install guide 2026-05-08 21:20:03 +00:00
yeasy 2cea196860 Replace chromium-browser snap with setup-chrome 2026-05-08 04:19:18 +00:00
yeasy 13fc8b34f0 Explain why docker run overrides crashing CMD 2026-05-08 04:13:09 +00:00
yeasy 29742c8f74 Clarify interactive debug uses new container 2026-05-08 04:10:38 +00:00
yeasy 7cae0b6bb3 Fix deprecated TLS protocols and mongo CLI 2026-05-03 15:20:57 +00:00
yeasy 10381deee4 Add healthcheck to Rails Compose example 2026-05-03 05:23:12 +00:00
yeasy 625d209fa8 Fix Docker Engine 29 release date and Rootless mode history 2026-05-02 22:26:19 +00:00
yeasy b148d9efa9 Update nginx to 1.30 stable, add IPVS deprecation note 2026-05-02 18:18:48 +00:00
yeasy 4cb91a75f3 Update etcd cluster demo to v3.5.29, Node to 22 LTS 2026-05-02 16:16:59 +00:00
yeasy bf3107b775 Update MySQL 8.0 to 8.4 LTS, fix Trivy tag count 2026-05-02 15:22:58 +00:00
yeasy 7e3f90b522 Update Node base images to 22 LTS 2026-05-01 10:24:43 +00:00
yeasy e6527ae769 Fix Docker Engine 29 release date 2026-05-01 07:17:56 +00:00
yeasy 9c378b1ef9 Use straight quotes in kubectl annotate examples 2026-04-30 19:18:49 +00:00
yeasy 340c8c9e61 Document ipvlan driver and update etcdctl v3 options 2026-04-30 09:20:59 +00:00
yeasy 89c2690a62 Correct Docker Engine 29 release date 2026-04-29 10:24:06 +00:00
yeasy c554799b08 Restore nginx 1.30 stable references 2026-04-29 07:53:31 +00:00
yeasy 99c56217f5 Fix Chinese curly quote direction 2026-04-29 05:21:02 +00:00
yeasy 9c98e35c62 Fix nginx version to 1.28 stable 2026-04-28 16:15:39 +00:00
yeasy 0e0afbd4d3 Update nginx to 1.30 and version references 2026-04-28 14:15:13 +00:00
yeasy 30f0115cb9 Update nginx, OS, Buildx, etcd and K8s refs 2026-04-28 12:22:57 +00:00
yeasy 62f48c1417 Update nginx, Debian, Ubuntu, Fedora, Docker versions 2026-04-28 11:14:55 +00:00
yeasy fab4e41587 Update OS examples to Debian 13, Ubuntu 26.04, Fedora 43 2026-04-28 09:24:17 +00:00
yeasy 229aec2f1e Update Kubernetes node status conditions terminology 2026-04-28 09:24:17 +00:00
yeasy 8ebf284f9e Update nginx references from 1.25 to 1.30 2026-04-28 09:24:03 +00:00
yeasy a89f7285c7 Fix typos and update Docker Hub limits and versions 2026-04-28 09:15:40 +00:00
yeasy 15c7fe1dc2 Update Docker Hub rate limits and version refs 2026-04-28 08:20:21 +00:00
yeasy 4d1e323faf Fix seccomp typo, postgres path and DCA exam details 2026-04-28 04:21:10 +00:00
yeasy 16203c5018 Complete Dockerfile instruction reference list 2026-04-27 23:17:39 +00:00
yeasy 3d3befa16a Add ipvlan driver and update EKS pricing 2026-04-27 22:45:17 +00:00
yeasy 09fd556c18 Refresh image CLI docs 2026-04-27 09:15:19 -07:00
yeasy 37e376d578 Fix mongosh, DCA price, compose healthcheck and cleanup 2026-04-27 14:17:57 +00:00
yeasy 04fd53ea3c Update Docker image tags and etcd commands 2026-04-27 11:18:08 +00:00
yeasy b1cd2f0878 Fix Docker Hub rate limits and etcdctl API version 2026-04-27 05:13:02 +00:00
yeasy e416a1be7e Fix Docker Hub rate limits, DCT timeline, image tags, etcd and Alertmanager 2026-04-27 01:15:52 +00:00
yeasy e406ed9185 Update Gateway API docs and image security practices 2026-04-26 00:18:39 +00:00
yeasy c36c420c7e Add nftables support and Time namespace documentation 2026-04-26 00:18:39 +00:00
yeasy 72513eb673 更新 Namespace/Gateway API/nftables/DCT 退役时间线
- ch12: 添加 TIME namespace (Linux 5.6+),内核 namespace 类型从 7 更新为 8
- ch12: 补充 Docker Engine v29.x 实���性 nftables 支持
- ch13: Ingress-NGINX 退役通知,添加 Gateway API 推荐方案和示例
- ch13: 添加 Pod Security Standards 章节(替代已移除的 PSP)
- ch18: 补充 DCT 退役时间线(2028-03-31 完全移除)和迁移建议
2026-04-26 00:12:59 +00:00
yeasy 8ea52620cc Update Prometheus to v3.11.2, fix etcdctl version 2026-04-25 22:39:33 +00:00
yeasy 22dd236122 Fix network IPs, compose healthcheck, update GH Actions versions 2026-04-25 21:11:50 +00:00
yeasy 98f4f7b1e5 Add official doc links to install guides 2026-04-25 21:11:50 +00:00
yeasy 87bb4b2ceb Add version notes and image tag best practices 2026-04-25 21:11:50 +00:00
yeasy dad26ccb28 Update docker0 default subnet to 172.17.0.0/16 2026-04-25 21:03:39 +00:00
yeasy 84a801f3ac Document depends_on condition and healthcheck 2026-04-25 21:03:39 +00:00
yeasy 420a5776ce Accurate cgroup v2 description, update Actions versions 2026-04-25 20:42:35 +00:00
yeasy b2839f735c Fix broken code block in laravel multistage Dockerfile 2026-04-25 20:42:18 +00:00
yeasy 98e299a38e Add version notes and official doc links 2026-04-25 15:58:42 +00:00
Baohua Yang aa204fb454 chore: lint cleanup and version corrections
- Accept benign linter changes (version notes, explicit tags, formatting)
- Fix incorrect version downgrades introduced by linter:
  - golang:1.22→1.26 (restored)
  - rust:1.82→1.95 (restored)
- 23 files updated
2026-04-25 15:58:27 +00:00
yeasy 1e9cdeea3f Update Grafana to v13, add version notes 2026-04-25 15:50:13 +00:00
yeasy 515ba9f64a Add blank lines before lists per CommonMark 2026-04-25 15:13:27 +00:00
yeasy 9abc1cbb69 Update Kubernetes to v1.36, build-push-action to v7 2026-04-25 15:10:51 +00:00
yeasy 839a63f5af Update versions and fix formatting issues 2026-04-25 15:10:43 +00:00
yeasy 20a3479f8a Add Docker Scout, remove deprecated type_name 2026-04-25 15:02:24 +00:00
yeasy 52329fee5a Update etcd to v3.5.29 2026-04-25 15:00:47 +00:00
yeasy 8093b198ce Update node-exporter to v1.11.1, fcct to butane 2026-04-25 14:58:40 +00:00
yeasy 77a537df54 Add blank lines before lists per CommonMark 2026-04-25 14:57:09 +00:00
yeasy e414d9475b Update containerd config path for 2.x 2026-04-25 14:22:55 +00:00
yeasy 037591e5af Update content and fix issues 2026-04-25 02:14:58 +00:00
yeasy 94f74fc86e Clarify image build semantics 2026-04-24 10:51:49 -07:00
yeasy 4b44d64cd8 Fix straight quotes to curly quotes in mirror doc 2026-04-24 13:24:52 +00:00
yeasy 49a85c802e Fix Ubuntu codenames and containerd LTS description 2026-04-24 03:16:05 +00:00
yeasy 2a7f7d9a3d Fix apt cache cleanup path in Dockerfile example 2026-04-23 13:16:21 -07:00
yeasy 544ede8498 Pin Prometheus and Grafana image versions 2026-04-22 12:24:31 -07:00
yeasy 54a9a6e55b Add runC CVEs and AuthZ plugin guidance 2026-04-22 12:24:31 -07:00
yeasy 27617ea619 Add section numbers to ecosystem headings 2026-04-22 12:24:30 -07:00
yeasy 69fc2234d0 Update nginx version and K8s dashboard date 2026-04-22 12:24:30 -07:00
yeasy ac92e6c536 Fix Debian dates and FAQ template syntax 2026-04-22 08:43:48 -07:00
yeasy 1fc64ab875 Refresh install guidance
# Conflicts:
#	03_install/3.1_ubuntu.md
#	03_install/3.2_debian.md
#	03_install/3.3_fedora.md
#	03_install/3.9_mirror.md
2026-04-22 08:24:38 -07:00
yeasy c9c72618c3 Refresh k8s docker versions and references 2026-04-21 20:57:33 -07:00
yeasy 4b93651989 Refine Docker concepts 2026-04-21 14:39:41 -07:00
yeasy b3d1508310 Add new content and update versions 2026-04-19 22:35:33 -07:00
yeasy 1d780f70c5 Drop legacy plugins 2026-04-19 20:14:36 -07:00
yeasy ff48ac79ee Clarify intro chapter 2026-04-18 20:25:29 -07:00
yeasy 077e55f494 Update software versions and fix security refs 2026-04-18 19:04:14 -07:00
yeasy 1bed644e5e Fix mermaid syntax and update K8s taint labels 2026-04-18 15:17:56 -07:00
yeasy da5867c921 Update Kind v0.31.0 and Flannel v0.28.2 2026-04-18 13:31:43 -07:00
yeasy 407d508590 Restructure README with badges and cover 2026-04-17 21:51:38 -07:00
yeasy 6fcb74bccc Add Ubuntu 20.04 EOL exact date 2026-04-17 21:19:32 -07:00
yeasy d81405a807 Update versions and fix stale data 2026-04-17 21:17:12 -07:00
github-actions[bot]andGitHub 983e7c18c3 Merge pull request #564 from yeasy/dependabot/github_actions/dependencies-8fe05ed821
chore(deps): bump the dependencies group with 2 updates
2026-04-15 18:46:57 +00:00
dependabot[bot]andGitHub 9e194b9a74 chore(deps): bump the dependencies group with 2 updates
Bumps the dependencies group with 2 updates: [softprops/action-gh-release](https://github.com/softprops/action-gh-release) and [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata).


Updates `softprops/action-gh-release` from 2 to 3
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3)

Updates `dependabot/fetch-metadata` from 2 to 3
- [Release notes](https://github.com/dependabot/fetch-metadata/releases)
- [Commits](https://github.com/dependabot/fetch-metadata/compare/v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: dependabot/fetch-metadata
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-15 18:46:44 +00:00
yeasy 6b2ebd12ac Fix Chinese curly quotes in prose text 2026-04-14 20:29:35 -07:00
yeasy f86e3567e8 Fix figure caption punctuation and table formatting 2026-04-13 18:37:00 -07:00
yeasy 2dacddb999 Fix figure caption format 2026-04-09 09:02:44 -07:00
yeasy 422123dd70 Add section numbering and archive notice 2026-04-08 22:40:15 -07:00
yeasy adee45f7bc Fix bash comment style to single hash 2026-04-08 22:39:51 -07:00
yeasy 04b81a8c05 Fix mdpress port 4000 to 9000 2026-04-05 13:39:46 -07:00
yeasy e85ca7a11e Fix typo in offline install image alt text 2026-04-05 12:59:09 -07:00
yeasy 66905627b8 Remove time annotation in install docs 2026-04-05 12:58:42 -07:00
yeasy aec453b9bb Remove duplicate release-pdf workflow 2026-04-05 08:55:52 -07:00
yeasy 565b40ab0b Add release-pdf CI workflow for automated PDF builds 2026-04-05 08:29:11 -07:00
yeasy 50fe8ebbbb Replace defunct AtomHub mirror with docker.1ms.run 2026-04-05 08:16:08 -07:00
yeasy c84927c196 ci: add auto-release.yml, remove release-pdf.yml, limit CI trigger to master 2026-04-05 07:57:56 -07:00
Baohua Yang 2b0c00c5e5 Add recommended reading paths table to README 2026-04-04 22:31:23 -07:00
120 changed files with 930 additions and 482 deletions
+14 -7
View File
@@ -16,17 +16,24 @@ jobs:
- uses: actions/checkout@v6
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
- name: Install mdpress 0.7.10
env:
MDPRESS_VERSION: "0.7.10"
MDPRESS_SHA256: "17e53e455996940bbbce64c69c43b3fb543f1501e03b74cf0434074efebd2db4"
run: |
LATEST_TAG=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" https://api.github.com/repos/yeasy/mdpress/releases/latest | jq -r .tag_name)
VERSION="${LATEST_TAG#v}"
echo "Installing mdpress $VERSION"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/$LATEST_TAG/mdpress_${VERSION}_linux_amd64.tar.gz" -o /tmp/mdpress.tar.gz
tar xzf /tmp/mdpress.tar.gz -C /tmp mdpress
archive="/tmp/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"
echo "Installing mdpress ${MDPRESS_VERSION}"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" -o "$archive"
echo "${MDPRESS_SHA256} $archive" | sha256sum -c -
tar xzf "$archive" -C /tmp mdpress
sudo mv /tmp/mdpress /usr/local/bin/
mdpress --version
+18 -9
View File
@@ -16,23 +16,32 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Check project rules
run: python3 check_project_rules.py
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress 0.7.10
env:
MDPRESS_VERSION: "0.7.10"
MDPRESS_SHA256: "17e53e455996940bbbce64c69c43b3fb543f1501e03b74cf0434074efebd2db4"
run: |
LATEST_TAG=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" https://api.github.com/repos/yeasy/mdpress/releases/latest | jq -r .tag_name)
VERSION="${LATEST_TAG#v}"
echo "Installing mdpress $VERSION"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/$LATEST_TAG/mdpress_${VERSION}_linux_amd64.tar.gz" -o mdpress.tar.gz
tar xzf mdpress.tar.gz
archive="/tmp/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"
echo "Installing mdpress ${MDPRESS_VERSION}"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" -o "$archive"
echo "${MDPRESS_SHA256} $archive" | sha256sum -c -
tar xzf "$archive"
sudo mv mdpress /usr/local/bin/
mdpress --version
- name: Build site
run: mdpress build --format site
- name: Build PDF
run: mdpress build --format pdf --output docker_practice.pdf
- name: Build site
run: npm run build
- name: Upload PDF as artifact
uses: actions/upload-artifact@v7
with:
+25 -3
View File
@@ -4,6 +4,7 @@ on: pull_request
permissions:
contents: write
pull-requests: write
checks: read
jobs:
dependabot:
@@ -12,15 +13,36 @@ jobs:
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v3
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Approve a PR
- name: Confirm required checks are configured
if: >
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
contains(fromJSON('["version-update:semver-patch","version-update:semver-minor"]'), steps.metadata.outputs.update-type)
run: |
REQUIRED=$(gh api "repos/${GITHUB_REPOSITORY}/branches/${{ github.event.pull_request.base.ref }}/protection/required_status_checks" --jq '((.contexts // []) | length) + ((.checks // []) | length)' 2>/dev/null || echo 0)
if [ "$REQUIRED" -eq 0 ]; then
echo "No required status checks configured on the base branch; refusing Dependabot auto-merge."
exit 1
fi
env:
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Approve low-risk Dependabot PR
if: >
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
contains(fromJSON('["version-update:semver-patch","version-update:semver-minor"]'), steps.metadata.outputs.update-type)
run: gh pr review --approve "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Enable auto-merge for Dependabot PRs
- name: Enable auto-merge for low-risk Dependabot PRs
if: >
steps.metadata.outputs.package-ecosystem == 'github_actions' &&
contains(fromJSON('["version-update:semver-patch","version-update:semver-minor"]'), steps.metadata.outputs.update-type)
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
+14 -7
View File
@@ -23,17 +23,24 @@ jobs:
- uses: actions/checkout@v6
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
- name: Install mdpress 0.7.10
env:
MDPRESS_VERSION: "0.7.10"
MDPRESS_SHA256: "17e53e455996940bbbce64c69c43b3fb543f1501e03b74cf0434074efebd2db4"
run: |
LATEST_TAG=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" https://api.github.com/repos/yeasy/mdpress/releases/latest | jq -r .tag_name)
VERSION="${LATEST_TAG#v}"
echo "Installing mdpress $VERSION"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/$LATEST_TAG/mdpress_${VERSION}_linux_amd64.tar.gz" -o /tmp/mdpress.tar.gz
tar xzf /tmp/mdpress.tar.gz -C /tmp mdpress
archive="/tmp/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz"
echo "Installing mdpress ${MDPRESS_VERSION}"
curl -fsSL "https://github.com/yeasy/mdPress/releases/download/v${MDPRESS_VERSION}/mdpress_${MDPRESS_VERSION}_linux_amd64.tar.gz" -o "$archive"
echo "${MDPRESS_SHA256} $archive" | sha256sum -c -
tar xzf "$archive" -C /tmp mdpress
sudo mv /tmp/mdpress /usr/local/bin/
mdpress --version
+2
View File
@@ -13,6 +13,7 @@ node_modules/
package-lock.json
docker-compose.override.yml
06_repository/demo/auth/nginx.htpasswd
# Editor configs
.obsidian/
@@ -26,6 +27,7 @@ Docker -- *_site/
# Check scripts
check*.py
!check_project_rules.py
find*.py
fix*.py
format*.py
+1 -1
View File
@@ -172,7 +172,7 @@ registry.example.com/myproject/myapp:v1.2.3
## 简写(使用 Docker Hub
nginx:1.25
nginx:1.28
ubuntu:24.04
## 省略标签(默认使用 latest)
+11 -11
View File
@@ -1,6 +1,6 @@
## 2.3 仓库
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.25``mysql:8.0``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.28``mysql:8.4``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
Docker Registry 是镜像分发和管理的核心组件本节将介绍 Registry 的基本概念公共和私有服务的选择以及镜像的安全管理
@@ -25,8 +25,8 @@ flowchart TB
subgraph RepoNginx ["Repository(仓库): nginx"]
direction LR
N1(":latest (tag)")
N2(":1.25 (tag)")
N3(":1.24 (tag)")
N2(":1.28 (tag)")
N3(":1.26 (tag)")
N4(":alpine (tag)")
N5("...")
N1 ~~~ N2 ~~~ N3 ~~~ N4 ~~~ N5
@@ -50,7 +50,7 @@ flowchart TB
|------|------|------|
| **Registry** | 存储镜像的服务 | Docker Hubghcr.io |
| **Repository (仓库)** | 同一软件的镜像集合 | `nginx``mysql``mycompany/myapp` |
| **Tag (标签)** | 仓库内的版本标识 | `latest``1.25``alpine` |
| **Tag (标签)** | 仓库内的版本标识 | `latest``1.28``alpine` |
#### 镜像的完整名称
@@ -73,7 +73,7 @@ registry.example.com/mycompany/myapp:v1.2.3
## Docker Hub 官方镜像(省略 registry 和用户名)
nginx:1.25
nginx:1.28
ubuntu:24.04
## Docker Hub 用户镜像
@@ -131,7 +131,7 @@ Google 的 Container Registry 已废弃并完成下线,当前应优先使用 A
由于网络原因在国内直接访问 Docker Hub 可能会很慢可以配置 **镜像加速器** (Registry Mirror) 来加速下载配置示例如下
```json
```jsonc
// /etc/docker/daemon.json
{
"registry-mirrors": [
@@ -217,7 +217,7 @@ $ docker login registry.example.com # 登录其他 Registry
## 拉取镜像
$ docker pull nginx:1.25
$ docker pull nginx:1.28
## 标记镜像(准备推送)
@@ -255,15 +255,15 @@ someuser/myapp # ⚠️ 需要评估
#### 镜像签名
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证`Docker Content Trust (DCT)` 2025 8 8 开始停用官方 Docker 镜像已停止 DCT 签名2028 3 31 日将完全删除此功能不建议作为新项目方案
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证`Docker Content Trust (DCT)` 进入弃用阶段2025 8 8 起最早的 DCT 签名证书开始过期2025 9 30 日起不能在新 Registry 启用 DCT2028 3 31 日将完全删除此功能不建议作为新项目方案
> 注意Cosign 默认会把签名推送回镜像所在仓库请使用你有推送权限的镜像地址
```bash
## 准备一个你有写权限的镜像地址
$ export IMAGE=<你的仓库名>/nginx:1.27
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ export IMAGE=<你的仓库名>/nginx:1.28
$ docker pull nginx:1.28
$ docker tag nginx:1.28 $IMAGE
$ docker push $IMAGE
## 生成签名密钥(会生成 cosign.key / cosign.pub
+1 -1
View File
@@ -91,7 +91,7 @@ $ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin do
在真正执行前建议先用 `--dry-run` 预览脚本动作
```bash
$ curl -fsSL get.docker.com -o get-docker.sh
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# 若需要测试频道:
+1 -1
View File
@@ -81,7 +81,7 @@ $ sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin do
在真正执行前建议先用 `--dry-run` 预览脚本动作
```bash
$ curl -fsSL get.docker.com -o get-docker.sh
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# 若需要测试频道:
+2 -2
View File
@@ -39,7 +39,7 @@ $ sudo dnf remove docker \
### 3.3.2 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式便于后续的更和管理
使用 dnf 包管理器安装是推荐的方式便于后续的更和管理
执行以下命令安装依赖包
@@ -91,7 +91,7 @@ $ sudo dnf -y install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING>
在真正执行前建议先用 `--dry-run` 预览脚本动作
```bash
$ curl -fsSL get.docker.com -o get-docker.sh
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# 若需要测试频道:
+1 -1
View File
@@ -88,7 +88,7 @@ Docker 官方提醒:如果主机使用 `ufw` 或 `firewalld` 管理防火墙
在真正执行前建议先用 `--dry-run` 预览脚本动作
```bash
$ curl -fsSL get.docker.com -o get-docker.sh
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# 若需要测试频道:
+1 -1
View File
@@ -114,7 +114,7 @@ $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugi
在真正执行前建议先用 `--dry-run` 预览脚本动作
```bash
$ curl -fsSL get.docker.com -o get-docker.sh
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh ./get-docker.sh --dry-run
# 若需要测试频道:
+10 -6
View File
@@ -90,9 +90,11 @@ $ sudo dnf versionlock clear
##### 挂载 ISO 镜像搭建本地 File
```bash
## 删除其他网络源
## 备份其他网络源
$ sudo rm -f /etc/yum.repos.d/*
$ repo_backup="/etc/yum.repos.d/backup-$(date +%Y%m%d%H%M%S)"
$ sudo mkdir -p "$repo_backup"
$ sudo find /etc/yum.repos.d -maxdepth 1 -type f -name '*.repo' -exec mv {} "$repo_backup"/ \;
## 挂载光盘或者iso镜像
@@ -106,7 +108,7 @@ $ sudo tee /etc/yum.repos.d/local-base.repo <<EOF
name=local_base
baseurl=file:///mnt
enabled=1
gpgcheck=0
gpgcheck=1
EOF
```
```bash
@@ -156,7 +158,9 @@ $ sudo createrepo_c /var/www/html/docker-ce/
##### DNF 客户端设置
```bash
$ sudo rm -f /etc/yum.repos.d/*
$ repo_backup="/etc/yum.repos.d/backup-$(date +%Y%m%d%H%M%S)"
$ sudo mkdir -p "$repo_backup"
$ sudo find /etc/yum.repos.d -maxdepth 1 -type f -name '*.repo' -exec mv {} "$repo_backup"/ \;
$ sudo tee /etc/yum.repos.d/local-files.repo <<EOF
[local_base]
name=local_base
@@ -165,7 +169,7 @@ name=local_base
baseurl=http://x.x.x.x/base
enabled=1
gpgcheck=0
gpgcheck=1
proxy=_none_
[docker-ce-stable]
name=docker-ce-stable
@@ -174,7 +178,7 @@ name=docker-ce-stable
baseurl=http://x.x.x.x/docker-ce
enabled=1
gpgcheck=0
gpgcheck=1
proxy=_none_
EOF
+20 -1
View File
@@ -72,6 +72,25 @@ $ docker stop webserver
$ docker rm webserver
```
### 3.7.4 镜像加速
### 3.7.4 替代容器运行时
Docker Desktop 并非 macOS 上运行容器的唯一选择以下两个工具也广泛使用各有侧重
| 特性 | Docker Desktop | OrbStack | Colima |
|------|---------------|-----------|--------|
| 启动速度 | 较慢 1030 | 极快 2 | 中等 510 |
| 空闲内存占用 | 46 GB | 200300 MB | 400 MB |
| 图形界面 | 完整 GUI | 轻量 GUI | 仅命令行 |
| Apple Silicon | 支持 | 原生优化 | 支持 |
| 商业许可 | 大型企业需付费 | 个人免费商业付费 | MIT 开源 |
| Kubernetes | 内置 | 内置 | 通过 k3s 支持 |
**[OrbStack](https://orbstack.dev/)**:以极低的资源占用和接近原生的 I/O 性能著称。对于 Apple Silicon 机型上需要频繁构建镜像的开发者,体验提升尤为明显。个人和教育用途免费。
**[Colima](https://github.com/abiosoft/colima)**:完全开源的命令行方案,底层基于 Lima 虚拟机。适合偏好终端工作流、不需要 GUI 的开发者,或企业中希望避免商业许可限制的团队。
> 上述三种工具均兼容标准的 `docker` CLI 命令 Docker Desktop 切换到 OrbStack Colima 已有的镜像和容器配置通常可以平滑迁移
### 3.7.5 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
+2 -2
View File
@@ -4,7 +4,7 @@
> **版本号最佳实践**
>
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.27`以确保镜像内容稳定一致
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.28`以确保镜像内容稳定一致
> - **在生产环境使用摘要**优先使用镜像摘要SHA256而非标签 `nginx@sha256:abc123...`因为摘要不可变
> - **定期评估依赖**即使指定了版本号仍应定期检查依赖的基础镜像是否有安全更新
@@ -160,7 +160,7 @@ root@e7009c6ce357:/# exit
Docker Hub 下载可能较慢可以配置镜像加速器
```json
```jsonc
// /etc/docker/daemon.json (Linux)
// ~/.docker/daemon.json (Docker Desktop)
{
+3 -3
View File
@@ -10,7 +10,7 @@
现在让我们以定制一个 Web 服务器为例子来讲解镜像是如何构建的
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.27`以避免镜像更新带来的不兼容性
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.28`以避免镜像更新带来的不兼容性
```bash
$ docker run --name webserver -d -p 8080:80 nginx
@@ -89,11 +89,11 @@ sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
$ docker image ls nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 07e334659748 9 seconds ago 181.5 MB
nginx 1.27 05a60462f8ba 12 days ago 181.5 MB
nginx 1.30 05a60462f8ba 12 days ago 181.5 MB
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB
```
> **版本说明**上面示例中 `nginx:1.27` 代表 1.27 系列的最新 patch 版本在实际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
> **版本说明**上面示例中 `nginx:1.30` 代表 1.30 系列的最新 patch 版本在实际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
我们还可以用 `docker history` 具体查看镜像内的历史记录例如先执行 `docker history nginx:v2`再对比 `docker history nginx:latest`就能看到我们刚刚提交出来的新层
+3 -3
View File
@@ -26,7 +26,7 @@ $ touch Dockerfile
```
其内容为
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.27`以确保 Dockerfile 的可重现性和稳定性
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.28`以确保 Dockerfile 的可重现性和稳定性
```docker
FROM nginx
@@ -40,7 +40,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
> **版本号最佳实践** `FROM` 指令中 **务必指定具体版本号** `FROM ubuntu:24.04` `FROM python:3.12-slim`而非 `FROM ubuntu` `FROM python:latest`这样可以确保 Dockerfile 在不同时间不同环境下构建出的镜像内容一致避免因基础镜像更新导致的不可预期的变化
[Docker Hub](https://hub.docker.com/search?q=&type=image&image_filter=official) 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 [`nginx`](https://hub.docker.com/_/nginx/)、[`redis`](https://hub.docker.com/_/redis/)、[`mongo`](https://hub.docker.com/_/mongo/)、[`mysql`](https://hub.docker.com/_/mysql/)、[`httpd`](https://hub.docker.com/_/httpd/)、[`php`](https://hub.docker.com/_/php/)、[`tomcat`](https://hub.docker.com/_/tomcat/) 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 [`node`](https://hub.docker.com/_/node)、[`openjdk`](https://hub.docker.com/_/openjdk/)、[`python`](https://hub.docker.com/_/python/)、[`ruby`](https://hub.docker.com/_/ruby/)、[`golang`](https://hub.docker.com/_/golang/) 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
[Docker Hub](https://hub.docker.com/search?q=&type=image&image_filter=official) 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 [`nginx`](https://hub.docker.com/_/nginx/)、[`redis`](https://hub.docker.com/_/redis/)、[`mongo`](https://hub.docker.com/_/mongo/)、[`mysql`](https://hub.docker.com/_/mysql/)、[`httpd`](https://hub.docker.com/_/httpd/)、[`php`](https://hub.docker.com/_/php/)、[`tomcat`](https://hub.docker.com/_/tomcat/) 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 [`node`](https://hub.docker.com/_/node)、[`eclipse-temurin`](https://hub.docker.com/_/eclipse-temurin/)、[`python`](https://hub.docker.com/_/python/)、[`ruby`](https://hub.docker.com/_/ruby/)、[`golang`](https://hub.docker.com/_/golang/) 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
如果没有找到对应服务的镜像官方镜像中还提供了一些更为基础的操作系统镜像 [`ubuntu`](https://hub.docker.com/_/ubuntu/)、[`debian`](https://hub.docker.com/_/debian/)、[`centos`](https://hub.docker.com/_/centos/)、[`fedora`](https://hub.docker.com/_/fedora/)、[`alpine`](https://hub.docker.com/_/alpine/) 等,这些操作系统的软件库为我们提供了更广阔的扩展空间。
@@ -98,7 +98,7 @@ Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c
```
从命令的输出结果中我们可以清晰看到镜像的构建过程 `Step 2` 如同我们之前所说的那样`RUN` 指令启动了一个容器 `9cdc27646c7b`执行了所要求的命令并最后提交了这一层 `44aa4490ce2c`随后删除了所用到的这个容器 `9cdc27646c7b`
从命令的输出结果中我们可以清晰看到镜像的构建过程 `Step 2` 如同我们之前所说的那样`RUN` 指令启动了一个容器 `9cdc27646c7b`执行了所要求的命令并最后提交了这一层 `44aa4490ce2c`随后删除了所用到的这个容器 `9cdc27646c7b`
这里我们使用了 `docker build` 命令进行镜像构建其格式为
+1 -1
View File
@@ -10,7 +10,7 @@
比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 16.04 [模板](https://wiki.openvz.org/Download/template/precreated)的镜像:
> **版本提示**示例中的 Ubuntu 16.04 (Xenial) 已于 2021 4 月停止支持如果用于生产环境建议更新至 Ubuntu 22.04 LTS 或更新版本
> **版本提示**`noble` 对应 Ubuntu 24.04 LTS实际用于生产环境应选择仍在安全维护期内的发行版并按团队的基础镜像更新策略定期重建
```bash
$ docker import \
+1 -1
View File
@@ -60,7 +60,7 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的
Docker 使用联合文件系统 (Union FS) 与写时复制思路来实现这种分层挂载传统的实现方式常见于 `overlay2``aufs``btrfs``zfs` 等存储驱动而在 Docker Engine 29.0 及之后的全新安装中默认镜像后端已经变为 containerd image store它使用 snapshotter 来管理这些层
> **版本背景**Docker Engine 29.0发布于 2024 2 是一个重要版本分界点引入了 containerd image store 作为默认镜像存储后端这对镜像管理OCI 合规性和供应链安全都有深远影响如果你的 Docker 版本低于 29.0镜像存储仍使用传统的 classic store 路径
> **版本背景**Docker Engine 29.0.0 发布于 2025 11 10 是一个重要版本分界点Docker Engine 29.0 及之后的全新安装默认使用 containerd image store从更早版本升级的 daemon 会继续使用 legacy graph driver直到显式启用 containerd image storeDocker Desktop 4.34 及之后也默认启用 containerd image store实际环境仍应以当前配置为准
虽然底层实现细节不同但它们都遵循上述的 **分层 + CoW** 模型因此无论你看到的是 `overlay2` 还是 containerd snapshotter理解镜像层容器层和写时复制的方式都是一样重要的
+4 -4
View File
@@ -126,14 +126,14 @@ $ docker run -d -p 80:80 nginx:latest
## 数据库
$ docker run -d -p 3306:3306 mysql:8.0
$ docker run -d -p 3306:3306 mysql:8.4
## 缓存服务
$ docker run -d -p 6379:6379 redis:latest
```
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.0`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.0.35`而非使用 `latest`
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.4`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.4.4`而非使用 `latest`
#### 2. 调试时先用前台模式
@@ -196,9 +196,9 @@ $ docker logs -t myapp
3. **以交互模式调试**
```bash
# /bin/sh 覆盖镜像原本的启动命令避免容器再次崩溃退出
# 进入 shell 后可手动执行原启动命令定位具体报错原因
$ docker run -it myimage:v1.0.0 /bin/sh
# 进入容器手动执行命令查找问题
```
#### Q容器在后台运行但无法访问服务
+1 -1
View File
@@ -212,7 +212,7 @@ FROM node:22-alpine
CMD ["node", "server.js"]
```
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:20-alpine``node:latest`
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:24-alpine``node:latest`
#### Q容器无法停止
+2 -1
View File
@@ -249,10 +249,11 @@ $ docker exec myapp python manage.py migrate
$ docker exec -it myapp bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found
## 解决方案使用调试容器
## 解决方案使用调试容器需要 Docker Desktop Pro/Team/Business 订阅
$ docker debug myapp
```
> **注意**`docker debug` Docker Desktop 4.33+ 提供的功能需要 ProTeam Business 订阅它会附加一个包含常用调试工具vimcurlhtop 的工具箱到目标容器即使目标镜像基于 `scratch` 也能使用
---
### 5.4.7 常见问题
+3 -3
View File
@@ -10,11 +10,11 @@
本章示例涉及多个 Docker 镜像遵循以下版本号最佳实践
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.0`而非 `latest`确保示例的可重复性
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.4`而非 `latest`确保示例的可重复性
- **镜像标签约定**
- `latest` `v1.0.0` 带标签的自定义镜像示例中指定具体版本
- `24.04``8.0`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.24.0``mysql:8.0.35`而非仅大版本号
- `24.04``8.4`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.28.0``mysql:8.4.4`而非仅大版本号
* [启动容器](5.1_run.md)
* [守护态运行](5.2_daemon.md)
+7 -6
View File
@@ -67,15 +67,15 @@ $ docker push username/myapp:v1
#### 镜像拉取限制
Docker Hub 对不同类型用户实施拉取速率限制2025 4 月起更新
Docker Hub 对不同类型用户实施拉取速率限制基于 6 小时周期
| 用户类型 | 限制 |
|---------|------|
| **匿名用户** (未登录) | 每小时 10 次请求 |
| **免费账户** (已登录) | 每小时 100 次请求 |
| **匿名用户** (未登录) | 6 小时 100 次请求 |
| **免费账户** (已登录) | 6 小时 200 次请求 |
| **Pro/Team/Business 账户** | 无限制公平使用政策 |
> **注意**2025 4 月前的旧限制为匿名用户每 6 小时 100 免费账户每 6 小时 200 新政策大幅收紧了匿名拉取额度建议在 CI/CD 环境中始终配置 `docker login`
> **注意**Docker 曾计划于 2025 4 月调整拉取限制策略但在 2025 2 月宣布取消该计划目前付费订阅用户享有无限制拉取额度匿名用户和免费账户的限制保持不变建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度
#### 滥用限流
@@ -107,10 +107,11 @@ Docker Hub 对不同类型用户实施拉取速率限制(2025 年 4 月起更
> ** 警告**绝不要在脚本或 CI/CD 系统中直接使用 `-p` 参数传递密码或 Token (类似 `docker login -p xxx`)这会导致凭证直接暴露在系统的命令历史进程列表和终端输出中
1. Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token (PAT)
2. Token 通过标准输入 (stdin) 安全传递给 Docker:
2. Token 保存在权限受限的本地文件或 CI secret 通过标准输入 (stdin) 传递给 Docker避免把真实 Token 写进脚本命令历史或日志
```bash
$ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin
$ chmod 600 "$HOME/.dockerhub-token"
$ cat "$HOME/.dockerhub-token" | docker login --username username --password-stdin
```
#### 3. 关注镜像漏洞
+11 -2
View File
@@ -70,10 +70,14 @@ $ openssl x509 -req -days 750 -in "site.csr" -sha256 \
-CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial \
-out "docker.domain.com.crt" -extfile "site.cnf" -extensions server
```
配套 demo 中的 [`ssl/README.md`](demo/ssl/README.md) 只保留本地生成证书的占位说明真实私钥和证书不应提交到仓库
这样已经拥有了 `docker.domain.com` 的网站 SSL 私钥 `docker.domain.com.key` SSL 证书 `docker.domain.com.crt` CA 根证书 `root-ca.crt`
新建 `ssl` 文件夹并将 `docker.domain.com.key` `docker.domain.com.crt` `root-ca.crt` 这三个文件移入删除其他文件
> **安全提示**这些私钥和证书应在本地或受控部署环境中生成不要提交进 Git 仓库示例目录只保留占位说明运行前请按上面的步骤重新生成
### 6.3.2 配置私有仓库
私有仓库默认的配置文件位于 `/etc/docker/registry/config.yml`我们先在本地编辑 `config.yml`之后挂载到容器中
@@ -99,7 +103,7 @@ auth:
realm: basic-realm
path: /etc/docker/registry/auth/nginx.htpasswd
http:
addr: :443
addr: :5000
host: https://docker.domain.com
headers:
X-Content-Type-Options: [nosniff]
@@ -126,6 +130,9 @@ $ docker run --rm \
-Bbn username password > auth/nginx.htpasswd
```
> 将上面的 `username` `password` 替换为你自己的用户名和密码
>
> **安全提示**上述命令会将密码明文暴露在 shell 历史记录和进程列表中生产环境建议使用交互式方式输入密码不带 `-b` 参数或通过环境变量/文件传入
> 配套 demo [`auth/README.md`](demo/auth/README.md) 仅说明本地生成步骤生成的 `auth/nginx.htpasswd` 已被忽略不应提交
> **版本说明**使用 `httpd:2.4-alpine` 基于 Apache 2.4 的精简镜像如需其他版本可替换为 `httpd:latest` 或指定具体版本号如 `httpd:2.4.58-alpine`
@@ -138,7 +145,7 @@ services:
registry:
image: registry:2
ports:
- "443:443"
- "443:5000"
volumes:
- ./:/etc/docker/registry
- registry-data:/var/lib/registry
@@ -147,6 +154,8 @@ volumes:
registry-data:
```
本书配套的 `06_repository/demo/` 也采用同样约定容器内 registry 监听 `:5000`宿主机通过 `443:5000` 暴露 HTTPS 服务这样可以避免在容器内占用特权端口同时仍让客户端使用 `https://docker.domain.com` 访问
> **版本说明**Compose 配置中明确指定 `registry:2` 版本生产环境建议固定版本号 `registry:2.8.3`而非使用 `latest`以保证部署的可重复性
### 6.3.5 修改 Hosts 文件
+1 -1
View File
@@ -80,7 +80,7 @@ server {
ssl_certificate_key key/example.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
large_client_header_buffers 4 32k;
+5
View File
@@ -0,0 +1,5 @@
# Generated Authentication File
Run the `htpasswd` command in section 6.3.3 to generate `nginx.htpasswd` locally before starting the demo registry.
Do not commit generated password hashes.
-2
View File
@@ -1,2 +0,0 @@
username:$2y$05$TRWvCC6ilpKpY3ICifw32Ok3.8SpG3etq8O5WGdCm9wvyDhtSbRgy
+3
View File
@@ -0,0 +1,3 @@
*
!.gitignore
!README.md
+5
View File
@@ -0,0 +1,5 @@
# Generated TLS Files
Run the certificate steps in section 6.3.1 to generate `docker.domain.com.key`, `docker.domain.com.crt`, and `root-ca.crt` locally before starting the demo registry.
Do not commit generated private keys or certificates.
@@ -1,35 +0,0 @@
-----BEGIN CERTIFICATE-----
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
7zJA
-----END CERTIFICATE-----
@@ -1,51 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
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
oKnsMQKCAQEA0iurbnOyrF050SfRdQcnG4shZs/HeBT2EB3CsR1OocWwXBeUkBlO
OKl+d1cYan1ppw+qGlbdQr+t3u7lLPFLUBghf+I/8CmSyiCbZlR4/LrePOmw551r
YXU1uvtFu/mQq3ieV+k4GOyHq3lhCDd61QFedyESfbkVK8f4ihvvX3izZAAtZfwU
HcmZ174vpwZploWQPsrL9A2B+Na42ccLM2qA45nPwXv1Jr/U6b/CzPw7r/4DvTXv
FIeolrELDkCgWBQ8lxB7Lt96BZy9Rbiwi1TzcP++BQu4IOwbAfq23tCybu8vDde4
Z15KVf7qyBansdqKx0njxWNu2/dpgKCPqQKCAQEAzWV4aajox7eeTi3iudP1Oxu3
OBiu8xie4xq0mlM13tMxAQry/uOAuTxbaQ48mNsSXdeYeSgmT45lUvFWROqdVScK
8gh04G1NiRAkITzXwCCwKkAQxvQppgypZ+aksBHkFQFBAIg2/mLizS4cicXNEY4G
vb+RImfn8MSqSMLu3cJ8zgFyqfRg6F0oHg9EgEwvbnCLYglN6Xm5KlZutjW4eu7m
Q+1y0lg05e7vFyj2UIVylfzT/aoF/xzXzNt9/LZs0klO3vMmaVyTjuF/71+AyphH
FTmpNs1wpZU2IRqKOMrimIhk6TTxvMSaN4pxKdLPqgHYLWhwkbsdmqtTnCljRg==
-----END RSA PRIVATE KEY-----
+4 -4
View File
@@ -82,9 +82,9 @@ RUN pwd # 输出 /app
```docker
## 构建阶段
## 建议使用 node:20 node: 等具体版本标签避免使用 latest
## 建议使用 node:22 node: 等具体版本标签避免使用 latest
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /build
COPY package*.json ./
RUN npm install
@@ -105,8 +105,8 @@ COPY --from=builder /build/dist .
#### 1. 尽早设置 WORKDIR
```docker
# 建议使用 node:20 等主/次版本号标签
FROM node:20
# 建议使用 node:22 等主/次版本号标签
FROM node:22
WORKDIR /app # 尽早设置
COPY package*.json ./
+4 -4
View File
@@ -35,7 +35,7 @@ flowchart LR
#### 创建并切换用户
```docker
FROM node:20-alpine
FROM node:22-alpine
## 1. 创建用户和组
@@ -173,7 +173,7 @@ $ docker run -u root myimage
切换用户后确保应用有权访问文件
```docker
FROM node:20-alpine
FROM node:22-alpine
## 创建用户
@@ -229,14 +229,14 @@ USER 1000:1000
```docker
## 构建阶段可以用 root
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段用非 root
FROM node:20-alpine
FROM node:22-alpine
RUN adduser -D appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appuser /app/dist .
+1 -1
View File
@@ -34,7 +34,7 @@ Starting ──成功──> Healthy ──失败N次──> Unhealthy
#### Web 服务检查
```docker
# nginx 镜像推荐使用具体的版本标签 nginx:1.25-alpine
# nginx 镜像推荐使用具体的版本标签 nginx:1.28-alpine
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
+2 -2
View File
@@ -30,7 +30,7 @@ ONBUILD <其它指令>
**基础镜像 (my-node-base)**
```docker
FROM node:20-alpine
FROM node:22-alpine
WORKDIR /app
## 这些指令将在子镜像构建时执行
@@ -126,7 +126,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
建议在镜像标签中添加 `-onbuild` 后缀明确告知使用者该镜像包含触发器
```bash
node:20-onbuild
node:22-onbuild
python:3.12-onbuild
```
+13 -5
View File
@@ -14,12 +14,20 @@ Dockerfile 中的常用指令包括:
- **FROM**: 指定基础镜像必须是第一条指令
- **RUN**: 在镜像中执行命令用于安装软件包等
- **WORKDIR**: 设置工作目录
- **COPY/ADD**: 复制文件到镜像中
- **EXPOSE**: 声明容器监听的端口
- **ENV**: 设置环境变量
- **ENTRYPOINT**: 容器启动时的入口点
- **COPY**: 复制文件到镜像中
- **ADD**: 更高级的复制文件支持 URL 和自动解压
- **CMD**: 容器默认执行的命令
- **ENTRYPOINT**: 容器启动时的入口点
- **ENV**: 设置环境变量
- **ARG**: 构建时的参数变量
- **VOLUME**: 定义匿名卷挂载点
- **EXPOSE**: 声明容器监听的端口
- **WORKDIR**: 设置工作目录
- **USER**: 指定运行容器时的用户
- **HEALTHCHECK**: 配置容器健康检查
- **ONBUILD**: 设置触发器指令在子镜像构建时执行
- **LABEL**: 为镜像添加元数据标签
- **SHELL**: 指定 RUN 等指令使用的 shell
### 最佳实践建议
+19 -8
View File
@@ -33,7 +33,7 @@ WORKDIR /go/src/github.com/go/helloworld/
COPY app.go .
RUN go mod init helloworld \
&& go get -d -v github.com/go-sql-driver/mysql \
&& go get github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \
&& cp /go/src/github.com/go/helloworld/app /root
@@ -62,13 +62,14 @@ WORKDIR /go/src/github.com/go/helloworld
COPY app.go .
RUN go get -d -v github.com/go-sql-driver/mysql \
RUN go mod init helloworld \
&& go get github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
```
编写 `Dockerfile.copy` 文件
```docker
FROM alpine:latest
FROM alpine:3
RUN apk --no-cache add ca-certificates
@@ -125,19 +126,20 @@ RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld/
RUN go get -d -v github.com/go-sql-driver/mysql
RUN go mod init helloworld \
&& go get github.com/go-sql-driver/mysql
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest as prod
FROM alpine:3 as prod
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/go/helloworld/app .
COPY --from=builder /go/src/github.com/go/helloworld/app .
CMD ["./app"]
```
@@ -158,6 +160,15 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
很明显使用多阶段构建的镜像体积小同时也完美解决了上边提到的问题
> **Go Modules 最佳实践**上述示例为简化演示在 Dockerfile 中临时执行 `go mod init`在实际项目中通常已在代码仓库中维护好 `go.mod` `go.sum` 文件推荐的 Dockerfile 写法是先拷贝这两个文件并执行 `go mod download` 以利用 Docker 层缓存再拷贝源码并构建
>
> ```docker
> COPY go.mod go.sum ./
> RUN go mod download
> COPY . .
> RUN go build -o app .
> ```
### 7.17.4 只构建某一阶段的镜像
我们可以使用 `as` 来为某一阶段命名例如
@@ -173,8 +184,8 @@ $ docker build --target builder -t username/imagename:tag .
### 7.17.5 构建时从其他镜像复制文件
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件我们也可以复制任意镜像中的文件
上面例子中我们使用 `COPY --from=builder /go/src/github.com/go/helloworld/app .` 通过已命名阶段`as builder`从上一阶段的镜像中复制文件命名引用比 `--from=0` 这种位置索引更易读也是当前官方推荐的最佳实践我们也可以复制任意镜像中的文件
```docker
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
COPY --from=nginx:1.28-alpine /etc/nginx/nginx.conf /nginx.conf
```
@@ -60,8 +60,8 @@ server {
第一阶段进行前端构建
```docker
# node 镜像推荐使用具体的版本标签 node:20-alpine
FROM node:alpine as frontend
# node 镜像推荐使用具体的版本标签 node:22-alpine
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -83,7 +83,7 @@ RUN set -x ; cd /app \
```docker
# composer 镜像推荐使用具体的版本标签 composer:2.x
FROM composer as composer
FROM composer:2 as composer
COPY database/ /app/database/
COPY composer.json composer.lock /app/
@@ -128,8 +128,8 @@ RUN set -x ; cd ${LARAVEL_PATH} \
### 7.18.5 最后一个阶段构建 NGINX 镜像
```docker
# nginx 镜像推荐使用具体的版本标签 nginx:1.25-alpine
FROM nginx:alpine as nginx
# nginx 镜像推荐使用具体的版本标签 nginx:1.28-alpine
FROM nginx:1.28-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
@@ -179,8 +179,8 @@ $ docker run -dit --rm --network=laravel -p 8080:80 my/nginx
完整的 `Dockerfile` 文件如下
```docker
# 生产环境推荐使用具体的版本标签 node:20-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.25-alpine
FROM node:alpine as frontend
# 生产环境推荐使用具体的版本标签 node:22-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.28-alpine
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -195,7 +195,7 @@ RUN set -x ; cd /app \
&& mkdir -p public \
&& npm run production
FROM composer as composer
FROM composer:2 as composer
COPY database/ /app/database/
COPY composer.json composer.lock /app/
@@ -229,7 +229,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
FROM nginx:alpine as nginx
FROM nginx:1.28-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+3 -1
View File
@@ -158,9 +158,11 @@ RUN --mount=type=cache,target=/go/pkg/mod \
```docker
RUN --mount=type=secret,id=mysecret \
cat /run/secrets/mysecret
my-private-tool --token-file /run/secrets/mysecret
```
不要在构建命令中 `cat``echo` 或打印密钥内容应把 `/run/secrets/<id>` 路径交给真正消费密钥的工具
#### 3. Heredoc 语法
BuildKit 支持使用 heredoc 语法编写多行脚本无需行末反斜杠 `\` 连接
+1 -1
View File
@@ -178,7 +178,7 @@ ADD app.tar.gz /app/
```docker
## 构建阶段
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
+4 -4
View File
@@ -6,8 +6,8 @@
这是 Dockerfile 使用中最常见的困惑之一简单的答案是
- **CMD**定义容器的默认命令如果用户在 `docker run` 时提供命令CMD 会被覆盖
- **ENTRYPOINT**定义容器的入口脚本通常用于启动应用的某个特定部分
- **CMD**定义容器的默认命令如果用户在 `docker run` 时提供命令CMD 会被覆盖
- **ENTRYPOINT**定义容器的入口脚本通常用于启动应用的某个特定部分
**决策树**
@@ -31,9 +31,9 @@ CMD 有三种格式:
| 格式 | 语法 | 推荐程度 |
|------|------|---------|
| **exec 格式**| `CMD [可执行文件, 参数1, 参数2]` | **推荐** |
| **exec 格式**| `CMD ["可执行文件", "参数1", "参数2"]` | **推荐** |
| **shell 格式** | `CMD 命令 参数1 参数2` | 简单场景 |
| **参数格式** | `CMD [参数1, 参数2]` | 配合 ENTRYPOINT |
| **参数格式** | `CMD ["参数1", "参数2"]` | 配合 ENTRYPOINT |
#### exec 格式推荐
+1 -1
View File
@@ -40,7 +40,7 @@
| 格式 | 语法 | 推荐程度 |
|------|------|---------|
| **exec 格式**| `ENTRYPOINT [可执行文件, 参数1]` | **推荐** |
| **exec 格式**| `ENTRYPOINT ["可执行文件", "参数1"]` | **推荐** |
| **shell 格式** | `ENTRYPOINT 命令 参数` | 不推荐 |
```docker
+5 -3
View File
@@ -89,6 +89,8 @@ const dbUrl = process.env.DATABASE_URL;
| `LABEL` | `LABEL version=$VERSION` |
| `FROM` | `FROM node:$NODE_VERSION` |
> **注意**`FROM` 是上表中的特例它只能引用在第一条 `FROM` 之前用 `ARG` 声明的变量**无法**使用 `ENV` 定义的环境变量`ENV` 要进入构建阶段后才生效其余指令才能引用 `ENV` 环境变量
---
### 7.6.5 运行时覆盖
@@ -158,15 +160,15 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp .
```docker
## 版本集中管理
ENV NGINX_VERSION=1.25 \
NODE_VERSION=20 \
ENV NGINX_VERSION=1.30 \
NODE_VERSION=22 \
PYTHON_VERSION=3.12
RUN apt-get install nginx=${NGINX_VERSION}
## 版本分散在各处
RUN apt-get install nginx=1.25
RUN apt-get install nginx=1.30
```
#### 2. 不要存储敏感信息
+4 -4
View File
@@ -93,14 +93,14 @@ RUN echo "Node version: $NODE_VERSION"
```docker
ARG BASE_VERSION=alpine
FROM node:20-${BASE_VERSION} AS builder
FROM node:22-${BASE_VERSION} AS builder
## 需要重新声明
ARG NODE_VERSION=20
RUN echo "Building with Node $NODE_VERSION"
FROM node:20-${BASE_VERSION}
FROM node:22-${BASE_VERSION}
## 每个阶段都需要重新声明
@@ -125,8 +125,8 @@ $ docker build --build-arg ALPINE_VERSION=3.19 .
#### 2. 设置软件版本
```docker
# 使用次版本号 (1.25) 而非完整版本号 (1.25.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.25
# 使用次版本号 (1.30) 而非完整版本号 (1.30.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.30
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
```
+7 -7
View File
@@ -44,7 +44,7 @@ flowchart LR
#### 定义单个卷
```docker
FROM mysql:8.0
FROM mysql:8.4
VOLUME /var/lib/mysql
```
@@ -63,7 +63,7 @@ VOLUME ["/data", "/logs", "/config"]
如果运行时未指定挂载Docker 会自动创建匿名卷
```bash
$ docker run mysql:8.0
$ docker run mysql:8.4
$ docker volume ls
DRIVER VOLUME NAME
local a1b2c3d4e5f6... # 自动创建的匿名卷
@@ -74,7 +74,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
```bash
## 使用命名卷替代匿名卷
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
```
#### 3. 可被 Bind Mount 覆盖
@@ -82,7 +82,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```bash
## 使用宿主机目录替代
$ docker run -v /my/data:/var/lib/mysql mysql:8.0
$ docker run -v /my/data:/var/lib/mysql mysql:8.4
```
---
@@ -145,7 +145,7 @@ VOLUME /app/uploads
```bash
## 查看镜像定义的 VOLUME
$ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq
$ docker inspect mysql:8.4 --format '{{json .Config.Volumes}}' | jq
{
"/var/lib/mysql": {}
}
@@ -196,7 +196,7 @@ volumes:
```bash
## 使用 --rm 运行的容器匿名卷会在容器删除时一起删除
$ docker run --rm mysql:8.0
$ docker run --rm mysql:8.4
## 容器停止后数据丢失
@@ -205,7 +205,7 @@ $ docker run --rm mysql:8.0
**解决**始终使用命名卷
```bash
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
```
---
+1 -1
View File
@@ -80,7 +80,7 @@ docker build -t my-image:1.0 .
本章中的 Dockerfile 示例使用的基础镜像标签遵循以下原则
- **通用标签** `ubuntu:24.04``alpine``nginx`保持原样无需修改
- **基础镜像版本号** `node:20``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **基础镜像版本号** `node:22``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **避免**不建议使用 `latest` 标签和完整的 patch 版本号 `20.10.0`作为基础镜像因为这会导致构建的不可重现性或安全风险
读者在使用这些示例时应根据实际生产环境需求选择合适的版本号
@@ -1,4 +1,4 @@
FROM node:alpine as frontend
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -13,7 +13,7 @@ RUN set -x ; cd /app \
&& mkdir -p public \
&& npm run production
FROM composer as composer
FROM composer:2 as composer
COPY database/ /app/database/
COPY composer.json /app/
@@ -47,7 +47,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
FROM nginx:alpine as nginx
FROM nginx:1.30-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+15
View File
@@ -21,6 +21,21 @@
| **LABEL** | 添加元数据 | 推荐 OCI 标准标签替代 MAINTAINER |
| **SHELL** | 更改默认 shell | 推荐 `["/bin/bash", "-o", "pipefail", "-c"]` |
### 生产镜像快速检查清单
在将镜像推向生产之前建议逐条过一遍以下清单
- [ ] 基础镜像选择了最小化版本 `alpine``distroless`
- [ ] 使用了[多阶段构建](7.17_multistage_builds.md)最终镜像不含编译工具链
- [ ] 以非 root 用户运行`USER` 指令
- [ ] `COPY` 优先于 `ADD`且仅复制必要文件
- [ ] `RUN` 指令合并了 `apt-get update && install && rm -rf /var/lib/apt/lists/*`
- [ ] 设置了 `HEALTHCHECK`
- [ ] 使用了 `.dockerignore` 排除 `.git``node_modules` 等无关文件
- [ ] 镜像标签使用了具体版本号或 commit hash而非 `latest`
> 更完整的编写指南见[附录Dockerfile 最佳实践](../appendix/best_practices.md)
### 延伸阅读
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)Dockerfile 入门
+3 -1
View File
@@ -238,7 +238,7 @@ $ docker run -u $(id -u):$(id -g) ...
Docker Desktop Bind Mount 性能通常不如 Volume因为数据需要在宿主机文件系统和 Linux VM 之间同步
```bash
## 使用 :cached :delegated 提高性能macOS
## 使用 :cached :delegated 提高性能macOS Docker Desktop 4.5 及更早版本
$ docker run -v /host/path:/container/path:cached myapp
```
@@ -248,6 +248,8 @@ $ docker run -v /host/path:/container/path:cached myapp
| `:delegated` | 容器权威宿主机读取可能延迟 |
| `:consistent` | 默认完全一致 (最慢)|
> **注意**Docker Desktop 4.6+ 默认使用 VirtioFS 文件共享引擎上述 `:cached`/`:delegated` 选项已被静默忽略如需优化文件同步性能请参考 Docker Desktop [Synchronized file shares](https://docs.docker.com/desktop/synchronized-file-sharing/) 功能。
---
### 8.2.9 最佳实践
+2 -1
View File
@@ -21,10 +21,11 @@ ghi789... none null local
| **none** | 禁用网络 | 完全隔离的容器 |
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
| **ipvlan** | 容器共享父接口 MAC独享 IP | 同网段大量容器 MAC 数量受限的网络 |
### 9.2.2 Bridge 网络默认
Bridge Docker 默认使用的网络模式Docker 启动时会自动创建 `docker0` 虚拟网桥所有未指定网络的容器会连接到这个网桥上
Bridge Docker 默认使用的网络模式在原生 Linux Docker Engine Docker 启动时通常会创建 `docker0` 虚拟网桥未指定网络的容器会连接到这个网桥上Docker Desktop 运行在虚拟机内宿主机上不会直接看到 `docker0`也不能假设宿主机可直接访问每个容器 IP
核心组件如下
+1 -1
View File
@@ -7,7 +7,7 @@
容器的网络访问规则如下
- **容器之间**可以通过 IP 或容器名 (自定义网络) 互通
- **宿主机访问容器**可以通过容器 IP 访问
- **宿主机访问容器**原生 Linux 环境下可按网络配置访问容器 IPDocker Desktop 上不能依赖容器 IP应通过端口映射容器名容器间 `host.docker.internal` 等机制访问
- **外部网络访问容器** 默认无法直接访问
为了让外部 (如你的浏览器其他局域网机器) 访问容器内的服务我们需要将容器的端口 **映射** 到宿主机的端口
+1 -1
View File
@@ -8,7 +8,7 @@ Overlay 网络在现有网络基础上建立虚拟网络,允许容器跨宿主
#### Overlay 网络工作原理
Overlay 网络通过隧道封装技术通常是 VXLAN将容器网络流量封装在宿主机物理网络的 UDP 数据包中传输
Overlay 网络通过隧道封装技术通常是 VXLAN将容器网络流量封装在宿主机物理网络的 UDP 数据包中传输Docker overlay 网络默认使用 `4789/udp` 作为数据通道端口同时 Swarm 控制面与节点通信还需要相应开放 `2377/tcp``7946/tcp` `7946/udp`
```text
容器 A (192.168.0.2)
+7 -7
View File
@@ -15,7 +15,7 @@ BuildKit 引入了多项新指令,旨在优化构建缓存和安全性。以
要使用最新的 Dockerfile 语法特性建议在 Dockerfile 开头添加语法指令
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
```
这将使用最新的稳定版语法解析器确保你可以使用所有最新特性
@@ -51,7 +51,7 @@ COPY --from=builder /app/dist /app/dist
`BuildKit` 提供了 `RUN --mount=type=cache` 指令可以实现上边的设想
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
FROM node:alpine as builder
@@ -105,7 +105,7 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
该指令可以将一个镜像 (或上一构建阶段) 的文件挂载到指定位置
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
cat /docker-php-entrypoint
@@ -116,7 +116,7 @@ RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoin
该指令可以将一个 `tmpfs` 文件系统挂载到指定位置
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
RUN --mount=type=tmpfs,target=/temp \
mount | grep /temp
@@ -127,10 +127,10 @@ RUN --mount=type=tmpfs,target=/temp \
该指令可以将一个文件 (例如密钥) 挂载到指定位置
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
cat /root/.aws/credentials
test -s /root/.aws/credentials && echo "credentials mounted"
```
```bash
$ docker build -t test --secret id=aws,src=$HOME/.aws/credentials .
@@ -141,7 +141,7 @@ $ docker build -t test --secret id=aws,src=$HOME/.aws/credentials .
该指令可以挂载 `ssh` 密钥
```docker
## syntax=docker/dockerfile:1
# syntax=docker/dockerfile:1
FROM alpine
RUN apk add --no-cache openssh-client
+12 -1
View File
@@ -13,6 +13,17 @@ $ docker buildx build .
```
Buildx 使用 [BuildKit 引擎](10.1_buildkit.md)进行构建支持许多新的功能具体参考 [Buildkit](10.1_buildkit.md) 一节
需要注意的是默认 `docker` driver 会把构建结果加载到本地镜像存储使用 `docker-container`remotecloud builder 如未指定 `--load``--push` `--output`结果通常只保留在构建缓存中
#### 构建前检查
Buildx 0.15 起支持构建检查常规构建会默认检查 Dockerfile 与构建参数如果只想做检查而不真正构建可以使用 `--check`
```bash
$ docker buildx build --check .
```
这适合作为 CI 的快速门禁普通构建中的检查告警默认不会让构建失败 `--check` 发现问题会以非零状态退出需要把告警提升为错误时可在 Dockerfile 顶部配合 `# check=error=true`
#### 使用 `bake`
`docker buildx bake` 是一个高级构建命令支持从 HCLJSON Compose 文件中定义构建目标实现复杂的流水线构建
@@ -39,7 +50,7 @@ $ docker buildx build --sbom=true -t myimage .
> ** 注意与失败模式**
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见对底层的存储格式有前置要求默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构
>
> 如果只简单运行上述命令你可能会面临 **命令成功执行但本地镜像中看不到 SBOM** 的体会落差
> 如果只简单运行上述命令你可能会面临 **命令成功执行但本地镜像中看不到 SBOM** 的体会落差
>
> **正确的解决路径有两条**
> 1. **推送到远端仓库**使用 `docker buildx build --sbom=true --push -t myimage:tag` SBOM 会正确保存到远端仓库远端 OCI 兼容的镜像仓库能够完整存储这些元数据
+1 -1
View File
@@ -2,7 +2,7 @@
Docker Buildx 是一个 docker CLI 插件其扩展了 docker 命令支持 [Moby BuildKit](10.1_buildkit.md) 提供的功能提供了与 docker build 相同的用户体验并增加了许多新功能
> Buildx 需要 Docker v19.03+ Docker 19.03 及以上版本在较新版本中已更常用且功能更完整
> Buildx 需要 Docker v23.0+该版本起 BuildKit 成为默认构建引擎推荐使用 Docker v28 及以上版本以获得最完整的 Buildx 功能支持
## 本章内容
+1
View File
@@ -8,6 +8,7 @@ Docker Buildx 是 Docker 构建系统的重要进化,提供了高效、安全
| **缓存挂载** | `RUN --mount=type=cache` 加速依赖安装 |
| **Secret 挂载** | `RUN --mount=type=secret` 安全传递密钥 |
| **buildx build** | 替代 `docker build`支持更多构建功能 |
| **构建检查** | `--check` 可在不执行构建的情况下检查 Dockerfile 与构建参数 |
| **多架构构建** | `--platform` 参数一键构建多种架构镜像 |
| **Manifest List** | 多架构镜像的索引文件 |
| **SBOM** | 通过 `--sbom=true` 生成软件物料清单 |
+1 -1
View File
@@ -19,7 +19,7 @@ $ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```bash
$ docker compose version
Docker Compose version v5.x
Docker Compose version v5.x.x
```
### 11.2.3 卸载
+1 -1
View File
@@ -42,7 +42,7 @@ if __name__ == "__main__":
```docker
FROM python:3.12-alpine
ADD . /code
COPY . /code
WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
+1 -1
View File
@@ -46,7 +46,7 @@ docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
* `-p, --project-name NAME` 指定项目名称默认将使用所在目录名称作为项目名
* `--verbose` 输出更多调试信息
* `--verbose` 输出更多调试信息(**已弃用** Docker Compose V2 请改用 `docker --log-level debug compose ...` 或设置环境变量 `COMPOSE_DEBUG=1`)
* `-v, --version` 打印版本并退出
+11 -12
View File
@@ -150,7 +150,7 @@ services:
redis:
image: redis
healthcheck:
test: [CMD, redis-cli, ping]
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
@@ -158,7 +158,7 @@ services:
db:
image: postgres
healthcheck:
test: [CMD-SHELL, pg_isready -U postgres]
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
@@ -411,14 +411,13 @@ ports:
```yaml
services:
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
secrets:
- db_root_password
- my_other_secret
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
secrets:
- db_root_password
- my_other_secret
secrets:
db_root_password:
@@ -490,7 +489,7 @@ volumes:
```yaml
services:
my_src:
image: mysql:8.0
image: mysql:8.4
volumes:
- mysql_data:/var/lib/mysql
@@ -524,7 +523,7 @@ domainname: your_website.com
hostname: test
mac_address: 08-00-27-00-0C-0A
```
允许容器中运行一些特权命令
允许容器中运行一些特权命令`privileged: true` 会显著扩大容器对宿主机设备和 Linux capability 的访问范围生产环境应优先使用更窄的 `cap_add``devices` 或只读挂载更多说明见 [内核能力机制](../18_security/18.4_kernel_capability.md)
```yaml
privileged: true
+8 -2
View File
@@ -106,6 +106,11 @@ services:
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
web:
build: .
@@ -115,7 +120,8 @@ services:
ports:
- "3000:3000"
depends_on:
- db
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://postgres:password@db:5432/myapp_development
@@ -128,7 +134,7 @@ volumes:
|--------|------|
| `rm -f tmp/pids/server.pid` | 清理上次异常退出留下的 PID 文件 |
| `volumes: .:/myapp` | 挂载代码目录支持热更新 |
| `depends_on: db` | 确保数据库启动 |
| `depends_on` + `condition` | 等待数据库健康检查通过后再启动 |
| `DATABASE_URL` | Rails 12-factor 风格的数据库配置 |
### 11.7.6 步骤 4生成 Rails 项目
+35 -16
View File
@@ -13,7 +13,10 @@ WordPress 是全球最流行的内容管理系统 (CMS)。使用 Docker Compose
```bash
wordpress/
compose.yaml
.env # 环境变量敏感信息
.env # 非敏感环境变量如版本端口
secrets/ # 本地密钥文件生产环境应由密钥管理系统提供
db_root_password.txt
db_password.txt
nginx/ # 可选反向代理配置
nginx.conf
```
@@ -21,27 +24,30 @@ wordpress/
### 11.8.2 编写 `compose.yaml`
这是一个生产可用的最小化配置
这是一个可运行的单机最小配置不是完整生产安全基线正式部署前应固定镜像版本放在反向代理/TLS 后面限制公开端口配置备份与监控并按 WordPress 与插件生命周期做升级测试
```yaml
services:
# 数据库服务
db:
image: mysql:8.0
image: mysql:8.4
container_name: wordpress_db
restart: always
command:
# 使用原生密码认证旧版 WP 兼容性
# 用原生密码认证MySQL 8.4 默认禁用旧版 WP 兼容性需要
- --default-authentication-plugin=mysql_native_password
- --mysql-native-password=ON
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
volumes:
- db_data:/var/lib/mysql
networks:
@@ -50,16 +56,20 @@ services:
# WordPress 服务
wordpress:
# 示例保留 latest 以便读者快速体验生产环境请固定到经过测试的明确版本标签
image: wordpress:latest
container_name: wordpress_app
restart: always
ports:
- "8000:80"
# 本机调试入口生产环境请通过反向代理发布 HTTPS
- "127.0.0.1:8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password
WORDPRESS_DB_NAME: wordpress
secrets:
- db_password
volumes:
- wp_data:/var/www/html
# 增加上传文件大小限制
@@ -76,20 +86,29 @@ volumes:
networks:
wp_net:
secrets:
db_root_password:
file: ./secrets/db_root_password.txt
db_password:
file: ./secrets/db_password.txt
```
---
### 11.8.3 配置文件详解
#### 1. 环境变量文件 .env
#### 1. 密钥文件
为了安全不要在 `compose.yaml` 中直接写密码创建 `.env` 文件
不要把数据库密码写入 `compose.yaml``.env`命令行或 GitCompose 官方建议敏感值使用 secrets本地练习可用只读密钥文件模拟
```ini
DB_ROOT_PASSWORD=somestrongrootpassword
DB_PASSWORD=somestronguserpassword
```bash
mkdir -p secrets
printf '%s\n' 'somestrongrootpassword' > secrets/db_root_password.txt
printf '%s\n' 'somestronguserpassword' > secrets/db_password.txt
chmod 600 secrets/*.txt
```
Compose 会自动读取此同级目录下的文件
`secrets/` 加入 `.gitignore`生产环境应改用平台密钥管理能力而不是把真实密码放在项目目录
#### 2. 数据持久化
@@ -192,7 +211,7 @@ WordPress 支持 Redis 缓存以提高性能。
1. 检查 `docker compose logs wordpress`
2. 确认 `.env` 中的密码与 YAML 文件引用一致
3. 确认 `WORDPRESS_DB_HOST` 也是 `db` (服务名)
4. MySQL 8.0 可能需要几秒钟启动WordPress 会自动重试稍等片刻即可
4. MySQL 8.4 可能需要几秒钟启动WordPress 会自动重试稍等片刻即可
#### Q无法上传大文件
+2 -2
View File
@@ -2,9 +2,9 @@
services:
db:
image: mysql:8.0
image: mysql:8.4
command:
- --default_authentication_plugin=mysql_native_password
- --mysql-native-password=ON
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
+1 -1
View File
@@ -75,7 +75,7 @@ flowchart TD
E["退出"]
U -->|1. REST API| D
K -->|2. gRPC| C
D -->|2. gRPC| C
C -->|3. 准备镜像和 Bundle| B
C -->|4. 启动 Shim| S
S -->|5. 执行| R
+1 -1
View File
@@ -198,7 +198,7 @@ $ docker run --rm --cpus=1 stress --cpu 4
#### Docker cgroups v2 的支持
Docker 19.03+ 默认优先使用 cgroups v2如果系统支持提供更好的性能和资源隔离如果需要明确控制或回退到 v1可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数
Docker 20.10+ 开始支持 cgroups v2如果系统支持提供更好的性能和资源隔离如果需要明确控制或回退到 v1可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数
```json
{
+1 -1
View File
@@ -41,7 +41,7 @@ flowchart TD
每个 Dockerfile 指令创建一层只有变化的层需要重建
```docker
FROM node:20 # 层1基础镜像
FROM node:22 # 层1基础镜像
COPY package.json ./ # 层2依赖定义
RUN npm install # 层3安装依赖
COPY . . # 层4应用代码
+6 -8
View File
@@ -19,7 +19,7 @@
### 13.2.1 节点
`Kubernetes` 节点是实际工作的点节点可以是虚拟机或者物理机器依赖于一个集群环境每个节点都有一些必要的服务以运行容器组并且它们都可以通过主节点来管理必要服务包括 Dockerkubelet 和代理服务
`Kubernetes` 节点是实际工作的点节点可以是虚拟机或者物理机器依赖于一个集群环境每个节点都有一些必要的组件以运行容器组并且它们都可以通过控制平面来管理必要组件包括 kubelet容器运行时 containerd CRI-O kube-proxyDocker 不再是 Kubernetes 节点的默认基线运行时
#### 容器状态
@@ -29,13 +29,11 @@
主机 IP 需要云平台来查询`Kubernetes` 把它作为状态的一部分来保存如果 `Kubernetes` 没有运行在云平台上节点 ID 就是必需的IP 地址可以变化并且可以包含多种类型的 IP 地址如公共 IP私有 IP动态 IPipv6 等等
##### 节点周期
通常来说节点有 `Pending``Running``Terminated` 三个周期如果 Kubernetes 发现了一个节点并且其可用那么 Kubernetes 就把它标记为 `Pending`然后在某个时刻Kubernetes 将会标记其为 `Running`节点的结束周期称为 `Terminated`一个已经 `Terminated` 的节点不会接受和调度任何请求并且已经在其上运行的容器组也会删除
##### 节点状态
节点的状态主要是用来描述处于 `Running` 的节点当前可用的有 `NodeReachable` `NodeReady`以后可能会增加其他状态`NodeReachable` 表示集群可达`NodeReady` 表示 kubelet 返回 Status Ok 并且 HTTP 状态检查健康
`Pending` / `Running` / `Succeeded` / `Failed` / `Unknown` **Pod 的生命周期阶段**`pod.status.phase`不是节点状态节点本身没有 `Terminated` 状态
节点的状态通过一组条件Conditions来描述主要条件包括 `Ready`kubelet 健康且可以接收 Pod`MemoryPressure`内存不足`DiskPressure`磁盘不足 `PIDPressure`进程数过多其中 `Ready` 条件最为关键值为 `True` 表示节点健康可调度`False` 表示节点异常`Unknown` 表示节点控制器超过一定时间未收到心跳被标记为 `Unknown` 较长时间的节点其上的 Pod 会被驱逐重新调度到其他节点
#### 节点管理
@@ -166,7 +164,7 @@ spec:
spec:
containers:
- name: nginx
image: nginx:1.30
image: nginx:1.28
ports:
- containerPort: 80
```
@@ -200,7 +198,7 @@ spec:
spec:
containers:
- name: mysql
image: mysql:8.0
image: mysql:8.4
volumeMounts:
- name: data
mountPath: /var/lib/mysql
+6 -1
View File
@@ -62,6 +62,7 @@ Ingress 资源仍可正常使用,但建议新项目直接采用 Gateway API。
* **PVC (Persistent Volume Claim)**用户申请存储的声明
* **PV (Persistent Volume)**实际的存储资源 (NFSAWS EBSCeph )
* **StorageClass**定义存储类支持动态创建 PV
* **VolumeAttributesClass**Kubernetes 1.34 GA用于在 CSI 驱动支持 `ModifyVolume` 时动态调整卷属性例如性能等级或服务质量参数
### 13.4.4 Horizontal Pod Autoscaling
@@ -91,7 +92,7 @@ spec:
### 13.4.5 ConfigMap Secret
* **ConfigMap**存储非机密的配置数据 (配置文件环境变量)
* **Secret**存储机密数据 (密码Token证书) Etcd 中加密存储
* **Secret**存储机密数据 (密码Token证书)Secret 值默认只是 Base64 编码并存入 etcd生产环境应显式启用 etcd 静态加密或 KMS
通过将配置与镜像分离保证了容器的可移植性
@@ -114,3 +115,7 @@ metadata:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restricted
```
### 13.4.7 Sidecar Containers
Kubernetes 1.33 Sidecar Containers 进入 GA它们通过 `initContainers` 中带 `restartPolicy: Always` 的容器表达既保留 init container 的启动顺序又会在主容器生命周期内持续运行对于旧集群或不需要启动顺序控制的场景仍可使用普通多容器 Pod
+2 -2
View File
@@ -31,7 +31,7 @@ spec:
spec:
containers:
- name: nginx
image: nginx:1.30
image: nginx:1.28
ports:
- containerPort: 80
```
@@ -73,7 +73,7 @@ kubectl get svc nginx-service
### 13.5.4 步骤 3模拟滚动更新
修改 `nginx-deployment.yaml`将镜像版本改为 `nginx:1.30-alpine`
修改 `nginx-deployment.yaml`将镜像版本改为 `nginx:1.28-alpine`
```bash
kubectl apply -f nginx-deployment.yaml
+2
View File
@@ -6,6 +6,8 @@
Kubernetes 的最小调度单位是 `Pod`一个 `Pod` 由一组紧密协作的容器构成它们共享网络命名空间IP 以及部分存储资源也可以根据需要对 Pod 进行端口映射
如果你已经熟悉 Docker可以用以下对照来理解 Kubernetes 的核心概念Docker 中的容器对应 Kubernetes `Pod`一个或多个容器的组合`docker-compose.yml` 的角色类似于 Kubernetes `Deployment` + `Service` 声明`docker run` 的端口映射和网络配置 Kubernetes 中由 `Service` `Ingress` 接管掌握这些映射关系有助于从单机 Docker 平滑过渡到集群编排
本章将分为 5 节介绍 `Kubernetes`
* [简介](13.1_intro.md)
+17 -14
View File
@@ -138,12 +138,14 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用Kubernetes 1.36 文档仍将其列为已弃用模式并推荐迁移到 nftables新部署应使用默认的 iptables 模式或 nftables 模式Kubernetes 1.33+ 稳定以下 IPVS 配置仅供旧环境参考
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
@@ -172,21 +174,20 @@ $ sudo kubeadm init \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16 \
--cri-socket unix:///run/containerd/containerd.sock \
--v 5 \
--ignore-preflight-errors=all
--v 5
```
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关这里以 `flannel` 为例若后续部署其他类型的网络插件请更改此参数
> 执行可能出现错误例如缺少依赖包根据提示安装即可
> `kubeadm` 预检失败应按提示修复缺失依赖内核参数swap 或运行时配置实验环境确需忽略预检时只忽略明确理解且可接受的单项检查不建议使用 `--ignore-preflight-errors=all`
执行成功会输出
```bash
...
[addons] Applied essential addon: CoreDNS
I1116 12:35:13.270407 86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://192.168.199.100:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292 86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://192.168.199.100:6443/api/v1/namespaces/kube-system/configmaps
I1116 12:35:13.270407 86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292 86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/configmaps
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
@@ -203,8 +204,8 @@ Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH>
```
#### node 工作节点
@@ -216,12 +217,14 @@ $ systemctl enable containerd
$ systemctl start containerd
$ kubeadm join 192.168.199.100:6443 \
--token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
$ kubeadm join <CONTROL_PLANE_HOST>:6443 \
--token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH> \
--cri-socket unix:///run/containerd/containerd.sock
```
其中 `<CONTROL_PLANE_HOST>``<TOKEN>` `<DISCOVERY_TOKEN_CA_CERT_HASH>` 应使用你自己的 `kubeadm init` 输出不要复用示例值
### 14.1.7 查看服务
所有服务启动后通过 `crictl` 查看本地实际运行的容器这些服务大概分为三类主节点服务工作节点服务和其它服务
@@ -271,9 +274,9 @@ $ kubectl get node -o yaml | grep CIDR
podCIDRs:
```
```bash
# 注意v0.28.2 编写本文档时的最新版本请根据需要替换为当前版本
# 注意以下以 v0.28.4 示例安装前请到 releases 页面核验当前版本
# 参见 https://github.com/flannel-io/flannel/releases
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.2/Documentation/kube-flannel.yml
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.4/Documentation/kube-flannel.yml
```
### 14.1.10 master 节点默认不能运行 pod
+23 -19
View File
@@ -24,12 +24,12 @@
```bash
# 安装 cri-dockerd
# 注意v0.3.24 为编写本文档时的最新版本请根据需要替换为当前版本
# 注意以下以 v0.4.3 为示例安装前请到 releases 页面核验当前版本和校验值
# 参见 https://github.com/Mirantis/cri-dockerd/releases
$ cd /tmp
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.24/cri-dockerd-0.3.24.amd64.tgz
$ tar xzvf cri-dockerd-0.3.24.amd64.tgz
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.3/cri-dockerd-0.4.3.amd64.tgz
$ tar xzvf cri-dockerd-0.4.3.amd64.tgz
$ sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
# 下载并安装 systemd service 文件
@@ -54,12 +54,12 @@ $ sudo /usr/local/bin/cri-dockerd --version
```bash
# 安装 cri-dockerd
# 注意v0.3.24 为编写本文档时的最新版本请根据需要替换为当前版本
# 注意以下以 v0.4.3 为示例安装前请到 releases 页面核验当前版本和校验值
# 参见 https://github.com/Mirantis/cri-dockerd/releases
$ cd /tmp
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.24/cri-dockerd-0.3.24.amd64.tgz
$ tar xzvf cri-dockerd-0.3.24.amd64.tgz
$ wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.3/cri-dockerd-0.4.3.amd64.tgz
$ tar xzvf cri-dockerd-0.4.3.amd64.tgz
$ sudo mv cri-dockerd/cri-dockerd /usr/local/bin/
# 下载并安装 systemd service 文件
@@ -169,12 +169,14 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用Kubernetes 1.36 文档仍将其列为已弃用模式并推荐迁移到 nftables新部署应使用默认的 iptables 模式或 nftables 模式Kubernetes 1.33+ 稳定以下 IPVS 配置仅供旧环境参考
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
@@ -198,22 +200,21 @@ $ sudo systemctl daemon-reload
$ sudo kubeadm init --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16 \
--cri-socket unix:///var/run/cri-dockerd.sock \
--v 5 \
--ignore-preflight-errors=all
--v 5
```
* `--cri-socket unix:///var/run/cri-dockerd.sock` 参数指定使用 cri-dockerd 作为容器运行时接口
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关这里以 `flannel` 为例若后续部署其他类型的网络插件请更改此参数
> 执行可能出现错误例如缺少依赖包根据提示安装即可
> `kubeadm` 预检失败应按提示修复缺失依赖内核参数swap 或运行时配置实验环境确需忽略预检时只忽略明确理解且可接受的单项检查不建议使用 `--ignore-preflight-errors=all`
执行成功会输出
```bash
...
[addons] Applied essential addon: CoreDNS
I1116 12:35:13.270407 86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://192.168.199.100:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292 86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://192.168.199.100:6443/api/v1/namespaces/kube-system/configmaps
I1116 12:35:13.270407 86677 request.go:538] Throttling request took 181.409184ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/serviceaccounts
I1116 12:35:13.470292 86677 request.go:538] Throttling request took 186.088112ms, request: POST:https://<CONTROL_PLANE_HOST>:6443/api/v1/namespaces/kube-system/configmaps
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
@@ -230,8 +231,8 @@ Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH>
```
#### node 工作节点
@@ -239,10 +240,13 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
**另一主机** 重复 **部署** 小节以前的步骤安装配置好 kubelet根据提示加入到集群
```bash
$ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
$ kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
--discovery-token-ca-cert-hash sha256:<DISCOVERY_TOKEN_CA_CERT_HASH> \
--cri-socket unix:///var/run/cri-dockerd.sock
```
其中 `<CONTROL_PLANE_HOST>``<TOKEN>` `<DISCOVERY_TOKEN_CA_CERT_HASH>` 应使用你自己的 `kubeadm init` 输出不要复用示例值
### 14.2.7 查看服务
所有服务启动后查看本地实际运行的 Docker 容器这些服务大概分为三类主节点服务工作节点服务和其它服务
@@ -288,9 +292,9 @@ $ kubectl get node -o yaml | grep CIDR
podCIDRs:
```
```bash
# 注意v0.28.2 编写本文档时的最新版本请根据需要替换为当前版本
# 注意以下以 v0.28.4 示例安装前请到 releases 页面核验当前版本
# 参见 https://github.com/flannel-io/flannel/releases
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.2/Documentation/kube-flannel.yml
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.4/Documentation/kube-flannel.yml
```
### 14.2.10 master 节点默认不能运行 pod
+1 -1
View File
@@ -17,7 +17,7 @@ K3s 的安装非常简单,官方提供了便捷的安装脚本。
#### 脚本安装
K3s 提供了极为便捷的安装脚本
K3s 提供了极为便捷的安装脚本该命令会从网络下载脚本并直接交给 `sh` 执行生产环境建议先下载审查脚本内容并按官方文档固定版本或安装参数
```bash
curl -sfL https://get.k3s.io | sh -
+10 -4
View File
@@ -29,14 +29,20 @@ $ kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-pro
### 14.7.3 登录
创建管理员服务账户并获取登录令牌
为历史 Dashboard 创建只读服务账户并获取短期登录令牌不要为 Dashboard 创建 `cluster-admin` 绑定如果确实需要临时管理员权限应走单独的 break-glass 审批和审计流程
```bash
$ kubectl create sa dashboard-admin -n kubernetes-dashboard
$ kubectl create sa dashboard-readonly -n kubernetes-dashboard
$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin
$ kubectl create clusterrole dashboard-readonly \
--verb=get,list,watch \
--resource=pods,deployments,services,configmaps,namespaces,nodes
$ kubectl create token dashboard-admin -n kubernetes-dashboard
$ kubectl create clusterrolebinding dashboard-readonly \
--clusterrole=dashboard-readonly \
--serviceaccount=kubernetes-dashboard:dashboard-readonly
$ kubectl create token dashboard-readonly -n kubernetes-dashboard --duration=1h
```
将输出的令牌粘贴到登录页面即可登录
+5 -3
View File
@@ -193,10 +193,10 @@ $ kubectl label pods -l app=nginx version=v1
```bash
# 添加注解
$ kubectl annotate pod my-pod description=Production pod
$ kubectl annotate pod my-pod description="Production pod"
# 修改注解
$ kubectl annotate pod my-pod description=Staging pod --overwrite
$ kubectl annotate pod my-pod description="Staging pod" --overwrite
# 删除注解
$ kubectl annotate pod my-pod description-
@@ -240,8 +240,10 @@ $ kubectl config set-context --current --namespace=my-namespace
# 显示集群信息
$ kubectl cluster-info
# 显示完整的集群状态包括所有组件
# 显示完整的集群状态componentstatuses 1.19 起已弃用建议使用下方替代命令
$ kubectl get componentstatuses
# 推荐替代
$ kubectl get --raw='/readyz?verbose'
```
### 14.8.15 version
+6
View File
@@ -5,6 +5,7 @@
你可以使用以下几种方式部署 Kubernetes接下来的小节会对各种方式进行详细介绍
* [使用 kubeadm 部署 (CRI 使用 containerd)](14.1_kubeadm.md)
* Kubernetes 也支持 CRI-O 等符合 CRI 的运行时本文以 containerd 为主线
* [使用 kubeadm 部署 (使用 Docker)](14.2_kubeadm-docker.md)
* [ Docker Desktop 使用](14.3_docker-desktop.md)
* [Kind - Kubernetes IN Docker](14.4_kind.md)
@@ -12,3 +13,8 @@
* [一步步部署 Kubernetes 集群](14.6_systemd.md)
* [部署 Dashboard](14.7_dashboard.md)
* [Kubernetes 命令行 kubectl](14.8_kubectl.md)
除了上述方式企业生产环境中还有两个常见的部署工具值得关注
* **[KubeKey](https://github.com/kubesphere/kubekey)**KubeSphere 社区开源的集群部署工具(CNCF 认证),支持一条命令从裸机部署到高可用集群,内置对 containerd 和多 Linux 发行版的适配,适合需要快速搭建私有化 Kubernetes 的团队。
* **[RKE2](https://docs.rke2.io/)**SUSE Rancher 出品的安全加固型 Kubernetes 发行版,默认启用 CIS 基准合规、SELinux 支持和 etcd 自动快照,适合对安全审计有严格要求的企业场景。
+1 -1
View File
@@ -1,6 +1,6 @@
## 15.1 简介
> **版本说明** 本章内容基于 etcd 3.5 系列版本编写当前最新 v3.5.x请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
> **版本说明** 本章内容基于 etcd 3.5 系列版本编写官方维护最新两个次版本当前为 3.5 3.6请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
如图 15-1 所示etcd 项目使用该标识
+3 -3
View File
@@ -4,7 +4,7 @@
`etcd` 基于 `Go` 语言实现因此用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
> 注意etcd 官方仅维护最新两个次版本当前为 3.5 3.6本章示例基于 etcd `3.5.x` 版本编写etcd 3.6.x 可用于新部署请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
> 注意etcd 官方仅维护最新两个次版本当前为 3.5 3.6etcd 3.4 已于 2026 5 月结束支持EOL仍在使用 3.4 的用户应尽快升级本章示例基于 etcd `3.5.x` 版本编写etcd 3.6.x 可用于新部署请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
### 15.2.1 二进制文件方式下载
@@ -51,7 +51,7 @@ $ ETCDCTL_API=3 etcdctl member list
$ ETCDCTL_API=3 etcdctl put testkey "hello world"
OK
$ etcdctl get testkey
$ ETCDCTL_API=3 etcdctl get testkey
testkey
hello world
```
@@ -96,5 +96,5 @@ $ brew install etcd
$ etcd
$ etcdctl member list
$ ETCDCTL_API=3 etcdctl member list
```
+4 -2
View File
@@ -111,9 +111,11 @@ hello
```
支持的选项为
`--sort` 对结果进行排序
`--sort-by` 指定排序字段CREATE / KEY / MODIFY / VALUE / VERSION
`--consistent` 将请求发给主节点保证获取内容的一致性
`--order` 指定排序顺序ASCEND / DESCEND
`--consistency` 指定一致性级别`l` 线性一致`s` 串行
#### del
+3 -3
View File
@@ -2,7 +2,7 @@ version: "3.6"
services:
node1:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node1-data:/etcd-data
expose:
@@ -34,7 +34,7 @@ services:
- docker-etcd
node2:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node2-data:/etcd-data
networks:
@@ -66,7 +66,7 @@ services:
- docker-etcd
node3:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node3-data:/etcd-data
networks:
+1 -1
View File
@@ -7,7 +7,7 @@
| 特性 | Google GKE | AWS EKS | Azure AKS |
| :--- | :--- | :--- | :--- |
| **版本更新** | 最快通常是 K8s 新特性的首发地 | 相对保守注重稳定性 | 跟随社区更新速度适中 |
| **控制平面管理** | 全托管自动升级$0.10/h Free Tier 抵扣| 托管$0.10/h | 全托管控制平面免费 |
| **控制平面管理** | 全托管自动升级$0.10/h Free Tier 抵扣| 托管$0.10/h | 全托管Free 层适合开发/测试Standard/Premium 层默认包含 Uptime SLA |
| **节点管理** | GKE Autopilot 模式完全托管节点 | Managed Node Groups 简化管理 | Virtual Machine Scale Sets |
| **网络模型** | VPC-native, 性能优秀 | AWS VPC CNI, Pod 直接获取 VPC IP | Azure CNI (消耗 IP ) Kubenet |
| **集成度** | GCP 数据分析AI 服务集成紧密 | AWS IAM, ALB, CloudWatch 集成深度高 | Active Directory, Azure DevOps 集成好 |
+1 -1
View File
@@ -8,7 +8,7 @@
Skopeo 是一个由 Red Hat 赞助开源的命令行工具它可以在不需要运行容器守护进程 Docker Daemon的前提下对容器镜像进行极其高效的操作和管理包括检查复制删除和签名等操作
Skopeo 最大的特点是其可以在不将镜像拉取到本地的情况下直接在远端 Registry镜像仓库之间完成检查和搬运从而大幅度节省带宽和磁盘空间这也是它在容器运维和分发领域非常受欢迎的原因
Skopeo 最大的特点是其可以在不将镜像拉取到本地的情况下直接在远端 Registry镜像仓库之间完成检查和搬运从而大幅度节省带宽和磁盘空间这也是它在容器运维和分发领域非常受欢迎的原因
### 17.5.2 核心特性
+1 -1
View File
@@ -40,7 +40,7 @@
Kubernetes 作为一个容器编排系统为了屏蔽底层不同容器运行时的实现差异引入了 CRIContainer Runtime Interface标准
- 早期版本中Kubernetes 默认使用 docker 作为运行时通过一个名为 `dockershim` 的桥接组件对接 DockerDocker 再对接 containerd
- 随着 containerd 原生支持了 CRI 插件Kubernetes 开始直接与 containerd 通信去掉了 `dockershim` `dockerd` 的中间层这就是为什么从 Kubernetes 1.24+ 开始弃用 Docker引发了广泛关注实际上 Kubernetes 只是弃用 `dockershim`底层依然在使用 Docker 基因中诞生的 containerd参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。
- 随着 containerd 原生支持了 CRI 插件Kubernetes 开始直接与 containerd 通信去掉了 `dockershim` `dockerd` 的中间层这就是为什么从 Kubernetes 1.24+ 开始弃用 Docker引发了广泛关注实际上 Kubernetes 只是弃用 `dockershim`底层可以使用 containerdCRI-O 等符合 CRI 的运行时参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)。
- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口仅保留 CRI v1Kubernetes 1.26+ 仅支持 CRI v1如果集群中仍有依赖 CRI v1alpha2 的组件升级 containerd 2.x 前需先完成迁移containerd 2.3+ 2.x 系列首个 LTS 版本支持从 1.7 LTS 直接升级生产环境推荐使用详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。
### 17.6.3 为什么直接使用 containerd
+1 -1
View File
@@ -10,7 +10,7 @@
尽管这种方式在性能和启动速度上拥有巨大优势但也带来了一个显著的缺点**隔离性Isolation不足**如果某个容器内的恶意进程利用了宿主机内核的漏洞完成了越狱Privilege Escalation它将对整个宿主机以及其上运行的所有其他容器造成毁灭性威胁
如果在公有云环境多租户场景或运行不可信的第三方代码时共享内核显然是不够安全的为了解决这一问题社区推出了安全容器Secure Containers/Sandboxed Containers的概念安全容器的核心理念是提供类似虚拟机的强隔离性同时保持类似容器的轻量快速启动和标准化管理
如果在公有云环境多租户场景或运行不可信的第三方代码时共享内核显然是不够安全的为了解决这一问题社区推出了安全容器Secure Containers/Sandboxed Containers的概念安全容器的核心理念是提供类似虚拟机的强隔离性同时保持类似容器的轻量快速启动和标准化管理
### 17.7.2 什么是 Kata Containers
+8 -1
View File
@@ -1,12 +1,19 @@
# 第十七章 容器其它生态
> **版本说明**本章介绍的工具和运行时PodmanBuildahSkopeocontainerdKata ContainersgVisorWasmEdge 都保持活跃的开发建议
> **版本说明核验日期2026-05-16**本章介绍的工具和运行时PodmanBuildahSkopeocontainerdKata ContainersgVisorWasmEdge 都保持活跃的开发建议
> - 查阅各项目官方文档获取最新版本
> - 在生产环境使用前验证版本兼容性
> - 关注官方发布说明了解重大变更
本章将介绍 Docker Kubernetes 之外的容器生态技术
同时Docker 自身的生态也在向云构建AI 本地推理和企业级桌面安全扩展当前需要额外关注
* **Docker Model Runner** Docker Desktop / Docker Engine 中管理运行和服务本地 AI 模型支持 OpenAI Ollama 兼容 API并可将 GGUFSafetensors 等模型文件作为 OCI Artifact 管理
* **Docker Build Cloud**通过远程 BuildKit 和共享构建缓存加速本地与 CI 构建适合多平台镜像和团队共享缓存场景
* **Docker Offload**把容器构建和运行卸载到云端适合 VDI受限本机或不支持嵌套虚拟化的开发环境
* **Hardened Docker Desktop / Enhanced Container Isolation (ECI)**通过更强的命名空间隔离敏感挂载保护和系统调用限制降低桌面容器逃逸风险
## 本章内容
* [Fedora CoreOS 简介](17.1_coreos_intro.md)
-7
View File
@@ -1,7 +0,0 @@
## Fedora CoreOS
`CoreOS` 是一个专门为安全和大规模运行容器化工作负载而构建的新 Fedora 版本它继承了 Fedora Atomic Host CoreOS Container Linux 的优势
`CoreOS` 的安装文件和运行依赖非常小它提供了精简的 Linux 系统它使用 Linux 容器在更高的抽象层来管理你的服务而不是通过常规的包管理工具 `yum` `apt` 来安装包
同时`CoreOS` 几乎可以运行在任何平台`VirtualBox` `Amazon EC2` `QEMU/KVM` `VMware` `Bare Metal` `OpenStack`
+1 -1
View File
@@ -14,7 +14,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
尽管命名空间提供了很好的隔离性但我们必须认识到**所有的容器依然共享同一个宿主机的 Linux 内核**
这意味着一旦宿主机的内核存在提权漏洞如著名的 Dirty COW 漏洞攻击者有可能通过突破 Namespace 的限制直接在内核层面执行恶意代码从而实现容器逃逸
这意味着一旦宿主机的内核存在提权漏洞如著名的 Dirty COW 漏洞攻击者有可能通过突破 Namespace 的限制直接在内核层面执行恶意代码从而实现容器逃逸
> [!WARNING]
> 为了缓解内核漏洞带来的威胁生产环境务必保持宿主机 Linux 内核的及时修补与更新或者借助诸如 gVisorKata Containers 等提供了独立内核的安全容器技术同时需要及时修补容器运行时 runC的漏洞2025 11 月披露的一系列 runC 容器逃逸漏洞CVE-2025-31133CVE-2025-52565CVE-2025-52881就表明即使内核保持更新运行时层的缺陷仍然可能导致容器隔离被突破
+10 -5
View File
@@ -50,13 +50,13 @@ dockerd \
### 18.3.3 Rootless 模式非特权运行
为了从根本上解决拥有 Docker socket 就是 root的问题Docker 在近年推出 **Rootless 模式**
为了从根本上解决拥有 Docker socket 就是 root的问题Docker 19.03 版本2019 起提供 **Rootless 模式**
Rootless 模式允许在完全局限于非 `root` 用户的环境中运行 Docker 守护进程`dockerd`和容器该模式利用了现代 Linux 内核的 User Namespace 技术和非特权网络命名空间实现
#### 配置运行 Rootless Docker
要在非 root 环境中运行 Docker需要简单几步
要在非 root 环境中运行 Docker需要先满足宿主机条件安装 `newuidmap` / `newgidmap`并在 `/etc/subuid` `/etc/subgid` 中为该用户分配足够的 subordinate UID/GID若系统级 Docker daemon 仍在运行命令行也仍可能连到 rootful socket因此应明确切换 Docker context `DOCKER_HOST`
1. 安装必要的依赖通常是 `uidmap` 工具包以便系统支持 `newuidmap` `newgidmap`
```bash
@@ -68,9 +68,11 @@ $ sudo apt-get install uidmap
$ su - testuser
```
3. 运行 Docker 官方提供的 Rootless 安装脚本
3. 下载并检查 Docker 官方提供的 Rootless 安装脚本确认来源和内容后再执行
```bash
$ curl -fsSL https://get.docker.com/rootless | sh
$ curl -fsSL https://get.docker.com/rootless -o install-rootless-docker.sh
$ less install-rootless-docker.sh
$ sh install-rootless-docker.sh
```
4. 配置环境变量指向新创建的私有 socket
@@ -80,6 +82,9 @@ $ docker version
```
安装并暴露相应的配置后该用户的环境将能独立启动属于他自己的 Docker Daemon即使由于某些未知 0-Day 漏洞使得攻击者突破了容器他们也只会受限于 `testuser` 这个非特权用户所在的有限系统环境内
> [!NOTE]
> Rootless 模式不是无条件替代 rootful Docker端口绑定网络cgroup存储驱动和系统服务自启动能力都受发行版内核与 systemd 用户服务配置影响生产环境应先验证具体工作负载并用 `loginctl enable-linger <user>` 等方式显式配置开机自启动
### 18.3.4 授权插件Authorization Plugin与访问策略
在企业环境中 Docker 守护进程的访问控制往往不仅限于文件系统权限还需要更细粒度的授权策略**Authorization Plugin** 机制允许在 API 层级对请求进行拦截和审批
@@ -110,4 +115,4 @@ $ docker version
### 18.3.5 结语
保障 Docker 服务端的安全主要是做减法关闭不必要的网络监听点严管 Socket 访问权限而一旦基础系统条件允许**毫不犹豫地在生产环境启用 Rootless 模式** 将是一项划算的安全加固选择
保障 Docker 服务端的安全主要是做减法关闭不必要的网络监听点严管 Socket 访问权限基础系统网络和存储约束都验证通过后Rootless 模式是一项值得优先评估的安全加固选择
+7 -3
View File
@@ -8,7 +8,7 @@
一个普通的 Linux 内核提供了 300 多个系统调用而一个正常运行的容器化应用例如 Nginx 服务通常只会用到几十个调用这就给攻击者留下了大量的闲置入口点来进行内核层的缓冲区溢出攻击
Docker 默认启用了 Seccomp 用预置的 [默认配置文件](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 将可以利用的系统调用缩减到了不足一半(默认禁用 44 个危险的统调用,比如修改时区或重启系统)
Docker 默认启用了 Seccomp使用预置的 [默认配置文件](https://docs.docker.com/engine/security/seccomp/) 作为 allowlist:默认拒绝未显式允许的系统调用,并额外允许常见应用所需的调用。Docker 官方文档将其描述为默认禁用 44 个系统调用(内核与 Docker 版本不同会有差异),例如与内核模块、系统重启或特权命名空间操作相关的调用
如果你对应用的系统调用特征了如指掌你可以为容器定制专属规则
@@ -44,8 +44,8 @@ chmod: /etc/passwd: Operation not permitted
在开启了上述机制的机器上
- **AppArmor**: Docker 为所有启动的应用加载了一个默认的 `docker-default` 模板文件如果你的某些异常写行为比如往特殊的内核心脏目录写入配置不在 AppArmor 许可列表之上即使拥有物理 Root写入同样失败
- **SELinux**: 所有的 Docker 操作强制附加特殊上下文标识标签就算把主机的 `/` 绑定给了黑客的某服务黑客对不属于 Docker 可见的标签的文件进行读写尝试亦会被阻止
- **AppArmor**: 在启用 AppArmor 的系统上Docker 默认为容器加载 `docker-default` profile如果需要自定义策略先用 `apparmor_parser` 加载 profile再通过 `--security-opt apparmor=<profile>` 指定
- **SELinux**: 在启用 SELinux 集成的系统上容器与挂载目录需要正确的 SELinux label绑定挂载时常用 `:z` 表示多个容器共享`:Z` 表示该挂载只给单个容器使用不要对 `/home``/usr` 等系统目录随意使用 `:Z`否则可能破坏宿主机标签
如果想为某些受信任应用施加特定的外部强化文件策略可以通过如下方法指派规则表
@@ -53,6 +53,10 @@ chmod: /etc/passwd: Operation not permitted
$ docker run --rm -it \
--security-opt apparmor=custom-nginx-profile \
nginx
$ docker run --rm -it \
-v "$PWD/html":/usr/share/nginx/html:Z \
nginx
```
### 18.5.3 容器镜像漏洞静态扫描
+70 -61
View File
@@ -20,7 +20,9 @@ Trivy 是由 Aqua Security 开发的开源漏洞扫描器,以其轻量级、
```bash
# 安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh -o install-trivy.sh
less install-trivy.sh # 先审阅脚本内容
sudo sh install-trivy.sh -b /usr/local/bin
# 扫描本地镜像
trivy image nginx:latest
@@ -58,7 +60,9 @@ Grype 由 Anchore 开发,支持更广泛的软件包管理器和语言。
```bash
# 安装 Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh -o install-grype.sh
less install-grype.sh
sudo sh install-grype.sh -b /usr/local/bin
# 扫描镜像
grype docker:nginx:latest
@@ -77,7 +81,7 @@ Snyk 提供了商业级的安全扫描服务,特别适合企业环境。
**特点**
- 支持开源漏洞和许可证扫描
- 支持开源漏洞许可证扫描和修复建议
- 与多个 Git 平台深度集成GitHubGitLabBitbucket
- 提供修复建议和自动化修复 PR
- 支持 Kubernetes 部署后安全监控
@@ -114,7 +118,7 @@ $ docker scout quickview myapp:latest
| Docker 集成 | 原生 | 需安装 | 需安装 | 需安装 |
| 零依赖 | | | | |
| 离线模式 | | | | |
| 许可证扫描 | | | | |
| 许可证扫描 | | | | |
| 自动修复建议 | | | | |
| 开源免费 | 部分 | | | 部分 |
| IDE 集成 | | | | |
@@ -130,7 +134,9 @@ Syft 是 Anchore 推出的专业 SBOM 生成工具。
**安装**
```bash
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh -o install-syft.sh
less install-syft.sh
sudo sh install-syft.sh -b /usr/local/bin
```
**生成 SBOM**
@@ -234,8 +240,9 @@ cosign generate-key-pair
**签名镜像**
```bash
# 使用私钥签名推送到仓库前
cosign sign --key cosign.key myregistry.com/myapp:v1.0.0
# 先推送镜像再使用不可变 digest 签名
IMAGE_DIGEST="myregistry.com/myapp@sha256:<digest>"
cosign sign --key cosign.key "$IMAGE_DIGEST"
# 系统会提示输入私钥密码
```
@@ -243,7 +250,7 @@ cosign sign --key cosign.key myregistry.com/myapp:v1.0.0
```bash
# 使用公钥验证
cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0
cosign verify --key cosign.pub "$IMAGE_DIGEST"
# 输出结果示例
# Verification successful!
@@ -260,10 +267,10 @@ cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0
```bash
# GitHub Actions CI 中无需存储密钥
cosign sign --yes myregistry.com/myapp:v1.0.0
cosign sign --yes "$IMAGE_DIGEST"
# 验证时自动使用 OIDC 令牌验证身份
cosign verify myregistry.com/myapp:v1.0.0 \
cosign verify "$IMAGE_DIGEST" \
--certificate-identity https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```
@@ -272,16 +279,13 @@ cosign verify myregistry.com/myapp:v1.0.0 \
> **注意DCT 退役时间线**
>
> Docker 已宣布[退役 Content Trust](https://www.docker.com/blog/retiring-docker-content-trust/)。关键节点:
> - 2025 8 月起最早一批 DCT 签名证书开始过期
> - 2025 9 30 日起新注册表不可再启用 DCT
> - **2028 3 31 **DCT 完全移除所有 DCT 数据永久删除
> Docker 已宣布[退役 Content Trust](https://www.docker.com/blog/retiring-docker-content-trust/)Docker Official Images 的部分 DCT 签名证书自 2025 年 8 月起已陆续过期;完整退役节奏应以 Docker 官方公告和你所使用的 registry 服务商文档为准。不要把云厂商特定日期直接当作 Docker 全局时间线
>
> 建议新项目直接使用上文介绍的 **Cosign (Sigstore)** 进行镜像签名现有 DCT 用户应尽早制定迁移计划
> 新项目应优先使用上文介绍的 **Cosign (Sigstore)** registry 原生签名/证明能力现有 DCT 用户应先盘点依赖验证替代方案制定迁移计划
Docker Content Trust 使用 Notary 实现镜像签名 Docker 官方的传统签名解决方案
**启用 DCT**
**历史用法示例不建议新项目采用**
```bash
# 在环境中启用 DCT
@@ -301,8 +305,8 @@ docker push --disable-content-trust myregistry.com/myapp:v1.0.0
# 首次推送时会提示创建 Delegation Key
# 密钥存储在 ~/.docker/trust/private/root_keys/ ~/.docker/trust/private/tuf_keys/
# 查看签名信息
docker inspect --format='{{.RepoDigests}}' myregistry.com/myapp:v1.0.0
# 查看 DCT/Notary 信任数据RepoDigests 只是内容摘要不等于签名验证
docker trust inspect --pretty myregistry.com/myapp:v1.0.0
```
### 18.6.4 供应链安全最佳实践
@@ -316,27 +320,20 @@ RUN apt-get update && apt-get install -y curl
# 推荐固定基础镜像版本和摘要
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e6e0e14...完整 64 位哈希
RUN apt-get update && apt-get install -y curl=7.68.0-1ubuntu1
RUN apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
```
#### 2. 构建时扫描
Dockerfile 中集成安全扫描
CI/CD 构建阶段集成安全扫描避免在 Dockerfile 里从分支 URL 下载并执行远程安装脚本
```dockerfile
FROM golang:1.26-alpine AS builder
WORKDIR /app
COPY . .
# 使用 Trivy 扫描源代码
RUN apk add --no-cache curl && \
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin && \
trivy fs . --exit-code 1 --severity HIGH,CRITICAL
RUN go build -o app .
FROM alpine:3.17@sha256:abcd1234...请替换为实际完整的 64 位摘要哈希
COPY --from=builder /app/app /app
```bash
docker run --rm \
-v "$PWD:/work" \
-w /work \
aquasec/trivy:latest \
fs . --exit-code 1 --severity HIGH,CRITICAL
```
#### 3. 运行时镜像扫描策略
@@ -417,6 +414,7 @@ jobs:
contents: read
packages: write
security-events: write
id-token: write
steps:
- name: Checkout code
@@ -425,7 +423,11 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Build Docker image
- name: Install Cosign
if: github.event_name == 'push'
uses: sigstore/cosign-installer@v3
- name: Build Docker image for scan
uses: docker/build-push-action@v7
with:
context: .
@@ -434,8 +436,8 @@ jobs:
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Run Trivy vulnerability scan
# 安全提醒2026 3 Trivy GitHub Actions 遭受供应链攻击
# 75 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 安全提醒2026 3 19 Trivy GitHub Actions 遭受供应链攻击
# 76 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
@@ -462,25 +464,27 @@ jobs:
name: sbom
path: sbom-cyclonedx.json
- name: Sign image with Cosign
if: github.event_name == 'push'
run: |
cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Login to Registry and Push
if: github.event_name == 'push'
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
if: github.event_name == 'push'
id: build-push
uses: docker/build-push-action@v7
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Sign image with Cosign
if: github.event_name == 'push'
run: |
cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-push.outputs.digest }}
```
#### GitLab CI 工作流示例
@@ -489,8 +493,8 @@ jobs:
stages:
- build
- scan
- sign
- push
- sign
variables:
REGISTRY: registry.gitlab.com
@@ -498,52 +502,57 @@ variables:
build:
stage: build
image: docker:latest
image: docker:<version>-cli@sha256:<docker-cli-digest>
services:
- docker:dind
- name: docker:<version>-dind@sha256:<docker-dind-digest>
script:
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker save $IMAGE_NAME:$CI_COMMIT_SHA > image.tar
scan:trivy:
stage: scan
image: aquasec/trivy:latest
image: aquasec/trivy:<version>@sha256:<trivy-digest>
script:
- trivy image --severity HIGH,CRITICAL --exit-code 1 docker-archive://image.tar
allow_failure: false
scan:grype:
stage: scan
image: anchore/grype:latest
image: anchore/grype:<version>@sha256:<grype-digest>
script:
- grype docker-archive://image.tar
generate:sbom:
stage: scan
image: anchore/syft:latest
image: anchore/syft:<version>@sha256:<syft-digest>
script:
- syft docker-archive://image.tar -o cyclonedx > sbom.xml
artifacts:
reports:
sbom: sbom.xml
sign:
stage: sign
image: gcr.io/projectsigstore/cosign:latest
push:
stage: push
image: docker:<version>-cli@sha256:<docker-cli-digest>
services:
- name: docker:<version>-dind@sha256:<docker-dind-digest>
script:
- cosign sign --key $COSIGN_KEY $IMAGE_NAME:$CI_COMMIT_SHA
- docker load < image.tar
- echo "$REGISTRY_PASSWORD" | docker login --username "$REGISTRY_USER" --password-stdin "$REGISTRY"
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- DIGEST=$(docker buildx imagetools inspect "$IMAGE_NAME:$CI_COMMIT_SHA" --format '{{.Manifest.Digest}}')
- echo "$IMAGE_NAME@$DIGEST" > image-digest.txt
artifacts:
paths:
- image-digest.txt
only:
- main
push:
stage: push
image: docker:latest
services:
- docker:dind
sign:
stage: sign
image: gcr.io/projectsigstore/cosign:<version>@sha256:<cosign-digest>
script:
- docker load < image.tar
- docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $REGISTRY
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
- cosign sign --key $COSIGN_KEY "$(cat image-digest.txt)"
only:
- main
```
+9 -1
View File
@@ -1,6 +1,14 @@
## 本章小结
Docker 的安全性依赖于多层隔离机制的协同工作同时需要用户遵循最佳实践
Docker 的安全性依赖于多层隔离机制的协同工作同时需要用户遵循最佳实践本章涵盖的核心安全维度包括
| 维度 | 关键措施 |
|------|---------|
| **内核隔离** | Namespace 隔离进程/网络/文件系统Cgroups 限制资源使用 |
| **权限控制** | root 运行`--cap-drop ALL` 最小能力集`--read-only` 只读根文件系统 |
| **镜像安全** | 使用可信基础镜像定期扫描漏洞Trivy / Snyk启用 Docker Content Trust 签名验证 |
| **运行时防护** | Seccomp 系统调用过滤AppArmor / SELinux 强制访问控制 |
| **网络隔离** | 自定义 bridge 网络隔离容器通信限制容器对宿主机网络的访问 |
总体来看Docker 容器还是十分安全的特别是在容器内不使用 root 权限来运行进程的话
+4 -4
View File
@@ -160,10 +160,10 @@ $ docker compose up -d
* **节点 CPU 使用率**`100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)`
* **节点内存使用率**`(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100`
* **节点磁盘空间使用率**`(1 - (node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"})) * 100`
* **容器 CPU**`sum by (name) (rate(container_cpu_usage_seconds_total[5m]))`
* **容器内存**`sum by (name) (container_memory_working_set_bytes)`
* **容器 CPU**`sum by (namespace, pod, container) (rate(container_cpu_usage_seconds_total[5m]))`
* **容器内存**`sum by (namespace, pod, container) (container_memory_working_set_bytes)`
说明不同版本 cAdvisor/Docker label 命名可能存在差异 ( `name``container``container_name`)如果查询为空建议先用 `label_values(container_cpu_usage_seconds_total, __name__)` Prometheus 图形界面查看可用 label
说明不同采集路径 label 命名不同Docker Compose 中独立部署的 cAdvisor 常见容器标签是 `name`Kubernetes kubelet `/metrics/cadvisor` `container_cpu_usage_seconds_total` 等稳定指标使用 `container``pod``namespace`如果查询为空先直接查询 `container_cpu_usage_seconds_total` 样本并 Prometheus 图形界面查看实际 label不要假设存在 `container_name`
#### Targets down 排错清单
@@ -245,7 +245,7 @@ receivers:
```yaml
alertmanager:
image: prom/alertmanager:v0.27.0
image: prom/alertmanager:v0.32.0
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
+2 -2
View File
@@ -22,7 +22,7 @@ ELK (ElasticsearchLogstashKibana) 是目前业界最流行的开源日志
```yaml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:9.3.3
image: docker.elastic.co/elasticsearch/elasticsearch:9.4.0
container_name: elasticsearch
environment:
- "discovery.type=single-node"
@@ -36,7 +36,7 @@ services:
- logging
kibana:
image: docker.elastic.co/kibana/kibana:9.3.3
image: docker.elastic.co/kibana/kibana:9.4.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
@@ -66,8 +66,11 @@ docker stats nginx redis
# 一次性输出不进入交互模式
docker stats --no-stream
# 指定刷新间隔单位默认 1
docker stats --no-stream --interval 2
# 2 秒采样一次docker stats 没有 --interval 选项
while true; do
docker stats --no-stream
sleep 2
done
# 格式化输出使用 Go 模板
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" --no-stream
@@ -100,6 +103,8 @@ done
cAdvisor Google 开发的容器监控工具提供比 `docker stats` 更详细的性能数据
> ** 安全权衡提示**下面的示例为简化部署使用了 `privileged: true` [ 18 ](../18_security/README.md) 最小权限 / `cap_drop=all`的原则相冲突生产环境建议改为按需授予能力 `cap_add: [SYS_ADMIN]` `device_cgroup_rules` 与精确的 `devices``volumes` 挂载并将 cAdvisor 部署在独立的监控网络中如何选择请参考 [18.4 ](../18_security/18.4_kernel_capability.md) 关于内核能力capabilities的细化授权
**Docker Compose 部署 cAdvisor**
```yaml
@@ -180,6 +185,8 @@ services:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
extra_hosts:
- "host.docker.internal:host-gateway"
networks:
- monitoring
@@ -256,7 +263,7 @@ scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['localhost:9323']
- targets: ['host.docker.internal:9323']
```
**常用的 Prometheus 查询PromQL**
@@ -274,7 +281,7 @@ rate(container_network_receive_bytes_total[5m]) / 1024 / 1024
rate(container_network_transmit_bytes_total[5m]) / 1024 / 1024
# 容器磁盘读取速率MB/s
rate(container_fs_io_current[5m]) / 1024 / 1024
rate(container_fs_reads_bytes_total[5m]) / 1024 / 1024
# CPU 限流情况
rate(container_cpu_cfs_throttled_seconds_total[5m])
@@ -623,5 +630,6 @@ docker exec <container_id> ping 8.8.8.8
docker inspect <container_id> | grep -A 10 NetworkSettings
# 解决方案更换网络驱动或调整 MTU
docker run --net=host myapp:latest # 使用宿主机网络性能最佳
# host 网络可降低网络栈开销但会放弃容器网络隔离仅在明确接受安全边界变化时使用
docker run --net=host myapp:latest
```
+1 -1
View File
@@ -9,7 +9,7 @@
- **容器监控** Prometheus 为主讲解如何采集和展示容器性能指标
- **日志管理** ELK (Elasticsearch, Logstash, Kibana) 套件为例介绍集中式日志收集平台
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
* 关键指标与日志的验证方法
* 常见故障排查路径
+1 -1
View File
@@ -5,7 +5,7 @@
* **指标监控** Prometheus + Grafana 为主完成指标采集存储与可视化
* **日志管理** EFK/ELK 为例完成容器日志的集中采集检索与分析
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
## 扩展阅读Docker 日志驱动
+10 -10
View File
@@ -25,7 +25,7 @@ Debian 是一个常用的基础镜像。
```bash
$ docker run -it debian bash
root@668e178d8d69:/# cat /etc/issue
Debian GNU/Linux 12
Debian GNU/Linux 13
```
`Debian` 镜像很适合作为基础镜像构建自定义镜像
@@ -36,25 +36,25 @@ Debian GNU/Linux 12
![Ubuntu 操作系统](../_images/ubuntu-logo.jpg)
`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统其名称来自非洲南部祖鲁语或豪萨语的 ubuntu 一词 (官方译名 友帮拓另有 吾帮托乌班图有奔头 乌斑兔 等译名)`Ubuntu` 意思是 人性 以及 我的存在是因为大家的存在是非洲传统的一种价值观类似华人社会的 仁爱 思想`Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境 `Debian` 的不同在于它每 6 个月会发布一个新版本 2 年推出一个长期支持 **(Long Term SupportLTS)** 版本一般支持 3 时间
`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统其名称来自非洲南部祖鲁语或豪萨语的 ubuntu 一词 (官方译名 友帮拓另有 吾帮托乌班图有奔头 乌斑兔 等译名)`Ubuntu` 意思是 人性 以及 我的存在是因为大家的存在是非洲传统的一种价值观类似华人社会的 仁爱 思想`Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境 `Debian` 的不同在于它每 6 个月会发布一个新版本 2 年推出一个长期支持 **(Long Term SupportLTS)** 版本LTS 版本通常提供 5 标准安全维护Ubuntu Pro/ESM 可进一步延长安全覆盖
#### 使用 Ubuntu 官方镜像
Ubuntu 是目前最流行的 Linux 发行版之一
下面以 `ubuntu:24.04` 为例演示如何使用该镜像安装一些常用软件
下面以 `ubuntu:26.04` 为例演示如何使用该镜像安装一些常用软件
首先使用 `-ti` 参数启动容器登录 `bash`查看 `ubuntu` 的发行版本号
```bash
$ docker run -ti ubuntu:24.04 /bin/bash
$ docker run -ti ubuntu:26.04 /bin/bash
root@7d93de07bf76:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
PRETTY_NAME="Ubuntu 26.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
VERSION_ID="26.04"
VERSION="26.04 LTS (Resolute Raccoon)"
VERSION_CODENAME=resolute
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
@@ -74,8 +74,8 @@ E: Unable to locate package curl
```bash
root@7d93de07bf76:/# apt-get update
Get:1 http://archive.ubuntu.com/ubuntu noble InRelease [256 kB]
Get:2 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Get:1 http://archive.ubuntu.com/ubuntu resolute InRelease [256 kB]
Get:2 http://security.ubuntu.com/ubuntu resolute-security InRelease [126 kB]
...
Fetched 25.8 MB in 8s (3215 kB/s)
Reading package lists... Done
+2 -2
View File
@@ -2,7 +2,7 @@
### 20.4.1 CentOS 系统简介
`CentOS` `Fedora` 都是基于 `Redhat` 的常见 Linux 分支`CentOS` 目前企业级服务器的常用操作系统`Fedora` 则主要面向个人桌面用户
`CentOS` `Fedora` 都是基于 `Redhat` 的常见 Linux 分支传统 `CentOS Linux` 是企业级服务器的常用操作系统但相关 Docker 官方镜像已停止维护新部署通常应评估 Rocky LinuxAlmaLinuxCentOS Stream 或直接使用 RHEL/UBI 等替代方案`Fedora` 则主要面向个人桌面用户
![CentOS 操作系统](../_images/centos-logo.png)
@@ -50,7 +50,7 @@ latest: Pulling from library/fedora
Digest: sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e
Status: Downloaded newer image for fedora:latest
[root@196ca341419b /]# cat /etc/redhat-release
Fedora release 39 (Thirty Nine)
Fedora release 43 (Forty Three)
```
### 20.4.3 相关资源
+1 -1
View File
@@ -8,7 +8,7 @@
本章示例中使用的操作系统镜像版本遵循以下原则
- **AlpineDebianUbuntuCentOS** 等操作系统镜像采用大版本或次版本标签 `alpine:3.21``ubuntu:24.04`避免使用 `latest` 标签确保构建的可再现性
- **AlpineDebianUbuntuCentOS** 等操作系统镜像采用大版本或次版本标签 `alpine:3.21``ubuntu:26.04`避免使用 `latest` 标签确保构建的可再现性
- **OS 大版本保留**以便获得最新的安全补丁和修复
- 在生产环境中建议根据实际需求选择合适的版本并定期更新以获得安全修复

Some files were not shown because too many files have changed in this diff Show More