369 Commits

Author SHA1 Message Date
Baohua Yang
70cab9e92d release v1.6.0 2026-02-27 22:29:50 -08:00
github-actions[bot]
67547c0c3e Merge pull request #559 from yeasy/dependabot/npm_and_yarn/dependencies-8b11ed37b5
chore(deps): bump the dependencies group with 2 updates
2026-02-28 05:57:27 +00:00
dependabot[bot]
0d012c2d27 chore(deps): bump the dependencies group with 2 updates
Bumps the dependencies group with 2 updates: [chalk](https://github.com/chalk/chalk) and [vuepress](https://github.com/vuejs/vuepress/tree/HEAD/packages/vuepress).


Updates `chalk` from 4.1.2 to 5.6.2
- [Release notes](https://github.com/chalk/chalk/releases)
- [Commits](https://github.com/chalk/chalk/compare/v4.1.2...v5.6.2)

Updates `vuepress` from 1.8.2 to 1.9.10
- [Release notes](https://github.com/vuejs/vuepress/releases)
- [Changelog](https://github.com/vuejs/vuepress/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vuepress/commits/v1.9.10/packages/vuepress)

---
updated-dependencies:
- dependency-name: chalk
  dependency-version: 5.6.2
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: vuepress
  dependency-version: 1.9.10
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 05:57:17 +00:00
Baohua Yang
1eddef954e Enable auto bump 2026-02-27 21:55:34 -08:00
Baohua Yang
6baf2c68f2 Minor fix words 2026-02-27 20:23:35 -08:00
github-actions[bot]
fd28d966ca Merge pull request #556 from yeasy/dependabot/npm_and_yarn/commander-14.0.3
chore(deps): bump commander from 7.2.0 to 14.0.3
2026-02-28 03:32:10 +00:00
dependabot[bot]
ba0c388384 chore(deps): bump commander from 7.2.0 to 14.0.3
Bumps [commander](https://github.com/tj/commander.js) from 7.2.0 to 14.0.3.
- [Release notes](https://github.com/tj/commander.js/releases)
- [Changelog](https://github.com/tj/commander.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tj/commander.js/compare/v7.2.0...v14.0.3)

---
updated-dependencies:
- dependency-name: commander
  dependency-version: 14.0.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 03:31:56 +00:00
github-actions[bot]
fc4f1ce2d0 Merge pull request #555 from yeasy/dependabot/npm_and_yarn/honkit-6.1.6
chore(deps): bump honkit from 5.1.5 to 6.1.6
2026-02-28 03:31:55 +00:00
dependabot[bot]
276eb356a2 chore(deps): bump honkit from 5.1.5 to 6.1.6
Bumps [honkit](https://github.com/honkit/honkit) from 5.1.5 to 6.1.6.
- [Release notes](https://github.com/honkit/honkit/releases)
- [Changelog](https://github.com/honkit/honkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/honkit/honkit/compare/v5.1.5...v6.1.6)

---
updated-dependencies:
- dependency-name: honkit
  dependency-version: 6.1.6
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 03:31:43 +00:00
github-actions[bot]
246fc35c8e Merge pull request #554 from yeasy/dependabot/github_actions/actions/checkout-6.0.2
chore(deps): bump actions/checkout from 4.1.1 to 6.0.2
2026-02-28 03:31:04 +00:00
dependabot[bot]
745b7c812a chore(deps): bump actions/checkout from 4.1.1 to 6.0.2
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4.1.1...v6.0.2)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 03:30:50 +00:00
Baohua Yang
ad3b86d727 Allow auto bump dependencies 2026-02-27 19:30:13 -08:00
Baohua Yang
16e884da51 Add more terms 2026-02-27 19:24:38 -08:00
Baohua Yang
5bd2c37c54 Add more tools 2026-02-27 19:23:50 -08:00
Baohua Yang
19aaad591c Reduce image size 2026-02-27 19:23:28 -08:00
Baohua Yang
bbfc9d34ff chore: remove version lock from plugins list 2026-02-27 13:52:22 -08:00
Baohua Yang
ecab788013 Add more content and fix format 2026-02-25 21:06:21 -08:00
Baohua Yang
dd449bc84f Minor fix level 2026-02-25 08:40:01 -08:00
Baohua Yang
d6e0838807 Simplify words and fix format issues 2026-02-24 22:01:02 -08:00
Baohua Yang
c44cbfcd62 Fix all missed links 2026-02-24 21:06:40 -08:00
Baohua Yang
c6e2ab8a4a Fix missing links 2026-02-24 13:01:16 -08:00
Baohua Yang
669da56662 Use list for simple content 2026-02-23 09:06:27 -08:00
Baohua Yang
4941ef171c Update figure 2026-02-23 08:56:56 -08:00
Baohua Yang
572266b2f4 Fix wrong links 2026-02-22 16:04:41 -08:00
Baohua Yang
4ca47b0ea1 Split chapter 20 2026-02-22 15:33:20 -08:00
Baohua Yang
24d26c0797 Fix double quotes 2026-02-22 14:54:52 -08:00
Baohua Yang
e57704271d Fix missing links 2026-02-22 13:40:20 -08:00
Baohua Yang
92ea9623b2 Fix naming of the chapter dir 2026-02-22 12:42:15 -08:00
Baohua Yang
b9ac198f19 Add number to section names 2026-02-22 08:37:51 -08:00
Baohua Yang
185da0cf88 Fix period mark 2026-02-21 22:44:57 -08:00
Baohua Yang
8965f084eb Update content 2026-02-21 22:42:46 -08:00
Baohua Yang
175aaae48a style(docs): standardize heading formats and numbering
- Enforce Level 1-3 structural numbering based on SUMMARY.md hierarchy
- Remove structural numbering from Level 4+ headings
- Eliminate single child headings by converting to bold text
- Auto-inject summary text for headings with multiple children missing intro text
- Exclude Appendix chapters from structural numbering
- Avoid modifying code block contents
- Add script to detect non-standard English usage in headers
2026-02-21 22:40:33 -08:00
Baohua Yang
33af380be1 Restruct and reorder chapters 2026-02-21 22:22:17 -08:00
Baohua Yang
2ab40eacc0 Fix space with bold markdown 2026-02-21 17:39:37 -08:00
Baohua Yang
6aa7a51fef chore: remove unused historic image files 2026-02-21 16:43:31 -08:00
Baohua Yang
79ac9c639a style: apply global formatting fixes (struct, spacing, zhlint) 2026-02-21 11:08:52 -08:00
Baohua Yang
ad68b2d973 Fix ascii figures 2026-02-21 10:59:17 -08:00
Baohua Yang
5ae315c9dd Continue to fix format issues 2026-02-21 10:47:37 -08:00
Baohua Yang
47cfc173a6 Fix format issue 2026-02-21 10:19:28 -08:00
Baohua Yang
063c3f1381 Fix grammar 2026-02-17 22:17:02 -08:00
Baohua Yang
f68795f34c Fix errors 2026-02-16 18:45:40 -08:00
Baohua Yang
acc74f17bb release: v1.5.4 2026-02-15 15:14:03 -08:00
Baohua Yang
4fa2fd8543 fix: ensure directories exist in CI before copying 2026-02-15 15:12:17 -08:00
Baohua Yang
95572d3d47 chore: remove combine.py and ignore it 2026-02-15 09:13:06 -08:00
Baohua Yang
e58bd39de5 chore: remove combine.py and ignore it 2026-02-15 09:12:40 -08:00
Baohua Yang
aa589406b9 release v1.5.3: fix CI image paths and update config 2026-02-15 09:09:02 -08:00
Baohua Yang
0835f8467a Fix and improve 2026-02-12 16:51:50 -08:00
Baohua Yang
bae82e993a Move more dockerfile content to chapter 7 2026-02-09 13:13:33 -08:00
Baohua Yang
b44c9acd6c Restruct 2026-02-09 12:56:12 -08:00
baohua
63377d0431 Fix and update 2026-02-09 11:34:35 -08:00
Baohua Yang
e669ee0fe8 Use a better structure 2026-02-09 09:32:05 -08:00
Baohua Yang
fdb879dcf2 Release v1.5.0: Restructure chapters and update for Docker v30.x 2026-02-04 22:14:22 -08:00
Baohua Yang
b4b0d4160a Add latest techniques 2026-02-03 11:09:52 -08:00
Baohua Yang
99e0eb14ce bump to latest stable versions 2026-02-03 10:14:25 -08:00
Baohua Yang
b92ccc8309 Add star history 2026-02-03 09:13:39 -08:00
Baohua Yang
cbfe75fe9b Add more practices 2026-01-30 17:10:28 -08:00
Baohua Yang
fec2e506d9 Add more content 2026-01-30 16:48:39 -08:00
Baohua Yang
c58f61dbed Clean up 2026-01-30 16:28:20 -08:00
Baohua Yang
8a0230e493 fix: remove non-existent advanced_network/_images from CI 2026-01-30 16:08:28 -08:00
Baohua Yang
16e0d3502d Fix wrong link 2026-01-26 18:16:39 -08:00
Baohua Yang
02898e346c Update to latest 2026-01-25 17:46:02 -08:00
Baohua Yang
7d8d7e63f4 Fix coding lang 2026-01-25 17:26:05 -08:00
Baohua Yang
cc6510d0b2 fix: resolve content issues found in user review
- fix(install): correct Docker version in macOS guide
- fix(intro): localize external image to prevent link rot
- doc(swarm): add context note about Kubernetes supremacy
- fix(network): remove broken missing image reference
2026-01-24 19:45:22 -08:00
Baohua Yang
306a205314 Update local serve using honkit 2026-01-22 09:01:49 -08:00
Baohua Yang
5eed72afa0 Fix missing files 2026-01-21 11:31:23 -08:00
Baohua Yang
6bba22679b Use latest tools 2026-01-12 09:33:56 -08:00
Baohua Yang
24eb615f54 Use latest version tools 2026-01-12 09:02:39 -08:00
Baohua Yang
43e12058eb Update tools to latest version 2026-01-11 10:05:49 -08:00
Baohua Yang
8bdb8406f9 Fix words 2026-01-10 22:39:51 -08:00
Baohua Yang
e08a34bcdf Merge networks 2026-01-02 16:57:09 -08:00
Baohua Yang
6e6d31d1d6 Merge networks 2026-01-02 16:55:39 -08:00
yeasy
5c3841dc98 GitBook: No commit message 2025-12-17 10:37:56 +00:00
Baohua Yang
61a71f3c25 Comment out unavailable gitee figures 2025-11-24 15:00:01 -08:00
Baohua Yang
39207f57cf Update docker book intro to v4 2025-11-24 13:27:16 -08:00
Baohua Yang
3a9d4bff61 Merge pull request #549 from CNAHYZ/patch-1
Update figure's path
2024-12-25 19:49:09 -08:00
intfoo
4bc29c0300 Update overview.md 修复图片地址问题 2024-12-25 16:20:30 +08:00
Kang Huaishuai
65bc905920 Update registry mirror 2024-11-23 23:23:50 +08:00
Baohua Yang
1b7d941fcd Merge pull request #548 from trevanlye/patch-1
Add go init
2024-11-20 10:17:28 -08:00
Baohua Yang
e0ff3d315a Merge pull request #542 from upbeat-backbone-bose/master
Update django version
2024-11-20 10:16:04 -08:00
trevanlye
09de77b543 Update README.md
we need 'go mod init first' before 'go get'
2024-11-11 11:05:23 +08:00
debian-go
344fc8bd3c Merge branch 'yeasy:master' into master 2024-11-08 11:42:06 +08:00
Baohua Yang
7ec5772432 Merge pull request #546 from liangbinfudan/master
ubuntu.md update #545
2024-09-26 16:38:42 -07:00
Hugo Dock
355dd3b051 Update ubuntu.md
The relationships among Ubuntu LTS versions have been described, and the relevant scripts have been modified slightly
2024-09-19 13:09:38 +08:00
Baohua Yang
ca011164c2 Merge pull request #543 from my-vegetable-has-exploded/debian11
Add suggestion for gpg in debian11
2024-07-30 14:02:19 -07:00
yi wang
0f2956a646 Update debian.md 2024-07-29 22:25:02 +08:00
debian-go
da7991660e Merge pull request #1 from upbeat-backbone-bose/dependabot/pip/compose/demo/django/pip-062e67ef1e
Update django requirement from <3.0,>=2.0 to >=5.0.6,<6.0 in /compose/demo/django in the pip group across 1 directory
2024-07-09 10:26:30 +08:00
dependabot[bot]
391c6364a0 Update django requirement
Updates the requirements on [django](https://github.com/django/django) to permit the latest version.

Updates `django` to 5.0.6
- [Commits](https://github.com/django/django/compare/2.0...5.0.6)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  dependency-group: pip
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-09 02:26:13 +00:00
Baohua Yang
99433b2e45 Merge pull request #540 from RockChinQ/master
Add error solution for docker installation on raspi OS
2024-02-03 19:46:31 -08:00
RockChinQ
32c6a91aa9 doc(raspberry-pi): tested on bookworm 2024-02-02 23:03:39 +08:00
RockChinQ
bea7b8d3f4 doc(raspberry-pi.md): error solution for bullseye 2024-02-02 10:36:14 +08:00
Baohua Yang
1be1db5a43 Merge pull request #538 from CybCom/master
Fix CI error
Close issue #537
2023-12-29 16:27:59 -08:00
CybCom
7052cea8a3 refactor(workflows): 💚 Update the YAMLs for GitHub workflows
Update the out dated action version. Remove redundant/useless lines. Some other updates.
2023-12-23 01:01:32 +08:00
CybCom
584087ad46 ci(workflows): 💚 Try to confirm and fix CI error:0308010C
There might be a conflict between the new version node.js and this project's dependencies, according to CI Error message "error:0308010C:digital envelope routines::unsupported". Try to confirm and fix it by specifying the old styled openssl.
2023-12-22 18:27:38 +08:00
Baohua Yang
dd6b022429 Merge pull request #536 from CybCom/master
Fix expression of using init
2023-12-20 14:43:33 -08:00
CybCom
46020ff786 fix(image\dockerfile\cmd.md): 🐛 Fix issue yeasy#535, 改进对issue进程的提法
fix(image): CMD指令讲解中,”则是希望 upstart 来以后台守护进程形式启动 nginx 服务“,鉴于当前多种init程序(特别是以systemd为代表的)的流行,改为  ”则是希望 init 系统以后台守护进程的形式启动 nginx 服务“

Issue #535: 关于init进程的提法改进
2023-12-21 01:06:07 +08:00
Baohua Yang
3ccba8afb4 Merge pull request #533 from lxg199788/patch-1
Update aliyun mirror configuration
2023-10-25 14:40:38 -07:00
lxg
f5e6a67664 Update aliyun mirror configuration.md
Update aliyun mirror configuration to the lastest version
2023-10-23 09:56:14 +08:00
Baohua Yang
439264a87f Merge pull request #530 from hellozrh/dev1
Fix rpm installation
2023-08-17 21:55:29 -07:00
hellozrh
41558e73b4 修复离线rpm包安装方式,解决各个rpm包先后依赖安装顺序不一致导致安装失败的问题。
修复离线rpm包安装方式,解决各个rpm包先后依赖安装顺序不一致导致安装失败的问题。
2023-08-17 16:15:16 +08:00
Baohua Yang
f34a985a78 Merge pull request #529 from hellozrh/hellozrh-patch
Fix installation steps when offline
2023-08-01 17:49:18 -07:00
hellozrh
bd8387083a Update to newer version of docker installation. 2023-07-29 16:32:28 +08:00
hellozrh
8d129d0ead 修复离线安装时依赖包下载、离线rpm包安装依赖先后顺序的问题。 2023-07-19 15:20:16 +08:00
Baohua Yang
85c5a280a4 Merge pull request #527 from hezhizhen/patch-2
Update install
2023-07-03 17:21:20 -07:00
Zhizhen He
98044d04b2 Update install 2023-07-03 10:54:23 +08:00
Kang Huaishuai
57873b1143 Merge pull request #523 from wushu037/patch-1
Update volume.md
2023-05-15 08:58:42 +08:00
无数
6acf209b9a Update volume.md
Correct confusing words
2023-05-07 21:34:34 +08:00
Kang Huaishuai
ed4b3efd3b Merge pull request #520 from ReginaldChen/patch-1
修改错别字
2023-02-27 08:10:33 +08:00
ReginaldChen
eb327bf908 修改错别字
轮寻应为轮询
2023-02-24 17:41:22 +08:00
Baohua Yang
cc683fdb56 Merge pull request #519 from docete/issue-518
Add docs of using HTTP/HTTPS proxy

Close #518
2023-01-17 12:03:57 -08:00
Gao Zhenghua
13b8e12f44 [issue-518] Add document on how to use HTTP/HTTPS proxy 2023-01-16 16:13:20 +08:00
Kang Huaishuai
ce4428adfb Merge pull request #517 from hezhizhen/patch-1
fix: typo
2023-01-08 20:04:47 +08:00
Zhizhen He
6443ddc07c fix: typo 2023-01-07 23:45:41 +08:00
Kang Huaishuai
ce5ae6a360 Merge pull request #515 from kingyue737/patch-1
fix: typo
2022-12-22 15:39:38 +08:00
Kang Huaishuai
35b264694b Merge pull request #516 from kingyue737/patch-2
fix: wrong key of registry mirrors
2022-12-22 15:39:14 +08:00
Yue JIN
e76b0b66a0 fix: wrong key of registry mirrors 2022-12-21 20:32:46 +08:00
Yue JIN
d80f3430b2 fix: typo 2022-12-21 19:38:21 +08:00
Baohua Yang
d9c5d2fb43 Merge pull request #514 from Hazel-Lin/install/mac
Update macos requirement in doc
2022-11-11 18:15:38 -08:00
linhuizi
fe7530c3f6 docs(install): 修改Mac安装系统要求 2022-11-11 11:31:02 +08:00
Baohua Yang
30f00323e0 Merge pull request #512 from WitchElaina/master
fix words
2022-10-22 11:29:13 -07:00
WitchElaina
93ea51ff07 修改语病
原句:“这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一”中的“为什么”和“的原因”重复赘余,因此删除掉“为什么”确保本句语法正确。
2022-10-22 15:42:59 +08:00
Baohua Yang
85be3008fa Update words
Fix #501
2022-05-12 14:37:08 -07:00
Baohua Yang
88f9183fd5 Merge pull request #500 from mrnyg/patch-1
Enable non-root read mod
2022-04-11 10:06:43 -07:00
mrnyg
1c4a43e34e Update secret.md
apache工作进程是www-data用户运行,而密钥文件(/run/secrets/wp_db_password)的属主是root,导致apache工作进程无法读取密钥,从而无法连接数据库
2022-04-09 14:27:53 +08:00
Baohua Yang
7014e4d87c Create FUNDING.yml 2022-03-16 15:14:06 -07:00
Kang Huaishuai
18028b8eaa Update dockerhub autobuild
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2022-02-24 21:08:22 +08:00
Kang Huaishuai
7c78d1c256 centos refer to centos:8, deprecated
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2022-02-24 21:06:15 +08:00
Baohua Yang
d4c6e590c6 Merge pull request #497 from npmmirror/master
Update https://registry.npm.taobao.org to https://registry.npmmirror.com
2022-02-16 11:50:56 -08:00
NPM Mirror Bot
1e415ac76c update https://registry.npm.taobao.org to https://registry.npmmirror.com 2022-02-11 22:09:47 -05:00
NPM Mirror Bot
664ac88c85 update https://registry.npm.taobao.org to https://registry.npmmirror.com 2022-02-11 13:56:55 +00:00
Kang Huaishuai
734079661d Merge pull request #496 from smartlixx/patch-1
Update best_practices.md
2022-01-04 11:01:18 +08:00
Xianxiang Li
1ed8c2c81f Update best_practices.md
Fix a typo
2022-01-04 10:41:51 +08:00
Baohua Yang
b9455b2169 Fix format 2021-12-01 14:58:32 -08:00
Baohua Yang
10a77adbe6 Merge pull request #495 from Dup4/master
Remove duplicated words
2021-11-07 16:37:20 -08:00
Dup4
31f3540fbc fix: typo 2021-11-01 19:27:25 +08:00
Kang Huaishuai
d5ce7f048b Update DD download link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-09-19 18:28:22 +08:00
Kang Huaishuai
a613c78c33 [Drone] update to v2
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-09-19 17:58:20 +08:00
Kang Huaishuai
d1d4f0f47d Update link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-16 12:46:38 +08:00
Kang Huaishuai
d4fc0a9da1 remove deprecated features: machine and swarm
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-16 12:43:50 +08:00
Kang Huaishuai
8dfdbc5b07 remove docker search
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-16 12:33:01 +08:00
Kang Huaishuai
5caddf4413 [Kubernetes] kubeadm cri based containerd
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-16 12:25:33 +08:00
Kang Huaishuai
95aed0099e Update minio case
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-15 13:29:08 +08:00
Kang Huaishuai
533f30a939 Update dead url
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-06 23:21:53 +08:00
Kang Huaishuai
1787c392c6 Update os version requirement
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-06 23:12:55 +08:00
Kang Huaishuai
ca29ab51b1 Update SUMMARY.md
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-07-05 00:35:13 +08:00
Kang Huaishuai
64b75e997f Update project compose file
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-06-27 22:34:53 +08:00
Kang Huaishuai
31ea892dfc Update aliyun mirror
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-06-27 18:03:05 +08:00
Kang Huaishuai
985e295d70 Add compose v2
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-06-12 23:26:44 +08:00
Kang Huaishuai
330beb4fdb don't push pages to coding.net
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-06-06 20:19:28 +08:00
Kang Huaishuai
baeb222455 Update vuepress config
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-06-06 11:10:01 +08:00
Kang Huaishuai
8705cede17 Update jd.com link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-05-31 19:42:07 +08:00
Kang Huaishuai
ba36c90b6c Update vuepress config
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-05-31 19:23:39 +08:00
Kang Huaishuai
96fc5acc75 Update laravel demo
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-05-28 21:50:15 +08:00
Kang Huaishuai
6cfc12eece cli experimental is deprecated on 20.10
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-04-18 19:11:47 +08:00
Kang Huaishuai
da614e8441 Update link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-20 11:22:13 +08:00
Kang Huaishuai
1e577a8c6f Update hello-world example
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-14 21:42:50 +08:00
Kang Huaishuai
9fe6c356f0 Remove us-en url
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-12 00:15:47 +08:00
Kang Huaishuai
aa08e32003 Update repository
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-12 00:12:47 +08:00
Kang Huaishuai
bc43b30964 Update image 2021-03-11 23:09:37 +08:00
Kang Huaishuai
7afb8991d3 Update install
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-11 21:27:50 +08:00
Kang Huaishuai
6f810c89f3 Update cmd result
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-07 23:56:19 +08:00
Kang Huaishuai
0a87d2a643 Update container markdown format
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-07 23:54:43 +08:00
Kang Huaishuai
8dd3141c57 Update format
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-07 23:51:02 +08:00
Kang Huaishuai
ce48a157d5 Update registry
* remove dtr
* add ghcr.io

Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-07 22:36:48 +08:00
Kang Huaishuai
ea00e0d82a Update format
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-07 15:29:05 +08:00
Kang Huaishuai
5ebd6fb6f8 Update brew command, fixed #484
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-06 11:02:43 +08:00
Kang Huaishuai
6265d0274b [vuepress] Update version
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2021-03-06 11:02:42 +08:00
Kang Huaishuai
d1480092bf Merge pull request #482 from GFZRZK/patch-1
fix wrong cmd
2021-01-19 23:47:07 +08:00
WC
d414505835 fix wrong cmd
fix wrong cmd
2021-01-11 18:14:38 +08:00
Kang Huaishuai
aa3d56fce9 remove travis ci
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-20 23:22:30 +08:00
Kang Huaishuai
2cd0fac44b remove mesos
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-20 22:58:09 +08:00
Kang Huaishuai
fb162df033 remove project travis ci
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-20 22:48:54 +08:00
Kang Huaishuai
cc726421c8 Update compose version
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-20 22:18:08 +08:00
Kang Huaishuai
47e83e7aa3 docker v20.10.0 released
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-20 22:10:25 +08:00
Kang Huaishuai
da10b3a7a1 remove docker desktop edge channel
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-11 22:00:57 +08:00
Kang Huaishuai
9d62668fcf close #479
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-12-09 23:49:26 +08:00
Kang Huaishuai
da09321b0e close #478
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-21 20:43:00 +08:00
Kang Huaishuai
2b7f954c65 [install] use aliyun mirror
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-09 17:38:22 +08:00
Kang Huaishuai
7b5a21bf6d [install] Update debian
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-03 15:42:09 +08:00
Kang Huaishuai
e8d45d3be9 [install] Update outdated content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-03 13:04:28 +08:00
Kang Huaishuai
7d51bacb12 [compose] Remove outdated content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-02 18:57:51 +08:00
Kang Huaishuai
00274b0615 Update Dockerfile USER,close #473
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-02 17:46:43 +08:00
Kang Huaishuai
0b1812aac8 Update fcos
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-11-02 10:33:27 +08:00
Kang Huaishuai
17ad494537 remove outdated content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-22 08:46:09 +08:00
Kang Huaishuai
8e8126756a [vuepress] Fixed https://github.com/Mister-Hope/vuepress-theme-hope/issues/406 2020-10-16 12:13:14 +08:00
Kang Huaishuai
f9182e5d19 [vuepress] bump 1.7.0
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-15 18:30:34 +08:00
Kang Huaishuai
0fdc2d64a9 based Docker v20.10
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 23:33:32 +08:00
Kang Huaishuai
bcc901ac9f [install] Docker 20.10 beta support CentOS 8
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 23:30:27 +08:00
Kang Huaishuai
47ec0e2ab8 [vuepress] bump 1.6.0
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 13:47:42 +08:00
Kang Huaishuai
c572a399f3 [vuepress] Update config
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 11:52:48 +08:00
Kang Huaishuai
fd85d5a0e5 project docker image add bash
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 00:40:07 +08:00
Kang Huaishuai
1b2c480a55 Add vscode devcontainer
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-14 00:28:50 +08:00
Kang Huaishuai
fc8b8867af [vuepress] Update config
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-13 22:41:28 +08:00
Kang Huaishuai
ff1f48a793 Update mirror: check docker.service first
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-13 09:35:40 +08:00
Kang Huaishuai
4751e59a6f rename docker ce to docker
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-12 18:54:47 +08:00
Kang Huaishuai
f6ec3b23d2 Update mirror
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-10 09:35:45 +08:00
Kang Huaishuai
1c932ef567 Fixed link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-10-07 13:44:57 +08:00
Kang Huaishuai
68d85ac31e Update laravel, close #465 2020-10-07 13:31:45 +08:00
Kang Huaishuai
83929dd096 [vuepress] support dark mode, close #463
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-16 18:05:52 +08:00
Kang Huaishuai
d071ed7b99 Fixed 404 link 2020-09-16 17:40:22 +08:00
Kang Huaishuai
58c09788f6 Add link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 21:04:01 +08:00
Kang Huaishuai
cbaa24c48f Dockerfile add shell label
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 20:16:04 +08:00
Kang Huaishuai
5d91c5a39f replace ip.cn
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 17:43:21 +08:00
Kang Huaishuai
48785525e0 Fixed kubeadm error
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 14:18:12 +08:00
Kang Huaishuai
6fcf302809 Update format
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 10:14:38 +08:00
Kang Huaishuai
4f08e73bfe [install] Update CentOS8
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 10:06:15 +08:00
Kang Huaishuai
4f7b448f0c [install] remove nightly version
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 09:51:53 +08:00
Kang Huaishuai
c1c7a7981d Fixed 301 link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 09:40:55 +08:00
Kang Huaishuai
cc210f75a7 [install] Update CentOS8
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 09:30:17 +08:00
Kang Huaishuai
b0ccb74dbd [install] Add CentOS 8
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-09-06 09:15:03 +08:00
Kang Huaishuai
90a7316322 buildkit more arg 2020-09-06 08:53:11 +08:00
Kang Huaishuai
6ceeec7f45 Merge pull request #462 from jackeylu/master
fix #461 https://github.com/yeasy/docker_practice/issues/461#issue-69…
2020-09-04 14:34:16 +08:00
jackeylv
d1e303d139 fix #461 https://github.com/yeasy/docker_practice/issues/461#issue-692771052
Signed-off-by: jackeylv <lvlin.whu@qq.com>
2020-09-04 14:24:36 +08:00
Kang Huaishuai
4b70a27151 link-check exclude ip.cn
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-29 15:46:24 +08:00
Kang Huaishuai
e021b27323 registry image not include htpasswd
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-29 15:30:32 +08:00
Kang Huaishuai
eac2a57633 Update vuepress nav
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-27 23:09:11 +08:00
Kang Huaishuai
c25c7283cf remove opensource
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-25 19:42:35 +08:00
Kang Huaishuai
4682ba336f improve content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-25 18:01:53 +08:00
Kang Huaishuai
ee26243625 use nginx:alpine as demo
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-25 16:54:59 +08:00
Kang Huaishuai
5fb17c90e0 Merge pull request #460 from myccccccc/master
Fix issue #459
2020-08-25 15:53:33 +08:00
mayingchun
6eb603a33b Fix issue #459 2020-08-25 14:19:23 +08:00
Kang Huaishuai
9bc245dfdc [Windows] v1903+ support WSL2
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-22 09:38:34 +08:00
Kang Huaishuai
9a4660492c ip.cn not support https
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-10 13:43:33 +08:00
Kang Huaishuai
edf1a3a07b remove outdated content #458
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-10 13:41:36 +08:00
Kang Huaishuai
acb8662c43 wechat is first
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-08-10 13:40:04 +08:00
Kang Huaishuai
85b2325513 Update link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-31 10:08:01 +08:00
Kang Huaishuai
cf7d53dc9c Merge pull request #456 from huiyifyj/master
Add "到" the word to read more fluently
2020-07-30 10:04:07 +08:00
huiyifyj
83fbb87fd1 Add the word to read more fluently 2020-07-30 09:26:49 +08:00
Kang Huaishuai
61bda4b259 Fixed docker image
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-14 16:58:22 +08:00
Kang Huaishuai
c815720349 Update image link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-14 16:20:36 +08:00
Kang Huaishuai
4aa20ecce3 Update actions 301 link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-14 00:09:11 +08:00
Kang Huaishuai
6efe0297fe Remove download link #455
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-14 00:08:15 +08:00
Kang Huaishuai
6c668a94df Update README
调整章节顺序

Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-04 13:02:37 +08:00
Kang Huaishuai
911ce1a2e4 Fixed #454
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-07-03 12:19:36 +08:00
Kang Huaishuai
8b186fb7e7 [windows] install by winget
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-06-22 09:22:53 +08:00
Kang Huaishuai
139b0ca65c Update raspberry os name
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-06-17 18:50:33 +08:00
Kang Huaishuai
67213bc2f5 Update ide content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-06-17 10:00:47 +08:00
Kang Huaishuai
d4d09f5154 docker hub support buildx
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-06-17 00:42:01 +08:00
Kang Huaishuai
f0568ebffd Update install content
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-06-17 00:10:09 +08:00
Kang Huaishuai
ddec6641b9 Merge pull request #451 from staticdax/master
Fix Typo issue #450: "运用"疑似笔误
2020-05-20 11:27:43 +08:00
staticdax
4d3d2d21fe fix typo: "运用"疑似笔误 2020-05-20 01:35:47 +08:00
Kang Huaishuai
f580130be0 Add baidu registry mirror
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-05-11 19:01:06 +08:00
Kang Huaishuai
acc5c6e723 Add link
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-05-10 10:43:51 +08:00
Kang Huaishuai
1316e41222 offline read image use cn mirror image
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-05-10 09:46:27 +08:00
Kang Huaishuai
9cfd1fda2b offline read docker image add tips
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-05-10 09:46:27 +08:00
Kang Huaishuai
683cf95ca7 build vuepress docker image
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-05-10 09:46:11 +08:00
Kang Huaishuai
8952dee0a8 Merge pull request #448 from niebayes/master
Fix issue #447: 删除了一个多余的"对" (line 97)
2020-05-08 19:44:52 +08:00
Nie Shicong
bdc8bd618c Fix issue #447: 删除了一个多余的"对" (line 97)
Signed-off-by: Nie Shicong <bayes@Nies-MacBook-Pro.local>
2020-05-08 19:20:23 +08:00
Baohua Yang
41da49b127 Migrating to new gitbook link 2020-04-29 11:36:50 -07:00
Kang Huaishuai
18ab3069a3 Update soft to latest version
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-04-26 10:34:02 +08:00
Kang Huaishuai
0fd981acc2 [buildx] buildkit image support tencent cloud env
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-04-26 10:17:19 +08:00
Kang Huaishuai
4561243c23 FCOS live iso require 3GB RAM
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2020-04-26 09:57:39 +08:00
Kang Huaishuai
ff28d7219d Recommit (#446)
* 添加离线部署docker和离线部署minio实践

Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>

Co-authored-by: Daiwj <daiwj@zz3s.com>
2020-04-26 09:42:59 +08:00
Daiwj
34b6b617b9 docker镜像的导入和导出修改了章节名字 2020-04-12 19:13:38 +08:00
Kang HuaiShuai
e0797515d3 Update buildx image
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-04-07 09:18:40 +08:00
Kang HuaiShuai
a691aa607a remove azk8s.cn mirror
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-04-04 22:54:32 +08:00
Kang Huaishuai
e9dc8dc974 Merge pull request #443 from boblau8686/master
Correct the wrong word
2020-03-31 18:32:40 +08:00
bob.liu
44fdf58ba5 Correct the wrong word 2020-03-31 18:23:17 +08:00
Kang HuaiShuai
bd74c85bb7 gitbook dist commit message include main repo sha
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-12 15:07:44 +08:00
Kang HuaiShuai
e38ea82f37 remove github actions files on gitbook dist
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-12 15:04:21 +08:00
Kang HuaiShuai
c887661c08 Add docker roadmap
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-12 14:50:34 +08:00
Kang HuaiShuai
fced7854ee Fixed #440 on fedora
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-12 14:47:09 +08:00
Touko
e4a68ea7e4 Fix issue #440
http://mirrors.ustc.edu.cn/help/docker-ce.html#id7
2020-03-12 14:23:20 +08:00
Kang HuaiShuai
d8e5cfe097 Update install
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-10 14:24:46 +08:00
Kang HuaiShuai
5634eb2fda Update aliyun customer case
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-10 14:08:20 +08:00
Kang HuaiShuai
c720d6959e Docker Desktop Support Windows Home
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-10 13:39:27 +08:00
Kang HuaiShuai
3a24901664 Change AUFS to OverlayFS
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-03-04 11:50:59 +08:00
Kang HuaiShuai
ca5502e208 Update alpine content: replace default repo
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-27 23:31:01 +08:00
Kang HuaiShuai
d2f5e120ae Fixed github pages
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-23 21:57:26 +08:00
Kang HuaiShuai
d887c8bda6 Update link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-23 21:17:32 +08:00
Kang HuaiShuai
1e026fb3a1 Remove 404 link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-23 11:36:56 +08:00
Kang HuaiShuai
33c2b2216d [actions] check md files link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-23 11:15:11 +08:00
Kang HuaiShuai
6c0fc9e416 cp _images to vuepress dist
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-23 10:53:24 +08:00
Kang HuaiShuai
a2e8595c42 vuepress remove archived content
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-22 14:59:31 +08:00
Kang HuaiShuai
5577c9caa6 Change CoreOS to Fedora CoreOS(FCOS)
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-02-22 13:55:13 +08:00
Kang Huaishuai
2f46c5180c Merge pull request #439 from firejq/patch-1
Fix a markdown grammatical error
2020-02-11 08:57:29 +08:00
FirejqWei
9a0a76a5bb Fix a markdown grammatical error 2020-02-11 02:03:57 +08:00
Kang HuaiShuai
9d450ffc26 [Compose] Add lnmp
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-01-09 17:08:35 +08:00
Kang HuaiShuai
e77c9ecbab [Kubernetes] Add dashboard
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2020-01-09 16:57:38 +08:00
Kang HuaiShuai
386b1e4cf6 Replace dead link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-31 21:10:06 +08:00
Kang HuaiShuai
9f0b2c725f Add podman
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-31 20:53:51 +08:00
Kang HuaiShuai
0dcc67da1c Add kubeadm, close #438
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-31 20:26:22 +08:00
Kang HuaiShuai
bbfe14e0af Update docker commit, Fixed #437 2019-12-26 11:54:45 +08:00
Kang Huaishuai
59317624bb Update link 2019-12-22 10:34:52 +08:00
Kang HuaiShuai
2092debcc0 [Cloud] Remove docker cloud
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 21:00:18 +08:00
Kang HuaiShuai
3ba77a7470 Drone agent use drone/drone-runner-docker:1
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 20:46:21 +08:00
Kang HuaiShuai
fbfab11293 Update registry mirror
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 15:05:06 +08:00
Kang HuaiShuai
f940d22950 Add CODEOWNERS
* https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners

Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 14:28:18 +08:00
Kang HuaiShuai
a601a83c0e Update vuepress
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 13:40:10 +08:00
Kang HuaiShuai
0ac24829e1 Add enable kubernetes on docker-sektop,close #262
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-12-09 12:21:52 +08:00
Kang HuaiShuai
a85ae7da1e Fixed buildx 2019-12-01 10:12:14 +08:00
Kang HuaiShuai
83619ad6e3 [Public] coding.net domain is *.mirror.docker-practice.com
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-29 23:36:58 +08:00
Kang Huaishuai
8e38beee0e Merge pull request #432 from loopever/master
Fix issue #431: AUFS全称修改为Wikipedia的内容
2019-11-26 19:50:29 +08:00
loopever
c574178a02 Fix issue #431: AUFS全称修改为Wikipedia的内容 2019-11-26 18:56:12 +08:00
Kang Huaishuai
e02f015a23 Fixed #430 2019-11-18 22:32:44 +08:00
Kang HuaiShuai
fde5496bb8 Update kubernetes
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-15 11:04:23 +08:00
Kang HuaiShuai
e1961d62eb Fixed 404 link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-14 09:22:06 +08:00
Kang HuaiShuai
c836c65a78 Update command
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-14 09:21:31 +08:00
Kang HuaiShuai
5cb92f63cf Update title style
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-06 14:58:03 +08:00
Kang HuaiShuai
99e470eb2a Update link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-06 14:36:28 +08:00
Kang HuaiShuai
61492ff11a [vuepress] push dist to coding.net
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-06 13:18:55 +08:00
Kang HuaiShuai
6f96aaf5a6 [CI] Fixed actions
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-06 10:44:57 +08:00
Kang HuaiShuai
709c77adcb Update title style
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 23:35:43 +08:00
Kang HuaiShuai
3ba7560b4d Add experimental
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 23:28:01 +08:00
Kang HuaiShuai
f44a3ee402 Add ide with docker
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 22:19:50 +08:00
Kang HuaiShuai
eb274b16f6 Add Docker Buildx
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 21:50:05 +08:00
Kang HuaiShuai
fadf84bb69 Archive docker-machine mesos docker-swarm, close #425
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 19:35:12 +08:00
Kang HuaiShuai
c788212aad Use vuepress build book
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-11-05 19:15:33 +08:00
Kang Huaishuai
7690686ddb Merge pull request #423 from uscwifi/patch-1
Update centos.md
2019-10-05 23:41:21 +08:00
uscwifi
a3647ec3a3 Update centos.md 2019-10-05 23:18:48 +08:00
Kang HuaiShuai
008f01592b Update docker hub
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-25 11:04:01 +08:00
Kang HuaiShuai
3923858f00 Update format
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-25 11:00:57 +08:00
Kang HuaiShuai
b11cac80fb [Registry Mirror] Update mirror
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-25 10:49:40 +08:00
Kang HuaiShuai
38e810a407 [install] Fixed script install, default channel is stable
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-25 10:30:12 +08:00
Kang HuaiShuai
224fbe9fed Fixed outdated content
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 16:51:04 +08:00
Kang HuaiShuai
f260e3ba88 Add wechat group
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 16:50:32 +08:00
Kang HuaiShuai
f17f29bf41 Update format
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 15:29:02 +08:00
Kang HuaiShuai
21a811d265 [install] Fixed error
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 15:05:06 +08:00
Kang HuaiShuai
803b93c1fc Update format
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 14:48:54 +08:00
Kang HuaiShuai
4873267f31 Update format
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 14:28:50 +08:00
Kang HuaiShuai
1aef2b7734 [cases] Fixed typo
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 14:12:56 +08:00
Kang HuaiShuai
49ef715e99 [install] Update settings
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-20 14:06:04 +08:00
Kang HuaiShuai
dd060d026a add docker-practice.com
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-05 13:40:53 +08:00
Kang HuaiShuai
96aa9b99de deploy pages to docker-practice/zh-cn
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-09-05 12:59:25 +08:00
Kang Huaishuai
4e84715725 Fixed error 2019-09-01 20:06:13 +08:00
Kang
48718d6035 Fixed error
Signed-off-by: Kang Huaishuai <khs1994@khs1994.com>
2019-09-01 15:15:53 +08:00
khs1994
8666d2683f Update Docker Desktop name
Signed-off-by: khs1994 <khs1994@khs1994.com>
2019-09-01 15:03:32 +08:00
khs1994
84c2183cc8 [Machine] Update to v0.16.1
Signed-off-by: khs1994 <khs1994@khs1994.com>
2019-09-01 14:50:40 +08:00
khs1994
7ec38273bb [Compose] Update to v1.24.1
Signed-off-by: khs1994 <khs1994@khs1994.com>
2019-09-01 14:46:33 +08:00
khs1994
6bca9e8dff Update CoreOS: remove outdated quickstart 2019-09-01 14:16:10 +08:00
khs1994
6c6d2ac973 [etcd] Update to v3.4.x 2019-08-31 22:57:43 +08:00
khs1994
8747860b95 compose wordpress update mysql to v8.0.x #415 2019-08-31 22:11:34 +08:00
khs1994
5a00a6b32f Update CI
* Update drone to v1.x
* Add GitHub Actions
2019-08-31 21:15:51 +08:00
khs1994
8a3be4634e Update install 2019-08-31 18:35:14 +08:00
khs1994
c075122492 Update project docker image name #416 2019-08-31 17:47:38 +08:00
Kang Huaishuai
593a0c39ff Merge pull request #413 from baijunyao/master
Use aliyun compose mirrors
2019-08-14 22:06:45 +08:00
baijunyao
823239010a Use aliyun compose mirrors 2019-08-14 21:50:30 +08:00
Kang HuaiShuai
b8dc1a7b16 Add image
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-07-03 12:22:22 +08:00
Kang HuaiShuai
710c1ec457 Fix dead link
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-07-03 12:06:31 +08:00
Kang HuaiShuai
b9247c16df Update compose django, Fixed #405
Signed-off-by: Kang HuaiShuai <khs1994@khs1994.com>
2019-07-03 11:49:11 +08:00
khs1994
59af28af86 Merge pull request #407 from yongchengzhao/master
- Fix issue #406: Describe more correctly.
2019-06-28 11:20:06 +08:00
khs1994
0baf0fec99 Merge pull request #409 from yongchengzhao/master
- Fix issue #408: Fix typos.
2019-06-28 11:17:28 +08:00
yongchengzhao
d14a0e0c4a - Fix issue #408: Fix typos. 2019-06-28 10:16:12 +08:00
yongchengzhao
e7c1782c51 - Fix issue #408: Fix typos. 2019-06-28 10:04:57 +08:00
yongchengzhao
7b02f90f09 - Fix issue #406: Describe more correctly. 2019-06-27 17:03:03 +08:00
khs1994
4ed6156a03 Add ci icon [skip ci] 2019-05-14 00:29:12 +08:00
khs1994
a0c7670738 Update README [skip ci] 2019-05-13 23:43:29 +08:00
khs1994
00ec580e74 Fix gitbook build error: use page-treeview@2.9.8 2019-05-13 22:58:26 +08:00
khs1994
3442dab121 Update cloud 2019-05-12 10:14:00 +08:00
khs1994
2e747fe2a5 [install] Update mirror: remove docker cn registry #370 2019-05-12 09:44:17 +08:00
khs1994
df2537b721 Update cloud 2019-05-12 09:41:35 +08:00
khs1994
bf04ac99a3 Update jd link [skip ci] 2019-05-10 07:27:55 +08:00
khs1994
77c8ae525a Buy book by wechat miniprogram [skip ci] 2019-05-07 23:16:36 +08:00
Baohua Yang
f7dcffc7be Merge branch 'master' of github.com:yeasy/docker_practice 2019-05-05 19:31:08 +08:00
Baohua Yang
a17f3f6b2f Add resource 2019-05-05 19:31:06 +08:00
khs1994
8576e16b61 ubuntu 14.04,debian 7 and 8 EOL 2019-04-29 09:29:46 +08:00
khs1994
4949de94c4 Merge pull request #399 from SmallTianTian/patch-1
expose port.
2019-04-15 20:22:09 +08:00
SmallTianTian
44e504c604 expose port. 2019-04-15 11:11:58 +08:00
khs1994
0370871867 Add BuildKit and docker manifest command. close #390 ,close #391
Signed-off-by: khs1994 <khs1994@khs1994.com>
2019-03-29 12:02:18 +08:00
khs1994
d3c197ddfc show repo language is go 2019-03-22 10:35:29 +08:00
khs1994
8fc2003414 Update README
* use jd.com cps url, analysis docker user trend
2019-03-09 11:16:27 +08:00
khs1994
c446640591 Fix format and update outdate content 2019-03-08 12:21:07 +08:00
Baohua Yang
6a97772e79 Merge pull request #388 from daixiang0/delete-blank
Remove unused blank spaces
2019-02-22 23:44:13 +08:00
Xiang Dai
d4bbcc0cfb delete all duplicate empty blanks
Signed-off-by: Xiang Dai <764524258@qq.com>
2019-02-21 10:53:33 +08:00
khs1994
994f6ac101 Replace http with https 2019-01-06 10:15:13 +08:00
khs1994
fbf5a286ab Update install 2019-01-06 10:00:38 +08:00
khs1994
81e68f241c Update docker official docs link 2019-01-06 09:50:03 +08:00
khs1994
aff886341f Update link 2019-01-06 09:40:31 +08:00
khs1994
44530ff366 Add aliyun mirror 2019-01-01 17:59:58 +08:00
khs1994
e2baa6401a replace crlf,Fix #338 2019-01-01 10:30:49 +08:00
465 changed files with 19276 additions and 8270 deletions

View File

@@ -0,0 +1,22 @@
// https://code.visualstudio.com/docs/remote/devcontainerjson-reference
{
"image": "yeasy/docker_practice:latest",
"mounts": [
"source=dp-code-remote-cache,target=/root/.vscode-server,type=volume"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/sh"
},
"forwardPorts": [
4000
],
"runArgs": [
"--cap-add=SYS_ADMIN"
],
"postStartCommand": [
"sh",
"-cx",
"pwd ; cd /workspaces/docker_practice ; mkdir -p ${PWD}/node_modules; mkdir -p ${PWD}/_book; mount --bind /srv/gitbook/node_modules ${PWD}/node_modules ; mount --bind /mnt ${PWD}/_book"
]
}

11
.docker/docker-entrypoint.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env sh
echo
echo
echo "Please open your browser: 127.0.0.1:4000"
echo
echo "欢迎加入 QQ 群:【 145983035 】 分享 Docker 资源,交流 Docker 技术"
echo
echo
exec nginx -g "daemon off;"

View File

@@ -1,17 +0,0 @@
workspace:
base: /srv/gitbook-src
path: .
pipeline:
build:
image: yeasy/docker_practice:latest
# pull: true
environment:
- TZ=Asia/Shanghai
secrets: [key1, key2]
commands:
# - echo $${key1}
# - echo $KEY2
- docker-entrypoint.sh build
when:
event: [push, pull_request, tag, deployment]
branch: master

View File

@@ -1,4 +1,4 @@
# EditorConfig is awesome: http://EditorConfig.org
# EditorConfig is awesome: https://EditorConfig.org
root = true

4
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
* text=auto
* text=auto eol=lf
*.sh text eol=lf
*.py linguist-language=go
* linguist-language=go

39
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,39 @@
* @yeasy @khs1994
/.github/* @khs1994
/.travis/* @khs1994
/.vuepress/* @khs1994
/01_introduction/* @yeasy @khs1994
/02_basic_concept/* @yeasy @khs1994
/03_install/* @khs1994
/04_image/* @yeasy @khs1994
/05_container/* @yeasy @khs1994
/06_repository/* @khs1994
/07_dockerfile/* @yeasy @khs1994
/08_data/* @yeasy @khs1994
/09_network/* @yeasy @khs1994
/10_buildx/* @khs1994
/11_compose/* @yeasy @khs1994
/12_implementation/* @yeasy @khs1994
/13_kubernetes_concepts/* @yeasy @khs1994
/14_kubernetes_setup/* @yeasy @khs1994
/15_etcd/* @yeasy @khs1994
/16_cloud/* @khs1994
/17_ecosystem/* @khs1994
/18_security/* @yeasy @khs1994
/19_observability/* @yeasy @khs1994
/20_cases_os/* @yeasy @khs1994
/21_case_devops/* @yeasy @khs1994
/appendix/* @yeasy @khs1994
/.drone.yml @khs1994
/.editorconfig/ @khs1994
/.gitattributes @khs1994
/.gitignore @khs1994
/_config.yml @yeasy @khs1994
/book.json @yeasy @khs1994
/CHANGELOG.md @yeasy @khs1994
/CONTRIBUTING.md @yeasy @khs1994
/docker-compose.yml @khs1994
/manifest @khs1994
/package.json @khs1994
/README.md @yeasy @khs1994
/SUMMARY.md @yeasy @khs1994

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: yeasy
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

View File

@@ -7,37 +7,33 @@ about: Create a report to help us improve
* [ ] Have u googled the problem? If no, pls do that first!
### Environment
<!--请提供环境信息包括操作系统版本等保留你的操作系统其他选项删除-->
<!--Provides env info like OS version-->
* [x] Linux
* [x] CentOS 7
* [x] Ubuntu 14.04
* [x] Fedora
* [x] Ubuntu 16.04 +
* [x] Debian 7
* [x] Debian 8 +
* [x] CoreOS
* [x] Debian 9 +
* [x] macOS
* [x] Windows 10
* [x] Raspberry Pi (ARM)
* [x] Others (Pls describe below)
### Docker Version
<!--如果你的 Docker 版本低于 18.09 请尽可能升级到该版本保留你的 Docker 版本其他选项删除-->
<!--if Docker version under 18.09, please upgrade Docker to 18.09-->
* [x] Edge (v18.09)
* [x] Stable (v18.09)
<!--如果你的 Docker 版本低于 20.10 请尽可能升级到该版本保留你的 Docker 版本其他选项删除-->
<!--if Docker version under 20.10, please upgrade Docker to 20.10-->
* [x] Test (v20.10)
* [x] Stable (v20.10)
* [x] 1.13.0 or Before
### Problem Description
<!--描述你的问题请贴出操作步骤终端报错截图或文字信息-->
<!--describe problem with detailed steps and logs-->
<!--提交问题之前请点击预览标签符合要求之后再提交问题-->

View File

@@ -7,37 +7,33 @@ about: Create a issue about Docker
* [ ] Have u googled the problem? If no, pls do that first!
### Environment
<!--请提供环境信息包括操作系统版本等保留你的操作系统其他选项删除-->
<!--Provides env info like OS version-->
* [x] Linux
* [x] CentOS 7
* [x] Ubuntu 14.04
* [x] Fedora
* [x] Ubuntu 16.04 +
* [x] Debian 7
* [x] Debian 8 +
* [x] CoreOS
* [x] Debian 9 +
* [x] macOS
* [x] Windows 10
* [x] Raspberry Pi (ARM)
* [x] Others (Pls describe below)
### Docker Version
<!--如果你的 Docker 版本低于 18.09 请尽可能升级到该版本保留你的 Docker 版本其他选项删除-->
<!--if Docker version under 18.09, please upgrade Docker to 18.09-->
* [x] Edge (v18.09)
* [x] Stable (v18.09)
<!--如果你的 Docker 版本低于 20.10 请尽可能升级到该版本保留你的 Docker 版本其他选项删除-->
<!--if Docker version under 20.10, please upgrade Docker to 20.10-->
* [x] Test (v20.10)
* [x] Stable (v20.10)
* [x] 1.13.0 or Before
### Problem Description
<!--描述你的问题请贴出操作步骤终端报错截图或文字信息-->
<!--describe problem with detailed steps and logs-->
<!--提交问题之前请点击预览标签符合要求之后再提交问题-->

View File

@@ -1,20 +1,20 @@
<!--
Thanks for your contribution.
See [CONTRIBUTING](CONTRIBUTING.md) for contribution guidelines.
Thanks for your contribution.
See [CONTRIBUTING](../CONTRIBUTING.md) for contribution guidelines.
-->
### Proposed changes (Mandatory)
**Proposed changes (Mandatory)**
<!--
Tell us what you did and why:
Tell us what you did and why:
One line short description
And details in other paragraphs.
-->
### Fix issues (Optional)
**Fix issues (Optional)**
<!--
Tell us what issues you fixed, e.g., fix #123
Tell us what issues you fixed, e.g., fix #123
-->

27
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "chore(deps)"
labels:
- "dependencies"
groups:
dependencies:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
commit-message:
prefix: "chore(deps)"
labels:
- "dependencies"
groups:
dependencies:
patterns:
- "*"

65
.github/workflows/check-link.yml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Check link
on:
workflow_dispatch:
jobs:
check-link:
name: check-link
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
# search Issues :-(
- run: |
docker run -i --rm \
-v $PWD:/mnt:ro \
dkhamsing/awesome_bot \
--white-list "localhost","0.0.0.0",\
"server","example.com","docker",\
"docker.domain.com","YourIP","register",\
"172.16.238.100","172.16.238.101","172.16.238.102",\
"192.168.199.100",\
"github.com/settings",\
"github.com/docker/compose/releases/download",\
"github.com/etcd-io/etcd/releases/download",\
"github.com/tianon/gosu/releases/download",\
"github.com/yeasy/docker_practice",\
"github.com/AliyunContainerService/k8s-for-docker-desktop/raw",\
"dl-cdn.alpinelinux.org/alpine/edge/testing",\
"www.w3.org/1999/xhtml",\
"cr.console.aliyun.com",\
"cloud.tencent.com",\
"nodejs.org/dist/",\
"c.163.com/hub",\
"drone.yeasy.com",\
"docs.docker.com",\
"dockerhub.azk8s.cn",\
"reg-mirror.qiniu.com",\
"registry.docker-cn.com",\
"mirror.ccs.tencentyun.com",\
"vuepress.mirror.docker-practice.com",\
"mc.qcloudimg.com/static/img",\
"www.daocloud.io/mirror",\
"download.docker.com",\
"www.ubuntu.com",\
"archive.ubuntu.com",\
"security.ubuntu.com/ubuntu",\
"nginx.com",\
"img.shields.io/github/release/yeasy/docker_practice",\
"launchpad.net",\
"www.w3.org/1999",\
"chat.freenode.net",\
"en.wikipedia.org/wiki/UnionFS",\
"product.china-pub.com",\
"union-click.jd.com",\
"x.x.x.x/base",\
"x.x.x.x:9090",\
"yeasy.gitbooks.io",\
"download.fastgit.org",\
"www.aliyun.com" \
--allow-dupe \
--skip-save-results \
-t 10 \
`find . \( -path "./mesos" -o -path "./swarm_mode" \) -prune -o -name "*.md" -exec ls {} \;`
name: check-link
timeout-minutes: 25

154
.github/workflows/ci.yaml vendored Normal file
View File

@@ -0,0 +1,154 @@
name: CI
on:
push:
pull_request:
workflow_dispatch:
defaults:
run:
shell: bash --noprofile --norc -exo pipefail {0}
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6.0.2
- name: Build Gitbook
uses: docker://yeasy/docker_practice
with:
args: build
- name: Build Gitbook Docker Image
if: github.repository == 'docker-practice/docker_practice'
run: |
sudo chmod -R 777 _book
echo "FROM nginx:alpine" >> Dockerfile
echo "COPY _book /usr/share/nginx/html" >> Dockerfile
echo "COPY .docker/docker-entrypoint.sh /" >> Dockerfile
echo "ENTRYPOINT [\"/docker-entrypoint.sh\"]" >> Dockerfile
export VCS_REF=`git rev-parse --short HEAD`
docker build \
-t dockerpracticesig/docker_practice \
-t dockerpracticesig/docker_practice:gitbook \
--label org.opencontainers.image.revision=$VCS_REF \
--label org.opencontainers.image.source="https://github.com/yeasy/docker_practice" \
--label maintainer="https://github.com/docker-practice" \
.
docker run -d --rm -p 4000:80 dockerpracticesig/docker_practice
sleep 5
echo "::group::Test"
curl 127.0.0.1:4000
echo "::endgroup::"
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker push dockerpracticesig/docker_practice
docker push dockerpracticesig/docker_practice:gitbook
env:
DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}}
- name: Upload Gitbook dist
uses: docker://pcit/pages
if: github.repository == 'docker-practice/docker_practice'
env:
PCIT_EMAIL: khs1994@khs1994.com
PCIT_GIT_TOKEN: ${{ secrets.PCIT_GIT_TOKEN }}
PCIT_GIT_URL: github.com/docker-practice/zh-cn
PCIT_KEEP_HISTORY: "true"
PCIT_LOCAL_DIR: _book
PCIT_MESSAGE: Build from yeasy/docker_practice@${{github.sha}}
PCIT_TARGET_BRANCH: master
PCIT_USERNAME: khs1994
- name: vuepress
run: |
export NODE_OPTIONS=--openssl-legacy-provider
sudo rm -rf _book
npm i
git clone https://github.com/docker-practice/.vuepress .vuepress2
cp -r .vuepress2/. .vuepress/
rm -rf .vuepress2
find . \( -path "./mesos" -o -path "./swarm_mode" -o -path "./node_modules" -o -path "./.vuepress" -o -path "./_book" -o -path "./CHANGELOG.md" -o -path "./CONTRIBUTING.md" \) -prune -o -name "*.md" -exec sed -i 'N;2a\<AdSenseTitle/>\n' {} \;
npx vuepress --version
npm run vuepress:build
echo "vuepress.mirror.docker-practice.com" > .vuepress/dist/CNAME
cp -r _images .vuepress/dist
mkdir -p .vuepress/dist/appendix
cp -r appendix/_images .vuepress/dist/appendix
mkdir -p .vuepress/dist/cloud
cp -r 16_cloud/_images .vuepress/dist/cloud
mkdir -p .vuepress/dist/data_management
cp -r 08_data/_images .vuepress/dist/data_management
mkdir -p .vuepress/dist/etcd
cp -r 15_etcd/_images .vuepress/dist/etcd
mkdir -p .vuepress/dist/kubernetes
cp -r 13_kubernetes_concepts/_images .vuepress/dist/kubernetes
echo "include: [_images]" > .vuepress/dist/_config.yml
- name: Upload Vuepress dist
uses: docker://pcit/pages
if: github.repository == 'docker-practice/docker_practice'
env:
PCIT_EMAIL: khs1994@khs1994.com
PCIT_GIT_TOKEN: ${{ secrets.PCIT_GIT_TOKEN }}
PCIT_GIT_URL: github.com/docker-practice/vuepress
PCIT_KEEP_HISTORY: "true"
PCIT_LOCAL_DIR: .vuepress/dist
PCIT_MESSAGE: Build from yeasy/docker_practice@${{github.sha}}
PCIT_TARGET_BRANCH: master
PCIT_USERNAME: khs1994
# - name: Set coding.net CNAME
# run: |
# echo "vuepress.mirror.docker-practice.com" > .vuepress/dist/CNAME
# - name: Upload Vuepress dist to coding.net
# uses: docker://pcit/pages
# if: github.repository == 'docker-practice/docker_practice'
# env:
# PCIT_EMAIL: khs1994@khs1994.com
# PCIT_GIT_TOKEN: ${{ secrets.CODING_GIT_TOKEN }}
# PCIT_GIT_URL: e.coding.net/dpsigs/docker_practice
# PCIT_KEEP_HISTORY: "true"
# PCIT_LOCAL_DIR: .vuepress/dist
# PCIT_MESSAGE: Build from yeasy/docker_practice@${{github.sha}}
# PCIT_TARGET_BRANCH: master
# PCIT_USERNAME: ptt0xjqzbke3
- name: Build vuepress docker image
if: github.repository == 'docker-practice/docker_practice'
run: |
sudo rm -rf .vuepress/dist/.git
echo "FROM nginx:alpine" > Dockerfile
echo "COPY .vuepress/dist /usr/share/nginx/html" >> Dockerfile
echo "COPY .docker/docker-entrypoint.sh /" >> Dockerfile
echo "ENTRYPOINT [\"/docker-entrypoint.sh\"]" >> Dockerfile
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
VCS_REF=`git rev-parse --short HEAD`
docker build -t dockerpracticesig/docker_practice:vuepress \
--label org.opencontainers.image.revision=$VCS_REF \
--label org.opencontainers.image.source="https://github.com/yeasy/docker_practice" \
--label maintainer="https://github.com/docker-practice" \
.
docker push dockerpracticesig/docker_practice:vuepress
docker run -it --rm -d -p 4001:80 dockerpracticesig/docker_practice:vuepress
sleep 5
echo "::group::Test"
curl 127.0.0.1:4001
echo "::endgroup::"
env:
DOCKER_PASSWORD: ${{secrets.DOCKER_PASSWORD}}
DOCKER_USERNAME: ${{secrets.DOCKER_USERNAME}}

View File

@@ -0,0 +1,27 @@
name: Dependabot auto-merge
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Approve a PR
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
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}

22
.gitignore vendored
View File

@@ -3,7 +3,29 @@
*.tmp
.idea/
_book/
format_report.txt
*.swp
*.edx
.DS_Store
node_modules/
package-lock.json
docker-compose.override.yml
# Editor configs
.obsidian/
.vscode/
.agent/
__pycache__/
# Check scripts
check_project_rules.py
check_dashes.py
checker.py
find_lists_no_space.py
fix_missing_spaces.py
fix_project_rules.py
fixer.py
format_headings.py

View File

@@ -1,44 +0,0 @@
language: bash
sudo: required
services:
- docker
before_install:
- openssl aes-256-cbc -K $encrypted_6cc8cff04075_key -iv $encrypted_6cc8cff04075_iv
-in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- export TZ='Asia/Shanghai'
- date
- git config --global user.name "khs1994"
- git config --global user.email "khs1994@khs1994.com"
script:
- docker run -it --rm -v $PWD:/srv/gitbook-src yeasy/docker_practice build
after_success:
- sudo chmod -R 777 _book
- echo "FROM nginx:1.13.8-alpine" >> Dockerfile
- echo "COPY _book /usr/share/nginx/html" >> Dockerfile
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker build -t dockerpracticecn/docker_practice .
- docker run -dit --rm -p 4000:80 dockerpracticecn/docker_practice
- sleep 5
- curl 127.0.0.1:4000
- docker push dockerpracticecn/docker_practice
- cd _book
- git init
- git remote add origin "$REPO"
- git add .
- COMMIT=`date "+%F %T"`
- git commit -m "Travis CI Site updated $COMMIT"
- git push -f origin master:"$DEPLOY_BRANCH"
env:
global:
- DEPLOY_BRANCH: pages
# - DEPLOY_BRANCH: legacy-pages
- REPO: git@github.com:yeasy/docker_practice.git
addons:
ssh_known_hosts:
- github.com
branches:
only:
- master
- dev
# - docker-legacy

View File

@@ -1,26 +0,0 @@
FROM node:9-alpine
ENV TZ=Asia/Shanghai
WORKDIR /srv/gitbook
COPY book.json book.json
COPY docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache \
tzdata \
&& npm install -g gitbook-cli \
&& gitbook install \
&& ln -s /usr/local/bin/docker-entrypoint.sh / \
&& rm -rf /root/.npm /tmp/*
EXPOSE 4000
VOLUME /srv/gitbook-src
WORKDIR /srv/gitbook-src
ENTRYPOINT ["docker-entrypoint.sh"]
CMD server

View File

@@ -1,37 +0,0 @@
{
"title": "Docker -- 从入门到实践",
"author": "yeasy",
"language": "zh-hans",
"links": {
"sidebar": {
"GitHub": "https://github.com/yeasy/docker_practice"
}
},
"plugins": [
"-livereload",
"image-captions",
"github",
"page-treeview",
"editlink"
],
"pluginsConfig": {
"image-captions": {
"attributes": {
"width": "600"
},
"caption": "图 _PAGE_LEVEL_._PAGE_IMAGE_NUMBER_ - _CAPTION_"
},
"github": {
"url": "https://github.com/yeasy/docker_practice"
},
"editlink": {
"base": "https://github.com/yeasy/docker_practice/blob/master/",
"label": "编辑本页"
},
"page-treeview": {
"copyright": "Copyright &#169; yeasy",
"minHeaderCount": "2",
"minHeaderDeep": "2"
}
}
}

View File

@@ -1,43 +0,0 @@
user root;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
index index.html index.php;
server {
server_name localhost;
listen 4000;
root /srv/www/;
index index.html;
}
}

View File

@@ -1,5 +0,0 @@
sut:
build: .
volumes:
- ../:/srv/gitbook-src
command: build

View File

@@ -1,19 +0,0 @@
#!/bin/sh
START=`date "+%F %T"`
if [ $1 = "sh" ];then sh ; exit 0; fi
rm -rf node_modules _book
cp -a . ../gitbook
cd ../gitbook
main(){
if [ "$1" = build ];then gitbook build; cp -a _book ../gitbook-src; echo $START; date "+%F %T"; exit 0; fi
exec gitbook serve
exit 0
}
main $1 $2 $3

Binary file not shown.

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env bash
# cd .travis
# ./update.sh
if [ ! -f Dockerfile ];then exit 1; fi
cp -a ../book.json book.json

3
.vuepress/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/*
!.gitignore
!config.js

463
.vuepress/config.js Normal file
View File

@@ -0,0 +1,463 @@
const { config } = require('vuepress-theme-hope')
module.exports = config({
title: 'Docker 从入门到实践',
base: '/',
head: [['script', {}, `
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "//hm.baidu.com/hm.js?81a3490c9cd141dbcf6d00bc18b6edae";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
`],
[
'script', {}, `
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
`
]
],
plugins: {
// sitemap: {
// hostname: 'https://vuepress.mirror.docker-practice.com'
// },
// 'git-log': {
// additionalArgs: '--no-merge',
// onlyFirstAndLastCommit: true,
// },
},
locales: {
"/": {
lang: "zh-CN"
}
},
themeConfig: {
blog: false,
// comment: false,
comment: {
type: "disable", // 使用 Valine
appId: "...", // your appId
appKey: "...", // your appKey
},
pageInfo: [
// 'author',
'reading-time',
'word',
],
footer: {
content: "Made with <a target='_blank' href='https://github.com/vuepress-theme-hope/vuepress-theme-hope'>vuepress-theme-hope</a>",
display: true,
copyright: false,
},
searchPlaceholder: 'Search',
repo: 'yeasy/docker_practice',
repoLabel: 'GitHub',
repoDisplay: true,
hostname: 'https://vuepress.mirror.docker-practice.com',
// author: 'yeasy',
mdEnhance: {
lineNumbers: true,
},
git: {
contributor: false,
},
themeColor: {
blue: '#2196f3',
// red: '#f26d6d',
// green: '#3eaf7c',
// orange: '#fb9b5f'
},
locales: {
"/": {
lang: "zh-CN"
}
},
darkmode: 'auto-switch',
//
showAds: true,
docsRepo: 'yeasy/docker_practice',
docsDir: '/',
docsBranch: 'master',
editLinks: true,
nav: [
{
text: '微信交流群',
link: 'https://docker_practice.gitee.io/pic/dpsig-wechat.jpg',
},
{
text: '小程序',
link: 'https://docker_practice.gitee.io/pic/dp-wechat-miniprogram.jpg',
},
{
text: '安装 Docker',
link: '/03_install/',
},
{
text: 'Docker 入门',
link: '/'
},
{
text: 'Docker 实战',
link: '/15_cases/os/'
},
{
text: 'CI/CD',
link: '/15_cases/ci/'
},
{
text: 'Compose',
link: '/10_compose/',
},
{
text: 'Kubernetes',
link: '/12_orchestration/kubernetes/',
},
{
text: "云计算",
link: "/13_ecosystem/cloud/",
},
// {
// text: 'GitHub',
// link: 'https://github.com/yeasy/docker_practice'
// },
// {
// text: '捐赠',
// link: ''
// },
{
text: '云服务器99/元首年特惠',
link: 'https://cloud.tencent.com/act/cps/redirect?redirect=1062&cps_key=3a5255852d5db99dcd5da4c72f05df61&from=console'
},
// {
// text: '语言',
// items: [{
// text: 'English',
// link: ''
// }]
// }
],
sidebar: "auto",
legacySidebar: {
'/cloud/': [
'intro',
'tencentCloud',
'alicloud',
'aws',
'summary',
],
'/kubernetes/': [
'intro',
'concepts',
'design',
{
title: "部署 Kubernetes",
collapsable: true,
children: [
"setup/",
"setup/kubeadm",
"setup/docker-desktop",
"setup/systemd",
"setup/dashboard",
]
},
{
title: "Kubernetes 命令行 kubectl",
collapsable: true,
children: [
'kubectl/'
]
}
],
'/compose/': [
'introduction',
'v2',
'install',
'usage',
'commands',
'compose_file',
'django',
'rails',
'wordpress',
'lnmp',
],
'/install/': [
'ubuntu',
'debian',
'fedora',
'centos',
'raspberry-pi',
// 'offline',
'mac',
'windows',
'mirror',
'experimental',
],
'/cases/os/': [
{
title: "操作系统",
collapsable: false,
children: [
'busybox',
'alpine',
'debian',
'centos',
'summary',
],
},
{
title: "在 IDE 中使用 Docker",
collapsable: false,
children: [
'/ide/',
'/ide/vsCode',
],
},
],
'/cases/ci/': [
'actions/',
{
title: "Drone",
collapsable: true,
children: [
'drone/',
'drone/install'
]
},
],
'/': [
'/',
'/CHANGELOG',
'/CONTRIBUTING',
{
title: "Docker 简介",
collapsable: false,
children: [
'introduction/',
'introduction/what',
'introduction/why',
]
}, {
title: "基本概念",
collapsable: false,
children: [
'basic_concept/',
'basic_concept/image',
'basic_concept/container',
'basic_concept/repository'
]
},
{
title: "使用镜像",
collapsable: false,
children: [
'image/',
'image/pull',
'image/list',
'image/rm',
'image/commit',
'image/build',
'image/other.md',
'image/internal.md',
]
},
{
title: 'Dockerfile',
collapsable: true,
children: [
"image/dockerfile/",
'image/dockerfile/copy',
'image/dockerfile/add',
'image/dockerfile/cmd',
'image/dockerfile/entrypoint',
'image/dockerfile/env',
'image/dockerfile/arg',
'image/dockerfile/volume',
'image/dockerfile/expose',
'image/dockerfile/workdir',
'image/dockerfile/user',
'image/dockerfile/healthcheck',
'image/dockerfile/label',
'image/dockerfile/shell',
'image/dockerfile/onbuild',
'image/dockerfile/references',
'image/dockerfile/7.17_multistage_builds.md',
'image/dockerfile/7.18_multistage_builds_laravel.md',
'image/manifest',
]
}, {
title: "操作容器",
collapsable: false,
children: [
'container/',
'container/run',
'container/daemon',
'container/stop',
'container/attach_exec',
'container/import_export',
'container/rm',
],
},
{
title: "Docker 仓库",
collapsable: false,
children: [
'repository/',
'repository/dockerhub',
'repository/registry',
'repository/registry_auth',
'repository/nexus3_registry',
],
},
{
title: "数据管理",
collapsable: false,
children: [
'data_management/',
'data_management/volume',
'data_management/bind-mounts',
],
}, {
title: "使用网络",
collapsable: false,
children: [
'network/',
'network/port_mapping',
'network/linking',
'network/dns',
],
},
{
title: "高级网络配置",
collapsable: true,
children: [
'advanced_network/',
'advanced_network/quick_guide',
'advanced_network/access_control',
'advanced_network/port_mapping',
'advanced_network/bridge',
'advanced_network/example',
'advanced_network/config_file',
'advanced_network/ptp',
],
},
{
title: "Swarm mode",
collapsable: true,
children: [
'swarm_mode/',
'swarm_mode/overview',
'swarm_mode/create',
'swarm_mode/deploy',
'swarm_mode/stack',
'swarm_mode/secret',
'swarm_mode/config',
'swarm_mode/rolling_update',
],
},
{
title: "安全",
collapsable: true,
children: [
'security/',
'security/kernel_ns',
'security/control_group',
'security/daemon_sec',
'security/kernel_capability',
'security/other_feature',
'security/summary',
],
},
{
title: "底层实现",
collapsable: true,
children: [
'underly/',
'underly/arch',
'underly/namespace',
'underly/cgroups',
'underly/ufs',
'underly/container_format',
'underly/network',
],
},
{
title: "Docker Buildx",
collapsable: false,
children: [
"buildx/",
"buildx/buildkit",
"buildx/buildx",
"buildx/multi-arch-images",
],
},
{
title: "Etcd",
collapsable: true,
children: [
'etcd/',
'etcd/intro',
'etcd/install',
'etcd/cluster',
'etcd/etcdctl',
],
},
{
title: "Fedora CoreOS",
collapsable: true,
children: [
'coreos/',
'coreos/intro',
'coreos/install',
],
},
'podman/',
'appendix/faq/',
{
title: "热门镜像介绍",
collapsable: true,
children: [
'appendix/repo/',
'appendix/repo/ubuntu',
'appendix/repo/centos',
'appendix/repo/nginx',
'appendix/repo/php',
'appendix/repo/nodejs',
'appendix/repo/mysql',
'appendix/repo/wordpress',
'appendix/repo/mongodb',
'appendix/repo/redis',
'appendix/repo/minio',
],
},
{
title: "Docker 命令",
collapsable: true,
children: [
'appendix/command/',
'appendix/command/docker',
'appendix/command/dockerd',
]
},
'appendix/best_practices',
'appendix/debug',
'appendix/resources',
],
},
}
});

3
.zhlintignore Normal file
View File

@@ -0,0 +1,3 @@
node_modules/
.vuepress/
.git/

View File

@@ -0,0 +1,68 @@
## 1.1 快速上手
本节将通过一个简单的 Web 应用例子带你快速体验 Docker 的核心流程构建镜像运行容器
### 1.1.1 准备代码
创建一个名为 `hello-docker` 的文件夹并在其中创建一个 `index.html` 文件
```html
<h1>Hello, Docker!</h1>
```
### 1.1.2 编写 Dockerfile
在同级目录下创建一个名为 `Dockerfile` (无后缀) 的文件
```dockerfile
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```
### 1.1.3 构建镜像
打开终端进入该目录执行构建命令
```bash
$ docker build -t my-hello-world .
```
* `docker build`构建命令
* `-t my-hello-world`给镜像起个名字 (标签)
* `.`指定上下文路径为当前目录
### 1.1.4 运行容器
使用刚才构建的镜像启动一个容器
```bash
$ docker run -d -p 8080:80 my-hello-world
```
* `docker run`运行命令
* `-d`后台运行
* `-p 8080:80`将宿主机的 8080 端口映射到容器的 80 端口
### 1.1.5 访问测试
打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “HelloDocker”。
### 1.1.6 清理
停止并删除容器
```bash
## 查看正在运行的容器 ID
$ docker ps
## 停止容器
$ docker stop <CONTAINER_ID>
## 删除容器
$ docker rm <CONTAINER_ID>
```
恭喜你已经完成了第一次 Docker 实战接下来请阅读 [Docker 核心概念](../02_basic_concept/README.md)做深入了解

120
01_introduction/1.2_what.md Normal file
View File

@@ -0,0 +1,120 @@
## 1.2 什么是 Docker
Docker 是彻底改变了软件开发和交付方式的革命性技术本节将从核心概念与传统虚拟机的对比技术基础以及历史生态等多个维度带你深入理解什么是 Docker
### 1.2.1 一句话理解 Docker
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元在任何地方都能一致地运行** 如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
在集装箱发明之前货物的运输是一件麻烦的事情不同的货物需要不同的包装不同的装卸方式换一种运输工具就要重新装卸集装箱的出现改变了这一切无论里面装的是什么集装箱的外形是标准的可以用同样的方式装卸堆放和运输
Docker 做的事情类似无论你的应用是用 PythonJavaNode.js 还是其他语言写的无论它需要什么样的依赖库和环境一旦被打包成 Docker 镜像就可以用同样的方式在任何支持 Docker 的机器上运行
### 1.2.2 Docker 的核心价值
笔者认为Docker 解决的是软件开发中最古老的问题之一**在我机器上明明能跑啊**
```mermaid
flowchart LR
subgraph Dev ["开发环境"]
direction TB
A["Python 3.14<br/>Ubuntu 24.04<br/>特定版本的库"] --> B["运行正常"]
end
subgraph Prod ["生产环境"]
direction TB
C["Python 3.11<br/>Ubuntu 22.04<br/>不同版本的库"] --> D["运行失败!"]
end
A -. "≠" .-> C
```
有了 Docker
```mermaid
flowchart LR
subgraph Dev ["开发环境"]
direction TB
A["Docker 镜像<br/>(包含所有依赖)"] --> B["运行正常"]
end
subgraph Prod ["生产环境"]
direction TB
C["同一个镜像<br/>(完全一致)"] --> D["运行正常!"]
end
A === "=" === C
```
### 1.2.3 Docker vs 虚拟机
很多人第一次接触 Docker 时会问**这不就是虚拟机吗** 答案是**不是而且差别很大**
#### 传统虚拟机
传统虚拟机技术是虚拟出一套完整的硬件在其上运行一个完整的操作系统再在该系统上运行应用
![传统虚拟化](../_images/virtualization.png)
#### Docker 容器
Docker 容器内的应用直接运行于宿主的内核容器内没有自己的内核也没有进行硬件虚拟
![Docker](../_images/docker.png)
#### 关键区别
| 特性 | Docker 容器 | 传统虚拟机 |
|------|-------------|------------|
| **启动速度** | 秒级 | 分钟级 |
| **资源占用** | MB 级别 | GB 级别 |
| **性能** | 接近原生 | 有明显损耗 |
| **隔离级别** | 进程级隔离 | 完全隔离 |
| **单机数量** | 可运行上千个 | 通常几十个 |
> 笔者经常用这个类比来解释虚拟机像是每个应用都住在一栋独立的房子里 (有自己的地基水电系统)而容器像是大家住在同一栋公寓楼里的不同房间 (共享地基和水电系统但各自独立)
### 1.2.4 Docker 的技术基础
Docker 使用 [Go 语言](https://golang.google.cn/)开发,基于 Linux 内核的以下技术:
- **[Namespace](https://en.wikipedia.org/wiki/Linux_namespaces)**:实现资源隔离 (进程、网络、文件系统等)
- **[Cgroups](https://zh.wikipedia.org/wiki/Cgroups)**:实现资源限制 (CPU、内存、I/O 等)
- **[Union FS](https://en.wikipedia.org/wiki/Union_mount)**:实现分层存储 (如 OverlayFS)
> 如果你对这些底层技术感兴趣可以阅读本书的[底层实现](../12_implementation/README.md)章节
#### Docker 架构演进
Docker 的底层实现经历了多次演进
```mermaid
flowchart LR
subgraph Timeline
direction LR
LXC["LXC<br/>(2013)"] --> libcontainer["libcontainer<br/>(2014)"]
libcontainer --> runC["runC<br/>(2015)"]
runC --> containerd["containerd + runC<br/>(现在)"]
runC --> OCI["OCI<br/>标准化"]
end
```
- **LXC** (2013)Docker 最初基于 Linux Containers
- **libcontainer** (2014v0.7)Docker 自研的容器运行时
- **runC** (2015v1.11)捐献给 OCI 的标准容器运行时
- **containerd**高级容器运行时管理容器生命周期
![Docker 架构](../_images/docker-on-linux.png)
> `runc` 是一个 Linux 命令行工具用于根据 [OCI 容器运行时规范](https://github.com/opencontainers/runtime-spec)创建和运行容器。
> `containerd` 是一个守护程序它管理容器生命周期提供了在一个节点上执行容器和管理镜像的最小功能集
### 1.2.5 Docker 的历史与生态
**Docker** 最初是 `dotCloud` 公司创始人 [Solomon Hykes](https://github.com/shykes) 在法国期间发起的一个公司内部项目,于 [2013 年 3 月以 Apache 2.0 授权协议开源](https://en.wikipedia.org/wiki/Docker_(software))。
Docker 的发展历程
- **2013 3 **开源发布
- **2013 年底**dotCloud 公司改名为 DockerInc
- **2015 **成立[开放容器联盟 (OCI)](https://opencontainers.org/),推动容器标准化
- **至今**[GitHub 项目](https://github.com/moby/moby)超过 7 万星标
Docker 的成功推动了整个容器生态的发展催生了 KubernetesPodman 等众多相关项目笔者认为Docker 最大的贡献不仅是技术本身更是它 **让容器技术从系统管理员的工具变成了每个开发者都能使用的标准工具**

212
01_introduction/1.3_why.md Normal file
View File

@@ -0,0 +1,212 @@
## 1.3 为什么要用 Docker
在回答 为什么用 Docker 之前笔者想先问一个问题**你有没有经历过这些场景**
### 1.3.1 没有 Docker 的世界
Docker 出现之前软件开发和运维面临着诸多棘手的问题我们先来看看以下三个典型的痛点场景
#### 场景一在我电脑上明明能跑
```bash
周五下午 5:00
├── 开发者:代码写完了,本地测试通过,提交!🎉
├── 周一早上 9:00
│ └── 测试:"这个功能在测试环境跑不起来"
└── 开发者:" 不可能,在我电脑上明明能跑啊……"
```
笔者统计过这个问题通常由以下原因导致
- Python/Node/Java 版本不一致
- 依赖库版本不一致
- 操作系统配置不一致
- 某些环境变量没有设置
- 忘了说我本地装了个 XXX
#### 场景二环境配置的噩梦
```bash
新同事入职
├── Day 1领电脑配环境
├── Day 2继续配环境遇到问题
├── Day 3换种方法配环境
├── Day 4问老同事怎么配的他也忘了
└── Day 5终于能跑起来了但不知道为什么……
```
#### 场景三服务器迁移的恐惧
```bash
运维:"我们需要把服务迁移到新服务器"
开发:"旧服务器上的配置文档在哪?"
运维:"当时是一个已经离职的同事配的……"
所有人:😱
```
### 1.3.2 Docker 如何解决这些问题
Docker 的出现为上述问题提供了完美的解决方案它通过 一次构建到处运行 的核心理念从根本上改变了软件交付的方式
#### 核心理念一次构建到处运行
```mermaid
flowchart LR
dev["开发团队"] -->|创建| img["Docker 镜像"]
img -->|测试团队验证| test["测试团队"]
test -- "有问题<br/>反馈修改和更新" --> dev
test -- "没问题<br/>发布" --> prod["生产环境"]
```
### 1.3.3 Docker 的核心优势
除了解决上述痛点Docker 还拥有诸多显著的技术优势包括环境一致性秒级启动高效的资源利用等
#### 1. 环境一致性
Docker 镜像包含了应用运行所需的 **一切**代码运行时系统工具配置这意味着
- 开发环境和生产环境完全一致
- 不会再有 在我机器上能跑 的问题
- 新人入职一条命令就能启动开发环境
```bash
## 新同事入职第一天
$ git clone https://github.com/company/project.git
$ docker compose up
## 完整的开发环境就准备好了
...
```
#### 2. 秒级启动
传统虚拟机启动需要几分钟 (引导操作系统) Docker 容器启动通常只需要 **几秒甚至几百毫秒**
笔者实测数据
| 启动内容 | 虚拟机 | Docker 容器 |
|---------|--------|-------------|
| 空系统 | ~60 | ~0.5 |
| MySQL | ~90 | ~3 |
| 完整 Web 应用 | ~120 | ~5 |
这个差异对以下场景尤为重要
- **CI/CD 流水线**每次构建节省几分钟一天累积下来就是几小时
- **弹性扩容**流量高峰时能快速启动更多实例
- **开发体验**快速重启服务进行调试
#### 3. 资源效率
Docker 容器共享宿主机内核无需为每个应用运行完整的操作系统以一台 64GB 内存的物理服务器为例
- **传统虚拟机方案**每个虚拟机都需要运行完整的操作系统每个额外占用如 2GB 内存产生大量资源开销实际可用于应用的内存可能只有约 18GB
- **Docker 方案**容器直接共享宿主机系统只需付出很少的基础开销OS及引擎约 4GB即可将约 60GB 的内存全部用于实际应用
```mermaid
flowchart TD
subgraph VM ["传统虚拟机方案 ❌"]
direction TB
Server1["物理服务器 (64GB 内存)"]
subgraph VMs ["可用应用内存: 约 18GB"]
direction LR
VM1["VM 1: 应用 1<br/>(含 2GB OS)"]
VM2["VM 2: 应用 2<br/>(含 2GB OS)"]
VM3["VM 3: 应用 3<br/>(含 2GB OS)"]
end
Server1 --- VMs
end
subgraph Docker ["Docker 方案 ✅"]
direction TB
Server2["物理服务器 (64GB 内存)<br/>含约 4GB OS及引擎配置"]
subgraph Containers ["可用应用内存: 约 60GB"]
direction LR
C1["容器 1: 应用 1<br/>(按需分配)"]
C2["容器 2: 应用 2<br/>(按需分配)"]
C3["容器 3: 应用 3<br/>(按需分配)"]
end
Server2 --- Containers
end
```
#### 4. 持续交付和部署
Docker 完美契合 DevOps 的工作流程
```mermaid
flowchart LR
A["代码提交<br/>(Git push)"] --> B["自动构建镜像<br/>(docker build)"]
B --> C["自动测试<br/>(容器内运行测试)"]
C --> D["自动部署<br/>(容器滚动更新)"]
```
使用 [Dockerfile](../04_image/4.5_build.md) 定义镜像构建过程使得
- 构建过程 **可重复可追溯**
- 任何人都能从代码重建完全相同的镜像
- 配合 [GitHub Actions](../21_case_devops/21.2_github_actions.md) CI 系统实现自动化
#### 5. 轻松迁移
Docker 可以在几乎任何平台上运行
- 本地开发机 (macOSWindowsLinux)
- 公有云 (AWSAzureGCP阿里云腾讯云)
- 私有云和自建数据中心
- 边缘设备和 IoT
**同一个镜像在任何地方运行结果都一致** 这让应用迁移变得前所未有的简单
#### 6. 微服务架构的基石
现代微服务架构几乎都依赖容器技术Docker 让你可以
- **隔离服务**每个服务运行在独立容器中互不干扰
- **独立扩展**哪个服务负载高就单独扩展哪个
- **独立部署**更新一个服务不影响其他服务
- **技术多样**不同服务可以用不同语言和框架
```mermaid
flowchart TD
subgraph Microservices ["微服务架构示例"]
direction TB
subgraph AppLayer ["应用层"]
direction LR
Frontend["前端容器<br/>(Node.js)"]
API["API 容器<br/>(Python)"]
Worker["Worker 容器<br/>(Go)"]
end
Redis["Redis 容器"]
DB["PostgreSQL 容器"]
Frontend --> API
API --> Redis
API --> DB
Worker --> Redis
Worker --> DB
end
```
### 1.3.4 Docker 不适合的场景
笔者认为技术选型要客观Docker 并非银弹以下场景可能不太适合
- **需要完全隔离的场景**容器共享宿主机内核隔离性不如虚拟机如果需要运行不受信任的代码虚拟机可能更安全
- **需要特殊内核的场景**容器使用宿主机内核如果应用需要特定版本的内核或内核模块可能需要虚拟机
- **Windows 原生应用**虽然 Docker 支持 Windows 容器但生态不如 Linux 容器成熟传统 Windows 应用的容器化仍有挑战
- **桌面应用**Docker 主要面向服务端应用桌面 GUI 应用的容器化虽然可行但通常得不偿失
### 1.3.5 与传统虚拟机的对比总结
下表对比了容器技术与传统虚拟机的区别
| 特性 | Docker 容器 | 传统虚拟机 |
|:------|:-----------|:-----------|
| 启动速度 | 秒级 | 分钟级 |
| 磁盘占用 | MB 级别 | GB 级别 |
| 性能 | 接近原生 | 5-20% 损耗 |
| 单机支持量 | 上千个容器 | 几十个虚拟机 |
| 隔离性 | 进程级别 | 完全隔离 |
| 最佳场景 | 微服务CI/CD开发环境 | 多租户高安全需求 |

27
01_introduction/README.md Normal file
View File

@@ -0,0 +1,27 @@
# 第一章 Docker 简介
本章将带领你进入 **Docker** 的世界
## 本章内容
* [快速上手](1.1_quickstart.md)
* 通过一个简单的 Web 应用例子带你快速体验 Docker 的核心流程构建镜像运行容器
* [什么是 Docker](1.2_what.md)
* 介绍 Docker 的起源发展历程以及其背后的核心技术 (CgroupsNamespacesUnionFS)
* 了解 Docker 是如何改变软件交付方式的
* [为什么要用 Docker](1.3_why.md)
* 对比传统虚拟机技术阐述 Docker 在启动速度资源利用率交付效率等方面的巨大优势
* 探讨 Docker DevOps微服务架构中的关键作用
## 学习目标
通过本章的学习你将能够
1. 理解 Docker 的核心概念与架构
2. 明白 Docker 解决了现代软件开发与运维中的哪些痛点
3. 建立起对容器技术的初步认知为后续的实战操作打下基础
好吧让我们带着问题开始这神奇之旅

View File

@@ -0,0 +1,8 @@
## 本章小结
- Docker 是一种轻量级虚拟化技术核心价值是 **环境一致性**
- 与虚拟机相比Docker 更轻量更快速资源利用率更高
- Docker 基于 Linux 内核的 NamespaceCgroups Union FS 技术
- Docker 推动了容器技术的标准化 (OCI) 和生态发展
Docker 的核心价值可以用一句话概括**让应用的开发测试部署保持一致同时极大提高资源利用效率** 笔者认为对于现代软件开发者来说Docker 已经不是 要不要学 的问题而是 **必备技能**无论你是前端后端运维还是全栈开发者掌握 Docker 都能让你的工作更高效

View File

@@ -0,0 +1,214 @@
## 2.1 镜像
Docker 镜像作为容器运行的基石其设计理念和实现机制至关重要本节将深入探讨镜像的本质与操作系统的关系内容构成以及核心的分层存储机制
### 2.1.1 一句话理解镜像
> **Docker 镜像是一个只读的模板包含了运行应用所需的一切代码运行时环境变量和配置文件** 如果用一个类比**镜像就像是一张光盘或 ISO 文件**你可以用同一张光盘在不同电脑上安装系统而光盘本身不会被修改同样一个镜像可以创建多个容器而镜像本身保持不变
### 2.1.2 镜像与操作系统的关系
我们都知道操作系统分为 **内核** **用户空间**
```mermaid
flowchart TD
subgraph UserSpace ["用户空间"]
direction TB
App["应用程序、工具、库、配置文件...<br/>(这部分被打包成 Docker 镜像)"]
end
subgraph KernelSpace ["Linux 内核"]
direction TB
Kernel["容器共享宿主机的内核"]
end
UserSpace --- KernelSpace
```
对于 Linux 而言内核启动后会挂载 `root` 文件系统来提供用户空间支持**Docker 镜像** 本质上就是一个 `root` 文件系统
例如官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统 **不包含 Linux 内核** (因为容器共享宿主机的内核)
### 2.1.3 镜像包含什么
Docker 镜像是一个特殊的文件系统包含
| 内容类型 | 示例 |
|---------|------|
| **程序文件** | 应用二进制文件Python/Node 解释器 |
| **库文件** | libcOpenSSL各种依赖库 |
| **配置文件** | nginx.confmy.cnf |
| **环境变量** | PATHLANG 等预设值 |
| **元数据** | 启动命令暴露端口数据卷定义 |
**关键特性**
- 镜像是 **只读**
- 镜像 **不包含** 动态数据
- 镜像构建后 **内容不会改变**
### 2.1.4 分层存储镜像的核心设计
镜像的分层存储机制是 Docker 最具创新性的特性之一通过 Union FS 技术Docker 能够高效地构建和管理镜像
#### 为什么需要分层
笔者认为分层存储是 Docker 最巧妙的设计之一
假设你有三个应用都基于 Ubuntu 运行
```mermaid
flowchart TD
subgraph Traditional ["传统方式(不分层)总计: 1.5GB ❌"]
direction LR
AppA_Trad["App A<br/>Ubuntu 500MB"]
AppB_Trad["App B<br/>Ubuntu 500MB"]
AppC_Trad["App C<br/>Ubuntu 500MB"]
end
subgraph DockerLayered ["Docker 分层方式 总计: 620MB ✅"]
direction TB
subgraph Apps ["应用层"]
direction LR
AppA["App A 50MB"]
AppB["App B 30MB"]
AppC["App C 40MB"]
end
Ubuntu["Ubuntu<br/>共享500MB"]
AppA --> Ubuntu
AppB --> Ubuntu
AppC --> Ubuntu
end
```
#### 分层是如何工作的
笔者用一个实际的 Dockerfile 来解释分层
```docker
FROM ubuntu:24.04 # 第 1 层:基础系统(约 78MB
RUN apt-get update # 第 2 层:更新包索引
RUN apt-get install nginx # 第 3 层:安装 nginx
COPY app.conf /etc/nginx/ # 第 4 层:复制配置文件
```
构建后的镜像结构
```mermaid
flowchart TD
Layer4["第 4 层: COPY app.conf (只读)<br/>← 最新添加的层"]
Layer3["第 3 层: nginx 安装文件 (只读)"]
Layer2["第 2 层: apt 缓存更新 (只读)"]
Layer1["第 1 层: Ubuntu 基础系统 (只读)<br/>← 基础镜像层"]
Layer4 --> Layer3 --> Layer2 --> Layer1
```
每一层的特点
- **只读**构建完成后不可修改
- **可共享**多个镜像可以共享相同的层
- **有缓存**未变化的层不会重新构建
#### 分层存储的 陷阱
> **笔者特别提醒**理解这一点可以帮你避免构建出臃肿的镜像**关键原理**每一层的文件变化会被记录 **删除操作只是标记不会真正减小镜像体积**
```docker
## 错误示范 ❌
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install -y build-essential # 安装编译工具(约 200MB
RUN make && make install # 编译应用
RUN apt-get remove build-essential # 试图删除编译工具
## 结果:镜像仍然包含 200MB 的编译工具!
```
```docker
## 正确做法 ✅
FROM ubuntu:24.04
RUN apt-get update && \
apt-get install -y build-essential && \
make && make install && \
apt-get remove -y build-essential && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
## 在同一层完成安装、使用、清理
```
#### 查看镜像的分层
```bash
## 查看镜像的历史(每层的构建记录)
$ docker history nginx:latest
IMAGE CREATED CREATED BY SIZE
a6bd71f48f68 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
<missing> 2 weeks ago STOPSIGNAL SIGQUIT 0B
<missing> 2 weeks ago EXPOSE map[80/tcp:{}] 0B
<missing> 2 weeks ago ENTRYPOINT ["/docker-entrypoint.sh"] 0B
<missing> 2 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB
...
```
### 2.1.5 镜像的标识
Docker 镜像有多种标识方式
#### 1. 镜像名称和标签
格式`[仓库地址/]仓库名[:标签]`
```bash
## 完整格式
registry.example.com/myproject/myapp:v1.2.3
## 简写(使用 Docker Hub
nginx:1.25
ubuntu:24.04
## 省略标签(默认使用 latest
nginx # 等同于 nginx:latest
```
#### 2. 镜像 ID (Content-Addressable)
每个镜像有一个基于内容计算的唯一 ID
```bash
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a6bd71f48f68 2 weeks ago 187MB
ubuntu 24.04 ca2b0f26964c 3 weeks ago 78.1MB
```
#### 3. 镜像摘要
更精确的标识基于镜像内容的 SHA256 哈希
```bash
$ docker images --digests
REPOSITORY TAG DIGEST IMAGE ID
nginx latest sha256:6db391d1c0cfb30588ba0bf72ea999404f2764184d8b8d10d89e8a9c6... a6bd71f48f68
```
> 💡 笔者建议在生产环境使用镜像摘要而非标签因为标签可以被覆盖但摘要是不可变的
### 2.1.6 镜像的来源
Docker 镜像可以通过以下方式获取
| 方式 | 说明 | 示例 |
|------|------|------|
| ** Registry 拉取** | 最常用的方式 | `docker pull nginx` |
| ** Dockerfile 构建** | 自定义镜像 | `docker build -t myapp .` |
| **从容器提交** | 保存容器状态 (不推荐)| `docker commit` |
| **从文件导入** | 离线传输 | `docker load < image.tar` |

View File

@@ -0,0 +1,239 @@
## 2.2 容器
容器是 Docker 技术的核心是应用实际运行的载体本节将从容器的本质与虚拟机的区别存储层机制以及生命周期管理等方面全面解析 Docker 容器
### 2.2.1 一句话理解容器
> **容器是镜像的运行实例如果把镜像比作程序那么容器就是进程** 用面向对象编程的术语来说**镜像是类 (Class)容器是对象 (Instance)**
- 一个镜像可以创建多个容器
- 每个容器相互独立互不影响
- 容器可以被创建启动停止删除暂停
### 2.2.2 容器的本质
> 💡 笔者认为理解这一点是理解 Docker 的关键**容器的本质是一个特殊的进程**
```mermaid
flowchart TD
subgraph NormalProcess ["普通进程"]
direction TB
N1["• 共享系统资源<br/>• 共享网络<br/>• 共享文件系统"]
end
subgraph ContainerProcess ["容器进程 (运行在宿主机内核上)"]
direction TB
C1["• 独立进程空间<br/>• 独立网络环境<br/>• 独立文件系统<br/>• 独立用户空间"]
end
```
这种隔离是通过 Linux 内核的 **Namespace** 技术实现的具体表现为
- **进程空间**容器看不到宿主机上的其他进程
- **网络**容器拥有独立的 IP端口等网络资源
- **文件系统**容器拥有独立的 root 目录
- **用户**容器内的 root 用户不等于宿主机的 root 用户
### 2.2.3 容器 vs 虚拟机核心区别
很多初学者会混淆容器和虚拟机笔者用一张图来说明
```mermaid
flowchart TD
subgraph VM ["虚拟机 (每个 VM 运行完整 OS)"]
direction TB
subgraph VMApp ["应用层"]
VA[App A] & VB[App B]
end
subgraph VMGuest ["Guest OS (完整系统)"]
G1[Guest OS] & G2[Guest OS]
end
V[Hypervisor]
VMH[Host OS]
VMHW[Hardware]
VMApp --> VMGuest --> V --> VMH --> VMHW
end
subgraph Container ["容器 (所有容器共享宿主机内核)"]
direction TB
subgraph CApp ["应用层"]
CA[App A] & CB[App B]
end
subgraph CContainer ["隔离层"]
CC1[Container 仅应用] & CC2[Container 仅应用]
end
CE[Docker Engine]
CH[Host OS]
CHW[Hardware]
CApp --> CContainer --> CE --> CH --> CHW
end
```
| 特性 | 容器 | 虚拟机 |
|------|------|--------|
| **隔离级别** | 进程级 (Namespace)| 硬件级 (Hypervisor)|
| **启动时间** | 秒级 (甚至毫秒)| 分钟级 |
| **资源占用** | MB 级别 | GB 级别 |
| **性能损耗** | 几乎为零 | 5-20% |
| **内核** | 共享宿主机内核 | 各自独立内核 |
### 2.2.4 容器的存储层
理解容器的存储层机制对于数据的持久化和镜像的优化至关重要本节将介绍容器的可写层以及 Copy-on-Write 机制
#### 镜像层 + 容器层
当容器运行时Docker 会在镜像的只读层之上创建一个 **可写层** (容器存储层)
```mermaid
flowchart TD
ContainerLayer["容器存储层(可读写)<br/>容器运行时创建,记录文件变化"]
ImageLayerN["镜像第 N 层(只读)"]
ImageLayerN1["镜像第 N-1 层(只读)"]
Dots["..."]
ImageLayer1["镜像第 1 层(只读)<br/>基础镜像层"]
ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1
```
#### Copy-on-Write (写时复制)
当容器需要修改镜像层中的文件时
1. Docker 将该文件 **复制** 到容器存储层
2. 在容器层中进行修改
3. 原始镜像层保持不变
```bash
读取文件:直接从镜像层读取(共享,高效)
修改文件:复制到容器层,然后修改(只有这个容器能看到修改)
```
#### 容器存储层的生命周期
> **笔者特别强调**这是新手最容易踩的坑**容器存储层与容器生命周期绑定容器删除数据就没了**
```bash
## 创建容器,写入数据
$ docker run -it ubuntu bash
root@abc123:/# echo "important data" > /data.txt
root@abc123:/# exit
## 删除容器
$ docker rm abc123
## 数据丢了!没有任何办法恢复!
```
#### 正确的数据持久化方式
按照 Docker 最佳实践容器存储层应该保持 **无状态**需要持久化的数据应该使用
| 方式 | 说明 | 适用场景 |
|------|------|---------|
| **[数据卷 (Volume) ](../08_data/8.1_volume.md)** | Docker 管理的存储 | 数据库应用数据 |
| **[绑定挂载 (Bind Mount) ](../08_data/8.2_bind-mounts.md)** | 挂载宿主机目录 | 开发时共享代码 |
```bash
## 使用数据卷(推荐)
$ docker run -v mydata:/var/lib/mysql mysql
## 使用绑定挂载
$ docker run -v /host/path:/container/path nginx
```
这些位置的读写 **会跳过容器存储层**直接写入宿主机性能更好也不会随容器删除而丢失
### 2.2.5 容器的生命周期
掌握容器的生命周期对于管理和调试 Docker 应用非常重要如图 2-1 所示容器会经历从创建到删除的完整状态流转
```mermaid
stateDiagram-v2
direction TB
[*] --> Created : docker create
Created --> Running : docker start
Running --> Stopped : docker stop
Running --> Paused : docker pause
Paused --> Running : docker unpause
Created --> Deleted : docker rm
Stopped --> Deleted : docker rm
Paused --> Deleted : docker rm
Deleted --> [*]
```
2-1 容器生命周期状态流转图
#### 常用生命周期命令
```bash
## 创建并启动容器(最常用)
$ docker run nginx
## 分步操作
$ docker create nginx # 创建容器(不启动)
$ docker start abc123 # 启动容器
## 停止容器
$ docker stop abc123 # 优雅停止(发送 SIGTERM等待后发送 SIGKILL
$ docker kill abc123 # 强制停止(直接发送 SIGKILL
## 暂停/恢复(不常用,但有时有用)
$ docker pause abc123 # 暂停容器内所有进程
$ docker unpause abc123 # 恢复
## 删除容器
$ docker rm abc123 # 删除已停止的容器
$ docker rm -f abc123 # 强制删除运行中的容器
```
### 2.2.6 容器与进程的关系
> **核心概念**容器的生命周期 = 主进程 (PID 1) 的生命周期
```bash
## 主进程运行,容器运行
## 主进程退出,容器停止
```
这就是为什么
```bash
## 这个容器会立即退出bash 没有输入就退出了)
$ docker run ubuntu
## 这个容器会持续运行nginx 作为守护进程持续运行)
$ docker run nginx
```
详细解释请参考[后台运行](../05_container/5.2_daemon.md)章节
### 2.2.7 容器的隔离性
Docker 容器通过以下 Namespace 实现隔离
| Namespace | 隔离内容 | 效果 |
|-----------|---------|------|
| **PID** | 进程 ID | 容器内 PID 1 是应用进程看不到宿主机其他进程 |
| **NET** | 网络 | 独立的网络栈IP 地址端口 |
| **MNT** | 文件系统 | 独立的根目录和挂载点 |
| **UTS** | 主机名 | 独立的主机名和域名 |
| **IPC** | 进程间通信 | 独立的信号量消息队列 |
| **USER** | 用户 | 独立的用户和组 ID |
> 想深入了解请阅读[底层实现 - 命名空间](../12_implementation/12.2_namespace.md)

View File

@@ -0,0 +1,288 @@
## 2.3 仓库
Docker Registry 是镜像分发和管理的核心组件本节将介绍 Registry 的基本概念公共和私有服务的选择以及镜像的安全管理
### 2.3.1 一句话理解 Registry
> **Docker Registry 是存储和分发 Docker 镜像的服务类似于代码的 GitHub 或包管理的 npm**
镜像构建完成后可以在当前机器上运行但如果需要在其他服务器上使用这个镜像就需要一个集中的存储和分发服务这就是 Docker Registry
### 2.3.2 核心概念
要熟练使用 Docker Registry首先需要理清它与仓库 (Repository)标签 (Tag) 之间的关系
#### Registry仓库标签的关系
Docker Registry 中可以包含多个 Repository每个 Repository 可以包含多个 Tag如图 2-2 所示它们之间具有清晰的层级关系
```mermaid
flowchart TB
subgraph Registry ["Docker Registry如 Docker Hub"]
direction TB
subgraph RepoNginx ["Repository仓库: nginx"]
direction LR
N1(":latest (tag)")
N2(":1.25 (tag)")
N3(":1.24 (tag)")
N4(":alpine (tag)")
N5("...")
N1 ~~~ N2 ~~~ N3 ~~~ N4 ~~~ N5
end
subgraph RepoMysql ["Repository仓库: mysql"]
direction LR
M1(":latest")
M2(":8.0")
M3(":5.7")
M4("...")
M1 ~~~ M2 ~~~ M3 ~~~ M4
end
RepoNginx ~~~ RepoMysql
end
```
2-2 RegistryRepository Tag 的层级关系
相关基本概念具体如下
| 概念 | 说明 | 示例 |
|------|------|------|
| **Registry** | 存储镜像的服务 | Docker Hubghcr.io |
| **Repository (仓库)** | 同一软件的镜像集合 | `nginx``mysql``mycompany/myapp` |
| **Tag (标签)** | 仓库内的版本标识 | `latest``1.25``alpine` |
#### 镜像的完整名称
一个完整的 Docker 镜像名称由 Registry 地址用户名/组织名仓库名和标签组成了解其结构有助于我们更准确地定位镜像基本格式如下
```bash
[registry地址/][用户名/]仓库名[:标签]
```
示例
```bash
## 完整格式
registry.example.com/mycompany/myapp:v1.2.3
│ │ │ │
│ │ │ └── 标签
│ │ └── 仓库名
│ └── 用户名/组织名
└── Registry 地址
## Docker Hub 官方镜像(省略 registry 和用户名)
nginx:1.25
ubuntu:24.04
## Docker Hub 用户镜像
jwilder/nginx-proxy:latest
## 其他 Registry
ghcr.io/username/myapp:v1.0
gcr.io/google-containers/pause:3.6
```
> 💡 **笔者提示**如果不指定 Registry 地址默认使用 Docker Hub如果不指定标签默认使用 `latest`
### 2.3.3 公共 Registry 服务
公共 Registry 服务为开发者提供了便捷的镜像获取途径其中最著名的是 Docker Hub
#### 默认的 Docker Hub
[Docker Hub](https://hub.docker.com/) 是最大的公共 Registry也是 Docker 的默认 Registry。
**特点**
- 拥有大量[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official) (nginx、mysql、redis 等)
- 免费账户可以创建公开仓库
- 付费账户支持私有仓库
```bash
## 从 Docker Hub 拉取镜像
$ docker pull nginx # 官方镜像
$ docker pull bitnami/redis # 第三方镜像
## 推送镜像到 Docker Hub
$ docker login
$ docker push username/myapp:v1.0
```
#### 其他公共 Registry
除了 Docker Hub还有以下几个常见的公共 Registry
| Registry | 地址 | 说明 |
|----------|------|------|
| **GitHub Container Registry** | ghcr.io | GitHub 提供 GitHub Actions 集成好 |
| **Google Container Registry** | gcr.io | Google Cloud 提供Kubernetes 镜像常用 |
| **Quay.io** | quay.io | Red Hat 提供 |
| **阿里云容器镜像服务** | registry.cn-*.aliyuncs.com | 国内访问快 |
| **腾讯云容器镜像服务** | ccr.ccs.tencentyun.com | 国内访问快 |
### 2.3.4 镜像加速器
由于网络原因在国内直接访问 Docker Hub 可能会很慢可以配置 **镜像加速器** (Registry Mirror) 来加速下载配置示例如下
```json
// /etc/docker/daemon.json
{
"registry-mirrors": [
"https://your-accelerator-url"
]
}
```
详细配置方法请参考[镜像加速器](../03_install/3.9_mirror.md)章节
> **笔者提醒**镜像加速器的可用性经常变化使用前建议先测试是否可用
### 2.3.5 私有 Registry
出于安全和隐私的考虑企业往往需要搭建自己的私有 Registry以下是几种常见的搭建方案
#### 官方 Registry 镜像
Docker 官方提供了 [registry](https://hub.docker.com/_/registry/) 镜像,可以快速搭建私有 Registry
```bash
## 启动一个本地 Registry
$ docker run -d -p 5000:5000 --name registry registry:2
## 推送镜像到本地 Registry
$ docker tag myapp:v1.0 localhost:5000/myapp:v1.0
$ docker push localhost:5000/myapp:v1.0
## 从本地 Registry 拉取
$ docker pull localhost:5000/myapp:v1.0
```
#### 企业级解决方案
官方 Registry 功能较为基础企业环境常用以下方案
| 方案 | 特点 |
|------|------|
| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面 (用户管理、漏洞扫描、镜像签名)|
| **[Nexus Repository](../06_repository/6.4_nexus3_registry.md)** | 支持多种制品类型 (DockerMavennpm )|
| **云厂商服务** | 阿里云 ACR腾讯云 TCRAWS ECR |
笔者建议
- 小团队可以先用官方 Registry够用即可
- 中大型团队推荐 Harbor功能完善且开源免费
- 已使用云服务直接用云厂商的 Registry 服务更省心
### 2.3.6 镜像的推送和拉取
掌握镜像的推送 (Push) 和拉取 (Pull) 是使用 Docker Registry 的基本功
#### 完整工作流程
如图 2-3 所示镜像从开发环境构建后推送到 Registry再由生产环境拉取并运行
```bash
开发者机器 Registry 生产服务器
│ │ │
│ docker build │ │
│ 构建镜像 │ │
│ │ │
│ docker push ─────────────▶ │
│ 推送镜像 │ 存储镜像 │
│ │ │
│ │ ◀───────────── docker pull │
│ │ 拉取镜像 │
│ │ │
│ │ docker run │
│ │ 运行容器 │
```
2-3 镜像构建推送与拉取流程
#### 常用命令
```bash
## 登录 Registry
$ docker login # 登录 Docker Hub
$ docker login registry.example.com # 登录其他 Registry
## 拉取镜像
$ docker pull nginx:1.25
## 标记镜像(准备推送)
$ docker tag myapp:latest registry.example.com/myteam/myapp:v1.0
## 推送镜像
$ docker push registry.example.com/myteam/myapp:v1.0
## 登出
$ docker logout
```
### 2.3.7 镜像的安全性
在使用公共镜像或维护私有镜像时安全性是不容忽视的重要环节
#### 使用官方镜像
Docker Hub [官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official) (标有 “Official Image” 标识) 经过 Docker 团队审核,相对更安全。示例如下:
```bash
## 官方镜像示例
nginx # ✅ 官方
mysql # ✅ 官方
redis # ✅ 官方
## 第三方镜像(需要自行评估可信度)
bitnami/redis # ⚠️ 需要评估
someuser/myapp # ⚠️ 需要评估
```
#### 镜像签名
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证`Docker Content Trust (DCT)` 已进入退场阶段不建议作为新项目主方案
> 注意Cosign 默认会把签名写回镜像所在仓库请使用你有推送权限的镜像地址
```bash
## 准备一个你有写权限的镜像地址
$ export IMAGE=<你的仓库名>/nginx:1.27
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ docker push $IMAGE
## 生成签名密钥(会生成 cosign.key / cosign.pub
$ cosign generate-key-pair
## 使用 Cosign 签名与验证
$ cosign sign --key cosign.key $IMAGE
$ cosign verify --key cosign.pub $IMAGE
```
#### 漏洞扫描
```bash
## 使用 Docker Scout 扫描镜像漏洞
$ docker scout cves nginx:latest
## 使用 Trivy开源工具
$ trivy image nginx:latest
```

View File

@@ -0,0 +1,9 @@
# 第二章 基本概念
**Docker** 包括三个基本概念
* **镜像** (`Image`)Docker 镜像是一个特殊的文件系统除了提供容器运行时所需的程序资源配置等文件外还包含了一些为运行时准备的一些配置参数 (如匿名卷环境变量用户等)镜像不包含任何动态数据其内容在构建之后也不会被改变
* **容器** (`Container`)镜像 (`Image`) 和容器 (`Container`) 的关系就像是面向对象程序设计中的 `` `实例` 一样镜像是静态的定义容器是镜像运行时的实体容器可以被创建启动停止删除暂停等
* **仓库** (`Repository`)镜像构建完成后可以很容易的在当前宿主机上运行但是如果需要在其它服务器上使用这个镜像我们就需要一个集中的存储分发镜像的服务Docker Registry 就是这样的服务
理解了这三个概念就理解了 **Docker** 的整个生命周期

View File

@@ -0,0 +1,51 @@
## 本章小结
| 概念 | 要点 |
|------|------|
| **镜像是什么** | 只读的应用模板包含运行所需的一切 |
| **分层存储** | 多层叠加共享基础层节省空间 |
| **只读特性** | 构建后不可修改保证一致性 |
| **层的陷阱** | 删除操作只是标记不减小体积 |
理解了镜像接下来让我们学习[容器](2.2_container.md)镜像的运行实例
### 2.4.1 延伸阅读
- [获取镜像](../04_image/4.1_pull.md) Registry 下载镜像
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)创建自己的镜像
- [Dockerfile 最佳实践](../appendix/best_practices.md)构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../12_implementation/12.4_ufs.md)深入理解分层存储的技术原理
| 概念 | 要点 |
|------|------|
| **容器是什么** | 镜像的运行实例本质是隔离的进程 |
| **容器 vs 虚拟机** | 共享内核更轻量但隔离性较弱 |
| **存储层** | 可写层随容器删除而消失 |
| **数据持久化** | 使用 Volume Bind Mount |
| **生命周期** | 与主进程 (PID 1) 绑定 |
理解了镜像和容器接下来让我们学习[仓库](2.3_repository.md)存储和分发镜像的服务
### 2.4.2 延伸阅读
- [启动容器](../05_container/5.1_run.md)详细的容器启动选项
- [后台运行](../05_container/5.2_daemon.md)理解容器为什么会 立即退出
- [进入容器](../05_container/5.4_attach_exec.md)如何操作运行中的容器
- [数据管理](../08_data/README.md)Volume 和数据持久化详解
| 概念 | 要点 |
|------|------|
| **Registry** | 存储和分发镜像的服务 |
| **仓库 (Repository)** | 同一软件的镜像集合 |
| **标签 (Tag)** | 版本标识默认为 latest |
| **Docker Hub** | 默认的公共 Registry |
| **私有 Registry** | 企业内部使用推荐 Harbor |
现在你已经了解了 Docker 的三个核心概念[镜像](2.1_image.md)[容器](2.2_container.md)和仓库接下来让我们开始[安装 Docker](../03_install/README.md)动手实践
### 2.4.3 延伸阅读
- [Docker Hub](../06_repository/6.1_dockerhub.md)Docker Hub 的详细使用
- [私有仓库](../06_repository/6.2_registry.md)搭建私有 Registry
- [私有仓库高级配置](../06_repository/6.3_registry_auth.md)认证TLS 配置
- [镜像加速器](../03_install/3.9_mirror.md)配置镜像加速

View File

@@ -0,0 +1,19 @@
## 3.10 开启实验特性
一些 docker 命令或功能仅当 **实验特性** 开启时才能使用请按照以下方法进行设置
### 3.10.1 Docker CLI 的实验特性
CLI 的实验特性通常包含仍在开发中的新功能幸运的是在较新版本中这些特性已经更加易用
`v20.10` 版本开始Docker CLI 所有实验特性的命令均默认开启无需再进行配置或设置系统环境变量
### 3.10.2 开启 dockerd 的实验特性
编辑 `/etc/docker/daemon.json`新增如下条目
```json
{
"experimental": true
}
```

182
03_install/3.1_ubuntu.md Normal file
View File

@@ -0,0 +1,182 @@
## 3.1 Ubuntu
Ubuntu Docker 最常用的运行环境之一本节将介绍如何在 Ubuntu 系统上安装 Docker并配置国内镜像加速
>警告切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker
### 3.1.1 准备工作
在开始安装之前我们需要确认系统版本是否满足要求并清理可能存在的旧版本
#### 系统要求
Docker 支持诸多版本的 [Ubuntu](https://ubuntu.com/server) 操作系统。但是较旧的版本上将不会有 Docker 新版本的持续更新,以截至 2026 年初的几个 Ubuntu LTS (Long Term Support长期支持) 版本为例:
* Ubuntu Noble 24.04 (LTS)Docker v29.x
* Ubuntu Jammy 22.04 (LTS), Docker v29.x
> **注意**Ubuntu 20.04 LTS 已于 2025 年结束标准支持不再推荐用于新部署
Ubuntu LTS 版本上目前 Docker 支持 amd64arm64armhfppc64els390x 5 个平台而非 LTS 版本支持的平台通常较少同时LTS 版本会获得 5 年的升级维护支持这样的系统会获得更长期的安全保障因此在生产环境中推荐使用 LTS 版本
#### 卸载旧版本
旧版本的 Docker 称为 `docker` 或者 `docker-engine`使用以下命令卸载旧版本
```bash
$ for pkg in docker \
docker-engine \
docker.io \
docker-doc \
podman-docker \
containerd \
runc;
do
sudo apt remove $pkg;
done
```
### 3.1.2 使用 APT 安装
由于 `apt` 源使用 HTTPS 以确保软件下载过程中不被篡改因此我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书
```bash
$ sudo apt update
$ sudo apt install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
```
鉴于国内网络问题强烈建议使用国内源官方源请在注释中查看
为了确认所下载软件包的合法性需要添加软件源的 `GPG` 密钥
```bash
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
## 官方源
## $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```
然后我们需要向 `sources.list` 中添加 Docker 软件源
```bash
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## 官方源
## $ echo \
## "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
>以上命令会添加稳定版本的 Docker APT 镜像源如果需要测试版本的 Docker 请将 stable 改为 test
#### 安装 Docker
更新 apt 软件包缓存并安装 `docker-ce`
```bash
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
```
### 3.1.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Ubuntu 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
> 若你想安装测试版的 Docker请从 test.docker.com 获取脚本
```bash
## $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定 (stable) 版本安装在系统中
### 3.1.4 启动 Docker
```bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.1.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好地做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
建立 `docker`
```bash
$ sudo groupadd docker
```
将当前用户加入 `docker`
```bash
$ sudo usermod -aG docker $USER
```
退出当前终端并重新登录进行如下测试
### 3.1.6 测试 Docker 是否安装正确
```bash
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
```
若能正常输出以上信息则说明安装成功
### 3.1.7 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 3.1.8 参考文档
* [Docker 官方 Ubuntu 安装文档](https://docs.docker.com/engine/install/ubuntu/)

173
03_install/3.2_debian.md Normal file
View File

@@ -0,0 +1,173 @@
## 3.2 Debian
Debian 以其稳定性著称 Docker 的理想宿主系统本节将指导你在 Debian 上完成 Docker 的安装
>警告切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker
### 3.2.1 准备工作
安装前请仔细检查 Debian 版本支持情况并卸载旧版本以避免冲突
#### 系统要求
Docker 支持以下版本的 [Debian](https://www.debian.org/intro/about) 操作系统:
* Debian Trixie 13 (stable)
* Debian Bookworm 12 (oldstable)
* Debian Bullseye 11 (LTS)
#### 卸载旧版本
旧版本的 Docker 称为 `docker` 或者 `docker-engine`使用以下命令卸载旧版本
```bash
$ sudo apt-get remove docker \
docker-engine \
docker.io
```
### 3.2.2 使用 APT 安装
由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改因此我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书
```bash
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
```
鉴于国内网络问题强烈建议使用国内源官方源请在注释中查看
为了确认所下载软件包的合法性需要添加软件源的 GPG 密钥
```bash
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
## 官方源
## $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```
然后我们需要向 `sources.list` 中添加 Docker 软件源
> 在一些基于 Debian Linux 发行版中 `$(lsb_release -cs)` 可能不会返回 Debian 的版本代号例如 [Kali Linux](https://www.kali.org/docs/policy/kali-linux-relationship-with-debian/)、[BunsenLabs Linux](https://www.bunsenlabs.org/)。在这些发行版中我们需要将下面命令中的 `$(lsb_release -cs)` 替换为 https://mirrors.aliyun.com/docker-ce/linux/debian/dists/ 中支持的 Debian 版本代号,例如 `buster`。
```bash
$ echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://mirrors.aliyun.com/docker-ce/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## 官方源
## $ echo \
## "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
>以上命令会添加稳定版本的 Docker APT 如果需要测试版本的 Docker 请将 stable 改为 testDebian11 可能不使用 `/etc/apt/keyrings/` gpg 错误可以考虑更换为 `/etc/apt/trusted.gpg.d` [issue 15727](https://github.com/docker/docs/issues/15727)。
#### 安装 Docker
更新 apt 软件包缓存并安装 `docker-ce`
```bash
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
### 3.2.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Debian 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
> 若你想安装测试版的 Docker请从 test.docker.com 获取脚本
```bash
## $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定 (stable) 版本安装在系统中
### 3.2.4 启动 Docker
```bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.2.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好地做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
建立 `docker`
```bash
$ sudo groupadd docker
```
将当前用户加入 `docker`
```bash
$ sudo usermod -aG docker $USER
```
退出当前终端并重新登录进行如下测试
### 3.2.6 测试 Docker 是否安装正确
```bash
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
```
若能正常输出以上信息则说明安装成功
### 3.2.7 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 3.2.8 参考文档
* [Docker 官方 Debian 安装文档](https://docs.docker.com/engine/install/debian/)

View File

@@ -1,16 +1,20 @@
## Fedora 安装 Docker CE
## 3.3 Fedora
>警告切勿在没有配置 Docker dnf 源的情况下直接使用 dnf 命令安装 Docker.
Fedora 作为技术前沿的 Linux 发行版 Docker 有着良好的支持本节介绍在 Fedora 上的安装步骤
### 准备工作
>警告切勿在没有配置 Docker dnf 源的情况下直接使用 dnf 命令安装 Docker
### 3.3.1 准备工作
确保你的 Fedora 版本在支持列表中并清理旧版本
#### 系统要求
Docker CE 支持以下版本的 [Fedora](https://fedoraproject.org/) 操作系统:
Docker 支持以下版本的 [Fedora](https://getfedora.org/) 操作系统:
* 26 (Docker CE v18.03 及以下版本)
* 27
* 28
* 41
* 42
* 43
#### 卸载旧版本
@@ -29,7 +33,9 @@ $ sudo dnf remove docker \
docker-engine
```
### 使用 dnf 安装
### 3.3.2 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式便于后续的更行和管理
执行以下命令安装依赖包
@@ -44,40 +50,39 @@ $ sudo dnf -y install dnf-plugins-core
```bash
$ sudo dnf config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/fedora/docker-ce.repo
https://mirrors.aliyun.com/docker-ce/linux/fedora/docker-ce.repo
$ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
## 官方源
## $ sudo dnf config-manager \
## --add-repo \
## https://download.docker.com/linux/fedora/docker-ce.repo
# 官方源
# $ sudo dnf config-manager \
# --add-repo \
# https://download.docker.com/linux/fedora/docker-ce.repo
```
如果需要测试版本的 Docker CE 请使用以下命令
如果需要测试版本的 Docker 请使用以下命令
```bash
$ sudo dnf config-manager --set-enabled docker-ce-test
```
如果需要每日构建版本的 Docker CE 请使用以下命令
```bash
$ sudo dnf config-manager --set-enabled docker-ce-nightly
```
你也可以禁用测试版本的 Docker CE
你也可以禁用测试版本的 Docker
```bash
$ sudo dnf config-manager --set-disabled docker-ce-test
```
#### 安装 Docker CE
#### 安装 Docker
更新 `dnf` 软件源缓存并安装 `docker-ce`
```bash
$ sudo dnf update
$ sudo dnf install docker-ce
$ sudo dnf install docker-ce docker-ce-cli containerd.io
```
你也可以使用以下命令安装指定版本的 Docker
@@ -90,25 +95,31 @@ docker-ce.x86_64 18.06.1.ce-3.fc28 docker-ce-stable
$ sudo dnf -y install docker-ce-18.06.1.ce
```
### 使用脚本自动安装
### 3.3.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Debian 系统上可以使用这套脚本安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Fedora 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
> 若你想安装测试版的 Docker请从 test.docker.com 获取脚本
```bash
## $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker CE 最新版本安装在系统中
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 最新稳定 (stable) 版本安装在系统中
### 启动 Docker CE
### 3.3.4 启动 Docker
```bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 建立 docker 用户组
### 3.3.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好地做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
@@ -126,15 +137,15 @@ $ sudo usermod -aG docker $USER
退出当前终端并重新登录进行如下测试
### 测试 Docker 是否安装正确
### 3.3.6 测试 Docker 是否安装正确
```bash
$ docker run hello-world
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
@@ -161,10 +172,10 @@ For more examples and ideas, visit:
若能正常输出以上信息则说明安装成功
### 镜像加速
### 3.3.7 镜像加速
鉴于国内网络问题后续拉取 Docker 镜像十分缓慢强烈建议安装 Docker 之后配置 [国内镜像加速](mirror.md)
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 参考文档
### 3.3.8 参考文档
* [Docker 官方 Fedora 安装文档](https://docs.docker.com/install/linux/docker-ce/fedora)。
* [Docker 官方 Fedora 安装文档](https://docs.docker.com/engine/install/fedora/)。

View File

@@ -1,12 +1,20 @@
## CentOS 安装 Docker CE
## 3.4 CentOS
>警告切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker.
CentOS (及其替代品 Rocky LinuxAlmaLinux) 是企业级服务器常用的操作系统本节介绍在这些系统上安装 Docker 的步骤
### 准备工作
>警告切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker
### 3.4.1 准备工作
安装前请确认系统版本和内核版本满足 Docker 的运行要求
#### 系统要求
Docker CE 支持 64 位版本 CentOS 7并且要求内核版本不低于 3.10 CentOS 7 满足最低内核的要求但由于内核版本比较低部分功能 `overlay2` 存储层驱动无法使用并且部分功能可能不太稳定
> **重要提示**CentOS 8 已于 2021 12 31 日停止维护CentOS 7 已于 2024 6 30 日结束支持建议新项目使用 **Rocky Linux** **AlmaLinux** 作为替代
Docker 支持 64 位版本 CentOS Stream 9Rocky Linux 8/9AlmaLinux 8/9并且要求内核版本不低于 3.10
对于 Rocky LinuxAlmaLinux CentOS Stream推荐使用 `dnf` 包管理器
#### 卸载旧版本
@@ -22,17 +30,19 @@ $ sudo yum remove docker \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
docker-engine \
docker-ce-cli \
containerd.io
```
### 使用 yum 安装
### 3.4.2 使用 yum 安装
使用 yum/dnf 安装是管理 Docker 生命周期的标准方式
执行以下命令安装依赖包
```bash
$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
$ sudo dnf install -y dnf-utils
```
鉴于国内网络问题强烈建议使用国内源官方源请在注释中查看
@@ -40,57 +50,81 @@ $ sudo yum install -y yum-utils \
执行下面的命令添加 `yum` 软件源
```bash
$ sudo yum-config-manager \
$ sudo dnf config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
## 官方源
## $ sudo dnf config-manager \
## --add-repo \
## https://download.docker.com/linux/centos/docker-ce.repo
# 官方源
# $ sudo yum-config-manager \
# --add-repo \
# https://download.docker.com/linux/centos/docker-ce.repo
```
如果需要测试版本的 Docker CE 请使用以下命令
如果需要测试版本的 Docker 请执行以下命令
```bash
$ sudo yum-config-manager --enable docker-ce-test
$ sudo dnf config-manager --set-enabled docker-ce-test
```
如果需要每日构建版本的 Docker CE 请使用以下命令
#### 安装 Docker
更新 `dnf` 软件源缓存并安装 `docker-ce`
```bash
$ sudo yum-config-manager --enable docker-ce-nightly
$ sudo dnf install docker-ce docker-ce-cli containerd.io
```
#### 安装 Docker CE
### 3.4.3 CentOS8 额外设置
更新 `yum` 软件源缓存并安装 `docker-ce`
CentOS 8/Stream 默认使用 `nftables`Docker 在新版本中已提供 `nftables` 实验支持但在一些环境下仍可能遇到兼容性问题若你遇到容器网络异常可以先切换回 `iptables` 后端
更改 `/etc/firewalld/firewalld.conf`
```bash
$ sudo yum makecache fast
$ sudo yum install docker-ce
## FirewallBackend=nftables
FirewallBackend=iptables
```
### 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本CentOS 系统上可以使用这套脚本安装
或者执行如下命令
```bash
$ firewall-cmd --permanent --zone=trusted --add-interface=docker0
$ firewall-cmd --reload
```
### 3.4.4 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本CentOS 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
> 若你想安装测试版的 Docker请从 test.docker.com 获取脚本
```bash
## $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker CE Edge 版本安装在系统中
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定 (stable) 版本安装在系统中
### 启动 Docker CE
### 3.4.5 启动 Docker
```bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 建立 docker 用户组
### 3.4.6 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好地做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
@@ -108,15 +142,15 @@ $ sudo usermod -aG docker $USER
退出当前终端并重新登录进行如下测试
### 测试 Docker 是否安装正确
### 3.4.7 测试 Docker 是否安装正确
```bash
$ docker run hello-world
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
d1725b59e92d: Pull complete
Digest: sha256:0add3ace90ecb4adbf7777e9aacf18357296e799f81cabc9fde470971e499788
b8dfde127a29: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
@@ -143,13 +177,13 @@ For more examples and ideas, visit:
若能正常输出以上信息则说明安装成功
### 镜像加速
### 3.4.8 镜像加速
鉴于国内网络问题后续拉取 Docker 镜像十分缓慢强烈建议安装 Docker 之后配置 [国内镜像加速](mirror.md)
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 添加内核参数
### 3.4.9 添加内核参数
默认配置下如果在 CentOS 使用 Docker CE 看到下面的这些警告信息
如果在 CentOS 使用 Docker 看到下面的这些警告信息
```bash
WARNING: bridge-nf-call-iptables is disabled
@@ -171,6 +205,8 @@ EOF
$ sudo sysctl -p
```
### 参考文档
### 3.4.10 参考文档
* [Docker 官方 CentOS 安装文档](https://docs.docker.com/install/linux/docker-ce/centos/)。
* [Docker 官方 CentOS 安装文档](https://docs.docker.com/engine/install/centos/)。
* https://firewalld.org/2018/07/nftables-backend
* https://github.com/moby/libnetwork/issues/2496

View File

@@ -0,0 +1,198 @@
## 3.5 Raspberry Pi
树莓派等 ARM 架构设备在物联网和边缘计算领域应用广泛本节介绍如何在树莓派上安装 Docker
>警告切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker
### 3.5.1 系统要求
Docker ARM 架构有着良好的支持
Docker 不仅支持 `x86_64` 架构的计算机同时也支持 `ARM` 架构的计算机本小节内容以树莓派单片电脑为例讲解 `ARM` 架构安装 Docker
Docker 支持以下版本的 [Raspberry Pi OS](https://www.raspberrypi.org/software/operating-systems/) 操作系统:
* Raspberry Pi OS Trixie
* Raspberry Pi OS Bookworm
* Raspberry Pi OS Bullseye
**`Raspberry Pi OS` 由树莓派的开发与维护机构[树莓派基金会](https://www.raspberrypi.org/)官方支持,并推荐用作树莓派的首选系统,其基于 `Debian`。
### 3.5.2 使用 APT 安装
推荐使用 APT 包管理器进行安装以确保版本的稳定性和安全性
由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改因此我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书
```bash
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
```
鉴于国内网络问题强烈建议使用国内源官方源请在注释中查看
为了确认所下载软件包的合法性需要添加软件源的 GPG 密钥
```bash
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/raspbian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
## 官方源
## $ sudo install -m 0755 -d /etc/apt/keyrings
## $ curl -fsSL https://download.docker.com/linux/raspbian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
## $ sudo chmod a+r /etc/apt/keyrings/docker.gpg
```
然后我们需要向 `sources.list` 中添加 Docker 软件源
```bash
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/raspbian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## 官方源
## $ echo \
## "deb [arch=$ signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian \
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
>以上命令会添加稳定版本的 Docker APT 如果需要测试版本的 Docker 请将 stable 改为 test
#### 报错解决办法
`Raspberry Pi OS Bullseye/Bookworm` 如果你使用 `add-apt-repository` 添加源可能会出现如下报错 (推荐改用上面的 `tee` 方式来写入 `/etc/apt/sources.list.d/docker.list`可避免此问题)
```bash
Traceback (most recent call last):
File "/usr/bin/add-apt-repository", line 95, in <module>
sp = SoftwareProperties(options=options)
File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 109, in __init__
self.reload_sourceslist()
File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 599, in reload_sourceslist
self.distro.get_sources(self.sourceslist)
File "/usr/lib/python3/dist-packages/aptsources/distro.py", line 91, in get_sources
raise NoDistroTemplateException(
aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for Raspbian/bullseye
```
通过以下命令手动添加镜像源到 `/etc/apt/sources.list` 文件中即可解决
```bash
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/raspbian $(lsb_release -cs) stable" | sudo tee -a /etc/apt/sources.list
## 官方源
## $ echo "deb [arch=$ signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian $ stable" | sudo tee -a /etc/apt/sources.list
```
#### 安装 Docker
更新 apt 软件包缓存并安装 `docker-ce`
```bash
$ sudo apt-get update
$ sudo apt-get install docker-ce
```
### 3.5.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Raspberry Pi OS 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
> 若你想安装测试版的 Docker请从 test.docker.com 获取脚本
```bash
## $ curl -fsSL test.docker.com -o get-docker.sh
$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定 (stable) 版本安装在系统中
### 3.5.4 启动 Docker
```bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.5.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好地做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
建立 `docker`
```bash
$ sudo groupadd docker
```
将当前用户加入 `docker`
```bash
$ sudo usermod -aG docker $USER
```
退出当前终端并重新登录进行如下测试
### 3.5.6 测试 Docker 是否安装正确
```bash
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
4ee5c797bcd7: Pull complete
Digest: sha256:308866a43596e83578c7dfa15e27a73011bdd402185a84c5cd7f32a88b501a24
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(arm32v7)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
```
若能正常输出以上信息则说明安装成功
*注意*ARM 平台不能使用 `x86` 镜像查看 Raspberry Pi OS 可使用镜像请访问 [arm32v7](https://hub.docker.com/u/arm32v7/) 或者 [arm64v8](https://hub.docker.com/u/arm64v8/)。
### 3.5.7 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)

266
03_install/3.6_offline.md Normal file
View File

@@ -0,0 +1,266 @@
## 3.6 Linux 离线安装
\[TOC]
生产环境中一般都是没有公网资源的本文介绍如何在生产服务器上离线部署 `Docker`
括号内的字母表示该操作需要在哪些服务器上执行
![Docker-offile-install-top](../_images/image-20200412202617411.png)
### 3.6.1 概述
### 3.6.2 CentOS/Rocky/AlmaLinux 离线安装 Docker
在无法连接外网的安全环境中离线安装是唯一的选择本节介绍如何在 RHEL 系发行版中进行离线安装
> 注意以下命令以 CentOS 7 为例对于 CentOS Stream 9Rocky Linux 9 AlmaLinux 9请将 `yum` 替换为 `dnf`并将软件包后缀 `el7` 替换为 `el9`
#### YUM 本地文件安装 (推荐)
推荐这种方式是因为在生产环境种一般会选定某个指定的文档软件版本使用
##### 查询可用的软件版本
```bash
#下载清华的镜像源文件
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum update
```
```bash
sudo yum list docker-ce --showduplicates|sort -r
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror
docker-ce.x86_64 24.0.4-1.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.7-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.6-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.5-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.4-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.3-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable
....
```
##### 下载到指定文件夹
```bash
sudo yum install --downloadonly --downloaddir=/tmp/docker24_offline_install/ docker-ce-24.0.4-1.el7 docker-ce-cli-24.0.4-1.el7
```
```bash
Dependencies Resolved
====================================================================================================================================================================================
Package Arch Version Repository Size
====================================================================================================================================================================================
Installing:
docker-ce x86_64 24.0.4-1.el7 docker 25 M
Installing for dependencies:
container-selinux noarch 24.0.4-1.el7 extras 39 k
containerd.io x86_64 24.0.4-1.el7 docker 23 M
docker-ce-cli x86_64 24.0.4-1.el7 docker 40 M
Transaction Summary
====================================================================================================================================================================================
Install 1 Package (+3 Dependent packages)
Total download size: 87 M
Installed size: 363 M
Background downloading packages, then exiting:
(1/4): container-selinux-24.0.4-1.el7.noarch.rpm | 39 kB 00:00:00
(2/4): containerd.io-24.0.4-1.el7.x86_64.rpm | 23 MB 00:00:00
(3/4): docker-ce-24.0.4-1.el7.x86_64.rpm | 25 MB 00:00:00
(4/4): docker-ce-cli-24.0.4-1.el7.x86_64.rpm | 40 MB 00:00:00
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 118 MB/s | 87 MB 00:00:00
exiting because "Download Only" specified
```
##### 复制到目标服务器之后进入文件夹安装 (C-N)
* 离线安装时必须使用 rpm 命令不检查依赖的方式安装
```bash
rpm -Uvh *.rpm --nodeps --force
```
##### 锁定软件版本 (C-N)
**下载锁定版本软件**
可参考下文的网络源搭建
```bash
sudo yum install yum-plugin-versionlock
```
**锁定软件版本**
```bash
sudo yum versionlock add docker
```
**查看锁定列表**
```bash
sudo yum versionlock list
```
```bash
Loaded plugins: fastestmirror, versionlock
3:docker-ce-24.0.4-1.el7.*
versionlock list done
```
**锁定后无法再更新**
```bash
sudo yum install docker-ce
Loaded plugins: fastestmirror, versionlock
Loading mirror speeds from cached hostfile
Excluding 1 update due to versionlock (use "yum versionlock status" to show it)
Package 3:docker-ce-24.0.4-1.el7.x86_64 already installed and latest version
Nothing to do
```
**解锁指定软件**
```bash
sudo yum versionlock delete docker-ce
```
```bash
Loaded plugins: fastestmirror, versionlock
Deleting versionlock for: 3:docker-ce-24.0.4-1.el7.*
versionlock deleted: 1
```
**解锁所有软件**
```bash
sudo yum versionlock delete all
```
#### YUM 本地源服务器搭建安装 Docker
##### 挂载 ISO 镜像搭建本地 File
```bash
## 删除其他网络源
rm -f /etc/yum.repos.d/*
## 挂载光盘或者iso镜像
mount /dev/cdrom /mnt
```
```bash
## 添加本地源
cat >/etc/yum.repos.d/local_files.repo<< EOF
[Local_Files]
name=Local_Files
baseurl=file:///mnt
enabled=1
gpgcheck=0
gpgkey=file:///mnt/RPM-GPG-KEY-CentOS-7
EOF
```
```bash
## 测试刚才的本地源,安装createrepo软件
yum clean all
yum install createrepo -y
```
##### 根据本地文件搭建 BASE 网络源
```bash
## 安装apache 服务器
yum install httpd -y
## 挂载光盘
mount /dev/cdrom /mnt
## 新建centos目录
mkdir /var/www/html/base
## 复制光盘内的文件到刚才新建的目录
cp -R /mnt/Packages/* /var/www/html/base/
createrepo /var/www/html/base/
systemctl enable httpd
systemctl start httpd
```
##### 下载 Docker-CE 镜像仓库
在有网络的服务器上下载 Docker-ce 镜像
```bash
## 下载清华的镜像源文件
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo
```
```bash
## 新建 docker-ce目录
mkdir /tmp/docker-ce/
## 把镜像源同步到镜像文件中
reposync -r docker-ce-stable -p /tmp/docker-ce/
```
##### 创建仓库索引
把下载的 docker-ce 文件夹复制到离线的服务器
```bash
## 把docker-ce 文件夹复制到/var/www/html/docker-ce
## 重建索引
createrepo /var/www/html/docker-ce/
```
##### YUM 客户端设置 (C...N)
```bash
rm -f /etc/yum.repos.d/*
cat >/etc/yum.repos.d/local_files.repo<< EOF
[local_base]
name=local_base
## 改成B服务器地址
baseurl=http://x.x.x.x/base
enabled=1
gpgcheck=0
proxy=_none_
[docker_ce]
name=docker_ce
## 改成B服务器地址
baseurl=http://x.x.x.x/docker-ce
enabled=1
gpgcheck=0
proxy=_none_
EOF
```
##### Docker 安装 (C...N)
```bash
sudo yum makecache fast
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl enable docker
```

76
03_install/3.7_mac.md Normal file
View File

@@ -0,0 +1,76 @@
## 3.7 macOS
### 3.7.1 系统要求
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonora 14.0 或更高版本,建议升级到最新版本的 macOS。
### 3.7.2 安装
> [!WARNING]
> **商业许可限制** 2021 年起Docker Desktop 对微型企业少于 250 名员工且年收入少于 1000 万美元个人使用教育和非商业开源项目仍然免费对于其他商业用途需要付费订阅企业用户请注意合规风险或考虑使用开源替代方案
Docker Desktop Mac 用户提供了无缝的 Docker 体验你可以选择使用 Homebrew 或手动下载安装包进行安装
#### 使用 Homebrew 安装
[Homebrew](https://brew.sh/) 的 [Cask](https://github.com/Homebrew/homebrew-cask) 已经支持 Docker Desktop for Mac因此可以很方便的使用 Homebrew Cask 来进行安装:
```bash
$ brew install --cask docker
```
#### 手动下载安装
如果需要手动下载请点击以下[链接](https://desktop.docker.com/mac/main/amd64/Docker.dmg)下载 Docker Desktop for Mac。
> 如果你的电脑搭载的是 Apple Silicon 芯片 (`arm64` 架构)请点击以下[链接](https://desktop.docker.com/mac/main/arm64/Docker.dmg)下载 Docker Desktop for Mac。你可以在[官方文档](https://docs.docker.com/docker-for-mac/apple-silicon/)查阅已知的问题。
如同 macOS 其它软件一样安装也非常简单双击下载的 `.dmg` 文件然后将那只叫 [Moby](https://www.docker.com/blog/call-me-moby-dock/) 的鲸鱼图标拖拽到 `Application` 文件夹即可 (其间需要输入用户密码)。
![](../_images/install-mac-dmg.jpg)
### 3.7.3 运行
从应用中找到 Docker 图标并点击运行
![](../_images/install-mac-apps.jpg)
运行之后会在右上角菜单栏看到多了一个鲸鱼图标这个图标表明了 Docker 的运行状态
![](../_images/install-mac-menubar.png)
每次点击鲸鱼图标会弹出操作菜单
![](../_images/install-mac-menu.png)
之后你可以在终端通过命令检查安装后的 Docker 版本
```bash
$ docker --version
Docker version 26.1.1, build 4cf5afa
```
如果 `docker version``docker info` 都正常的话可以尝试运行一个 [Nginx 服务器](https://hub.docker.com/_/nginx/)
```bash
$ docker run -d -p 80:80 --name webserver nginx
```
服务运行后可以访问 [http://localhost](http://localhost),如果看到了 “Welcome to nginx就说明 Docker Desktop for Mac 安装成功了。
![](../_images/install-mac-example-nginx.png)
要停止 Nginx 服务器并删除执行下面的命令
```bash
$ docker stop webserver
$ docker rm webserver
```
### 3.7.4 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 3.7.5 参考链接
* [官方文档](https://docs.docker.com/desktop/setup/install/mac-install/)

51
03_install/3.8_windows.md Normal file
View File

@@ -0,0 +1,51 @@
## 3.8 Windows 10/11
Windows 平台上Docker Desktop 提供了完整的 Docker 开发环境本节介绍在 Windows 10/11 上的安装和配置
### 3.8.1 系统要求
[Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/) 支持 64 位版本的 Windows 11 或 Windows 10 (需开启 Hyper-V),推荐使用 Windows 11。
### 3.8.2 安装
> [!WARNING]
> **商业许可限制** 2021 年起Docker Desktop 对微型企业少于 250 名员工且年收入少于 1000 万美元个人使用教育和非商业开源项目仍然免费对于其他商业用途需要付费订阅企业用户请注意合规风险或考虑使用开源替代方案
**手动下载安装**
点击以下[链接](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe)下载 Docker Desktop for Windows。
下载好之后双击 `Docker Desktop Installer.exe` 开始安装
**使用** [**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/) **安装**
```powershell
$ winget install Docker.DockerDesktop
```
### 3.8.3 WSL2 运行 Docker
若你的 Windows 版本为 Windows 10 专业版或家庭版 v1903 及以上版本可以使用 WSL2 运行 Docker具体请查看 [Docker Desktop WSL 2 backend](https://docs.docker.com/docker-for-windows/wsl/)。
### 3.8.4 运行
Windows 搜索栏输入 **Docker** 点击 **Docker Desktop** 开始运行
![](../_images/install-win-docker-app-search.png)
Docker 启动之后会在 Windows 任务栏出现鲸鱼图标
![](../_images/install-win-taskbar-circle.png)
等待片刻当鲸鱼图标静止时说明 Docker 启动成功之后你可以打开 PowerShell 使用 Docker
> 推荐使用 [Windows Terminal](https://docs.microsoft.com/zh-cn/windows/terminal/get-started) 在终端使用 Docker。
### 3.8.5 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
### 3.8.6 参考链接
* [官方文档](https://docs.docker.com/desktop/setup/install/windows-install/)
* [WSL 2 Support is coming to Windows 10 Versions 1903 and 1909](https://devblogs.microsoft.com/commandline/wsl-2-support-is-coming-to-windows-10-versions-1903-and-1909/)

113
03_install/3.9_mirror.md Normal file
View File

@@ -0,0 +1,113 @@
## 3.9 镜像加速器
国内从 Docker Hub 拉取镜像有时会遇到困难此时可以配置镜像加速器
> **注意**镜像加速器的可用性经常变化配置前请先访问 [docker-practice/docker-registry-cn-mirror-test](https://github.com/docker-practice/docker-registry-cn-mirror-test/actions) 查看各镜像站的实时状态。
### 3.9.1 推荐配置方案
针对不同的使用场景我们推荐以下几种镜像加速配置方案以确保最佳的拉取速度
1. **云服务器用户**优先使用所在云平台提供的内部加速器 (见本页末尾)
2. **本地开发用户**使用阿里云个人加速器或其他可用的公共加速器
3. **代理方案**如有条件可配置 HTTP 代理直接访问 Docker Hub
* [阿里云加速器](https://cr.console.aliyun.com/cn-hangzhou/instances) (需登录获取个人加速地址)
本节以 [AtomHub 可信镜像中心](https://hub.atomgit.com/)镜像服务 `https://hub.atomgit.com` 为例进行介绍。
> `hub.atomgit.com` 仅包含部分官方镜像可以满足初学者的使用
### 3.9.2 Ubuntu 22.04+Debian 12+Rocky/Alma/CentOS Stream 9+
目前主流 Linux 发行版均已使用 [systemd](https://systemd.io/) 进行服务管理,这里介绍如何在使用 systemd 的 Linux 发行版中配置镜像加速器。
请首先执行以下命令查看是否在 `docker.service` 文件中配置过镜像地址
```bash
$ systemctl cat docker | grep '\-\-registry\-mirror'
```
如果该命令有输出那么请执行 `$ systemctl cat docker` 查看 `ExecStart=` 出现的位置修改对应的文件内容去掉 `--registry-mirror` 参数及其值并按接下来的步骤进行配置
如果以上命令没有任何输出那么就可以在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件)
```json
{
"registry-mirrors": [
"https://hub.atomgit.com"
]
}
```
> 注意一定要保证该文件符合 json 规范否则 Docker 将不能启动
之后重新启动服务
```bash
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker
```
### 3.9.3 Windows 10/11
对于使用 `Windows 10/11` 的用户在任务栏托盘 Docker 图标内右键菜单选择 `Change settings`打开配置窗口后在左侧导航菜单选择 `Docker Engine`在右侧像下边一样编辑 json 文件之后点击 `Apply & Restart` 保存后 Docker 就会重启并应用配置的镜像地址了
```json
{
"registry-mirrors": [
"https://hub.atomgit.com"
]
}
```
### 3.9.4 macOS
对于使用 macOS 的用户在任务栏点击 Docker Desktop 应用图标 -> `Settings...`在左侧导航菜单选择 `Docker Engine`在右侧像下边一样编辑 json 文件修改完成之后点击 `Apply & restart` 按钮Docker 就会重启并应用配置的镜像地址了
```json
{
"registry-mirrors": [
"https://hub.atomgit.com"
]
}
```
### 3.9.5 检查加速器是否生效
执行 `$ docker info`如果从结果中看到了如下内容说明配置成功
```bash
Registry Mirrors:
https://hub.atomgit.com/
```
### 3.9.6 Kubernetes 官方镜像地址迁移
可以登录[阿里云容器镜像服务](https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu&type=copy)**镜像中心**->**镜像搜索** 查找。
Kubernetes 社区已将官方镜像地址从 `k8s.gcr.io` 迁移到 `registry.k8s.io`建议优先使用新地址
一般情况下有如下对应关系
```bash
$ docker pull registry.k8s.io/xxx
```
### 3.9.7 不再提供服务的镜像
某些镜像不再提供服务添加无用的镜像加速器会拖慢镜像拉取速度你可以从镜像配置列表中删除它们
* https://dockerhub.azk8s.cn **已转为私有**
* https://reg-mirror.qiniu.com
* https://registry.docker-cn.com
* https://hub-mirror.c.163.com
* https://mirror.baidubce.com
建议 **watch (页面右上角)** [镜像测试](https://github.com/docker-practice/docker-registry-cn-mirror-test)这个 GitHub 仓库,我们会在此更新各个镜像地址的状态。
### 3.9.8 云服务商
某些云服务商提供了 **仅供内部** 访问的镜像服务当您的 Docker 运行在云平台时可以选择它们
* [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)

18
03_install/README.md Normal file
View File

@@ -0,0 +1,18 @@
# 第三章 安装 Docker
Docker 分为 `stable` `test` `nightly` 三个更新频道
官方网站上有各种环境下的[安装指南](https://docs.docker.com/get-docker/),这里主要介绍 Docker 在 `Linux`、`Windows 10` 和 `macOS` 上的安装。
## 详细安装指南
* [Ubuntu](3.1_ubuntu.md)
* [Debian](3.2_debian.md)
* [Fedora](3.3_fedora.md)
* [CentOS](3.4_centos.md)
* [Raspberry Pi](3.5_raspberry-pi.md)
* [Linux 离线安装](3.6_offline.md)
* [macOS](3.7_mac.md)
* [Windows 10/11](3.8_windows.md)
* [镜像加速器](3.9_mirror.md)
* [开启实验特性](3.10_experimental.md)

27
03_install/summary.md Normal file
View File

@@ -0,0 +1,27 @@
## 本章小结
Docker 支持在多种平台上安装和使用选择合适的安装方式是顺利使用 Docker 的第一步
| 平台 | 推荐方式 | 说明 |
|------|---------|------|
| **Ubuntu/Debian** | 官方 APT 仓库 | 最完善的支持推荐首选 |
| **CentOS/Fedora** | 官方 YUM/DNF 仓库 | 注意关闭 SELinux 或配置策略 |
| **macOS** | Docker Desktop | 图形化安装包含 Compose Kubernetes |
| **Windows 10/11** | Docker Desktop (WSL 2) | 需启用 WSL 2 后端 |
| **Raspberry Pi** | 官方安装脚本 | 支持 ARM 架构 |
| **离线环境** | 二进制包安装 | 适用于无法联网的服务器 |
### 3.11.1 安装后验证
安装完成后运行以下命令验证 Docker 是否正常工作
```bash
$ docker version
$ docker run --rm hello-world
```
### 3.11.2 延伸阅读
- [镜像加速器](3.9_mirror.md)解决国内拉取镜像慢的问题
- [开启实验特性](3.10_experimental.md)使用最新功能
- [Docker Hub](../06_repository/6.1_dockerhub.md)官方镜像仓库

241
04_image/4.1_pull.md Normal file
View File

@@ -0,0 +1,241 @@
## 4.1 获取镜像
Docker 镜像仓库获取镜像可谓是 Docker 运作的第一步本节将介绍如何使用 `docker pull` 命令下载镜像以及如何理解下载过程
### 4.1.1 docker pull 命令
从镜像仓库获取镜像的命令是 `docker pull`
```bash
docker pull [选项] [Registry地址/]仓库名[:标签]
```
#### 镜像名称格式
Docker 镜像名称由 Registry 地址用户名仓库名和标签组成其标准格式如下
```bash
docker.io / library / ubuntu : 24.04
────┬──── ───┬─── ──┬─── ──┬──
│ │ │ │
Registry地址 用户名 仓库名 标签
(可省略) (可省略)
```
| 组成部分 | 说明 | 默认值 |
|---------|------|--------|
| Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)|
| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)|
| 仓库名 | 镜像名称 | 必须指定 |
| 标签 | 版本标识 | `latest` |
#### 示例
```bash
## 完整格式
$ docker pull docker.io/library/ubuntu:24.04
## 省略 Registry默认 Docker Hub
$ docker pull library/ubuntu:24.04
## 省略 library官方镜像
$ docker pull ubuntu:24.04
## 省略标签(默认 latest
$ docker pull ubuntu
## 拉取第三方镜像
$ docker pull bitnami/redis:latest
## 从其他 Registry 拉取
$ docker pull ghcr.io/username/myapp:v1.0
```
---
### 4.1.2 下载过程解析
当我们执行 `docker pull` 命令时Docker 会输出详细的下载进度让我们以 `ubuntu:24.04` 为例来解析这些信息
```bash
$ docker pull ubuntu:24.04
24.04: Pulling from library/ubuntu
92dc2a97ff99: Pull complete
be13a9d27eb8: Pull complete
c8299583700a: Pull complete
Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
```
#### 输出解读
| 输出内容 | 说明 |
|---------|------|
| `Pulling from library/ubuntu` | 正在从官方 ubuntu 仓库拉取 |
| `92dc2a97ff99: Pull complete` | 各层的下载状态 (显示层 ID 12 )|
| `Digest: sha256:...` | 镜像内容的唯一摘要 |
| `docker.io/library/ubuntu:24.04` | 镜像的完整名称 |
#### 分层下载
从输出可以看到镜像是 **分层下载**
```mermaid
flowchart TD
subgraph Image ["ubuntu:24.04 镜像"]
direction TB
L3["第3层 c8299583700a<br/>(已存在,跳过下载)"]
L2["第2层 be13a9d27eb8<br/>(下载中... 完成)"]
L1["第1层 92dc2a97ff99<br/>(下载中... 完成)"]
L3 --- L2 --- L1
end
```
如果本地已有相同的层Docker 会跳过下载节省带宽和时间
---
### 4.1.3 常用选项
`docker pull` 命令支持多种选项来满足不同的下载需求例如下载所有标签指定平台架构等
| 选项 | 说明 | 示例 |
|------|------|------|
| `--all-tags, -a` | 拉取所有标签 | `docker pull -a ubuntu` |
| `--platform` | 指定平台架构 | `docker pull --platform linux/arm64 nginx` |
| `--quiet, -q` | 静默模式 | `docker pull -q nginx` |
#### 指定平台
Apple Silicon Mac 上拉取 x86 镜像
```bash
$ docker pull --platform linux/amd64 nginx
```
---
### 4.1.4 拉取后运行
拉取镜像后可以基于它启动容器
```bash
## 拉取镜像
$ docker pull ubuntu:24.04
## 运行容器
$ docker run -it --rm ubuntu:24.04 bash
root@e7009c6ce357:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
...
root@e7009c6ce357:/# exit
```
**参数说明**
| 参数 | 说明 |
|------|------|
| `-it` | 交互式终端模式 |
| `--rm` | 退出后自动删除容器 |
| `bash` | 启动命令 |
> 💡 `docker run` 在需要时会自动 `pull` 镜像因此通常不需要单独执行 `docker pull`
---
### 4.1.5 镜像加速
Docker Hub 下载可能较慢可以配置镜像加速器
```json
// /etc/docker/daemon.json (Linux)
// ~/.docker/daemon.json (Docker Desktop)
{
"registry-mirrors": [
"https://your-accelerator-url"
]
}
```
配置后重启 Docker
```bash
$ sudo systemctl restart docker # Linux
## 或在 Docker Desktop 中重启
## 或在 Docker Desktop 中重启
```
详见[镜像加速器](../03_install/3.9_mirror.md)章节
---
### 4.1.6 验证镜像完整性
为了确保下载的镜像没有被篡改且内容一致我们可以校验镜像的摘要 (Digest)
#### 查看镜像摘要
```bash
$ docker images --digests ubuntu
REPOSITORY TAG DIGEST IMAGE ID
ubuntu 24.04 sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26 ca2b0f26964c
```
#### 使用摘要拉取
用摘要拉取可确保获取完全相同的镜像
```bash
$ docker pull ubuntu@sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
```
> 笔者建议生产环境使用摘要而非标签因为标签可能被覆盖摘要则是不可变的
---
### 4.1.7 常见问题
在使用 `docker pull` 过程中可能会遇到下载速度慢镜像不存在或磁盘空间不足等问题以下是一些常见问题的排查思路
#### Q下载速度很慢
1. 配置镜像加速器
2. 检查网络连接
3. 尝试拉取更小的镜像版本 ( `alpine` 变体)
#### Q提示镜像不存在
```bash
Error: pull access denied, repository does not exist
```
可能原因
- 镜像名拼写错误
- 私有镜像未登录 (需要 `docker login`)
- 镜像确实不存在
#### Q磁盘空间不足
```bash
## 清理未使用的镜像
$ docker image prune
## 清理所有未使用资源
$ docker system prune
```
---

267
04_image/4.2_list.md Normal file
View File

@@ -0,0 +1,267 @@
## 4.2 列出镜像
在下载了镜像后我们可以使用 `docker image ls` 命令列出本地主机上的镜像
### 4.2.1 基本用法
查看本地已下载的镜像
```bash
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 5f515359c7f8 5 days ago 183MB
nginx latest 05a60462f8ba 5 days ago 181MB
ubuntu 24.04 329ed837d508 3 days ago 78MB
ubuntu noble 329ed837d508 3 days ago 78MB
```
> 💡 `docker images` `docker image ls` 的简写两者等效
---
### 4.2.2 输出字段说明
`docker image ls` 命令默认输出的列表包含仓库名标签镜像 ID创建时间和占用空间等信息
| 字段 | 说明 |
|------|------|
| **REPOSITORY** | 仓库名 |
| **TAG** | 标签 (版本)|
| **IMAGE ID** | 镜像唯一标识 ( ID 12 )|
| **CREATED** | 创建时间 |
| **SIZE** | 本地占用空间 |
#### 同一镜像多个标签
注意上面的 `ubuntu:24.04` `ubuntu:noble` 拥有相同的 IMAGE ID它们是同一个镜像的不同标签只占用一份存储空间
---
### 4.2.3 理解镜像大小
Docker 镜像的大小可能与我们通常理解的文件大小有所不同这涉及到分层存储的概念
#### 本地大小 vs Hub 显示大小
| 位置 | 显示大小 | 说明 |
|------|---------|------|
| Docker Hub | 29MB | 压缩后的网络传输大小 |
| docker image ls | 78MB | 本地解压后的实际大小 |
#### 实际磁盘占用
由于镜像是分层存储不同镜像可能共享相同的层
```bash
ubuntu:24.04 nginx:latest redis:latest
│ │ │
└───────┬───────┘ │
▼ │
共享基础层 ◄───────────────────┘
```
因此`docker image ls` 中各镜像大小之和 > 实际磁盘占用
#### 查看实际空间占用
```bash
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 15 3 2.5GB 1.8GB (72%)
Containers 5 2 100MB 80MB (80%)
Local Volumes 8 2 500MB 400MB (80%)
Build Cache 0 0 0B 0B
```
---
### 4.2.4 过滤镜像
随着本地镜像数量的增加我们需要更有效的方式来查找特定的镜像Docker 提供了多种过滤方式
#### 按仓库名过滤
```bash
## 列出所有 ubuntu 镜像
$ docker images ubuntu
REPOSITORY TAG IMAGE ID SIZE
ubuntu 24.04 329ed837d508 78MB
ubuntu noble 329ed837d508 78MB
ubuntu 22.04 a1b2c3d4e5f6 72MB
```
#### 按仓库名和标签过滤
```bash
$ docker images ubuntu:24.04
REPOSITORY TAG IMAGE ID SIZE
ubuntu 24.04 329ed837d508 78MB
```
#### 使用过滤器 --filter
| 过滤条件 | 说明 | 示例 |
|---------|------|------|
| `dangling=true` | 虚悬镜像 | `-f dangling=true` |
| `before=镜像` | 在某镜像之前创建 | `-f before=nginx:latest` |
| `since=镜像` | 在某镜像之后创建 | `-f since=nginx:latest` |
| `label=key=value` | LABEL 过滤 | `-f label=version=1.0` |
| `reference=pattern` | 按名称模式 | `-f reference='*:latest'` |
```bash
## 列出 nginx 之后创建的镜像
$ docker images -f since=nginx:latest
## 列出所有带 latest 标签的镜像
$ docker images -f reference='*:latest'
## 列出带特定 LABEL 的镜像
$ docker images -f label=maintainer=example@email.com
```
---
### 4.2.5 虚悬镜像
在镜像列表里你可能会看到一些仓库名和标签都为 `<none>` 的镜像这类镜像被称为虚悬镜像
#### 什么是虚悬镜像
仓库名和标签都显示为 `<none>` 的镜像
```bash
$ docker images
REPOSITORY TAG IMAGE ID SIZE
<none> <none> 00285df0df87 342MB
```
#### 产生原因
1. **镜像重新构建**新镜像使用了旧镜像的标签旧镜像标签被移除
2. **docker pull 更新**拉取更新版本时旧版本失去标签
#### 处理虚悬镜像
```bash
## 列出虚悬镜像
$ docker images -f dangling=true
## 删除虚悬镜像
$ docker image prune
```
---
### 4.2.6 中间层镜像
除了虚悬镜像`docker image ls` 默认列出的只是顶层镜像还有一种镜像是为了加速镜像构建重复利用资源而存在的中间层镜像
#### 查看所有镜像 (包含中间层)
```bash
$ docker images -a
```
会显示很多无标签镜像这些是构建过程中产生的中间层被其他镜像依赖
> 不要删除中间层镜像它们是其他镜像的依赖删除会导致上层镜像无法使用删除顶层镜像时会自动清理不再需要的中间层
---
### 4.2.7 格式化输出
为了配合脚本使用或展示更关注的信息我们可以使用 `--format` 参数来自定义输出格式
#### 只输出 ID
```bash
$ docker images -q
5f515359c7f8
05a60462f8ba
329ed837d508
```
常用于配合其他命令
```bash
## 删除所有镜像
$ docker rmi $(docker images -q)
## 删除所有 redis 镜像
$ docker rmi $(docker images -q redis)
```
#### 显示完整 ID
```bash
$ docker images --no-trunc
```
#### 显示摘要
```bash
$ docker images --digests
REPOSITORY TAG DIGEST IMAGE ID
nginx latest sha256:b4f0e0bdeb5... e43d811ce2f4
```
#### 自定义格式
使用 Go 模板语法自定义输出
```bash
## 只显示 ID 和仓库名
$ docker images --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
329ed837d508: ubuntu
## 表格形式(带标题)
$ docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
REPOSITORY TAG SIZE
redis latest 183MB
nginx latest 181MB
ubuntu 24.04 78MB
```
#### 可用模板字段
| 字段 | 说明 |
|------|------|
| `.ID` | 镜像 ID |
| `.Repository` | 仓库名 |
| `.Tag` | 标签 |
| `.Digest` | 摘要 |
| `.CreatedSince` | 创建后经过的时间 |
| `.CreatedAt` | 创建时间 |
| `.Size` | 大小 |
---
### 4.2.8 常用命令组合
```bash
## 列出所有镜像及其大小,按大小排序(需要系统 sort 命令)
$ docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | sort -h
## 查找大于 500MB 的镜像
$ docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | grep -E "^[0-9]+GB|^[5-9][0-9]{2}MB"
## 导出镜像列表
$ docker images --format "{{.Repository}}:{{.Tag}}" > images.txt
```
---

270
04_image/4.3_rm.md Normal file
View File

@@ -0,0 +1,270 @@
## 4.3 删除本地镜像
当不再需要某个镜像时我们可以将其删除以释放存储空间本节介绍删除镜像的常用方法
### 4.3.1 基本用法
使用 `docker image rm` 删除本地镜像
```bash
$ docker image rm [选项] <镜像1> [<镜像2> ...]
```
> 💡 `docker rmi` `docker image rm` 的简写两者等效
---
### 4.3.2 镜像标识方式
删除镜像时可以使用多种方式指定镜像
| 方式 | 说明 | 示例 |
|------|------|------|
| ** ID** | ID 的前几位 (通常 3-4 )| `docker rmi 501` |
| ** ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` |
| **镜像名:标签** | 仓库名和标签 | `docker rmi redis:alpine` |
| **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` |
#### 使用短 ID 删除
```bash
$ docker image ls
REPOSITORY TAG IMAGE ID SIZE
redis alpine 501ad78535f0 30MB
nginx latest e43d811ce2f4 142MB
## 只需输入足够区分的前几位
$ docker rmi 501
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
#### 使用镜像名删除
```bash
$ docker rmi redis:alpine
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
#### 使用摘要删除
摘要删除最精确适用于 CI/CD 场景
```bash
## 查看镜像摘要
$ docker images --digests
REPOSITORY TAG DIGEST IMAGE ID
nginx latest sha256:b4f0e0bdeb5... e43d811ce2f4
## 使用摘要删除
$ docker rmi nginx@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
```
---
### 4.3.3 理解输出信息
执行删除命令后Docker 会输出一系列的操作记录理解这些信息有助于我们掌握镜像删除的机制
删除镜像时会看到两类信息**Untagged** **Deleted**
```bash
$ docker rmi redis:alpine
Untagged: redis:alpine
Untagged: redis@sha256:f1ed3708f538b537eb9c2a7dd50dc90a706f7debd7e1196c9264edeea521a86d
Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
```
#### Untagged vs Deleted
| 操作 | 含义 |
|------|------|
| **Untagged** | 移除镜像的标签 |
| **Deleted** | 删除镜像的存储层 |
#### 删除流程
Docker 会检测镜像是否有容器依赖或其他标签指向只有在确认为无用资源时才会真正删除存储层
```mermaid
flowchart TD
Start(["docker rmi redis:alpine"]) --> Step1
subgraph Process ["删除流程"]
direction TB
Step1["1. Untag移除 redis:alpine 标签"] --> Step2
Step2{"2. 检查是否还有其他标签指向此镜像"}
Step2 -- "有" --> Keep1["只 Untag不删除"]
Step2 -- "无" --> Step3
Step3{"3. 检查是否有容器依赖"}
Step3 -- "有" --> Error["报错,无法删除"]
Step3 -- "无" --> Step4
Step4{"4. 从上到下逐层删除,检查每层是否被其他镜像使用"}
Step4 -- "被使用" --> Keep2["保留该层"]
Step4 -- "未使用" --> Delete["Deleted (删除该层)"]
end
```
---
### 4.3.4 批量删除
手动一个一个删除镜像非常繁琐Docker 提供了 `image prune` 命令和 shell 组合命令来实现批量清理
#### 删除所有虚悬镜像
虚悬镜像 (dangling)没有标签的镜像通常是旧版本被新版本覆盖后产生的
```bash
## 查看虚悬镜像
$ docker images -f dangling=true
## 删除虚悬镜像
$ docker image prune
## 不提示确认
$ docker image prune -f
```
#### 删除所有未使用的镜像
```bash
## 删除所有没有被容器使用的镜像
$ docker image prune -a
## 保留最近 24 小时的
$ docker image prune -a --filter "until=24h"
```
#### 按条件删除
```bash
## 删除所有 redis 镜像
$ docker rmi $(docker images -q redis)
## 删除 mongo:8.0 之前的所有镜像
$ docker rmi $(docker images -q -f before=mongo:8.0)
## 删除某个时间之前的镜像
$ docker image prune -a --filter "until=168h" # 7天前
```
---
### 4.3.5 删除失败的常见原因
在删除镜像时Docker 可能会提示错误并拒绝执行这通常是为了防止误删正在使用的资源
#### 原因一有容器依赖
```bash
$ docker rmi nginx
Error: conflict: unable to remove repository reference "nginx"
(must force) - container abc123 is using its referenced image
```
**解决方案**
```bash
## 方案1先删除依赖的容器
$ docker rm abc123
$ docker rmi nginx
## 方案2强制删除镜像容器仍可运行但无法再创建新容器
$ docker rmi -f nginx
```
#### 原因二多个标签指向同一镜像
```bash
$ docker images
REPOSITORY TAG IMAGE ID
ubuntu 24.04 ca2b0f26964c
ubuntu latest ca2b0f26964c # 同一个镜像
$ docker rmi ubuntu:24.04
Untagged: ubuntu:24.04
## 只是移除标签,镜像仍存在(因为还有 ubuntu:latest 指向它)
当同一个镜像有多个标签时,`docker rmi` 只是删除指定的标签,不会删除镜像本身。
```
#### 原因三被其他镜像依赖 (中间层)
```bash
$ docker rmi some_base_image
Error: image has dependent child images
```
中间层镜像被其他镜像依赖无法删除需要先删除依赖它的镜像
---
### 4.3.6 常用过滤条件
| 过滤条件 | 说明 | 示例 |
|---------|------|------|
| `dangling=true` | 虚悬镜像 | `-f dangling=true` |
| `before=镜像` | 在某镜像之前 | `-f before=mongo:3.2` |
| `since=镜像` | 在某镜像之后 | `-f since=mongo:3.2` |
| `label=key=value` | 按标签过滤 | `-f label=version=1.0` |
| `reference=pattern` | 按名称模式 | `-f reference='*:latest'` |
---
### 4.3.7 清理策略
针对不同的环境 (开发环境 vs 生产环境)我们应该采用不同的镜像清理策略
#### 开发环境
```bash
## 定期清理虚悬镜像
$ docker image prune -f
## 一键清理所有未使用资源
$ docker system prune -a
```
#### CI/CD 环境
```bash
## 只保留最近使用的镜像
$ docker image prune -a --filter "until=72h" -f
```
#### 查看空间占用
```bash
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 15 3 2.5GB 1.8GB (72%)
Containers 5 2 100MB 80MB (80%)
Local Volumes 8 2 500MB 400MB (80%)
Build Cache 0 0 0B 0B
```
---

View File

@@ -1,9 +1,8 @@
## 4.4 利用 commit 理解镜像构成
>注意如果您是初学者您可以暂时跳过后面的内容直接学习 [容器](../container) 一节
> 注意如果您是初学者您可以暂时跳过后面的内容直接学习[容器](../05_container/)一节
## 利用 commit 理解镜像构成
注意 `docker commit` 命令除了学习之外还有一些特殊的应用场合比如被入侵后保存现场等但是不要使用 `docker commit` 定制镜像定制镜像应该使用 `Dockerfile` 来完成如果你想要定制镜像请查看下一小节
注意`docker commit` 命令除了学习之外还有一些特殊的应用场合比如被入侵后保存现场等但是不要使用 `docker commit` 定制镜像定制镜像应该使用 `Dockerfile` 来完成如果你想要定制镜像请查看下一小节
镜像是容器的基础每次执行 `docker run` 的时候都会指定哪个镜像作为容器运行的基础在之前的例子中我们所使用的都是来自于 Docker Hub 的镜像直接使用这些镜像是可以满足一定的需求而当这些镜像无法直接满足需求时我们就需要定制这些镜像接下来的几节就将讲解如何定制镜像
@@ -17,11 +16,11 @@ $ docker run --name webserver -d -p 80:80 nginx
这条命令会用 `nginx` 镜像启动一个容器命名为 `webserver`并且映射了 80 端口这样我们可以用浏览器去访问这个 `nginx` 服务器
如果是在 Linux 本机运行的 Docker或者如果使用的是 Docker for MacDocker for Windows那么可以直接访问<http://localhost>;如果使用的是 Docker Toolbox或者是在虚拟机、云服务器上安装的 Docker,则需要将 `localhost` 换为虚拟机地址或者实际云服务器地址。
如果是在本机运行的 Docker那么可以直接访问`http://localhost`如果是在虚拟机云服务器上安装的 Docker则需要将 `localhost` 换为虚拟机地址或者实际云服务器地址
直接用浏览器访问的话我们会看到默认的 Nginx 欢迎页面
<img src="_images/images-mac-example-nginx.png" width="80%" >
![](../_images/images-mac-example-nginx.png)
现在假设我们非常不喜欢这个欢迎页面我们希望改成欢迎 Docker 的文字我们可以使用 `docker exec` 命令进入容器修改其内容
@@ -38,7 +37,7 @@ exit
现在我们再刷新浏览器的话会发现内容被改变了
<img src="_images/images-create-nginx-docker.png" width="80%" >
![](../_images/images-create-nginx-docker.png)
我们修改了容器的文件也就是改动了容器的存储层我们可以通过 `docker diff` 命令看到具体的改动
@@ -64,7 +63,7 @@ A /var/cache/nginx/uwsgi_temp
现在我们定制好了变化我们希望能将其保存下来形成镜像
要知道当我们运行一个容器的时候如果不使用卷的话我们做的任何文件修改都会被记录于容器存储层里 Docker 提供了一个 `docker commit` 命令可以将容器的存储层保存下来成为镜像换句话说就是在原有镜像的基础上再叠加上容器的存储层并构成新的镜像以后我们运行这个新镜像的时候就会拥有原有容器最后的文件变化
要知道当我们运行一个容器的时候 (如果不使用卷的话)我们做的任何文件修改都会被记录于容器存储层里 Docker 提供了一个 `docker commit` 命令可以将容器的存储层保存下来成为镜像换句话说就是在原有镜像的基础上再叠加上容器的存储层并构成新的镜像以后我们运行这个新镜像的时候就会拥有原有容器最后的文件变化
`docker commit` 的语法格式为
@@ -91,8 +90,9 @@ sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
$ docker image ls nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 07e334659748 9 seconds ago 181.5 MB
nginx 1.11 05a60462f8ba 12 days ago 181.5 MB
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB```
nginx 1.27 05a60462f8ba 12 days ago 181.5 MB
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB
```
我们还可以用 `docker history` 具体查看镜像内的历史记录如果比较 `nginx:latest` 的历史记录我们会发现新增了我们刚刚提交的这一层
@@ -104,7 +104,7 @@ e43d811ce2f4 4 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "da
<missing> 4 weeks ago /bin/sh -c #(nop) EXPOSE 443/tcp 80/tcp 0 B
<missing> 4 weeks ago /bin/sh -c ln -sf /dev/stdout /var/log/nginx/ 22 B
<missing> 4 weeks ago /bin/sh -c apt-key adv --keyserver hkp://pgp. 58.46 MB
<missing> 4 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.11.5-1 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.27.0-1 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) MAINTAINER NGINX Docker Ma 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:23aa4f893e3288698c 123 MB
@@ -116,16 +116,18 @@ e43d811ce2f4 4 weeks ago /bin/sh -c #(nop) CMD ["nginx" "-g" "da
docker run --name web2 -d -p 81:80 nginx:v2
```
这里我们命名为新的服务为 `web2`并且映射到 `81` 端口如果是 Docker for Mac/Windows Linux 桌面的话我们就可以直接访问 <http://localhost:81> 看到结果,其内容应该和之前修改后的 `webserver` 一样
这里我们命名为新的服务为 `web2`并且映射到 `81` 端口访问 `http://localhost:81` 看到结果其内容应该和之前修改后的 `webserver` 一样
至此我们第一次完成了定制镜像使用的是 `docker commit` 命令手动操作给旧的镜像添加了新的一层形成新的镜像对镜像多层存储应该有了更直观的感觉
### 慎用 `docker commit`
### 4.4.1 概述
### 4.4.2 慎用 `docker commit`
使用 `docker commit` 命令虽然可以比较直观的帮助理解镜像分层存储的概念但是实际环境中并不会这样使用
首先如果仔细观察之前的 `docker diff webserver` 的结果你会发现除了真正想要修改的 `/usr/share/nginx/html/index.html` 文件外由于命令的执行还有很多文件被改动或添加了这还仅仅是最简单的操作如果是安装软件包编译构建那会有大量的无关内容被添加进来如果不小心清理将会导致镜像极为臃肿
首先如果仔细观察之前的 `docker diff webserver` 的结果你会发现除了真正想要修改的 `/usr/share/nginx/html/index.html` 文件外由于命令的执行还有很多文件被改动或添加了这还仅仅是最简单的操作如果是安装软件包编译构建那会有大量的无关内容被添加进来将会导致镜像极为臃肿
此外使用 `docker commit` 意味着所有对镜像的操作都是黑箱操作生成的镜像也被称为**黑箱镜像**换句话说就是除了制作镜像的人知道执行过什么命令怎么生成的镜像别人根本无从得知而且即使是这个制作镜像的人过一段时间后也无法记清具体操作虽然 `docker diff` 或许可以告诉得到一些线索但是远远不到可以确保生成一致镜像的地步这种黑箱镜像的维护工作是非常痛苦的
此外使用 `docker commit` 意味着所有对镜像的操作都是黑箱操作生成的镜像也被称为 **黑箱镜像**换句话说就是除了制作镜像的人知道执行过什么命令怎么生成的镜像别人根本无从得知而且即使是这个制作镜像的人过一段时间后也无法记清具体操作这种黑箱镜像的维护工作是非常痛苦的
而且回顾之前提及的镜像所使用的分层存储的概念除当前层外之前的每一层都是不会发生改变的换句话说任何修改的结果仅仅是在当前层进行标记添加修改而不会改动上一层如果使用 `docker commit` 制作镜像以及后期修改的话每一次修改都会让镜像更加臃肿一次所删除的上一层的东西并不会丢失会一直如影随形的跟着这个镜像即使根本无法访问到这会让镜像更加臃肿

View File

@@ -1,8 +1,20 @@
## 使用 Dockerfile 定制镜像
## 4.5 使用 Dockerfile 定制镜像
从刚才的 `docker commit` 的学习中我们可以了解到镜像的定制实际上就是定制每一层所添加的配置文件如果我们可以把每一层修改安装构建操作的命令都写入一个脚本用这个脚本来构建定制镜像那么之前提及的无法重复的问题镜像构建透明性的问题体积的问题就都会解决这个脚本就是 Dockerfile
Dockerfile 是一个文本文件其内包含了一条条的**指令(Instruction)**每一条指令构建一层因此每一条指令的内容就是描述该层应当如何构建
Dockerfile 是一个文本文件其内包含了一条条的 **指令 (Instruction)**每一条指令构建一层因此每一条指令的内容就是描述该层应当如何构建
### 4.5.1 使用 docker init 快速创建 (推荐)
Docker 提供了 `docker init` 命令可以根据项目类型自动生成 Dockerfiledockerignore compose.yaml 文件
```bash
$ docker init
```
该命令会交互式地询问项目类型 ( GoNode.jsPythonRust )并生成符合最佳实践的配置文件对于新项目这是推荐的起步方式
### 4.5.2 手动创建 Dockerfile
还以之前定制 `nginx` 镜像为例这次我们使用 Dockerfile 来定制
@@ -16,16 +28,16 @@ $ touch Dockerfile
其内容为
```dockerfile
```docker
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
```
这个 Dockerfile 很简单一共就两行涉及到了两条指令`FROM` `RUN`
### FROM 指定基础镜像
### 4.5.3 FROM 指定基础镜像
所谓定制镜像那一定是以一个镜像为基础在其上进行定制就像我们之前运行了一个 `nginx` 镜像的容器再进行修改一样基础镜像是必须指定的 `FROM` 就是指定**基础镜像**因此一个 `Dockerfile` `FROM` 是必备的指令并且必须是第一条指令
所谓定制镜像那一定是以一个镜像为基础在其上进行定制就像我们之前运行了一个 `nginx` 镜像的容器再进行修改一样基础镜像是必须指定的 `FROM` 就是指定 **基础镜像**因此一个 `Dockerfile` `FROM` 是必备的指令并且必须是第一条指令
[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/) 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。
@@ -33,76 +45,38 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
除了选择现有镜像为基础镜像外Docker 还存在一个特殊的镜像名为 `scratch`这个镜像是虚拟的概念并不实际存在它表示一个空白的镜像
```dockerfile
```docker
FROM scratch
...
```
如果你以 `scratch` 为基础镜像的话意味着你不以任何镜像为基础接下来所写的指令将作为镜像第一层开始存在
不以任何系统为基础直接将可执行文件复制进镜像的做法并不罕见比如 [`swarm`](https://hub.docker.com/_/swarm/)、[`coreos/etcd`](https://quay.io/repository/coreos/etcd)。对于 Linux 下静态编译的程序来说并不需要有操作系统提供运行时支持所需的一切库都已经在可执行文件里了,因此直接 `FROM scratch` 会让镜像体积更加小巧。使用 [Go 语言](https://golang.org/) 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
不以任何系统为基础直接将可执行文件复制进镜像的做法并不罕见对于 Linux 下静态编译的程序来说并不需要有操作系统提供运行时支持所需的一切库都已经在可执行文件里了因此直接 `FROM scratch` 会让镜像体积更加小巧使用 [Go 语言](https://golang.google.cn/)开发的应用很多会使用这种方式来制作镜像,这也是有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
### RUN 执行命令
### 4.5.4 RUN 执行命令
`RUN` 指令是用来执行命令行命令的由于命令行的强大能力`RUN` 指令在定制镜像时是最常用的指令之一其格式有两种
* *shell* 格式`RUN <命令>`就像直接在命令行中输入的命令一样刚才写的 Dockerfile 中的 `RUN` 指令就是这种格式
```Dockerfile
```docker
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
```
* *exec* 格式`RUN ["可执行文件", "参数1", "参数2"]`这更像是函数调用中的格式
* *exec* 格式`RUN [可执行文件, 参数1, 参数2]`这更像是函数调用中的格式
既然 `RUN` 就像 Shell 脚本一样可以执行命令那么我们是否就可以像 Shell 脚本一样把每个命令对应一个 RUN 比如这样
Dockerfile 中每一个指令都会建立一层`RUN` 也不例外每一个 `RUN` 的行为就和刚才我们手工建立镜像的过程一样新建立一层在其上执行这些命令执行结束后`commit` 这一层的修改构成新的镜像
```dockerfile
FROM debian:stretch
> **注意**
>
> 每一个 `RUN` 指令都会产生一个新的镜像层为了减少镜像体积和层数我们通常会将多个命令合并到一个 `RUN` 指令中执行
>
> 更多关于 `RUN` 指令的详细用法最佳实践 (如清理缓存使用 pipefail ) `Union FS` 的层数限制等内容请参阅 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 中的 **[RUN 指令](../07_dockerfile/7.1_run.md)** 小节
RUN apt-get update
RUN apt-get install -y gcc libc6-dev make wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install
```
要想编写优秀的 `Dockerfile`必须了解每一条指令的作用和副作用 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 我们将对 `COPY``ADD``CMD``ENTRYPOINT` 等指令进行详细讲解
之前说过Dockerfile 中每一个指令都会建立一层`RUN` 也不例外每一个 `RUN` 的行为就和刚才我们手工建立镜像的过程一样新建立一层在其上执行这些命令执行结束后`commit` 这一层的修改构成新的镜像
而上面的这种写法创建了 7 层镜像这是完全没有意义的而且很多运行时不需要的东西都被装进了镜像里比如编译环境更新的软件包等等结果就是产生非常臃肿非常多层的镜像不仅仅增加了构建部署的时间也很容易出错
这是很多初学 Docker 的人常犯的一个错误
*Union FS 是有最大层数限制的比如 AUFS曾经是最大不得超过 42 现在是不得超过 127 *
上面的 `Dockerfile` 正确的写法应该是这样
```dockerfile
FROM debian:stretch
RUN buildDeps='gcc libc6-dev make wget' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
```
首先之前所有的命令只有一个目的就是编译安装 redis 可执行文件因此没有必要建立很多层这只是一层的事情因此这里没有使用很多个 `RUN` 对一一对应不同的命令而是仅仅使用一个 `RUN` 指令并使用 `&&` 将各个所需命令串联起来将之前的 7 简化为了 1 在撰写 Dockerfile 的时候要经常提醒自己这并不是在写 Shell 脚本而是在定义每一层该如何构建
并且这里为了格式化还进行了换行Dockerfile 支持 Shell 类的行尾添加 `\` 的命令换行方式以及行首 `#` 进行注释的格式良好的格式比如换行缩进注释等会让维护排障更为容易这是一个比较好的习惯
此外还可以看到这一组命令的最后添加了清理工作的命令删除了为了编译构建所需要的软件清理了所有下载展开的文件并且还清理了 `apt` 缓存文件这是很重要的一步我们之前说过镜像是多层存储每一层的东西并不会在下一层被删除会一直跟随着镜像因此镜像构建时一定要确保每一层只添加真正需要添加的东西任何无关的东西都应该清理掉
很多人初学 Docker 制作出了很臃肿的镜像的原因之一就是忘记了每一层构建的最后一定要清理掉无关文件
### 构建镜像
### 4.5.5 构建镜像
好了让我们再回到之前定制的 nginx 镜像的 Dockerfile 现在我们明白了这个 Dockerfile 的内容那么让我们来构建这个镜像吧
@@ -130,11 +104,11 @@ docker build [选项] <上下文路径/URL/->
在这里我们指定了最终镜像的名称 `-t nginx:v3`构建成功后我们可以像之前运行 `nginx:v2` 那样来运行这个镜像其结果会和 `nginx:v2` 一样
### 镜像构建上下文Context
### 4.5.6 镜像构建上下文
如果注意会看到 `docker build` 命令最后有一个 `.``.` 表示当前目录 `Dockerfile` 就在当前目录因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径这么理解其实是不准确的如果对应上面的命令格式你可能会发现这是在指定**上下文路径**那么什么是上下文呢
如果注意会看到 `docker build` 命令最后有一个 `.``.` 表示当前目录 `Dockerfile` 就在当前目录因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径这么理解其实是不准确的如果对应上面的命令格式你可能会发现这是在指定 **上下文路径**那么什么是上下文呢
首先我们要理解 `docker build` 的工作原理Docker 在运行时分为 Docker 引擎也就是服务端守护进程和客户端工具Docker 的引擎提供了一组 REST API被称为 [Docker Remote API](https://docs.docker.com/engine/reference/api/docker_remote_api/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端Docker 引擎完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
首先我们要理解 `docker build` 的工作原理Docker 在运行时分为 Docker 引擎 (也就是服务端守护进程) 和客户端工具Docker 的引擎提供了一组 REST API被称为 [Docker Remote API](https://docs.docker.com/develop/sdk/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端 (Docker 引擎) 完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。
当我们进行镜像构建的时候并非所有定制都会通过 `RUN` 指令完成经常会需要将一些本地文件复制进镜像比如通过 `COPY` 指令`ADD` 指令等 `docker build` 命令构建镜像其实并非在本地构建而是在服务端也就是 Docker 引擎中构建的那么在这种客户端/服务端的架构中如何才能让服务端获得本地文件呢
@@ -142,11 +116,11 @@ docker build [选项] <上下文路径/URL/->
如果在 `Dockerfile` 中这么写
```Dockerfile
```docker
COPY ./package.json /app/
```
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`也不是复制 `Dockerfile` 所在目录下的 `package.json`而是复制 **上下文context** 目录下的 `package.json`
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`也不是复制 `Dockerfile` 所在目录下的 `package.json`而是复制 **上下文 (context)** 目录下的 `package.json`
因此`COPY` 这类指令中的源文件的路径都是*相对路径*这也是初学者经常会问的为什么 `COPY ../package.json /app` 或者 `COPY /opt/xxxx /app` 无法工作的原因因为这些路径已经超出了上下文的范围Docker 引擎无法获得这些位置的文件如果真的需要那些文件应该将它们复制到上下文目录中去
@@ -170,24 +144,31 @@ Sending build context to Docker daemon 2.048 kB
当然一般大家习惯性的会使用默认的文件名 `Dockerfile`以及会将其置于镜像构建上下文目录中
### 其它 `docker build` 的用法
### 4.5.7 其它 `docker build` 的用法
#### 直接用 Git repo 进行构建
或许你已经注意到了`docker build` 还支持从 URL 构建比如可以直接从 Git repo 中构建
```bash
$ docker build https://github.com/twang2218/gitlab-ce-zh.git#:11.1
## $env:DOCKER_BUILDKIT=0
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM gitlab/gitlab-ce:11.1.0-ce.0
11.1.0-ce.0: Pulling from gitlab/gitlab-ce
aed15891ba52: Already exists
773ae8583d14: Already exists
...
## export DOCKER_BUILDKIT=0
$ docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello /
---> ac779757d46e
Step 3/3 : CMD ["/hello"]
---> Running in d2a513a760ed
Removing intermediate container d2a513a760ed
---> 038ad4142d2b
Successfully built 038ad4142d2b
```
这行命令指定了构建所需的 Git repo并且指定默认的 `master` 分支构建目录为 `/11.1/`然后 Docker 就会自己去 `git clone` 这个项目切换到指定分支并进入到指定目录后开始构建
这行命令指定了构建所需的 Git repo并且指定分支为 `master`构建目录为 `/amd64/hello-world/`然后 Docker 就会自己去 `git clone` 这个项目切换到指定分支并进入到指定目录后开始构建
#### 用给定的 tar 压缩包构建

View File

@@ -1,42 +1,43 @@
## 其它制作镜像的方式
## 4.6 其它制作镜像的方式
除了标准的使用 `Dockerfile` 生成镜像的方法外由于各种特殊需求和历史原因还提供了一些其它方法用以生成镜像
### rootfs 压缩包导入
### 4.6.1 rootfs 压缩包导入
格式`docker import [选项] <文件>|<URL>|- [<仓库名>[:<标签>]]`
压缩包可以是本地文件远程 Web 文件甚至是从标准输入中得到压缩包将会在镜像 `/` 目录展开并直接作为镜像第一层提交
比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 14.04 [模板](https://openvz.org/Download/template/precreated)的镜像:
比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 16.04 [模板](https://wiki.openvz.org/Download/template/precreated)的镜像:
```bash
$ docker import \
http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz \
openvz/ubuntu:14.04
Downloading from http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz
sha256:f477a6e18e989839d25223f301ef738b69621c4877600ae6467c4e5289822a79B/78.42 MB
http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz \
openvz/ubuntu:16.04
Downloading from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz
sha256:412b8fc3e3f786dca0197834a698932b9c51b69bd8cf49e100c35d38c9879213
```
这条命令自动下载了 `ubuntu-14.04-x86_64-minimal.tar.gz` 文件并且作为根文件系统展开导入并保存为镜像 `openvz/ubuntu:14.04`
这条命令自动下载了 `ubuntu-16.04-x86_64.tar.gz` 文件并且作为根文件系统展开导入并保存为镜像 `openvz/ubuntu:16.04`
导入成功后我们可以用 `docker image ls` 看到这个导入的镜像
```bash
$ docker image ls openvz/ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
openvz/ubuntu 14.04 f477a6e18e98 55 seconds ago 214.9 MB
openvz/ubuntu 16.04 412b8fc3e3f7 55 seconds ago 505MB
```
如果我们查看其历史的话会看到描述中有导入的文件链接
```bash
$ docker history openvz/ubuntu:14.04
$ docker history openvz/ubuntu:16.04
IMAGE CREATED CREATED BY SIZE COMMENT
f477a6e18e98 About a minute ago 214.9 MB Imported from http://download.openvz.org/template/precreated/ubuntu-14.04-x86_64-minimal.tar.gz
f477a6e18e98 About a minute ago 214.9 MB Imported from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz
```
### `docker save` `docker load`
### 4.6.2 Docker 镜像的导入和导出 `docker save` `docker load`
Docker 还提供了 `docker save` `docker load` 命令用以将镜像保存为一个文件然后传输到另一个位置上再加载进来这是在没有 Docker Registry 时的做法现在已经不推荐镜像迁移应该直接使用 Docker Registry无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以
@@ -62,7 +63,7 @@ filename: POSIX tar archive
这里的 filename 可以为任意名称甚至任意后缀名但文件的本质都是归档文件
**注意如果同名则会覆盖没有警告**
**注意如果同名则会覆盖 (没有警告)**
若使用 `gzip` 压缩

65
04_image/4.7_internal.md Normal file
View File

@@ -0,0 +1,65 @@
## 4.7 实现原理
Docker 镜像是怎么实现增量的修改和维护的为什么容器启动如此之快这一切都归功于 Docker 的镜像分层存储设计
### 4.7.1 镜像与分层存储
在之前的章节中我们一直强调镜像包含操作系统完整的 `root` 文件系统其体积往往是庞大的因此在 Docker 设计时就充分利用 **Union FS** 的技术将其设计为分层存储的架构
Docker 镜像并不是一个单纯的文件而是由一组文件系统叠加构成的
最底层的镜像称为 **基础镜像 (Base Image)**通常是各种 Linux 发行版的 root 文件系统 UbuntuDebianCentOS
当我们在基础镜像之上构建新的镜像时 (例如安装了 Nginx)Docker 并不是复制一份基础镜像而是在基础镜像之上**新建一个层 (Layer)**并在该层中仅记录为了安装 Nginx 而发生的文件变更 (添加修改删除)
这种分层存储结构使得镜像的复用分发变得非常高效
* **复用**如果多个镜像都基于同一个基础镜像 (例如都基于 `ubuntu:24.04`)那么宿主机只需要下载一份 `ubuntu:24.04`所有镜像都可以共享它
* **轻量**镜像仅仅记录了与基础镜像的差异因此体积非常小
### 4.7.2 容器层与读写
我们要理解的一个关键概念是**镜像的每一层都是只读的 (Read-only)**
那么既然镜像只读容器为什么能写文件呢
当容器启动时Docker 会在镜像的最上层添加一个新的 **可写层 (Writable Layer)**通常被称为 **容器层**
```mermaid
flowchart TD
subgraph Container ["运行中的容器"]
direction TB
L4["容器层 (可写, Writable Container Layer)"]
L3["镜像层 (只读, Read-only Image Layer)"]
L2["镜像层 (只读, Read-only Image Layer)"]
L1["基础镜像层 (只读, Base Image Layer)"]
L4 --- L3 --- L2 --- L1
end
Note["所有的写操作都在容器层这里"] -.-> L4
```
* **读取文件**当容器需要读取文件时Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找直到找到该文件为止
* **修改文件**当容器需要修改某个文件时Docker 会从下层镜像中将该文件复制到上层的容器层然后对副本进行修改这被称为 **写时复制 (Copy-on-WriteCoW)** 策略
* **删除文件**当容器删除某个文件时Docker 并不是真的去下层删除它 (因为下层是只读的)而是在容器层创建一个特殊的 白障 (Whiteout) 文件用来标记该文件已被删除从而在容器视图中隐藏它
这就是为什么
1. **容器删除后数据会丢失**因为所有的数据修改都保存在最上层的容器层中容器销毁时这个层也就随之销毁了(除非使用了数据卷详见[数据管理](../08_data/README.md))
2. **镜像不可变**无论我们在容器里删除了多少文件基础镜像的体积并不会减小因为它们依然存在于底层的只读层中
### 4.7.3 内容寻址与镜像 ID
Docker 镜像的每一层都有一个唯一的 ID这个 ID 是根据该层的内容计算出来的哈希值 (SHA256)这意味着
* **内容即 ID**只要层的内容有一丁点变化ID 就会变
* **安全性**确保了镜像内容的完整性下载过程中如果数据损坏ID 校验就会失败
* **去重**如果两个不同的镜像 (甚至是不同来源的镜像) 包含相同的层 (ID 相同)Docker 引擎在本地只会存储一份绝不重复下载
### 4.7.4 联合文件系统
Docker 使用联合文件系统 (Union FS) 来实现这种分层挂载常见的驱动包括 `overlay2` (目前推荐)`aufs` (早期使用)`btrfs``zfs`
虽然实现细节不同但它们都遵循上述的 **分层 + CoW** 模型
> 想要深入了解 Overlay2 等文件系统的具体实现原理包括 WorkDirUpperDirLowerDir 等底层细节请阅读 **[第十二章 底层实现](../12_implementation/README.md)** 中的 **[联合文件系统](../12_implementation/12.4_ufs.md)** 章节

17
04_image/README.md Normal file
View File

@@ -0,0 +1,17 @@
# 第四章 使用镜像
在之前的介绍中我们知道镜像是 Docker 的三大组件之一
Docker 运行容器前需要本地存在对应的镜像如果本地不存在该镜像Docker 会从镜像仓库下载该镜像
## 本章内容
本章将介绍更多关于镜像的内容包括
* [从仓库获取镜像](4.1_pull.md)
* [列出镜像](4.2_list.md)
* [删除本地镜像](4.3_rm.md)
* [利用 commit 理解镜像构成](4.4_commit.md)
* [使用 Dockerfile 定制镜像](4.5_build.md)
* [其它制作镜像的方式](4.6_other.md)
* [镜像的实现原理](4.7_internal.md)

View File

@@ -0,0 +1,16 @@
FROM node:alpine as builder
WORKDIR /app
COPY package.json /app/
RUN npm i --registry=https://registry.npmmirror.com \
&& rm -rf ~/.npm
COPY src /app/src
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /app/dist

View File

@@ -0,0 +1,37 @@
# syntax = docker/dockerfile:experimental
FROM node:alpine as builder
WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npmmirror.com
COPY src /app/src
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
# --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
npm run build
FROM nginx:alpine
# COPY --from=builder /app/dist /app/dist
# 为了更直观的说明 from source 指令这里使用 RUN 指令
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
cat /docker-php-entrypoint
RUN --mount=type=tmpfs,target=/temp \
mount | grep /temp
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
cat /root/.aws/credentials
# docker build -t test --secret id=aws,src=$PWD/aws.txt --progress=plain -f Dockerfile.buildkit .

View File

@@ -0,0 +1 @@
awskey

View File

@@ -0,0 +1,11 @@
{
"name": "my_app",
"version": "19.6.0",
"devDependencies": {
"webpack": "*",
"webpack-cli": "*"
},
"scripts": {
"build": "mkdir -p $PWD/dist && cp -r src/* dist/"
}
}

View File

@@ -0,0 +1 @@
console.log(1);

View File

@@ -0,0 +1,5 @@
FROM --platform=$TARGETPLATFORM alpine
RUN uname -a > /os.txt
CMD cat /os.txt

View File

@@ -1,4 +1,4 @@
FROM golang:1.9-alpine as builder
FROM golang:alpine as builder
RUN apk --no-cache add git

View File

@@ -1,4 +1,4 @@
FROM golang:1.9-alpine
FROM golang:alpine
RUN apk --no-cache add git

View File

@@ -1,4 +1,4 @@
FROM golang:1.9-alpine
FROM golang:alpine
RUN apk --no-cache add git ca-certificates

46
04_image/summary.md Normal file
View File

@@ -0,0 +1,46 @@
## 本章小结
| 操作 | 命令 |
|------|------|
| 拉取镜像 | `docker pull 镜像名:标签` |
| 拉取所有标签 | `docker pull -a 镜像名` |
| 指定平台 | `docker pull --platform linux/amd64 镜像名` |
| 用摘要拉取 | `docker pull 镜像名@sha256:...` |
### 4.8.1 延伸阅读
- [列出镜像](4.2_list.md)查看本地镜像
- [删除镜像](4.3_rm.md)清理本地镜像
- [镜像加速器](../03_install/3.9_mirror.md)加速镜像下载
- [Docker Hub](../06_repository/6.1_dockerhub.md)官方镜像仓库
| 操作 | 命令 |
|------|------|
| 列出所有镜像 | `docker images` |
| 按仓库名过滤 | `docker images nginx` |
| 列出虚悬镜像 | `docker images -f dangling=true` |
| 只输出 ID | `docker images -q` |
| 显示摘要 | `docker images --digests` |
| 自定义格式 | `docker images --format "..."` |
| 查看空间占用 | `docker system df` |
### 4.8.2 延伸阅读
- [获取镜像](4.1_pull.md) Registry 拉取镜像
- [删除镜像](4.3_rm.md)清理本地镜像
- [镜像](../02_basic_concept/2.1_image.md)理解镜像概念
| 操作 | 命令 |
|------|------|
| 删除指定镜像 | `docker rmi 镜像名:标签` |
| 强制删除 | `docker rmi -f 镜像名` |
| 删除虚悬镜像 | `docker image prune` |
| 删除未使用镜像 | `docker image prune -a` |
| 批量删除 | `docker rmi $(docker images -q -f ...)` |
| 查看空间占用 | `docker system df` |
### 4.8.3 延伸阅读
- [列出镜像](4.2_list.md)查看和过滤镜像
- [删除容器](../05_container/5.6_rm.md)清理容器
- [数据卷](../08_data/8.1_volume.md)清理数据卷

225
05_container/5.1_run.md Normal file
View File

@@ -0,0 +1,225 @@
## 5.1 启动
本节将详细介绍 Docker 容器的启动方式包括新建启动和重新启动已停止的容器
### 5.1.1 启动方式概述
启动容器有两种方式
- **新建并启动**基于镜像创建新容器
- **重新启动**将已终止的容器重新运行
由于 Docker 容器非常轻量实际使用中常常是随时删除和新建容器而不是反复重启同一个容器
### 5.1.2 新建并启动
#### 基本语法
```bash
docker run [选项] 镜像 [命令] [参数...]
```
#### 最简单的例子
输出 Hello World 后容器自动终止
```bash
$ docker run ubuntu:24.04 /bin/echo 'Hello world'
Hello world
```
这与直接执行 `/bin/echo 'Hello world'` 几乎没有区别但实际上已经启动了一个完整的 Ubuntu 容器来执行这条命令
#### 交互式容器
启动一个可以交互的 bash 终端
```bash
$ docker run -it ubuntu:24.04 /bin/bash
root@af8bae53bdd3:/#
```
**参数说明**
| 参数 | 作用 |
|------|------|
| `-i` | 保持标准输入 (stdin) 打开允许输入 |
| `-t` | 分配伪终端 (pseudo-TTY)提供终端界面 |
| `-it` | 两者组合使用获得交互式终端 |
在交互模式下可以执行命令
```bash
root@af8bae53bdd3:/# pwd
/
root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@af8bae53bdd3:/# exit # 退出容器
```
### 5.1.3 docker run 的完整流程
执行 `docker run` Docker 在后台完成以下操作
```mermaid
flowchart TD
Cmd["docker run ubuntu:24.04 /bin/echo 'Hello'"] --> Step1
Step1{"1. 检查本地是否有 ubuntu:24.04 镜像"}
Step1 -- 有 --> Step1_Yes["使用本地镜像"]
Step1 -- 无 --> Step1_No["从 Registry 下载"]
Step1_Yes --> Step2
Step1_No --> Step2
Step2["2. 创建容器<br/>• 基于镜像的只读层<br/>• 添加一层可读写层(容器存储层)"] --> Step3
Step3["3. 配置网络<br/>• 创建虚拟网卡<br/>• 分配 IP 地址<br/>• 连接到 Docker 网桥"] --> Step4
Step4["4. 启动容器,执行指定命令"] --> Step5
Step5["5. 命令执行完毕,容器停止"]
```
### 5.1.4 常用启动选项
#### 基础选项
| 选项 | 说明 | 示例 |
|------|------|------|
| `-d` | 后台运行 (detach)| `docker run -d nginx` |
| `-it` | 交互式终端 | `docker run -it ubuntu bash` |
| `--name` | 指定容器名称 | `docker run --name myapp nginx` |
| `--rm` | 退出后自动删除容器 | `docker run --rm ubuntu echo hi` |
#### 端口映射
```bash
## 将容器的 80 端口映射到宿主机的 8080 端口
$ docker run -d -p 8080:80 nginx
## 随机映射端口
$ docker run -d -P nginx
## 只绑定到 localhost
$ docker run -d -p 127.0.0.1:8080:80 nginx
```
#### 数据卷挂载
```bash
## 挂载命名卷
$ docker run -v mydata:/data nginx
## 挂载宿主机目录
$ docker run -v /host/path:/container/path nginx
## 只读挂载
$ docker run -v /host/path:/container/path:ro nginx
```
#### 环境变量
```bash
## 设置单个环境变量
$ docker run -e MYSQL_ROOT_PASSWORD=secret mysql
## 从文件加载环境变量
$ docker run --env-file .env myapp
```
#### 资源限制
```bash
## 限制内存
$ docker run -m 512m nginx
## 限制 CPU
$ docker run --cpus=1.5 nginx
```
### 5.1.5 启动已终止容器
使用 `docker start` 重新启动已停止的容器
```bash
## 查看所有容器(包括已停止的)
$ docker ps -a
CONTAINER ID IMAGE STATUS NAMES
af8bae53bdd3 ubuntu Exited (0) 2 minutes ago myubuntu
## 重新启动
$ docker start myubuntu
## 启动并附加终端
$ docker start -ai myubuntu
```
### 5.1.6 容器内进程的特点
容器内只运行指定的应用程序及其必需资源
```bash
root@ba267838cc1b:/# ps
PID TTY TIME CMD
1 ? 00:00:00 bash
11 ? 00:00:00 ps
```
可见容器中仅运行了 `bash` 进程这种特点使得 Docker 对资源的利用率极高
> 💡 笔者提示容器内的 PID 1 进程很重要它是容器的主进程该进程退出则容器停止详见[后台运行](5.2_daemon.md)章节
### 5.1.7 常见问题
#### Q容器启动后立即退出
**原因**主进程执行完毕或无法保持运行
```bash
## 这个容器会立即退出echo 执行完就结束了)
$ docker run ubuntu echo "hello"
## 解决:使用能持续运行的命令
$ docker run -d nginx # nginx 是持续运行的服务
```
详细解释见[后台运行](5.2_daemon.md)
#### Q无法连接容器内的服务
**原因**未正确映射端口
```bash
## 错误:没有 -p 参数,外部无法访问
$ docker run -d nginx
## 正确:映射端口
$ docker run -d -p 80:80 nginx
```
#### Q容器内修改的文件丢失
**原因**未使用数据卷数据保存在容器存储层
```bash
## 使用数据卷持久化
$ docker run -v mydata:/app/data myapp
```
详见[数据管理](../08_data/README.md)

234
05_container/5.2_daemon.md Normal file
View File

@@ -0,0 +1,234 @@
## 5.2 守护态运行
在生产环境中我们通常需要容器持续运行不受终端关闭的影响本节将深入讲解如何让容器在后台运行以及理解容器生命周期的核心概念
### 5.2.1 核心概念前台 vs 后台
当你在终端运行一个程序时有两种模式
- **前台运行**程序占用当前终端输出直接显示关闭终端程序就停止
- **后台运行**程序在后台执行不占用终端终端关闭也不影响程序
Docker 容器默认是 **前台运行** 使用 `-d` (detach) 参数可以让容器在后台运行
### 5.2.2 基本使用
#### 前台运行 (默认)
```bash
$ docker run ubuntu:24.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
```
容器会把输出的结果 (STDOUT) 打印到宿主机上面此时
- 终端被占用无法执行其他命令
- `Ctrl+C` 会终止容器
- 关闭终端窗口容器也会停止
#### 后台运行 (使用 -d 参数)
```bash
$ docker run -d ubuntu:24.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"
77b2dc01fe0f3f1265df143181e7b9af5e05279a884f4776ee75350ea9d8017a
```
使用 `-d` 参数后
- 容器在后台运行
- 返回容器的完整 ID
- 终端立即释放可以继续执行其他命令
- 输出不会直接显示 (需要用 `docker logs` 查看)
### 5.2.3 深入理解容器为什么会 立即退出
> **这是初学者最常遇到的困惑** 理解这个问题你就理解了 Docker 的核心设计理念
很多人尝试这样启动容器
```bash
$ docker run -d ubuntu:24.04
```
然后用 `docker ps` 查看发现容器根本不在运行这是为什么
#### 核心原理容器的生命周期与主进程绑定
```mermaid
flowchart TD
subgraph Lifecycle ["Docker 容器的生命周期 = 容器内 PID 1 进程的生命周期"]
direction LR
Start["主进程启动"] --> Run["容器运行"]
Exit["主进程退出"] --> Stop["容器停止"]
end
```
当你运行 `docker run -d ubuntu:24.04`
1. 容器启动
2. 没有指定命令默认执行 `/bin/bash`
3. 但没有交互式终端 (没有 `-it` 参数)bash 发现没有输入源
4. bash 立即退出
5. 主进程退出容器停止
**关键理解**
- `-d` 参数 **不是** 让容器 一直运行
- `-d` 参数是让容器 在后台运行能运行多久取决于主进程
#### 常见的 立即退出 场景
| 场景 | 原因 | 解决方案 |
|------|------|---------|
| `docker run -d ubuntu` | 默认 bash 无输入立即退出 | 指定长期运行的命令 |
| `docker run -d nginx` 后改了配置 | 配置错误导致 nginx 启动失败 | 查看 `docker logs` |
| 自定义镜像容器启动即退 | Dockerfile CMD 执行完毕 | 确保 CMD 是前台进程 |
### 5.2.4 查看后台容器
#### 查看运行中的容器
```bash
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77b2dc01fe0f ubuntu:24.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright
```
#### 查看容器输出日志
```bash
$ docker container logs 77b2dc01fe0f
hello world
hello world
hello world
...
```
**实时查看日志** (类似 `tail -f`)
```bash
$ docker container logs -f 77b2dc01fe0f
```
#### 查看已停止的容器
```bash
$ docker container ls -a
```
加上 `-a` 参数可以看到所有容器包括已停止的这对于调试 容器启动即退出 的问题非常有用
### 5.2.5 最佳实践
#### 1. 长期运行的服务使用 -d
```bash
## Web 服务器
$ docker run -d -p 80:80 nginx
## 数据库
$ docker run -d -p 3306:3306 mysql:8
## 缓存服务
$ docker run -d -p 6379:6379 redis
```
#### 2. 调试时先用前台模式
当容器启动有问题时**去掉 `-d` 参数** 可以直接看到输出和错误
```bash
## 有问题的容器,先前台运行看看发生了什么
$ docker run myimage:latest
```
#### 3. 使用 --rm 自动清理
对于一次性任务使用 `--rm` 参数让容器退出后自动删除
```bash
$ docker run --rm ubuntu:24.04 echo "Hello, World!"
Hello, World!
## 容器执行完后自动删除
...
```
#### 4. 配合日志查看
```bash
## 后台启动
$ docker run -d --name myapp myimage:latest
## 查看最近 100 行日志
$ docker logs --tail 100 myapp
## 实时跟踪日志
$ docker logs -f myapp
## 查看带时间戳的日志
$ docker logs -t myapp
```
### 5.2.6 常见问题排查
#### Q容器启动后立即退出
1. **查看退出状态码**
```bash
$ docker ps -a --filter "name=mycontainer"
# 查看 STATUS 列,如 “Exited (1)” 表示异常退出
```
2. **查看容器日志**
```bash
$ docker logs mycontainer
```
3. **以交互模式调试**
```bash
$ docker run -it myimage:latest /bin/sh
# 进入容器手动执行命令,查找问题
```
#### Q容器在后台运行但无法访问服务
1. **检查端口映射**
```bash
$ docker port mycontainer
```
2. **检查容器内服务状态**
```bash
$ docker exec mycontainer ps aux
```
#### Q如何让已经在后台运行的容器回到前台
使用 `docker attach`
```bash
$ docker attach mycontainer
```
> **注意**`attach` 会连接到容器的主进程如果主进程不是交互式的你可能只能看到输出使用 `Ctrl+P` `Ctrl+Q` 可以安全退出而不停止容器
### 5.2.7 延伸阅读
- [进入容器](5.4_attach_exec.md)如何进入正在运行的容器执行命令
- [容器日志](../appendix/best_practices.md)生产环境的日志管理最佳实践
- [HEALTHCHECK 健康检查](../07_dockerfile/7.12_healthcheck.md)自动检测容器内服务是否正常
- [Docker Compose](../11_compose/README.md)管理多个后台容器的更好方式

233
05_container/5.3_stop.md Normal file
View File

@@ -0,0 +1,233 @@
## 5.3 终止
本节将介绍如何终止一个运行中的容器以及几种不同的终止方式及其区别
### 5.3.1 终止方式概述
终止容器有三种方式
| 方式 | 命令 | 说明 |
|------|------|------|
| **优雅停止** | `docker stop` | 先发 SIGTERM超时后发 SIGKILL |
| **强制停止** | `docker kill` | 直接发 SIGKILL |
| **自动终止** | - | 容器主进程退出时自动停止 |
---
### 5.3.2 docker stop (推荐)
#### docker stop 基本用法
```bash
$ docker stop 容器名或ID
```
#### 工作原理
```mermaid
flowchart TD
cmd["docker stop mycontainer"] --> A["1. 发送 SIGTERM 信号给容器主进程 (PID 1)"]
A --> B["2. 等待容器优雅退出 (默认 10 秒)"]
B --> C["3. 如果超时仍未退出,发送 SIGKILL 强制终止"]
```
#### 自定义超时时间
```bash
## 等待 30 秒后强制终止
$ docker stop -t 30 mycontainer
## 立即发送 SIGKILL相当于 docker kill
$ docker stop -t 0 mycontainer
```
#### 停止多个容器
```bash
## 停止多个指定容器
$ docker stop container1 container2 container3
## 停止所有运行中的容器
$ docker stop $(docker ps -q)
```
---
### 5.3.3 docker kill
#### 基本用法
```bash
$ docker kill 容器名或ID
```
#### stop 的区别
| 命令 | 信号 | 使用场景 |
|------|------|---------|
| `docker stop` | SIGTERM SIGKILL | 正常停止让应用优雅退出 |
| `docker kill` | SIGKILL | 应用无响应强制终止 |
#### 发送自定义信号
```bash
## 发送 SIGHUP让进程重新加载配置
$ docker kill -s HUP mycontainer
## 发送 SIGTERM
$ docker kill -s TERM mycontainer
```
---
### 5.3.4 容器自动终止
容器的生命周期与主进程绑定主进程退出时容器自动停止
```bash
## 主进程是交互式 bash
$ docker run -it ubuntu bash
root@abc123:/# exit # 退出 bash → 容器停止
## 主进程执行完毕
$ docker run ubuntu echo "Hello" # echo 执行完 → 容器停止
```
---
### 5.3.5 查看已停止的容器
```bash
$ docker ps -a
CONTAINER ID IMAGE COMMAND STATUS NAMES
ba267838cc1b ubuntu "/bin/bash" Exited (0) 2 minutes ago myubuntu
c5d3a5e8f7b2 nginx "nginx" Up 5 minutes mynginx
```
**STATUS 字段说明**
| 状态 | 说明 |
|------|------|
| `Up X minutes` | 运行中 |
| `Exited (0)` | 正常退出 (退出码 0)|
| `Exited (1)` | 异常退出 (非零退出码)|
| `Exited (137)` | SIGKILL 终止 (128 + 9)|
| `Exited (143)` | SIGTERM 终止 (128 + 15)|
---
### 5.3.6 重新启动容器
#### 启动已停止的容器
```bash
$ docker start 容器名或ID
## 启动并附加终端
$ docker start -ai 容器名
```
#### 重启运行中的容器
```bash
## 先停止再启动
$ docker restart 容器名
## 自定义停止超时
$ docker restart -t 30 容器名
```
---
### 5.3.7 生命周期状态图
```mermaid
stateDiagram-v2
direction TB
[*] --> Created : docker create
Created --> Running : docker start
Running --> Stopped : docker stop
Running --> Paused : docker pause
Paused --> Running : docker unpause
Created --> Deleted : docker rm
Stopped --> Deleted : docker rm
Paused --> Deleted : docker rm
Deleted --> [*]
```
---
### 5.3.8 批量操作
#### 停止所有容器
```bash
$ docker stop $(docker ps -q)
```
#### 删除所有已停止的容器
```bash
$ docker container prune
```
#### 停止并删除所有容器
```bash
$ docker stop $(docker ps -q) && docker container prune -f
```
---
### 5.3.9 常见问题
#### Q容器停止很慢
原因应用没有正确处理 SIGTERM 信号需要等待超时后强制终止
解决方案
1. 在应用中正确处理 SIGTERM
2. 使用 `docker stop -t 0` 立即终止
3. 检查 Dockerfile 中的 `STOPSIGNAL` 配置
#### Q如何让容器优雅退出
确保容器主进程正确处理信号
```dockerfile
## Dockerfile 示例
FROM node:22
...
## 使用 exec 形式确保信号能传递给 node 进程
CMD ["node", "server.js"]
```
#### Q容器无法停止
```bash
## 强制终止
$ docker kill 容器名
## 如果仍无法停止,检查系统资源
$ docker inspect 容器名
```
---

View File

@@ -0,0 +1,282 @@
## 5.4 进入容器
### 5.4.1 为什么需要进入容器
使用 `-d` 参数启动容器后容器在后台运行以下场景需要进入容器内部操作
| 场景 | 示例 |
|------|------|
| **调试问题** | 查看日志检查配置排查错误 |
| **临时操作** | 执行数据库迁移清理缓存 |
| **检查状态** | 查看进程网络连接文件系统 |
| **开发测试** | 交互式测试命令验证环境 |
### 5.4.2 两种进入方式
Docker 提供两种进入容器的命令
| 命令 | 推荐程度 | 特点 |
|------|---------|------|
| `docker exec` | **推荐** | 启动新进程退出不影响容器 |
| `docker attach` | 谨慎使用 | 附加到主进程退出可能停止容器 |
---
### 5.4.3 docker exec (推荐)
#### docker exec 基本用法
```bash
## 进入容器并启动交互式 shell
$ docker exec -it 容器名 /bin/bash
## 或使用 sh适用于 Alpine 等精简镜像)
$ docker exec -it 容器名 /bin/sh
```
#### 参数说明
| 参数 | 作用 |
|------|------|
| `-i` | 保持标准输入打开 (interactive)|
| `-t` | 分配伪终端 (TTY)|
| `-it` | 两者组合获得完整交互体验 |
| `-u` | 指定用户 ( `-u root`)|
| `-w` | 指定工作目录 |
| `-e` | 设置环境变量 |
#### docker exec 示例
```bash
## 启动一个后台容器
$ docker run -dit --name myubuntu ubuntu
69d137adef7a...
## 进入容器(交互式 shell
$ docker exec -it myubuntu bash
root@69d137adef7a:/# ls
bin boot dev etc home lib ...
root@69d137adef7a:/# exit
## 容器仍在运行!
$ docker ps
CONTAINER ID IMAGE STATUS NAMES
69d137adef7a ubuntu Up 2 minutes myubuntu
```
#### 执行单条命令
不进入交互模式直接执行命令
```bash
## 查看容器内进程
$ docker exec myubuntu ps aux
## 查看配置文件
$ docker exec myubuntu cat /etc/nginx/nginx.conf
## 以 root 用户执行
$ docker exec -u root myubuntu apt update
```
#### 只用 -i 不用 -t 的区别
```bash
## 只用 -i可以执行命令但没有提示符
$ docker exec -i myubuntu bash
ls # 输入命令
bin # 输出结果
boot
dev
...
## 用 -it有完整的终端体验
$ docker exec -it myubuntu bash
root@69d137adef7a:/# # 有提示符
```
> 💡 通常使用 `-it` 组合只有在脚本中需要通过管道传入命令时才只用 `-i`
---
### 5.4.4 docker attach (谨慎使用)
#### docker attach 基本用法
```bash
$ docker attach 容器名
```
#### 工作原理
`attach` 会附加到容器的 **主进程** (PID 1) 的标准输入输出
```mermaid
flowchart LR
subgraph Container ["容器"]
direction TB
subgraph Process ["主进程"]
P1["PID 1: /bin/bash<br>(你的输入直接发送到主进程)"]
end
end
Attach["docker attach"] -->|"附加到这里"| P1
```
#### docker attach 示例
```bash
## 启动容器
$ docker run -dit --name myubuntu ubuntu
243c32535da7...
## 附加到容器
$ docker attach myubuntu
root@243c32535da7:/#
```
#### 重要警告
** attach 会话中输入 `exit` 或按 `Ctrl+D` 会导致容器停止**
```bash
$ docker attach myubuntu
root@243c32535da7:/# exit # 这会停止容器!
$ docker ps
CONTAINER ID IMAGE STATUS NAMES
243c32535da7 ubuntu Exited (0) 2 seconds ago myubuntu
```
**原因**attach 附加到主进程退出主进程就等于退出容器
#### 安全退出 attach
使用 `Ctrl+P` 然后 `Ctrl+Q` 可以从 attach 会话中 **分离**而不停止容器
```bash
$ docker attach myubuntu
root@243c32535da7:/#
## 按 Ctrl+P 然后 Ctrl+Q
read escape sequence
$ docker ps # 容器仍在运行
CONTAINER ID IMAGE STATUS NAMES
243c32535da7 ubuntu Up 5 minutes myubuntu
```
---
### 5.4.5 exec vs attach 对比
| 特性 | docker exec | docker attach |
|------|-------------|---------------|
| **工作方式** | 在容器内启动新进程 | 附加到主进程 |
| **退出影响** | 不影响容器 | 可能停止容器 |
| **多终端** | 可以开多个 | 共享同一个会话 |
| **适用场景** | 调试临时操作 | 查看主进程输出 |
| **推荐程度** | 推荐 | 特殊场景使用 |
```mermaid
flowchart LR
subgraph Exec ["docker exec"]
direction TB
subgraph Container1 ["容器"]
E_PID1["PID 1: nginx"]
E_PID50["PID 50: bash"]
end
NewProc["新进程"] -- 附加到 --> E_PID50
end
subgraph Attach ["docker attach"]
direction TB
subgraph Container2 ["容器"]
A_PID1["PID 1: bash"]
end
MainProc["附加到主进程"] --> A_PID1
end
note1["退出 bash 不影响 nginx"]
note2["退出 bash 容器停止"]
Container1 -.-> note1
Container2 -.-> note2
```
---
### 5.4.6 最佳实践
#### 1. 首选 docker exec
```bash
## 进入容器调试
$ docker exec -it myapp bash
## 查看日志
$ docker exec myapp tail -f /var/log/app.log
## 执行数据库迁移
$ docker exec myapp python manage.py migrate
```
#### 2. 生产环境避免进入容器
笔者建议生产环境应尽量避免进入容器直接操作而是通过
- 日志系统查看日志 ( `docker logs` 或集中式日志)
- 监控系统查看状态
- 重新部署而非手动修改
#### 3. shell 镜像的处理
某些精简镜像 (如基于 `scratch` `distroless`) 没有 shell
```bash
## 这会失败
$ docker exec -it myapp bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found
## 解决方案使用调试容器Docker Desktop 或 Kubernetes debug
$ docker debug myapp
```
---
### 5.4.7 常见问题
#### Qexec 进入后看不到其他终端的操作
这是正常的exec 启动的是独立进程多个 exec 会话互不影响
#### Q容器没有 bash
尝试使用 sh
```bash
$ docker exec -it myapp /bin/sh
```
#### Q需要 root 权限
```bash
$ docker exec -u root -it myapp bash
```
---

View File

@@ -1,18 +1,20 @@
## 导出和导入容器
## 5.5 导出和导入
### 导出容器
当我们需要迁移容器或者备份容器时可以使用 Docker 的导入和导出功能本节将介绍这两个命令的使用方法
### 5.5.1 导出容器
如果要导出本地某个容器可以使用 `docker export` 命令
```bash
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7691a814370e ubuntu:18.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
7691a814370e ubuntu:24.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test
$ docker export 7691a814370e > ubuntu.tar
```
这样将导出容器快照到本地文件
### 导入容器快照
### 5.5.2 导入容器快照
可以使用 `docker import` 从容器快照文件中再导入为镜像例如
@@ -29,4 +31,4 @@ test/ubuntu v1.0 9d37a6082e97 About a minute ago
$ docker import http://example.com/exampleimage.tgz example/imagerepo
```
*用户既可以使用 `docker load` 来导入镜像存储文件到本地镜像库也可以使用 `docker import` 来导入一个容器快照到本地镜像库这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息即仅保存容器当时的快照状态而镜像存储文件将保存完整记录体积也要大此外从容器快照文件导入时可以重新指定标签等元数据信息*
*用户既可以使用 `docker load` 来导入镜像存储文件到本地镜像库也可以使用 `docker import` 来导入一个容器快照到本地镜像库这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息 (即仅保存容器当时的快照状态)而镜像存储文件将保存完整记录体积也要大此外从容器快照文件导入时可以重新指定标签等元数据信息*

246
05_container/5.6_rm.md Normal file
View File

@@ -0,0 +1,246 @@
## 5.6 删除
随着容器的创建和停止系统中会积累大量的容器本节将介绍如何删除不再需要的容器以及如何清理所有停止的容器
### 5.6.1 基本用法
使用 `docker rm` 删除已停止的容器
```bash
$ docker rm 容器名或ID
```
> 💡 `docker rm` `docker container rm` 的简写两者等效
---
### 5.6.2 删除选项
| 选项 | 说明 | 示例 |
|------|------|------|
| 无参数 | 删除已停止的容器 | `docker rm mycontainer` |
| `-f` | 强制删除运行中的容器 | `docker rm -f mycontainer` |
| `-v` | 同时删除关联的匿名卷 | `docker rm -v mycontainer` |
#### 删除已停止的容器
```bash
$ docker rm mycontainer
mycontainer
```
#### 强制删除运行中的容器
```bash
## 不加 -f 会报错
$ docker rm running_container
Error: cannot remove running container
## 加 -f 强制删除
$ docker rm -f running_container
running_container
```
> 强制删除会向容器发送 SIGKILL 信号可能导致数据丢失建议先 `docker stop` 优雅停止
#### 删除容器及其数据卷
```bash
## 删除容器时同时删除其匿名卷
$ docker rm -v mycontainer
```
> 注意只删除匿名卷命名卷不会被删除
---
### 5.6.3 批量删除
#### 删除所有已停止的容器
```bash
## 方式一:使用 prune 命令(推荐)
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
abc123...
def456...
Total reclaimed space: 150MB
## 方式二:不提示确认
$ docker container prune -f
```
#### 删除所有容器 (包括运行中的)
```bash
## 先停止所有容器,再删除
$ docker stop $(docker ps -q)
$ docker rm $(docker ps -aq)
## 或者直接强制删除
$ docker rm -f $(docker ps -aq)
```
#### 按条件删除
```bash
## 删除所有已退出的容器
$ docker rm $(docker ps -aq -f status=exited)
## 删除名称包含 "test" 的容器
$ docker rm $(docker ps -aq -f name=test)
## 删除 24 小时前创建的容器
$ docker container prune --filter "until=24h"
```
---
### 5.6.4 常用过滤条件
`docker ps` 的过滤条件可以配合 `rm` 使用
| 过滤条件 | 说明 | 示例 |
|---------|------|------|
| `status=exited` | 已退出的容器 | `-f status=exited` |
| `status=created` | 已创建未启动 | `-f status=created` |
| `name=xxx` | 名称匹配 | `-f name=myapp` |
| `ancestor=xxx` | 基于某镜像创建 | `-f ancestor=nginx` |
| `before=xxx` | 在某容器之前创建 | `-f before=mycontainer` |
| `since=xxx` | 在某容器之后创建 | `-f since=mycontainer` |
#### 示例
```bash
## 删除所有基于 nginx 镜像的容器
$ docker rm $(docker ps -aq -f ancestor=nginx)
## 删除所有创建后未启动的容器
$ docker rm $(docker ps -aq -f status=created)
```
---
### 5.6.5 容器与镜像的依赖关系
> 有容器依赖的镜像无法删除
```bash
## 尝试删除有容器依赖的镜像
$ docker image rm nginx
Error: image is being used by stopped container abc123
## 需要先删除依赖该镜像的容器
$ docker rm abc123
$ docker image rm nginx
```
---
### 5.6.6 清理策略建议
#### 开发环境
```bash
## 定期清理已停止的容器
$ docker container prune -f
## 一键清理所有未使用资源
$ docker system prune -f
```
#### 生产环境
```bash
## 使用 --rm 参数运行临时容器
$ docker run --rm ubuntu echo "Hello"
## 容器退出后自动删除
## 定期清理(设置保留时间)
$ docker container prune --filter "until=168h" # 保留 7 天内的
```
#### 完整清理脚本
```bash
#!/bin/bash
## cleanup.sh - Docker 资源清理脚本
echo "清理已停止的容器..."
docker container prune -f
echo "清理未使用的镜像..."
docker image prune -f
echo "清理未使用的数据卷..."
docker volume prune -f
echo "清理未使用的网络..."
docker network prune -f
echo "清理完成!"
docker system df
```
---
### 5.6.7 常见问题
#### Q容器无法删除
```bash
Error: container is running
```
解决先停止容器或使用 `-f` 强制删除
```bash
$ docker stop mycontainer
$ docker rm mycontainer
## 或
$ docker rm -f mycontainer
```
#### Q删除后磁盘空间没释放
可能原因
1. 容器的数据卷未删除 (使用 `-v` 参数)
2. 镜像未删除
3. 构建缓存未清理
解决
```bash
## 查看空间占用
$ docker system df
## 完整清理
$ docker system prune -a --volumes
```
---

14
05_container/README.md Normal file
View File

@@ -0,0 +1,14 @@
# 第五章 操作容器
容器是 Docker 又一核心概念
简单的说容器是独立运行的一个或一组应用以及它们的运行态环境对应的虚拟机可以理解为模拟运行的一整套操作系统 (提供了运行态环境和其他系统环境) 和跑在上面的应用
本章将具体介绍如何来管理一个容器包括创建启动和停止等
* [启动容器](5.1_run.md)
* [守护态运行](5.2_daemon.md)
* [终止容器](5.3_stop.md)
* [进入容器](5.4_attach_exec.md)
* [导出和导入容器](5.5_import_export.md)
* [删除容器](5.6_rm.md)

55
05_container/summary.md Normal file
View File

@@ -0,0 +1,55 @@
## 本章小结
| 操作 | 命令 | 说明 |
|------|------|------|
| 新建并运行 | `docker run` | 最常用的启动方式 |
| 交互式启动 | `docker run -it` | 用于调试或临时操作 |
| 后台运行 | `docker run -d` | 用于服务类应用 |
| 启动已停止的容器 | `docker start` | 重用已有容器 |
### 5.7.1 延伸阅读
- [后台运行](5.2_daemon.md)理解 `-d` 参数和容器生命周期
- [进入容器](5.4_attach_exec.md)操作运行中的容器
- [网络配置](../09_network/README.md)理解端口映射的原理
- [数据管理](../08_data/README.md)数据持久化方案
| 操作 | 命令 | 说明 |
|------|------|------|
| 优雅停止 | `docker stop` | SIGTERM超时后 SIGKILL |
| 强制停止 | `docker kill` | 直接 SIGKILL |
| 重新启动 | `docker start` | 启动已停止的容器 |
| 重启 | `docker restart` | 停止后立即启动 |
| 停止全部 | `docker stop $(docker ps -q)` | 停止所有运行中容器 |
### 5.7.2 延伸阅读
- [启动容器](../05_container/5.1_run.md)容器启动详解
- [删除容器](5.6_rm.md)清理容器
- [容器日志](5.2_daemon.md)排查停止原因
| 需求 | 推荐命令 |
|------|---------|
| 进入容器调试 | `docker exec -it 容器名 bash` |
| 执行单条命令 | `docker exec 容器名 命令` |
| 查看主进程输出 | `docker attach 容器名` (慎用)|
### 5.7.3 延伸阅读
- [后台运行](5.2_daemon.md)理解容器主进程
- [查看容器](5.1_run.md)列出和过滤容器
- [容器日志](5.2_daemon.md)查看容器输出
| 操作 | 命令 |
|------|------|
| 删除已停止容器 | `docker rm 容器名` |
| 强制删除运行中容器 | `docker rm -f 容器名` |
| 删除容器及匿名卷 | `docker rm -v 容器名` |
| 清理所有已停止容器 | `docker container prune` |
| 删除所有容器 | `docker rm -f $(docker ps -aq)` |
### 5.7.4 延伸阅读
- [终止容器](5.3_stop.md)优雅停止容器
- [删除镜像](../04_image/4.3_rm.md)清理镜像
- [数据卷](../08_data/8.1_volume.md)数据卷管理

View File

@@ -0,0 +1,127 @@
## 6.1 Docker Hub
### 6.1.1 什么是 Docker Hub
Docker Hub Docker 的中央镜像仓库通过它您可以轻松地分享和获取 Docker 镜像
[Docker Hub](https://hub.docker.com/) 是 Docker 官方维护的公共镜像仓库,也是全球最大的容器镜像库。
它提供了
- **官方镜像** Docker 官方和软件厂商 ( NginxMySQLNode.js) 维护的高质量镜像
- **个人/组织仓库**用户可以上传自己的镜像
- **自动构建** GitHub/Bitbucket 集成 (需付费)
- **Webhooks**镜像更新时触发回调
---
### 6.1.2 核心功能
#### 1. 搜索镜像
我们可以通过 `docker search` 命令来查找官方仓库中的镜像并利用 `docker pull` 命令来将它下载到本地
除了网页搜索也可以使用命令行
```bash
$ docker search centos
NAME DESCRIPTION STARS OFFICIAL
centos The official build of CentOS. 7000+ [OK]
```
> **技巧**始终优先使用 `OFFICIAL` 标记为 `[OK]` 的镜像安全性更有保障
#### 2. 拉取镜像
```bash
$ docker pull nginx:alpine
```
#### 3. 推送镜像
需要先登录
```bash
$ docker login
## 输入用户名和密码
...
```
打标签并推送
```bash
## 1. 标记镜像
$ docker tag myapp:v1 username/myapp:v1
## 2. 推送
$ docker push username/myapp:v1
```
---
### 6.1.3 限制与配额
#### 镜像拉取限制
2020 11 月起Docker Hub 对匿名和免费用户实施了拉取速率限制
| 用户类型 | 限制 |
|---------|------|
| **匿名用户** (未登录) | 6 小时 100 次请求 |
| **免费账户** (已登录) | 6 小时 200 次请求 |
| **Pro/Team 账户** | 无限制 |
> **提示**如果在 CI/CD 环境中遇到 `toomanyrequests` 错误建议
> 1. CI 中配置 `docker login`
> 2. 使用国内镜像加速器
> 3. 搭建私有仓库代理
---
### 6.1.4 安全最佳实践
#### 1. 启用 2FA (双因素认证)
为了保护您的 Docker Hub 账号安全我们建议采取以下措施
Account Settings -> Security 中启用 2FA保护账号安全启用后CLI 登录需要使用 **Access Token** 而非密码
#### 2. 使用 Access Token
不要在脚本或 CI/CD 中直接使用登录密码
1. Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token
2. 使用 Token 作为密码登录
```bash
$ docker login -u username -p dckr_pat_xxxxxxx
```
#### 3. 关注镜像漏洞
Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描在镜像标签页可以看到漏洞扫描结果
---
### 6.1.5 Webhooks
当镜像被推送时可以自动触发 HTTP 回调 (例如通知 CI 系统部署)
**配置方法**
仓库页面 -> Webhooks -> Create Webhook
---
### 6.1.6 自动构建
> 目前仅限付费用户 (Pro/Team) 使用
链接 GitHub/Bitbucket 仓库后当代码有提交或打标签时Docker Hub 会自动运行构建这保证了镜像总是与代码同步且由可信的官方环境构建
---

View File

@@ -1,4 +1,4 @@
## 私有仓库
## 6.2 私有仓库
有时候使用 Docker Hub 这样的公共仓库可能不方便用户可以创建一个本地仓库供私人使用
@@ -6,11 +6,13 @@
[`docker-registry`](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文内容基于 [`docker-registry`](https://github.com/docker/distribution) v2.x 版本。
### 安装运行 docker-registry
### 6.2.1 安装运行 docker-registry
#### 容器运行
你可以通过获取官方 `registry` 镜像来运行
如果您需要搭建私有仓库可以通过官方提供的 `registry` 镜像快速部署
你可以使用官方 `registry` 镜像来运行
```bash
$ docker run -d -p 5000:5000 --restart=always --name registry registry
@@ -25,7 +27,7 @@ $ docker run -d \
registry
```
### 在私有仓库上传搜索下载镜像
### 6.2.2 在私有仓库上传搜索下载镜像
创建好私有仓库之后就可以使用 `docker tag` 来标记一个镜像然后推送它到仓库例如私有仓库地址为 `127.0.0.1:5000`
@@ -91,34 +93,24 @@ REPOSITORY TAG IMAGE ID CREAT
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
```
### 注意事项
### 6.2.3 配置非 https 仓库地址
如果你不想使用 `127.0.0.1:5000` 作为仓库地址比如想让本网段的其他主机也能把镜像推送到私有仓库你就得把例如 `192.168.199.100:5000` 这样的内网地址作为私有仓库地址这时你会发现无法成功推送镜像
这是因为 Docker 默认不允许非 `HTTPS` 方式推送镜像我们可以通过 Docker 的配置选项来取消这个限制或者查看下一节配置能够通过 `HTTPS` 访问的私有仓库
#### Ubuntu 14.04, Debian 7 Wheezy
#### Linux
对于使用 `upstart` 的系统而言编辑 `/etc/default/docker` 文件在其中的 `DOCKER_OPTS` 中增加如下内容
默认情况下Docker 强制使用 HTTPS 协议推送镜像如果您搭建的私有仓库是 HTTP 协议需要进行如下配置
```bash
DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com --insecure-registries=192.168.199.100:5000"
```
重新启动服务
```bash
$ sudo service docker restart
```
#### Ubuntu 16.04+, Debian 8+, centos 7
对于使用 `systemd` 的系统请在 `/etc/docker/daemon.json` 中写入如下内容如果文件不存在请新建该文件
对于使用 `systemd` 的系统请在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件)
```json
{
"registry-mirror": [
"https://registry.docker-cn.com"
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
],
"insecure-registries": [
"192.168.199.100:5000"
@@ -128,6 +120,6 @@ $ sudo service docker restart
>注意该文件必须符合 `json` 规范否则 Docker 将不能启动
### 其他
### 6.2.4 其他
对于 Docker for Windows Docker for Mac 在设置中编辑 `daemon.json` 增加和上边一样的字符串即可
对于 Docker Desktop for WindowsDocker Desktop for Mac 在设置中 `Docker Engine` 中进行编辑增加和上边一样的字符串即可

View File

@@ -1,10 +1,10 @@
## 私有仓库高级配置
## 6.3 私有仓库高级配置
上一节我们搭建了一个具有基础功能的私有仓库本小节我们来使用 `Docker Compose` 搭建一个拥有权限认证TLS 的私有仓库
新建一个文件夹以下步骤均在该文件夹中进行
### 准备站点证书
### 6.3.1 准备站点证书
如果你拥有一个域名国内各大云服务商均提供免费的站点证书你也可以使用 `openssl` 自行签发证书
@@ -82,12 +82,11 @@ $ openssl x509 -req -days 750 -in "site.csr" -sha256 \
新建 `ssl` 文件夹并将 `docker.domain.com.key` `docker.domain.com.crt` `root-ca.crt` 这三个文件移入删除其他文件
### 配置私有仓库
### 6.3.2 配置私有仓库
私有仓库默认的配置文件位于 `/etc/docker/registry/config.yml`我们先在本地编辑 `config.yml`之后挂载到容器中
```yaml
version: 0.1
log:
accesslog:
disabled: true
@@ -124,24 +123,24 @@ health:
threshold: 3
```
### 生成 http 认证文件
### 6.3.3 生成 http 认证文件
```bash
$ mkdir auth
$ docker run --rm \
--entrypoint htpasswd \
registry \
httpd:alpine \
-Bbn username password > auth/nginx.htpasswd
```
> 将上面的 `username` `password` 替换为你自己的用户名和密码
### 编辑 `docker-compose.yml`
### 6.3.4 编辑 Docker Compose 配置
编辑 `compose.yaml` ( `docker-compose.yml`) 配置如下
```yaml
version: '3'
services:
registry:
image: registry
@@ -155,7 +154,7 @@ volumes:
registry-data:
```
### 修改 hosts
### 6.3.5 修改 Hosts 文件
编辑 `/etc/hosts`
@@ -163,15 +162,15 @@ volumes:
127.0.0.1 docker.domain.com
```
### 启动
### 6.3.6 启动
```bash
$ docker-compose up -d
$ docker compose up -d
```
这样我们就搭建好了一个具有权限认证TLS 的私有仓库接下来我们测试其功能是否正常
### 测试私有仓库功能
### 6.3.7 测试私有仓库功能
由于自行签发的 CA 根证书不被系统信任所以我们需要将 CA 根证书 `ssl/root-ca.crt` 移入 `/etc/docker/certs.d/docker.domain.com` 文件夹中
@@ -190,15 +189,15 @@ $ docker login docker.domain.com
尝试推送拉取镜像
```bash
$ docker pull ubuntu:18.04
$ docker pull ubuntu:24.04
$ docker tag ubuntu:18.04 docker.domain.com/username/ubuntu:18.04
$ docker tag ubuntu:24.04 docker.domain.com/username/ubuntu:24.04
$ docker push docker.domain.com/username/ubuntu:18.04
$ docker push docker.domain.com/username/ubuntu:24.04
$ docker image rm docker.domain.com/username/ubuntu:18.04
$ docker image rm docker.domain.com/username/ubuntu:24.04
$ docker pull docker.domain.com/username/ubuntu:18.04
$ docker pull docker.domain.com/username/ubuntu:24.04
```
如果我们退出登录尝试推送镜像
@@ -206,13 +205,13 @@ $ docker pull docker.domain.com/username/ubuntu:18.04
```bash
$ docker logout docker.domain.com
$ docker push docker.domain.com/username/ubuntu:18.04
$ docker push docker.domain.com/username/ubuntu:24.04
no basic auth credentials
```
发现会提示没有登录不能将镜像推送到私有仓库中
### 注意事项
### 6.3.8 注意事项
如果你本机占用了 `443` 端口你可以配置 [Nginx 代理](https://docs.docker.com/registry/recipes/nginx/),这里不再赘述。

View File

@@ -0,0 +1,126 @@
## 6.4 Nexus 3
使用 Docker 官方的 Registry 创建的仓库面临一些维护问题比如某些镜像删除以后空间默认是不会回收的需要一些命令去回收空间然后重启 Registry在企业中把内部的一些工具包放入 `Nexus` 中是比较常见的做法最新版本 `Nexus3.x` 全面支持 Docker 的私有镜像所以使用 [`Nexus3.x`](https://www.sonatype.com/product/repository-oss-download) 一个软件来管理 `Docker``Maven``Yum``PyPI` 等是一个明智的选择。
### 6.4.1 启动 Nexus 容器
```bash
$ docker run -d --name nexus3 --restart=always \
-p 8081:8081 \
--mount src=nexus-data,target=/nexus-data \
sonatype/nexus3
```
首次运行需等待 3-5 分钟你可以使用 `docker logs nexus3 -f` 查看日志
```bash
$ docker logs nexus3 -f
2021-03-11 15:31:21,990+0000 INFO [jetty-main-1] *SYSTEM org.sonatype.nexus.bootstrap.jetty.JettyServer -
-------------------------------------------------
Started Sonatype Nexus OSS 3.30.0-01
-------------------------------------------------
```
如果你看到以上内容说明 `Nexus` 已经启动成功你可以使用浏览器打开 `http://YourIP:8081` 访问 `Nexus`
首次运行请通过以下命令获取初始密码
```bash
$ docker exec nexus3 cat /nexus-data/admin.password
9266139e-41a2-4abb-92ec-e4142a3532cb
```
首次启动 Nexus 的默认帐号是 `admin`密码则是上边命令获取到的点击右上角登录首次登录需更改初始密码
登录之后可以点击页面上方的齿轮按钮按照下面的方法进行设置
### 6.4.2 创建仓库
创建一个私有仓库的方法`Repository->Repositories` 点击右边菜单 `Create repository` 选择 `docker (hosted)`
* **Name**仓库的名称
* **HTTP**仓库单独的访问端口 (例如**5001**)
* **Hosted -> Deployment policy**请选择 **Allow redeploy** 否则无法上传 Docker 镜像
其它的仓库创建方法请各位自己摸索还可以创建一个 `docker (proxy)` 类型的仓库链接到 DockerHub 再创建一个 `docker (group)` 类型的仓库把刚才的 `hosted` `proxy` 添加在一起主机在访问的时候默认下载私有仓库中的镜像如果没有将链接到 DockerHub 中下载并缓存到 Nexus
### 6.4.3 添加访问权限
菜单 `Security->Realms` Docker Bearer Token Realm 移到右边的框中保存
添加用户规则菜单 `Security->Roles`->`Create role` `Privileges` 选项搜索 docker 把相应的规则移动到右边的框中然后保存
添加用户菜单 `Security->Users`->`Create local user` `Roles` 选项中选中刚才创建的规则移动到右边的窗口保存
### 6.4.4 NGINX 反向代理配置
证书的生成请参见 [`私有仓库高级配置`](6.3_registry_auth.md) 里面证书生成一节
NGINX 示例配置如下
```nginx
upstream register
{
server "YourHostName OR IP":5001; #端口为上面添加私有镜像仓库时设置的 HTTP 选项的端口号
check interval=3000 rise=2 fall=10 timeout=1000 type=http;
check_http_send "HEAD / HTTP/1.0\r\n\r\n";
check_http_expect_alive http_4xx;
}
server {
server_name YourDomainName;#如果没有 DNS 服务器做解析,请删除此选项使用本机 IP 地址访问
listen 443 ssl;
ssl_certificate key/example.crt;
ssl_certificate_key key/example.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
large_client_header_buffers 4 32k;
client_max_body_size 300m;
client_body_buffer_size 512k;
proxy_connect_timeout 600;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_buffer_size 128k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 512k;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://register;
proxy_read_timeout 900s;
}
error_page 500 502 503 504 /50x.html;
}
```
### 6.4.5 Docker 主机访问镜像仓库
如果不启用 SSL 加密可以通过[前面章节](6.2_registry.md)的方法添加非 https 仓库地址到 Docker 的配置文件中然后重启 Docker
使用 SSL 加密以后程序需要访问就不能采用修改配置的方式了具体方法如下
```bash
$ openssl s_client -showcerts -connect YourDomainName OR HostIP:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >ca.crt
$ cat ca.crt | sudo tee -a /etc/ssl/certs/ca-certificates.crt
$ systemctl restart docker
```
使用 `docker login YourDomainName OR HostIP` 进行测试用户名密码填写上面 Nexus 中设置的

7
06_repository/README.md Normal file
View File

@@ -0,0 +1,7 @@
# 第六章 访问仓库
仓库 (`Repository`) 是集中存放镜像的地方
一个容易混淆的概念是注册服务器 (`Registry`)实际上注册服务器是管理仓库的具体服务器每个服务器上可以有多个仓库而每个仓库下面有多个镜像从这方面来说仓库可以被认为是一个具体的项目或目录例如对于仓库地址 `docker.io/ubuntu` 来说`docker.io` 是注册服务器地址`ubuntu` 是仓库名
大部分时候并不需要严格区分这两者的概念

View File

@@ -1,8 +1,8 @@
version: '3'
services:
registry:
image: registry
image: registry:2
ports:
- "443:5000"
volumes:

15
06_repository/summary.md Normal file
View File

@@ -0,0 +1,15 @@
## 本章小结
| 功能 | 说明 |
|------|------|
| **官方镜像** | 优先使用的基础镜像 |
| **拉取限制** | 匿名 100/6h登录 200/6h |
| **安全** | 推荐开启 2FA 并使用 Access Token |
| **自动化** | 支持 Webhooks 和自动构建 |
### 6.5.1 概述
### 6.5.2 延伸阅读
- [私有仓库](6.2_registry.md)搭建自己的 Registry
- [镜像加速器](../03_install/3.9_mirror.md)加速下载

View File

@@ -0,0 +1,190 @@
## 7.10 WORKDIR 指定工作目录
### 7.10.1 基本语法
```docker
WORKDIR <工作目录路径>
```
`WORKDIR` 指定后续指令的工作目录如果目录不存在Docker 会自动创建
---
### 7.10.2 基本用法
```docker
WORKDIR /app
RUN pwd # 输出 /app
RUN echo "hello" > world.txt # 创建 /app/world.txt
COPY . . # 复制到 /app/
```
---
### 7.10.3 为什么需要 WORKDIR
#### 常见错误
```docker
## ❌ 错误cd 在下一个 RUN 中无效
RUN cd /app
RUN echo "hello" > world.txt # 文件在根目录!
```
#### 原因分析
```dockerfile
RUN cd /app
启动容器 → cd /app仅内存变化→ 提交镜像层 → 容器销毁
↓ 工作目录未改变!
RUN echo "hello" > world.txt
启动新容器(工作目录在 /)→ 创建 /world.txt
```
每个 RUN 都在新容器中执行**前一个 RUN 的内存状态 (包括工作目录) 不会保留**
#### 正确做法
```docker
## ✅ 正确:使用 WORKDIR
WORKDIR /app
RUN echo "hello" > world.txt # 创建 /app/world.txt
```
---
### 7.10.4 相对路径
WORKDIR 支持相对路径基于上一个 WORKDIR
```docker
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd # 输出 /a/b/c
```
---
### 7.10.5 使用环境变量
```docker
ENV APP_HOME=/app
WORKDIR $APP_HOME
RUN pwd # 输出 /app
```
---
### 7.10.6 多阶段构建中的 WORKDIR
```docker
## 构建阶段
FROM node:20 AS builder
WORKDIR /build
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
## 生产阶段
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY --from=builder /build/dist .
```
---
### 7.10.7 最佳实践
#### 1. 尽早设置 WORKDIR
```docker
FROM node:20
WORKDIR /app # 尽早设置
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "server.js"]
```
#### 2. 使用绝对路径
```docker
## ✅ 推荐:绝对路径,意图明确
WORKDIR /app
## ⚠️ 避免:相对路径可能造成混淆
WORKDIR app
```
#### 3. 不要用 RUN cd
```docker
## ❌ 避免
RUN cd /app && echo "hello" > world.txt
## ✅ 推荐
WORKDIR /app
RUN echo "hello" > world.txt
```
#### 4. 适时重置 WORKDIR
```docker
WORKDIR /app
## ... 应用相关操作 ...
WORKDIR /data
## ... 数据相关操作 ...
...
```
---
### 7.10.8 与其他指令的关系
| 指令 | WORKDIR 的影响 |
|------|---------------|
| `RUN` | WORKDIR 中执行命令 |
| `CMD` | WORKDIR 中启动 |
| `ENTRYPOINT` | WORKDIR 中启动 |
| `COPY` | 相对目标路径基于 WORKDIR |
| `ADD` | 相对目标路径基于 WORKDIR |
```docker
WORKDIR /app
RUN pwd # /app
COPY . . # 复制到 /app
CMD ["./start.sh"] # /app/start.sh
```
---
### 7.10.9 运行时覆盖
使用 `-w` 参数覆盖工作目录
```bash
$ docker run -w /tmp myimage pwd
/tmp
```
---

279
07_dockerfile/7.11_user.md Normal file
View File

@@ -0,0 +1,279 @@
## 7.11 USER 指定当前用户
### 7.11.1 基本语法
```docker
USER <用户名>[:<用户组>]
USER <UID>[:<GID>]
```
`USER` 指令切换后续指令 (RUNCMDENTRYPOINT) 的执行用户
---
### 7.11.2 为什么要使用 USER
> 笔者强调以非 root 用户运行容器是最重要的安全实践之一
```mermaid
flowchart LR
subgraph Root ["root 用户运行的风险:"]
direction TB
R_C["容器内 root"] -- 可能逃逸 --> R_H["宿主机 root"]
R_C -- 漏洞利用 --> R_Control["完全控制宿主机"]
end
subgraph NonRoot ["非 root 用户运行:"]
direction TB
NR_C["容器内普通用户"] -- 逃逸后 --> NR_H["宿主机普通用户"]
NR_C -- 权限受限,危害降低 --> NR_Safe["无法控制系统"]
end
```
---
### 7.11.3 基本用法
#### 创建并切换用户
```docker
FROM node:20-alpine
## 1. 创建用户和组
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
## 2. 设置目录权限
WORKDIR /app
COPY --chown=appuser:appgroup . .
## 3. 切换用户
USER appuser
## 4. 后续命令以 appuser 身份运行
CMD ["node", "server.js"]
```
#### 使用 UID/GID
```docker
## 也可以使用数字
USER 1001:1001
```
---
### 7.11.4 用户必须已存在
`USER` 指令只能切换到 **已存在** 的用户
```docker
## ❌ 错误:用户不存在
USER nonexistent
## Error: unable to find user nonexistent
## ✅ 正确:先创建用户
RUN useradd -r -s /bin/false appuser
USER appuser
```
#### 创建用户的方式
**Debian/Ubuntu**
```docker
RUN groupadd -r appgroup && \
useradd -r -g appgroup appuser
```
**Alpine**
```docker
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S -G appgroup appuser
```
| 选项 | 说明 |
|------|------|
| `-r` (useradd) / `-S` (adduser) | 创建系统用户 |
| `-g` | 指定主组 |
| `-G` | 指定附加组 |
| `-u` | 指定 UID |
| `-s /bin/false` | 禁用登录 shell |
---
### 7.11.5 运行时切换用户
#### 使用 gosu (推荐)
ENTRYPOINT 脚本中切换用户时不要使用 `su` `sudo`应使用 [gosu](https://github.com/tianon/gosu)
```docker
FROM debian:bookworm
## 创建用户
RUN groupadd -r redis && useradd -r -g redis redis
## 安装 gosu
RUN apt-get update && apt-get install -y gosu && rm -rf /var/lib/apt/lists/*
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["redis-server"]
```
**docker-entrypoint.sh**
```bash
#!/bin/bash
set -e
## 以 root 执行初始化
chown -R redis:redis /data
## 用 gosu 切换到 redis 用户运行服务
exec gosu redis "$@"
```
#### 为什么不用 su/sudo
| 问题 | su/sudo | gosu |
|------|---------|------|
| TTY 要求 | 需要 | 不需要 |
| 信号传递 | 不正确 | 正确 |
| 子进程 | | exec 替换 |
| 容器中使用 | | |
---
### 7.11.6 运行时覆盖用户
使用 `-u` `--user` 参数
```bash
## 以指定用户运行
$ docker run -u 1001:1001 myimage
## 以 root 运行(调试时)
$ docker run -u root myimage
```
---
### 7.11.7 文件权限处理
切换用户后确保应用有权访问文件
```docker
FROM node:20-alpine
## 创建用户
RUN adduser -D -u 1001 appuser
WORKDIR /app
## 方式1使用 --chown
COPY --chown=appuser:appuser . .
## 方式2手动 chown减少层数
## COPY . .
## RUN chown -R appuser:appuser /app
USER appuser
CMD ["node", "server.js"]
```
---
### 7.11.8 最佳实践
#### 1. 始终使用非 root 用户
```docker
## ✅ 推荐
RUN adduser -D appuser
USER appuser
CMD ["myapp"]
## ❌ 避免
CMD ["myapp"] # 以 root 运行
```
#### 2. 使用固定 UID/GID
便于在宿主机和容器间共享文件
```docker
## 使用常见的非 root UID
RUN addgroup -g 1000 -S appgroup && \
adduser -u 1000 -S -G appgroup appuser
USER 1000:1000
```
#### 3. 多阶段构建中的 USER
```docker
## 构建阶段可以用 root
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段用非 root
FROM node:20-alpine
RUN adduser -D appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appuser /app/dist .
USER appuser
CMD ["node", "server.js"]
```
---
### 7.11.9 常见问题
#### Q权限被拒绝
```bash
permission denied: '/app/data.log'
```
**解决**确保目录权限正确
```docker
RUN mkdir -p /app/data && chown appuser:appuser /app/data
```
#### Q无法绑定低于 1024 的端口
root 用户无法绑定 80443 等端口
**解决**
1. 使用高端口 ( 8080)
2. 在运行时映射端口`docker run -p 80:8080`
---

View File

@@ -0,0 +1,196 @@
## 7.12 HEALTHCHECK 健康检查
### 7.12.1 基本语法
```docker
HEALTHCHECK [选项] CMD <命令>
HEALTHCHECK NONE
```
`HEALTHCHECK` 指令告诉 Docker 如何判断容器状态是否正常这是保障服务高可用的重要机制
---
### 7.12.2 为什么需要 HEALTHCHECK
在没有 HEALTHCHECK 之前Docker 只能通过 **进程退出码** 来判断容器状态**问题场景**
- Web 服务死锁无法响应请求但进程仍在运行
- 数据库正在启动中尚未准备好接受连接
- 应用陷入死循环CPU 爆满但进程存活
**引入 HEALTHCHECK **
Docker 定期执行指定的检查命令根据返回值判断容器是否 健康
```bash
容器状态转换:
Starting ──成功──> Healthy ──失败N次──> Unhealthy
▲ │
└──────成功──────┘
```
---
### 7.12.3 基本用法
#### Web 服务检查
```docker
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -fs http://localhost/ || exit 1
```
#### 命令返回值
- `0`成功 (healthy)
- `1`失败 (unhealthy)
- `2`保留值 (不使用)
#### 常用选项
| 选项 | 说明 | 默认值 |
|------|------|--------|
| `--interval` | 两次检查的间隔 | 30s |
| `--timeout` | 检查命令的超时时间 | 30s |
| `--start-period` | 启动缓冲期 (期间失败不计入次数)| 0s |
| `--retries` | 连续失败多少次标记为 unhealthy | 3 |
---
### 7.12.4 屏蔽健康检查
如果基础镜像定义了 HEALTHCHECK但你不想使用它
```docker
FROM my-base-image
HEALTHCHECK NONE
```
---
### 7.12.5 常见检查脚本
#### HTTP 服务
使用 `curl` `wget`
```docker
## 使用 curl
HEALTHCHECK CMD curl -f http://localhost/ || exit 1
## 使用 wgetAlpine 默认包含)
HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
```
#### 数据库
```docker
## MySQL
HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
## Redis
HEALTHCHECK CMD redis-cli ping || exit 1
```
#### 自定义脚本
```docker
COPY healthcheck.sh /usr/local/bin/
HEALTHCHECK CMD ["healthcheck.sh"]
```
---
### 7.12.6 Compose 中使用
可以在 `compose.yaml` ( `docker-compose.yml`) 中覆盖或定义健康检查
```yaml
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
```
带健康检查的依赖启动
```yaml
services:
web:
depends_on:
db:
condition: service_healthy # 等待 db 变健康才启动 web
db:
image: mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
```
---
### 7.12.7 查看健康状态
```bash
## 查看容器状态(包含健康信息)
$ docker ps
CONTAINER ID STATUS
abc123 Up 1 minute (healthy)
def456 Up 2 minutes (unhealthy)
## 查看详细健康日志
$ docker inspect --format '{{json .State.Health}}' mycontainer | jq
{
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "...",
"End": "...",
"ExitCode": 0,
"Output": "..."
}
]
}
```
---
### 7.12.8 最佳实践
#### 1. 避免副作用
健康检查会被频繁执行不要在检查脚本中进行写操作或消耗大量资源的操作
#### 2. 使用轻量级工具
优先使用镜像中已有的工具 ( `wget`)避免为了健康检查安装庞大的依赖 ( `curl`)
#### 3. 设置合理的 Start Period
应用启动可能需要时间 ( Java 应用)设置 `--start-period` 可以防止在启动阶段因检查失败而误判
```docker
## 给应用 1 分钟启动时间
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
```
#### 4. 只检查核心依赖
健康检查应主要关注 **当前服务** 是否可用而不是检查其下游依赖 (数据库等)下游依赖的检查应由应用逻辑处理
---

View File

@@ -0,0 +1,145 @@
## 7.13 ONBUILD 为他人作嫁衣裳
### 7.13.1 基本语法
```docker
ONBUILD <其它指令>
```
`ONBUILD` 是一个特殊的指令它后面跟的是其它指令 ( `RUN``COPY` )这些指令 **在当前镜像构建时不会执行**只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行
---
### 7.13.2 为什么需要 ONBUILD
`ONBUILD` 主要用于制作 **语言栈基础镜像** **框架基础镜像**
#### 场景维护 Node.js 项目
假设你有多个 Node.js 项目它们的构建流程都一样
1. 创建目录
2. 复制 `package.json`
3. 执行 `npm install`
4. 复制源码
5. 启动应用
如果不使用 `ONBUILD`每个项目的 Dockerfile 都要重复这些步骤且通过 `COPY` 复制文件时基础镜像无法预知子项目的文件名
#### 使用 ONBUILD 的解决方案
**基础镜像 (my-node-base)**
```docker
FROM node:20-alpine
WORKDIR /app
## 这些指令将在子镜像构建时执行
ONBUILD COPY package*.json ./
ONBUILD RUN npm install
ONBUILD COPY . .
CMD ["npm", "start"]
```
**子项目 Dockerfile**
```docker
FROM my-node-base
## 只需要一行!
## 构建时会自动执行 COPY 和 RUN
...
```
---
### 7.13.3 执行机制
```bash
基础镜像构建:
Dockerfile (含 ONBUILD) ──build──> 基础镜像 (记录了 ONBUILD 触发器)
(指令未执行)
子镜像构建:
FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行触发器指令 ──> 继续执行子 Dockerfile
```
---
### 7.13.4 常见使用场景
#### 1. 自动处理依赖安装
```docker
## Python 基础镜像
ONBUILD COPY requirements.txt ./
ONBUILD RUN pip install -r requirements.txt
```
#### 2. 自动编译代码
```docker
## Go 基础镜像
ONBUILD COPY . .
ONBUILD RUN go build -o app main.go
```
#### 3. 处理静态资源
```docker
## Nginx 静态网站基础镜像
ONBUILD COPY dist/ /usr/share/nginx/html/
```
---
### 7.13.5 注意事项
#### 1. 继承性限制
`ONBUILD` 指令 **只会继承一次**
- 镜像 A ( ONBUILD)
- 镜像 B (FROM A) -> 触发 ONBUILD
- 镜像 C (FROM B) -> **不会** 再次触发 ONBUILD
#### 2. 构建上下文
子镜像构建时`ONBUILD COPY . .` 中的 `.` 指的是 **子项目** 的构建上下文而不是基础镜像的上下文
#### 3. 不允许级联
`ONBUILD ONBUILD` 是非法的你不能写 `ONBUILD ONBUILD COPY ...`
#### 4. 可能会导致构建失败
由于 `ONBUILD` 实际上是在子镜像中执行指令如果子项目的上下文不满足要求 (例如缺少 `package.json`)会导致子镜像构建失败且错误信息可能比较隐晦
---
### 7.13.6 最佳实践
#### 1. 命名规范
建议在镜像标签中添加 `-onbuild` 后缀明确告知使用者该镜像包含触发器
```bash
node:20-onbuild
python:3.12-onbuild
```
#### 2. 避免执行耗时操作
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件)这会让子镜像构建变得缓慢且不可控
#### 3. 清理工作
如果 `ONBUILD` 指令产生了临时文件最好在同一个指令链中清理或者提供机制让子镜像清理
---

144
07_dockerfile/7.14_label.md Normal file
View File

@@ -0,0 +1,144 @@
## 7.14 LABEL 为镜像添加元数据
### 7.14.1 基本语法
```docker
LABEL <key>=<value> <key>=<value> ...
```
`LABEL` 指令以键值对的形式给镜像添加元数据这些数据不会影响镜像的功能但可以帮助用户理解镜像或被自动化工具使用
---
### 7.14.2 为什么需要 LABEL
1. **版本管理**记录版本号构建时间Git Commit ID
2. **联系信息**维护者邮箱文档地址支持渠道
3. **自动化工具**CI/CD 工具可以读取标签触发操作
4. **许可证信息**声明开源协议
---
### 7.14.3 基本用法
#### 定义单个标签
```docker
LABEL version="1.0"
LABEL description="这是一个 Web 应用服务器"
```
#### 定义多个标签 (推荐)
```docker
LABEL maintainer="user@example.com" \
version="1.2.0" \
description="My App Description" \
org.opencontainers.image.authors="Yeasy"
```
> 💡 包含空格的值需要用引号括起来
---
### 7.14.4 常用标签规范
为了标准和互操作性推荐使用 [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys) 定义的标准标签:
| 标签 Key | 说明 | 示例 |
|----------|------|------|
| `org.opencontainers.image.created` | 构建时间(RFC 3339) | `2024-01-01T00:00:00Z` |
| `org.opencontainers.image.authors` | 作者/维护者 | `support@example.com` |
| `org.opencontainers.image.url` | 项目主页 | `https://example.com` |
| `org.opencontainers.image.documentation`| 文档地址 | `https://example.com/docs` |
| `org.opencontainers.image.source` | 源码仓库 | `https://github.com/user/repo` |
| `org.opencontainers.image.version` | 版本号 | `1.0.0` |
| `org.opencontainers.image.licenses` | 许可证 | `MIT` |
| `org.opencontainers.image.title` | 镜像标题 | `My App` |
| `org.opencontainers.image.description` | 描述 | `Production ready web server` |
#### 示例
```docker
LABEL org.opencontainers.image.authors="yeasy" \
org.opencontainers.image.documentation="https://yeasy.gitbooks.io" \
org.opencontainers.image.source="https://github.com/yeasy/docker_practice" \
org.opencontainers.image.licenses="MIT"
```
---
### 7.14.5 MAINTAINER 指令 (已废弃)
旧版本的 Dockerfile 中常看到 `MAINTAINER` 指令
```docker
## ❌ 已弃用
MAINTAINER user@example.com
```
现在推荐使用 `LABEL`
```docker
## ✅ 推荐
LABEL maintainer="user@example.com"
## 或
LABEL org.opencontainers.image.authors="user@example.com"
```
---
### 7.14.6 动态标签
配合 `ARG` 使用可以在构建时动态注入标签
```docker
ARG BUILD_DATE
ARG VCS_REF
LABEL org.opencontainers.image.created=$BUILD_DATE \
org.opencontainers.image.revision=$VCS_REF
```
构建命令
```bash
$ docker build \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=$(git rev-parse --short HEAD) \
.
```
---
### 7.14.7 查看标签
#### docker inspect
查看镜像的标签信息
```bash
$ docker inspect nginx --format '{{json .Config.Labels}}' | jq
{
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
}
```
#### 过滤器
可以使用标签过滤镜像
```bash
## 列出作者是 yeasy 的所有镜像
$ docker images --filter "label=org.opencontainers.image.authors=yeasy"
## 删除所有带有特定标签的镜像
$ docker rmi $(docker images -q --filter "label=stage=builder")
```
---

138
07_dockerfile/7.15_shell.md Normal file
View File

@@ -0,0 +1,138 @@
## 7.15 SHELL 指令
### 7.15.1 基本语法
```docker
SHELL ["executable", "parameters"]
```
`SHELL` 指令允许覆盖 Docker 默认的 shell
- **Linux 默认**`["/bin/sh", "-c"]`
- **Windows 默认**`["cmd", "/S", "/C"]`
该指令会影响后续的 `RUN``CMD``ENTRYPOINT` 指令 (当它们使用 shell 格式时)
---
### 7.15.2 为什么要用 SHELL 指令
#### 1. 使用 bash 特性
默认的 `/bin/sh` (通常是 dash alpine ash) 功能有限如果你需要使用 bash 的特有功能 (如数组`{}` 扩展`pipefail` )可以切换 shell
```docker
FROM ubuntu:24.04
## 切换到 bash
SHELL ["/bin/bash", "-c"]
## 现在可以使用 bash 特性了
RUN echo {a..z}
```
#### 2. 增强错误处理
默认情况下管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功整个指令就视为成功这可能掩盖构建错误
```docker
## ❌ 这里的 wget 失败了,但构建继续(因为 tar 成功了)
RUN wget -O - https://invalid-url | tar xz
```
使用 `SHELL` 启用 `pipefail`
```docker
## ✅ 启用 pipefail
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
## 如果 wget 失败,整个 RUN 就会失败
RUN wget -O - https://invalid-url | tar xz
```
#### 3. Windows 环境
Windows 容器中经常需要在 `cmd` `powershell` 之间切换
```docker
FROM mcr.microsoft.com/windows/servercore:ltsc2022
## 默认是 cmd
RUN echo Default shell is cmd
## 切换到 powershell
SHELL ["powershell", "-command"]
RUN Write-Host "Hello from PowerShell"
## 切回 cmd
SHELL ["cmd", "/S", "/C"]
```
---
### 7.15.3 作用范围
`SHELL` 指令可以出现多次每次只影响其后的指令
```docker
FROM ubuntu:24.04
## 使用默认 sh
RUN echo "Using sh"
SHELL ["/bin/bash", "-c"]
## 使用 bash
RUN echo "Using bash"
SHELL ["/bin/sh", "-c"]
## 回到 sh
RUN echo "Using sh again"
```
---
### 7.15.4 对其他指令的影响
`SHELL` 影响的是所有使用 **shell 格式** 的指令
| 指令格式 | 是否受 SHELL 影响 |
|---------|-------------------|
| `RUN command` | |
| `RUN ["exec", "param"]` | |
| `CMD command` | |
| `CMD ["exec", "param"]` | |
| `ENTRYPOINT command` | |
| `ENTRYPOINT ["exec", "param"]` | |
---
### 7.15.5 最佳实践
#### 1. 推荐开启 pipefail
对于使用 bash 的镜像强烈建议开启 `pipefail`以确保构建过程中的错误能被及时捕获
```docker
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
```
#### 2. 明确意图
如果由于脚本需求必须更改 shell最好在 Dockerfile 中显式声明而不是依赖默认行为
#### 3. 尽量保持一致
避免在 Dockerfile 中频繁切换 SHELL这会使构建过程难以理解和调试尽量在头部定义一次即可
---

View File

@@ -0,0 +1,7 @@
## 7.16 参考文档
* `Dockerfile` 官方文档https://docs.docker.com/engine/reference/builder/
* `Dockerfile` 最佳实践文档https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* `Docker` 官方镜像 `Dockerfile`https://github.com/docker-library/docs

View File

@@ -1,12 +1,10 @@
## 多阶段构建
### 之前的做法
## 7.17 多阶段构建
Docker 17.05 版本之前我们构建 Docker 镜像时通常会采用两种方式
#### 全部放入一个 Dockerfile
### 7.17.1 全部放入一个 Dockerfile
一种方式是将所有的构建过程包含在一个 `Dockerfile` 包括项目及其依赖库的编译测试打包等流程这里可能会带来的一些问题
一种方式是将所有的构建过程包含在一个 `Dockerfile` 包括项目及其依赖库的编译测试打包等流程这里可能会带来的一些问题
* 镜像层次多镜像体积较大部署时间变长
@@ -15,19 +13,19 @@
例如编写 `app.go` 文件该程序输出 `Hello World!`
```go
package main
package main
import "fmt"
import "fmt"
func main(){
func main(){
fmt.Printf("Hello World!");
}
```
编写 `Dockerfile.one` 文件
```dockerfile
FROM golang:1.9-alpine
```docker
FROM golang:alpine
RUN apk --no-cache add git ca-certificates
@@ -35,7 +33,8 @@ 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 -d -v 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
@@ -50,14 +49,14 @@ CMD ["./app"]
$ docker build -t go/helloworld:1 -f Dockerfile.one .
```
#### 分散到多个 Dockerfile
### 7.17.2 分散到多个 Dockerfile
另一种方式就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后再将其拷贝到运行环境中这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来这种方式虽然可以很好地规避第一种方式存在的风险但明显部署过程较复杂
例如编写 `Dockerfile.build` 文件
```dockerfile
FROM golang:1.9-alpine
```docker
FROM golang:alpine
RUN apk --no-cache add git
@@ -71,7 +70,7 @@ RUN go get -d -v github.com/go-sql-driver/mysql \
编写 `Dockerfile.copy` 文件
```dockerfile
```docker
FROM alpine:latest
RUN apk --no-cache add ca-certificates
@@ -119,14 +118,14 @@ go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
### 使用多阶段构建
## 7.17 使用多阶段构建
为解决以上问题Docker v17.05 开始支持多阶段构建 (`multistage builds`)使用多阶段构建我们就可以很容易解决前面提到的问题并且只需要编写一个 `Dockerfile`
例如编写 `Dockerfile` 文件
```dockerfile
FROM golang:1.9-alpine as builder
```docker
FROM golang:alpine as builder
RUN apk --no-cache add git
@@ -146,7 +145,7 @@ WORKDIR /root/
COPY --from=0 /go/src/github.com/go/helloworld/app .
CMD ["./app"]
CMD ["./app"]
```
构建镜像
@@ -168,12 +167,12 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
很明显使用多阶段构建的镜像体积小同时也完美解决了上边提到的问题
#### 只构建某一阶段的镜像
### 7.17.1 只构建某一阶段的镜像
我们可以使用 `as` 来为某一阶段命名例如
```dockerfile
FROM golang:1.9-alpine as builder
```docker
FROM golang:alpine as builder
```
例如当我们只想构建 `builder` 阶段的镜像时增加 `--target=builder` 参数即可
@@ -182,10 +181,10 @@ FROM golang:1.9-alpine as builder
$ docker build --target builder -t username/imagename:tag .
```
#### 构建时从其他镜像复制文件
### 7.17.2 构建时从其他镜像复制文件
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件我们也可以复制任意镜像中的文件
```dockerfile
$ COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
```docker
COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
```

View File

@@ -1,8 +1,8 @@
## 实战多阶段构建 Laravel 镜像
## 7.18 实战多阶段构建 Laravel 镜像
> 本节适用于 PHP 开发者阅读
> 本节适用于 PHP 开发者阅读`Laravel` 基于 8.x 版本各个版本的文件结构可能会有差异请根据实际自行修改
### 准备
### 7.18.1 准备
新建一个 `Laravel` 项目或在已有的 `Laravel` 项目根目录下新建 `Dockerfile` `.dockerignore` `laravel.conf` 文件
@@ -11,16 +11,23 @@
```bash
.idea/
.git/
vendor/
node_modules/
public/js/
public/css/
public/mix-manifest.json
yarn-error.log
bootstrap/cache/*
storage/
# 自行添加其他需要排除的文件例如 .env.* 文件
## 自行添加其他需要排除的文件例如 .env.* 文件
...
```
`laravel.conf` 文件中写入 nginx 配置
@@ -40,43 +47,48 @@ server {
include fastcgi.conf;
# fastcgi_connect_timeout 300;
# fastcgi_send_timeout 300;
# fastcgi_read_timeout 300;
}
}
```
### 前端构建
### 7.18.2 前端构建
第一阶段进行前端构建
```dockerfile
```docker
FROM node:alpine as frontend
COPY package.json /app/
RUN cd /app \
&& npm install --registry=https://registry.npm.taobao.org
RUN set -x ; cd /app \
&& npm install --registry=https://registry.npmmirror.com
COPY webpack.mix.js /app/
COPY resources/assets/ /app/resources/assets/
COPY webpack.mix.js webpack.config.js tailwind.config.js /app/
COPY resources/ /app/resources/
RUN cd /app \
&& npm run production
RUN set -x ; cd /app \
&& touch artisan \
&& mkdir -p public \
&& npm run production
```
### 安装 Composer 依赖
### 7.18.3 安装 Composer 依赖
第二阶段安装 Composer 依赖
```dockerfile
```docker
FROM composer as composer
COPY database/ /app/database/
COPY composer.json composer.lock /app/
RUN cd /app \
&& composer config -g repo.packagist composer https://packagist.laravel-china.org \
RUN set -x ; cd /app \
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \
&& composer install \
--ignore-platform-reqs \
--no-interaction \
@@ -85,12 +97,12 @@ RUN cd /app \
--prefer-dist
```
### 整合以上阶段所生成的文件
### 7.18.4 整合以上阶段所生成的文件
第三阶段对以上阶段生成的文件进行整合
```dockerfile
FROM php:7.2-fpm-alpine as laravel
```docker
FROM php:7.4-fpm-alpine as laravel
ARG LARAVEL_PATH=/app/laravel
@@ -98,22 +110,22 @@ COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
COPY . ${LARAVEL_PATH}
COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
COPY --from=frontend /app/public/mix-manifest.json ${LARAVEL_PATH}/public/mix-manifest.json
RUN cd ${LARAVEL_PATH} \
&& php artisan package:discover \
RUN set -x ; cd ${LARAVEL_PATH} \
&& mkdir -p storage \
&& mkdir -p storage/framework/cache \
&& mkdir -p storage/framework/sessions \
&& mkdir -p storage/framework/testing \
&& mkdir -p storage/framework/views \
&& mkdir -p storage/logs \
&& chmod -R 777 storage
&& chmod -R 777 storage \
&& php artisan package:discover
```
### 最后一个阶段构建 NGINX 镜像
### 7.18.5 最后一个阶段构建 NGINX 镜像
```dockerfile
```docker
FROM nginx:alpine as nginx
ARG LARAVEL_PATH=/app/laravel
@@ -122,7 +134,7 @@ COPY laravel.conf /etc/nginx/conf.d/
COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public
```
### 构建 Laravel Nginx 镜像
### 7.18.6 构建 Laravel Nginx 镜像
使用 `docker build` 命令构建镜像
@@ -132,7 +144,7 @@ $ docker build -t my/laravel --target=laravel .
$ docker build -t my/nginx --target=nginx .
```
### 启动容器并测试
### 7.18.7 启动容器并测试
新建 Docker 网络
@@ -140,42 +152,46 @@ $ docker build -t my/nginx --target=nginx .
$ docker network create laravel
```
启动 laravel 容器 `--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致
启动 laravel 容器`--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致
```bash
$ docker run -it --rm --name=laravel --network=laravel my/laravel
$ docker run -dit --rm --name=laravel --network=laravel my/laravel
```
启动 nginx 容器
```bash
$ docker run -it --rm --network=laravel -p 8080:80 my/nginx
$ docker run -dit --rm --network=laravel -p 8080:80 my/nginx
```
浏览器访问 `127.0.0.1:8080` 可以看到 Laravel 项目首页
> 也许 Laravel 项目依赖其他外部服务例如 redisMySQL请自行启动这些服务之后再进行测试本小节不再赘述
### 生产环境优化
### 7.18.8 生产环境优化
本小节内容为了方便测试将配置文件直接放到了镜像中实际在使用时 **建议** 将配置文件作为 `config` `secret` 挂载到容器中请读者自行学习 `Swarm mode` `Kubernetes` 的相关内容
本小节内容为了方便测试将配置文件直接放到了镜像中实际在使用时 **建议** 将配置文件作为 `config` `secret` 挂载到容器中请读者自行学习 `Kubernetes` 的相关内容
### 附录
由于篇幅所限本小节只是简单列出更多内容可以参考 https://github.com/khs1994-docker/laravel-demo 项目。
### 7.18.9 附录
完整的 `Dockerfile` 文件如下
```dockerfile
```docker
FROM node:alpine as frontend
COPY package.json /app/
RUN cd /app \
&& npm install --registry=https://registry.npm.taobao.org
RUN set -x ; cd /app \
&& npm install --registry=https://registry.npmmirror.com
COPY webpack.mix.js /app/
COPY resources/assets/ /app/resources/assets/
COPY webpack.mix.js webpack.config.js tailwind.config.js /app/
COPY resources/ /app/resources/
RUN cd /app \
RUN set -x ; cd /app \
&& touch artisan \
&& mkdir -p public \
&& npm run production
FROM composer as composer
@@ -183,8 +199,8 @@ FROM composer as composer
COPY database/ /app/database/
COPY composer.json /app/
RUN cd /app \
&& composer config -g repo.packagist composer https://packagist.laravel-china.org \
RUN set -x ; cd /app \
&& composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ \
&& composer install \
--ignore-platform-reqs \
--no-interaction \
@@ -192,7 +208,7 @@ RUN cd /app \
--no-scripts \
--prefer-dist
FROM php:7.2-fpm-alpine as laravel
FROM php:7.4-fpm-alpine as laravel
ARG LARAVEL_PATH=/app/laravel
@@ -200,17 +216,17 @@ COPY --from=composer /app/vendor/ ${LARAVEL_PATH}/vendor/
COPY . ${LARAVEL_PATH}
COPY --from=frontend /app/public/js/ ${LARAVEL_PATH}/public/js/
COPY --from=frontend /app/public/css/ ${LARAVEL_PATH}/public/css/
COPY --from=frontend /app/mix-manifest.json ${LARAVEL_PATH}/mix-manifest.json
COPY --from=frontend /app/public/mix-manifest.json ${LARAVEL_PATH}/public/mix-manifest.json
RUN cd ${LARAVEL_PATH} \
&& php artisan package:discover \
RUN set -x ; cd ${LARAVEL_PATH} \
&& mkdir -p storage \
&& mkdir -p storage/framework/cache \
&& mkdir -p storage/framework/sessions \
&& mkdir -p storage/framework/testing \
&& mkdir -p storage/framework/views \
&& mkdir -p storage/logs \
&& chmod -R 777 storage
&& chmod -R 777 storage \
&& php artisan package:discover
FROM nginx:alpine as nginx

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