mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-14 05:41:11 +00:00
Compare commits
54 Commits
ecab788013
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f653cf338 | ||
|
|
4cc09a28fa | ||
|
|
1dded72085 | ||
|
|
d3e253a6cc | ||
|
|
d6fff9a3f7 | ||
|
|
fc276d3b4f | ||
|
|
40ded62baa | ||
|
|
89b0dc4425 | ||
|
|
330e084e00 | ||
|
|
e62b203f1a | ||
|
|
cb6bf74a2e | ||
|
|
a980e34276 | ||
|
|
3d33e00802 | ||
|
|
1a820c8c8b | ||
|
|
585b364574 | ||
|
|
a0a5de7f11 | ||
|
|
83ba6b7b47 | ||
|
|
53f20dede7 | ||
|
|
48c8b50cf7 | ||
|
|
70ef2cba58 | ||
|
|
f5cfa4140a | ||
|
|
d174cf327c | ||
|
|
6a9ce44c5a | ||
|
|
c09f66da55 | ||
|
|
635e05ad34 | ||
|
|
6f22d0f5f0 | ||
|
|
17517e26b7 | ||
|
|
9fcaff6673 | ||
|
|
a096947382 | ||
|
|
be09a95d0d | ||
|
|
3af007b176 | ||
|
|
551dcfd2cb | ||
|
|
0d2654fbf2 | ||
|
|
3894ba56bc | ||
|
|
0dd0d036a2 | ||
|
|
a9c4189c0c | ||
|
|
56deeaee0f | ||
|
|
0ff67cc893 | ||
|
|
70cab9e92d | ||
|
|
67547c0c3e | ||
|
|
0d012c2d27 | ||
|
|
1eddef954e | ||
|
|
6baf2c68f2 | ||
|
|
fd28d966ca | ||
|
|
ba0c388384 | ||
|
|
fc4f1ce2d0 | ||
|
|
276eb356a2 | ||
|
|
246fc35c8e | ||
|
|
745b7c812a | ||
|
|
ad3b86d727 | ||
|
|
16e884da51 | ||
|
|
5bd2c37c54 | ||
|
|
19aaad591c | ||
|
|
bbfc9d34ff |
27
.github/dependabot.yml
vendored
Normal file
27
.github/dependabot.yml
vendored
Normal 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:
|
||||
- "*"
|
||||
2
.github/workflows/check-link.yml
vendored
2
.github/workflows/check-link.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
name: check-link
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- uses: actions/checkout@v6.0.2
|
||||
# search Issues :-(
|
||||
- run: |
|
||||
docker run -i --rm \
|
||||
|
||||
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- name: Build Gitbook
|
||||
uses: docker://yeasy/docker_practice
|
||||
with:
|
||||
|
||||
27
.github/workflows/dependabot-automerge.yml
vendored
Normal file
27
.github/workflows/dependabot-automerge.yml
vendored
Normal 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}}
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -21,11 +21,7 @@ docker-compose.override.yml
|
||||
__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
|
||||
check*.py
|
||||
find*.py
|
||||
fix*.py
|
||||
format*.py
|
||||
|
||||
@@ -45,7 +45,7 @@ $ docker run -d -p 8080:80 my-hello-world
|
||||
|
||||
### 1.1.5 访问测试
|
||||
|
||||
打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “Hello,Docker!”。
|
||||
打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “Hello, Docker!”。
|
||||
|
||||
### 1.1.6 清理
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ $ docker compose up
|
||||
|
||||
Docker 容器共享宿主机内核,无需为每个应用运行完整的操作系统。以一台 64GB 内存的物理服务器为例:
|
||||
- **传统虚拟机方案**:每个虚拟机都需要运行完整的操作系统(每个额外占用如 2GB 内存),产生大量资源开销,实际可用于应用的内存可能只有约 18GB。
|
||||
- **Docker 方案**:容器直接共享宿主机系统,只需付出很少的基础开销(OS及引擎约 4GB),即可将约 60GB 的内存全部用于实际应用。
|
||||
- **Docker 方案**:容器直接共享宿主机系统,只需付出很少的基础开销(OS 及引擎约 4GB),即可将约 60GB 的内存全部用于实际应用。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
@@ -200,13 +200,7 @@ flowchart TD
|
||||
|
||||
### 1.3.5 与传统虚拟机的对比总结
|
||||
|
||||
下表对比了容器技术与传统虚拟机的区别:
|
||||
关于容器与虚拟机的详细特性对比,请参阅 [1.2.3 Docker vs 虚拟机](1.2_what.md) 中的对比表。总结来说:
|
||||
|
||||
| 特性 | Docker 容器 | 传统虚拟机 |
|
||||
|:------|:-----------|:-----------|
|
||||
| 启动速度 | 秒级 | 分钟级 |
|
||||
| 磁盘占用 | MB 级别 | GB 级别 |
|
||||
| 性能 | 接近原生 | 有 5-20% 损耗 |
|
||||
| 单机支持量 | 上千个容器 | 几十个虚拟机 |
|
||||
| 隔离性 | 进程级别 | 完全隔离 |
|
||||
| 最佳场景 | 微服务、CI/CD、开发环境 | 多租户、高安全需求 |
|
||||
- **性能差异**:虚拟机通常有 5-20% 的性能损耗,而容器接近原生性能。
|
||||
- **最佳场景**:Docker 容器适合微服务、CI/CD、开发环境;虚拟机适合多租户、高安全需求场景。
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
本章将带领你进入 **Docker** 的世界。
|
||||
|
||||
> **版本提示**:本书内容及示例基于 **Docker Engine v29.x** 及以上版本。值得注意的是,自 Docker Engine v29 起,官方在全新安装场景下 **默认启用了 `containerd image store` 作为镜像存储后端**(取代了传统的经典存储引擎如 overlay2 graph driver)。这项底层革新极大增强了 Docker 对多架构镜像(Multi-platform)、以及软件供应链安全元数据(Attestations, SBOM, Provenance)的本地支持原生性。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [快速上手](1.1_quickstart.md)
|
||||
* 通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。
|
||||
|
||||
* [什么是 Docker](1.2_what.md)
|
||||
* 介绍 Docker 的起源、发展历程以及其背后的核心技术 (Cgroups,Namespaces,UnionFS)。
|
||||
* 介绍 Docker 的起源、发展历程以及其背后的核心技术 (Cgroups,Namespaces,UnionFS,以及 `containerd` 引擎的演进)。
|
||||
* 了解 Docker 是如何改变软件交付方式的。
|
||||
|
||||
* [为什么要用 Docker](1.3_why.md)
|
||||
|
||||
@@ -6,3 +6,6 @@
|
||||
- Docker 推动了容器技术的标准化 (OCI) 和生态发展
|
||||
|
||||
Docker 的核心价值可以用一句话概括:**让应用的开发、测试、部署保持一致,同时极大提高资源利用效率。** 笔者认为,对于现代软件开发者来说,Docker 已经不是 “要不要学” 的问题,而是 **必备技能**。无论你是前端、后端、运维还是全栈开发者,掌握 Docker 都能让你的工作更高效。
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -123,7 +123,6 @@ RUN apt-get install -y build-essential # 安装编译工具(约 200MB)
|
||||
RUN make && make install # 编译应用
|
||||
RUN apt-get remove build-essential # 试图删除编译工具
|
||||
## 结果:镜像仍然包含 200MB 的编译工具!
|
||||
|
||||
```
|
||||
|
||||
```docker
|
||||
|
||||
@@ -12,22 +12,26 @@
|
||||
|
||||
### 2.2.2 容器的本质
|
||||
|
||||
> 💡 **笔者认为,理解这一点是理解 Docker 的关键:** **容器的本质是一个特殊的进程。**
|
||||
> 💡 笔者认为,理解这一点是理解 Docker 的关键:**容器的本质是一个特殊的进程**。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph NormalProcess ["普通进程"]
|
||||
direction TB
|
||||
N1["• 与其他进程共享系统资源<br/>• 可以看到其他进程<br/>• 共享网络和文件系统"]
|
||||
N1["• 共享系统资源<br/>• 共享网络<br/>• 共享文件系统"]
|
||||
end
|
||||
|
||||
subgraph ContainerProcess ["容器进程 (运行在宿主机内核上)"]
|
||||
direction TB
|
||||
C1["• 有自己的进程空间(看不到宿主机上的其他进程)<br/>• 有自己的网络(独立 IP、端口)<br/>• 有自己的文件系统(独立的 root 目录)<br/>• 有自己的用户(容器内的 root ≠ 宿主机的 root)"]
|
||||
C1["• 独立进程空间<br/>• 独立网络环境<br/>• 独立文件系统<br/>• 独立用户空间"]
|
||||
end
|
||||
```
|
||||
|
||||
这种隔离是通过 Linux 内核的 **Namespace** 技术实现的。
|
||||
这种隔离是通过 Linux 内核的 **Namespace** 技术实现的。具体表现为:
|
||||
- **进程空间**:容器看不到宿主机上的其他进程。
|
||||
- **网络**:容器拥有独立的 IP、端口等网络资源。
|
||||
- **文件系统**:容器拥有独立的 root 目录。
|
||||
- **用户**:容器内的 root 用户不等于宿主机的 root 用户。
|
||||
|
||||
### 2.2.3 容器 vs 虚拟机:核心区别
|
||||
|
||||
@@ -164,7 +168,7 @@ stateDiagram-v2
|
||||
Deleted --> [*]
|
||||
```
|
||||
|
||||
图 2-1 容器生命周期状态流转图
|
||||
图 2-1:容器生命周期状态流转图
|
||||
|
||||
#### 常用生命周期命令
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ flowchart TB
|
||||
end
|
||||
```
|
||||
|
||||
图 2-2 Registry、Repository 与 Tag 的层级关系
|
||||
图 2-2:Registry、Repository 与 Tag 的层级关系
|
||||
|
||||
相关基本概念具体如下:
|
||||
|
||||
@@ -56,7 +56,7 @@ flowchart TB
|
||||
一个完整的 Docker 镜像名称由 Registry 地址、用户名/组织名、仓库名和标签组成。了解其结构有助于我们更准确地定位镜像。基本格式如下:
|
||||
|
||||
```bash
|
||||
[registry地址/][用户名/]仓库名[:标签]
|
||||
[registry 地址/][用户名/]仓库名[:标签]
|
||||
```
|
||||
|
||||
示例:
|
||||
@@ -206,7 +206,7 @@ $ docker pull localhost:5000/myapp:v1.0
|
||||
│ │ 运行容器 │
|
||||
```
|
||||
|
||||
图 2-3 镜像构建、推送与拉取流程
|
||||
图 2-3:镜像构建、推送与拉取流程
|
||||
|
||||
#### 常用命令
|
||||
|
||||
|
||||
@@ -7,3 +7,9 @@
|
||||
* **仓库** (`Repository`):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。
|
||||
|
||||
理解了这三个概念,就理解了 **Docker** 的整个生命周期。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [Docker 镜像](2.1_image.md)
|
||||
* [Docker 容器](2.2_container.md)
|
||||
* [Docker 仓库](2.3_repository.md)
|
||||
|
||||
@@ -1,40 +1,18 @@
|
||||
## 本章小结
|
||||
|
||||
本章介绍了 Docker 的三个核心概念:镜像、容器和仓库。
|
||||
|
||||
| 概念 | 要点 |
|
||||
|------|------|
|
||||
| **镜像是什么** | 只读的应用模板,包含运行所需的一切 |
|
||||
| **分层存储** | 多层叠加,共享基础层,节省空间 |
|
||||
| **只读特性** | 构建后不可修改,保证一致性 |
|
||||
| **层的陷阱** | 删除操作只是标记,不减小体积 |
|
||||
|
||||
理解了镜像,接下来让我们学习[容器](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 |
|
||||
@@ -43,9 +21,20 @@
|
||||
|
||||
现在你已经了解了 Docker 的三个核心概念:[镜像](2.1_image.md)、[容器](2.2_container.md)和仓库。接下来,让我们开始[安装 Docker](../03_install/README.md),动手实践!
|
||||
|
||||
### 2.4.3 延伸阅读
|
||||
### 延伸阅读
|
||||
|
||||
- [获取镜像](../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):深入理解分层存储的技术原理
|
||||
- [启动容器](../05_container/5.1_run.md):详细的容器启动选项
|
||||
- [后台运行](../05_container/5.2_daemon.md):理解容器为什么会“立即退出”
|
||||
- [进入容器](../05_container/5.4_attach_exec.md):如何操作运行中的容器
|
||||
- [数据管理](../08_data/README.md):Volume 和数据持久化详解
|
||||
- [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):配置镜像加速
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -59,11 +59,8 @@ $ sudo apt install \
|
||||
```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
|
||||
|
||||
# 官方源
|
||||
# $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
```
|
||||
|
||||
然后,我们需要向 `sources.list` 中添加 Docker 软件源
|
||||
@@ -73,15 +70,10 @@ $ 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
|
||||
|
||||
# 官方源
|
||||
# $ 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。
|
||||
@@ -103,12 +95,11 @@ $ sudo apt install docker-ce docker-ce-cli containerd.io
|
||||
> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本
|
||||
|
||||
```bash
|
||||
## $ curl -fsSL test.docker.com -o get-docker.sh
|
||||
# $ 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
|
||||
|
||||
# $ sudo sh get-docker.sh --mirror AzureChinaCloud
|
||||
```
|
||||
|
||||
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。
|
||||
@@ -122,7 +113,12 @@ $ 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` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
|
||||
|
||||
> ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限**
|
||||
>
|
||||
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。
|
||||
> 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
|
||||
|
||||
建立 `docker` 组:
|
||||
|
||||
|
||||
@@ -48,11 +48,8 @@ $ sudo apt-get install \
|
||||
```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
|
||||
|
||||
# 官方源
|
||||
# $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
|
||||
```
|
||||
|
||||
然后,我们需要向 `sources.list` 中添加 Docker 软件源:
|
||||
@@ -64,15 +61,10 @@ $ 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
|
||||
|
||||
# 官方源
|
||||
# $ 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 改为 test。Debian11 可能不使用 `/etc/apt/keyrings/`,如 gpg 错误可以考虑更换为 `/etc/apt/trusted.gpg.d`,见 [issue 15727](https://github.com/docker/docs/issues/15727)。
|
||||
@@ -94,12 +86,11 @@ $ sudo apt-get install docker-ce docker-ce-cli containerd.io
|
||||
> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本
|
||||
|
||||
```bash
|
||||
## $ curl -fsSL test.docker.com -o get-docker.sh
|
||||
# $ 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
|
||||
|
||||
# $ sudo sh get-docker.sh --mirror AzureChinaCloud
|
||||
```
|
||||
|
||||
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。
|
||||
@@ -113,7 +104,12 @@ $ 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` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
|
||||
|
||||
> ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限**
|
||||
>
|
||||
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。
|
||||
> 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
|
||||
|
||||
建立 `docker` 组:
|
||||
|
||||
|
||||
@@ -54,14 +54,10 @@ $ sudo dnf config-manager \
|
||||
|
||||
$ 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 请使用以下命令:
|
||||
@@ -102,12 +98,11 @@ $ sudo dnf -y install docker-ce-18.06.1.ce
|
||||
> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本
|
||||
|
||||
```bash
|
||||
## $ curl -fsSL test.docker.com -o get-docker.sh
|
||||
# $ 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
|
||||
|
||||
# $ sudo sh get-docker.sh --mirror AzureChinaCloud
|
||||
```
|
||||
|
||||
执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 最新稳定 (stable) 版本安装在系统中。
|
||||
@@ -121,7 +116,12 @@ $ sudo systemctl start 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` 用户组。
|
||||
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
|
||||
|
||||
> ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限**
|
||||
>
|
||||
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。
|
||||
> 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
|
||||
|
||||
建立 `docker` 组:
|
||||
|
||||
|
||||
@@ -56,14 +56,10 @@ $ sudo dnf config-manager \
|
||||
|
||||
$ 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 dnf config-manager \
|
||||
# --add-repo \
|
||||
# https://download.docker.com/linux/centos/docker-ce.repo
|
||||
```
|
||||
|
||||
如果需要测试版本的 Docker 请执行以下命令:
|
||||
@@ -126,7 +122,12 @@ $ sudo systemctl start 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` 用户组。
|
||||
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
|
||||
|
||||
> ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限**
|
||||
>
|
||||
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。
|
||||
> 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
|
||||
|
||||
建立 `docker` 组:
|
||||
|
||||
|
||||
@@ -44,15 +44,10 @@ $ 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
|
||||
|
||||
# 官方源
|
||||
# $ 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 软件源:
|
||||
@@ -62,15 +57,10 @@ $ 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
|
||||
|
||||
# 官方源
|
||||
# $ 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。
|
||||
@@ -140,7 +130,12 @@ $ 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` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
|
||||
|
||||
> ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限**
|
||||
>
|
||||
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。
|
||||
> 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
|
||||
|
||||
建立 `docker` 组:
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
## 3.6 Linux 离线安装
|
||||
|
||||
\[TOC]
|
||||
|
||||
生产环境中一般都是没有公网资源的,本文介绍如何在生产服务器上离线部署 `Docker`
|
||||
|
||||
括号内的字母表示该操作需要在哪些服务器上执行
|
||||
|
||||

|
||||
|
||||
### 3.6.1 概述
|
||||
|
||||
### 3.6.2 CentOS/Rocky/AlmaLinux 离线安装 Docker
|
||||
### 3.6.1 CentOS/Rocky/AlmaLinux 离线安装 Docker
|
||||
|
||||
在无法连接外网的安全环境中,离线安装是唯一的选择。本节介绍如何在 RHEL 系发行版中进行离线安装。
|
||||
|
||||
@@ -18,7 +14,7 @@
|
||||
|
||||
#### YUM 本地文件安装 (推荐)
|
||||
|
||||
推荐这种方式,是因为在生产环境种一般会选定某个指定的文档软件版本使用。
|
||||
推荐这种方式,是因为在生产环境中一般会选定某个指定的文档软件版本使用。
|
||||
|
||||
##### 查询可用的软件版本
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### 3.7.1 系统要求
|
||||
|
||||
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonora 14.0 或更高版本,建议升级到最新版本的 macOS。
|
||||
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonoma 14.0 或更高版本,建议升级到最新版本的 macOS。
|
||||
|
||||
### 3.7.2 安装
|
||||
|
||||
@@ -27,13 +27,13 @@ $ brew install --cask docker
|
||||
|
||||
如同 macOS 其它软件一样,安装也非常简单,双击下载的 `.dmg` 文件,然后将那只叫 [Moby](https://www.docker.com/blog/call-me-moby-dock/) 的鲸鱼图标拖拽到 `Application` 文件夹即可 (其间需要输入用户密码)。
|
||||
|
||||

|
||||

|
||||
|
||||
### 3.7.3 运行
|
||||
|
||||
从应用中找到 Docker 图标并点击运行。
|
||||
|
||||

|
||||

|
||||
|
||||
运行之后,会在右上角菜单栏看到多了一个鲸鱼图标,这个图标表明了 Docker 的运行状态。
|
||||
|
||||
@@ -47,7 +47,7 @@ $ brew install --cask docker
|
||||
|
||||
```bash
|
||||
$ docker --version
|
||||
Docker version 26.1.1, build 4cf5afa
|
||||
Docker version 27.0.3, build 7d4bcd8
|
||||
```
|
||||
|
||||
如果 `docker version`、`docker info` 都正常的话,可以尝试运行一个 [Nginx 服务器](https://hub.docker.com/_/nginx/):
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
下载好之后双击 `Docker Desktop Installer.exe` 开始安装。
|
||||
|
||||
**使用** [**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/) **安装**
|
||||
**使用**[**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/)**安装**
|
||||
|
||||
```powershell
|
||||
$ winget install Docker.DockerDesktop
|
||||
|
||||
Binary file not shown.
@@ -11,7 +11,7 @@ Docker 支持在多种平台上安装和使用,选择合适的安装方式是
|
||||
| **Raspberry Pi** | 官方安装脚本 | 支持 ARM 架构 |
|
||||
| **离线环境** | 二进制包安装 | 适用于无法联网的服务器 |
|
||||
|
||||
### 3.11.1 安装后验证
|
||||
### 安装后验证
|
||||
|
||||
安装完成后,运行以下命令验证 Docker 是否正常工作:
|
||||
|
||||
@@ -20,8 +20,11 @@ $ 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):官方镜像仓库
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -171,9 +171,6 @@ root@e7009c6ce357:/# exit
|
||||
```bash
|
||||
$ sudo systemctl restart docker # Linux
|
||||
## 或在 Docker Desktop 中重启
|
||||
|
||||
## 或在 Docker Desktop 中重启
|
||||
|
||||
```
|
||||
|
||||
详见[镜像加速器](../03_install/3.9_mirror.md)章节。
|
||||
|
||||
@@ -204,11 +204,10 @@ ubuntu latest ca2b0f26964c # 同一个镜像
|
||||
$ docker rmi ubuntu:24.04
|
||||
Untagged: ubuntu:24.04
|
||||
## 只是移除标签,镜像仍存在(因为还有 ubuntu:latest 指向它)
|
||||
```
|
||||
|
||||
当同一个镜像有多个标签时,`docker rmi` 只是删除指定的标签,不会删除镜像本身。
|
||||
|
||||
```
|
||||
|
||||
#### 原因三:被其他镜像依赖 (中间层)
|
||||
|
||||
```bash
|
||||
|
||||
@@ -120,9 +120,7 @@ docker run --name web2 -d -p 81:80 nginx:v2
|
||||
|
||||
至此,我们第一次完成了定制镜像,使用的是 `docker commit` 命令,手动操作给旧的镜像添加了新的一层,形成新的镜像,对镜像多层存储应该有了更直观的感觉。
|
||||
|
||||
### 4.4.1 概述
|
||||
|
||||
### 4.4.2 慎用 `docker commit`
|
||||
### 4.4.1 慎用 `docker commit`
|
||||
|
||||
使用 `docker commit` 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Dockerfile 是一个文本文件,其内包含了一条条的 **指令 (Instruc
|
||||
|
||||
### 4.5.1 使用 docker init 快速创建 (推荐)
|
||||
|
||||
Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、。dockerignore 和 compose.yaml 文件:
|
||||
Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、.dockerignore 和 compose.yaml 文件:
|
||||
|
||||
```bash
|
||||
$ docker init
|
||||
@@ -64,7 +64,7 @@ FROM scratch
|
||||
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
```
|
||||
|
||||
* *exec* 格式:`RUN ["可执行文件", "参数1", "参数2"]`,这更像是函数调用中的格式。
|
||||
* *exec* 格式:`RUN [“可执行文件”, “参数1”, “参数2”]`,这更像是函数调用中的格式。
|
||||
|
||||
Dockerfile 中每一个指令都会建立一层,`RUN` 也不例外。每一个 `RUN` 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,`commit` 这一层的修改,构成新的镜像。
|
||||
|
||||
|
||||
@@ -15,3 +15,8 @@ Docker 运行容器前需要本地存在对应的镜像,如果本地不存在
|
||||
* [使用 Dockerfile 定制镜像](4.5_build.md)
|
||||
* [其它制作镜像的方式](4.6_other.md)
|
||||
* [镜像的实现原理](4.7_internal.md)
|
||||
|
||||
> **版本提示:镜像存储后端的变迁**
|
||||
>
|
||||
> 在 Docker Engine v29 及后续版本中,Docker 全新安装默认启用了 **containerd image store**(替代了传统的 classic store)。这一底层架构级别的变迁,意味着 Docker 解锁了对 OCI Image Index 和 Attestations (例如原生的 provenance 来源证明与 SBOM 软件物料清单)的全量本地支持。
|
||||
> 读者在执行类似 `docker buildx build --provenance=mode=min --sbom=true` 甚至使用后续审查工具(如 `docker buildx imagetools inspect`)时,其元数据能够与镜像数据一并完好地管理于本地存储系统中,为供应链安全验证补齐了最后一块拼图。
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
## 本章小结
|
||||
|
||||
本章介绍了 Docker 镜像的获取、列出、删除以及构建方式。
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 拉取镜像 | `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` |
|
||||
@@ -23,24 +15,22 @@
|
||||
| 显示摘要 | `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.1_pull.md):从 Registry 拉取镜像
|
||||
- [列出镜像](4.2_list.md):查看和过滤镜像
|
||||
- [删除镜像](4.3_rm.md):清理本地镜像
|
||||
- [镜像加速器](../03_install/3.9_mirror.md):加速镜像下载
|
||||
- [Docker Hub](../06_repository/6.1_dockerhub.md):官方镜像仓库
|
||||
- [镜像](../02_basic_concept/2.1_image.md):理解镜像概念
|
||||
- [删除容器](../05_container/5.6_rm.md):清理容器
|
||||
- [数据卷](../08_data/8.1_volume.md):清理数据卷
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -1,55 +1,33 @@
|
||||
## 本章小结
|
||||
|
||||
本章介绍了 Docker 容器的启动、停止、进入和删除等核心操作。
|
||||
|
||||
| 操作 | 命令 | 说明 |
|
||||
|------|------|------|
|
||||
| 新建并运行 | `docker run` | 最常用的启动方式 |
|
||||
| 交互式启动 | `docker run -it` | 用于调试或临时操作 |
|
||||
| 后台运行 | `docker run -d` | 用于服务类应用 |
|
||||
| 启动已停止的容器 | `docker start` | 重用已有容器 |
|
||||
| 优雅停止 | `docker stop` | 先 SIGTERM,超时后 SIGKILL |
|
||||
| 强制停止 | `docker kill` | 直接 SIGKILL |
|
||||
| 重启 | `docker restart` | 停止后立即启动 |
|
||||
| 停止全部 | `docker stop $(docker ps -q)` | 停止所有运行中容器 |
|
||||
| 进入容器调试 | `docker exec -it 容器名 bash` | 推荐方式 |
|
||||
| 执行单条命令 | `docker exec 容器名 命令` | 不进入交互模式 |
|
||||
| 查看主进程输出 | `docker attach 容器名` | 慎用,退出可能停止容器 |
|
||||
| 删除已停止容器 | `docker rm 容器名` | 需先停止 |
|
||||
| 强制删除运行中容器 | `docker rm -f 容器名` | 直接删除 |
|
||||
| 删除容器及匿名卷 | `docker rm -v 容器名` | 同时清理匿名卷 |
|
||||
| 清理所有已停止容器 | `docker container prune` | 批量清理 |
|
||||
|
||||
### 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):数据卷管理
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -45,7 +45,8 @@ $ docker pull nginx:alpine
|
||||
|
||||
```bash
|
||||
$ docker login
|
||||
## 输入用户名和密码
|
||||
## 默认情况下,不带其它参数进行 docker login 会自动走 Device Code Web Flow (浏览器认证)
|
||||
## 若在非交互 CI 环境中,推荐结合 --username 与 --password-stdin 参数使用
|
||||
|
||||
...
|
||||
```
|
||||
@@ -76,10 +77,18 @@ $ docker push username/myapp:v1
|
||||
| **免费账户** (已登录) | 每 6 小时 200 次请求 |
|
||||
| **Pro/Team 账户** | 无限制 |
|
||||
|
||||
> **提示**:如果在 CI/CD 环境中遇到 `toomanyrequests` 错误,建议:
|
||||
> 1. 在 CI 中配置 `docker login`
|
||||
> 2. 使用国内镜像加速器
|
||||
> 3. 搭建私有仓库代理
|
||||
#### 滥用限流
|
||||
|
||||
除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外,Docker Hub 对所有用户(包含已认证及付费用户)还实施了 **滥用保护限流 (Abuse Rate Limiting)**。它是根据网络出口 IP (IPv4 或 IPv6 /64 子网) 计算整体请求频率,阈值动态触发(通常为每分钟数千级别请求)。
|
||||
|
||||
**两类的差异与排查方法**:
|
||||
- **Pull Rate Limit**:针对拉取量达到上限。报错返回 `429 Too Many Requests`,并且 HTTP 返回体/CLI 错误提示中会带有明确的 `toomanyrequests: You have reached your pull rate limit` 提示,常附有账户升级链接。
|
||||
- **Abuse Rate Limit**:防范接口频率打击。报错仅返回简化的 `429 Too Many Requests`。这一限流不分付费与否,常发生在“多终端共享出口 IP”的企业局域网或者第三方云 CI 服务(如 GitHub Actions 等)中,即使你已正常配置 `docker login` 也依旧可能触发。
|
||||
|
||||
> **提示**:如果在 CI/CD 等环境遇到 429 错误,建议:
|
||||
> 1. 先甄别具体是哪类限流:普通的 pull rate limit 只要在 CI 中配置 `docker login` (并使用有效账号) 就能解除匿名限制。
|
||||
> 2. 如果是 Abuse 频控导致,应考虑搭建私有仓库作为拉取缓存代理 (Registry pull-through cache),避免频繁直接请求官方 Hub。
|
||||
> 3. 使用国内镜像加速器。
|
||||
|
||||
---
|
||||
|
||||
@@ -94,13 +103,13 @@ $ docker push username/myapp:v1
|
||||
|
||||
#### 2. 使用 Access Token
|
||||
|
||||
不要在脚本或 CI/CD 中直接使用登录密码。
|
||||
> **⚠️ 警告**:绝不要在脚本或 CI/CD 系统中,直接使用 `-p` 参数传递密码或 Token (类似 `docker login -p xxx`)!这会导致凭证直接暴露在系统的命令历史、进程列表和终端输出中。
|
||||
|
||||
1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token。
|
||||
2. 使用 Token 作为密码登录:
|
||||
1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token (PAT)。
|
||||
2. 将 Token 通过标准输入 (stdin) 安全传递给 Docker:
|
||||
|
||||
```bash
|
||||
$ docker login -u username -p dckr_pat_xxxxxxx
|
||||
$ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin
|
||||
```
|
||||
|
||||
#### 3. 关注镜像漏洞
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -5,3 +5,10 @@
|
||||
一个容易混淆的概念是注册服务器 (`Registry`)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 `docker.io/ubuntu` 来说,`docker.io` 是注册服务器地址,`ubuntu` 是仓库名。
|
||||
|
||||
大部分时候,并不需要严格区分这两者的概念。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [Docker Hub](6.1_dockerhub.md)
|
||||
* [私有仓库](6.2_registry.md)
|
||||
* [私有仓库高级配置](6.3_registry_auth.md)
|
||||
* [Nexus 3](6.4_nexus3_registry.md)
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
## 本章小结
|
||||
|
||||
本章介绍了 Docker Hub 的使用、私有仓库的搭建以及 Nexus 3 等企业级方案。
|
||||
|
||||
| 功能 | 说明 |
|
||||
|------|------|
|
||||
| **官方镜像** | 优先使用的基础镜像 |
|
||||
| **拉取限制** | 匿名 100次/6h,登录 200次/6h |
|
||||
| **拉取限制** | 匿名 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):加速下载
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -1,7 +1,36 @@
|
||||
## 7.16 参考文档
|
||||
|
||||
* `Dockerfile` 官方文档:https://docs.docker.com/engine/reference/builder/
|
||||
### 官方文档
|
||||
|
||||
* `Dockerfile` 最佳实践文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
|
||||
* `Dockerfile` 官方参考手册:https://docs.docker.com/engine/reference/builder/
|
||||
|
||||
* `Docker` 官方镜像 `Dockerfile`:https://github.com/docker-library/docs
|
||||
* `Dockerfile` 最佳实践指南:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
|
||||
|
||||
* `Docker` 官方镜像 `Dockerfile` 库:https://github.com/docker-library/docs
|
||||
|
||||
### 常用指令总结
|
||||
|
||||
Dockerfile 中的常用指令包括:
|
||||
|
||||
- **FROM**: 指定基础镜像,必须是第一条指令
|
||||
- **RUN**: 在镜像中执行命令,用于安装软件包等
|
||||
- **WORKDIR**: 设置工作目录
|
||||
- **COPY/ADD**: 复制文件到镜像中
|
||||
- **EXPOSE**: 声明容器监听的端口
|
||||
- **ENV**: 设置环境变量
|
||||
- **ENTRYPOINT**: 容器启动时的入口点
|
||||
- **CMD**: 容器默认执行的命令
|
||||
|
||||
### 最佳实践建议
|
||||
|
||||
1. 使用具体的基础镜像版本标签而非 latest
|
||||
2. 最小化镜像层数,合并 RUN 指令
|
||||
3. 使用 .dockerignore 文件排除不必要的文件
|
||||
4. 安装必要的软件包后清理缓存
|
||||
5. 使用多阶段构建减小最终镜像体积
|
||||
6. 避免以 root 身份运行容器应用
|
||||
|
||||
### 相关资源
|
||||
|
||||
- Docker 官方镜像库:https://hub.docker.com/
|
||||
- Docker 镜像构建最佳实践:https://docs.docker.com/build/building/best-practices/
|
||||
|
||||
@@ -118,7 +118,7 @@ go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
|
||||
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
```
|
||||
|
||||
## 7.17 使用多阶段构建
|
||||
### 7.17.3 使用多阶段构建
|
||||
|
||||
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:
|
||||
|
||||
@@ -167,7 +167,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
|
||||
很明显使用多阶段构建的镜像体积小,同时也完美解决了上边提到的问题。
|
||||
|
||||
### 7.17.1 只构建某一阶段的镜像
|
||||
### 7.17.4 只构建某一阶段的镜像
|
||||
|
||||
我们可以使用 `as` 来为某一阶段命名,例如
|
||||
|
||||
@@ -181,7 +181,7 @@ FROM golang:alpine as builder
|
||||
$ docker build --target builder -t username/imagename:tag .
|
||||
```
|
||||
|
||||
### 7.17.2 构建时从其他镜像复制文件
|
||||
### 7.17.5 构建时从其他镜像复制文件
|
||||
|
||||
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
|
||||
|
||||
|
||||
@@ -268,3 +268,7 @@ COPY . .
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **🔥 踩坑实录**
|
||||
>
|
||||
> 某公司在优化 Node.js 应用的 Docker 镜像时,发现构建出来的镜像体积超过了 2GB,远远超过生产部署的需求。排查发现,Dockerfile 中使用了 `COPY . .` 把整个构建上下文复制进镜像,导致 `node_modules/`、`.git/` 目录和大量测试数据全部被打包进镜像。最初他们没有创建 `.dockerignore` 文件,默认会复制所有文件。解决方案是添加一个 `.dockerignore` 文件,排除这些不必要的目录,使镜像缩小到了 200MB。这个教训深刻地说明了:`.dockerignore` 和 `.gitignore` 一样重要,应该在项目初始化时就创建,而不是等到出现问题时才想起来。建议的标准做法是先复制 `package.json` 和 `package-lock.json` 安装依赖,再复制应用代码,同时在 `.dockerignore` 中明确列出 `node_modules`、`.git`、test 目录等。
|
||||
|
||||
@@ -14,9 +14,9 @@ CMD 有三种格式:
|
||||
|
||||
| 格式 | 语法 | 推荐程度 |
|
||||
|------|------|---------|
|
||||
| **exec 格式**| `CMD ["可执行文件", "参数1", "参数2"]` | ✅**推荐** |
|
||||
| **exec 格式**| `CMD [“可执行文件”, “参数1”, “参数2”]` | ✅**推荐** |
|
||||
| **shell 格式** | `CMD 命令 参数1 参数2` | ⚠️ 简单场景 |
|
||||
| **参数格式** | `CMD ["参数1", "参数2"]` | 配合 ENTRYPOINT |
|
||||
| **参数格式** | `CMD [“参数1”, “参数2”]` | 配合 ENTRYPOINT |
|
||||
|
||||
#### exec 格式 (推荐)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
| 格式 | 语法 | 推荐程度 |
|
||||
|------|------|---------|
|
||||
| **exec 格式**| `ENTRYPOINT ["可执行文件", "参数1"]` | ✅**推荐** |
|
||||
| **exec 格式**| `ENTRYPOINT [“可执行文件”, “参数1”]` | ✅**推荐** |
|
||||
| **shell 格式** | `ENTRYPOINT 命令 参数` | ⚠️ 不推荐 |
|
||||
|
||||
```docker
|
||||
|
||||
@@ -103,7 +103,7 @@ VOLUME /data
|
||||
RUN echo "hello" > /data/test.txt
|
||||
```
|
||||
|
||||
**原因**:VOLUME 指令之后,Docker 将该目录视为外部挂载点,不再记录对它的修改。
|
||||
**原因**:在构建过程中,VOLUME 指令会为该目录创建一个临时的匿名卷。后续 RUN 指令对该目录的写入实际发生在这个临时卷中,而非镜像层。当该 RUN 指令结束后,临时卷被丢弃,因此写入的内容不会保存到最终镜像中。注意:这与容器运行时创建的匿名卷是不同的——运行时创建的卷会在容器生命周期内持续存在。
|
||||
|
||||
#### 正确做法
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## 什么是 Dockerfile
|
||||
|
||||
Dockerfile 是一个文本文件,其內包含了一条条的 **指令 (Instruction)**,每一条指令构建一层,therefore 每一条指令的内容,就是描述该层应当如何构建。
|
||||
Dockerfile 是一个文本文件,其内包含了一条条的 **指令 (Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
|
||||
|
||||
在[第四章](../04_image/README.md)中,我们通过 `docker commit` 学习了镜像的构成。但是,手动 `commit` 只能作为临时修补,并不适合作为生产环境镜像的构建方式。
|
||||
|
||||
@@ -21,6 +21,7 @@ Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像
|
||||
|
||||
本章将详细讲解 Dockerfile 中的各个指令:
|
||||
|
||||
* [RUN 执行命令](7.1_run.md)
|
||||
* [COPY 复制文件](7.2_copy.md)
|
||||
* [ADD 更高级的复制文件](7.3_add.md)
|
||||
* [CMD 容器启动命令](7.4_cmd.md)
|
||||
@@ -35,7 +36,15 @@ Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像
|
||||
* [ONBUILD 为他人作嫁衣裳](7.13_onbuild.md)
|
||||
* [LABEL 为镜像添加元数据](7.14_label.md)
|
||||
* [SHELL 指令](7.15_shell.md)
|
||||
* [RUN 执行命令](7.1_run.md)
|
||||
|
||||
### 高级特性
|
||||
|
||||
本章还将介绍 Dockerfile 的高级特性:
|
||||
|
||||
* [多阶段构建](7.17_multistage_builds.md)
|
||||
* [多阶段构建实战:Laravel 应用](7.18_multistage_builds_laravel.md)
|
||||
|
||||
### 参考与最佳实践
|
||||
|
||||
此外,我们还将介绍 Dockerfile 的最佳实践和常见问题。
|
||||
|
||||
|
||||
@@ -1,208 +1,33 @@
|
||||
## 本章小结
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 设置后续指令的工作目录 |
|
||||
| **语法** | `WORKDIR /path` |
|
||||
| **自动创建** | 目录不存在会自动创建 |
|
||||
| **持久性** | 影响后续所有指令,直到下次 WORKDIR |
|
||||
| **不要用** | `RUN cd /path` (无效)|
|
||||
本章详细介绍了 Dockerfile 的所有核心指令,以下是各指令要点的速查表。
|
||||
|
||||
### 7.19.1 延伸阅读
|
||||
| 指令 | 作用 | 关键要点 |
|
||||
|------|------|---------|
|
||||
| **FROM** | 指定基础镜像 | 必须是第一条指令 |
|
||||
| **RUN** | 在新层执行命令 | 合并命令、清理缓存以减小体积 |
|
||||
| **COPY** | 复制文件 | 优先使用,支持 `--from` |
|
||||
| **ADD** | 更高级的复制 | 自动解压 tar,不推荐用于下载 |
|
||||
| **CMD** | 容器启动默认命令 | 可被 `docker run` 参数覆盖 |
|
||||
| **ENTRYPOINT** | 容器入口点 | 固定启动命令,CMD 作为默认参数 |
|
||||
| **ENV** | 设置环境变量 | 构建时 + 运行时均生效 |
|
||||
| **ARG** | 构建参数 | 仅构建时生效,FROM 后需重新声明 |
|
||||
| **VOLUME** | 定义匿名卷 | VOLUME 之后的修改会丢失 |
|
||||
| **EXPOSE** | 声明端口 | 仅文档作用,不自动映射 |
|
||||
| **WORKDIR** | 指定工作目录 | 替代 `RUN cd`,目录不存在会自动创建 |
|
||||
| **USER** | 指定运行用户 | 用户必须已存在,推荐 gosu |
|
||||
| **HEALTHCHECK** | 健康检查 | 支持 starting/healthy/unhealthy 状态 |
|
||||
| **ONBUILD** | 延迟执行指令 | 只继承一次,不可级联 |
|
||||
| **LABEL** | 添加元数据 | 推荐 OCI 标准标签,替代 MAINTAINER |
|
||||
| **SHELL** | 更改默认 shell | 推荐 `["/bin/bash", "-o", "pipefail", "-c"]` |
|
||||
|
||||
- [COPY 复制文件](7.2_copy.md):文件复制
|
||||
- [RUN 执行命令](../04_image/4.5_build.md):执行构建命令
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 编写指南
|
||||
### 延伸阅读
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 切换后续指令的执行用户 |
|
||||
| **语法** | `USER username` 或 `USER UID:GID` |
|
||||
| **前提** | 用户必须已存在 |
|
||||
| **运行时覆盖** | `docker run -u` |
|
||||
| **切换工具** | 使用 gosu,不用 su/sudo |
|
||||
|
||||
### 7.19.2 延伸阅读
|
||||
|
||||
- [安全](../18_security/README.md):容器安全实践
|
||||
- [ENTRYPOINT](7.5_entrypoint.md):入口脚本中的用户切换
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 安全
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 检测容器应用是否真实可用 |
|
||||
| **命令** | `HEALTHCHECK [选项] CMD command` |
|
||||
| **状态** | starting, healthy, unhealthy |
|
||||
| **Compose** | 支持 `condition: service_healthy` 依赖 |
|
||||
| **注意** | 避免副作用,节省资源 |
|
||||
|
||||
### 7.19.3 延伸阅读
|
||||
|
||||
- [CMD 容器启动命令](7.4_cmd.md):启动主进程
|
||||
- [Compose 模板文件](../11_compose/11.5_compose_file.md):Compose 中的健康检查
|
||||
- [Docker 调试](../appendix/debug.md):容器排障
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 定义在子镜像构建时执行的指令 |
|
||||
| **语法** | `ONBUILD INSTRUCTION` |
|
||||
| **适用** | 基础架构镜像 (Node, Python, Go 等)|
|
||||
| **限制** | 只继承一次,不可级联 |
|
||||
| **规范** | 建议使用 `-onbuild` 标签后缀 |
|
||||
|
||||
### 7.19.4 延伸阅读
|
||||
|
||||
- [COPY 指令](7.2_copy.md):文件复制
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md):基础镜像设计
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 添加 key-value 元数据 |
|
||||
| **语法** | `LABEL k=v k=v ...` |
|
||||
| **规范** | 推荐使用 OCI 标准标签 |
|
||||
| **弃用** | 不要再使用 `MAINTAINER` |
|
||||
| **查看** | `docker inspect` |
|
||||
|
||||
### 7.19.5 延伸阅读
|
||||
|
||||
- [OCI 标签规范](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md)
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 更改 RUN/CMD/ENTRYPOINT 的默认 shell |
|
||||
| **Linux 默认** | `["/bin/sh", "-c"]` |
|
||||
| **Windows 默认** | `["cmd", "/S", "/C"]` |
|
||||
| **推荐用法** | `SHELL ["/bin/bash", "-o", "pipefail", "-c"]` |
|
||||
| **影响范围** | 后续所有使用 shell 格式的指令 |
|
||||
|
||||
### 7.19.6 延伸阅读
|
||||
|
||||
- [RUN 指令](../04_image/4.5_build.md):执行命令
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md):错误处理与调试
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 在新层执行命令 |
|
||||
| **原则** | 合并命令,清理缓存 |
|
||||
| **格式** | Shell (常用) vs Exec |
|
||||
| **陷阱** | `cd` 不持久,环境变量不持久 |
|
||||
| **进阶** | 使用 Cache Mount 加速构建 |
|
||||
|
||||
### 7.19.7 延伸阅读
|
||||
|
||||
- [CMD 容器启动命令](7.4_cmd.md):容器启动时的命令
|
||||
- [WORKDIR 指定工作目录](7.10_workdir.md):改变目录
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md)
|
||||
|
||||
| 操作 | 示例 |
|
||||
|------|------|
|
||||
| 复制文件 | `COPY app.js /app/` |
|
||||
| 复制多个文件 | `COPY *.json /app/` |
|
||||
| 复制目录内容 | `COPY src/ /app/src/` |
|
||||
| 修改所有者 | `COPY --chown=node:node . /app/` |
|
||||
| 从构建阶段复制 | `COPY --from=builder /app/dist ./` |
|
||||
|
||||
### 7.19.8 延伸阅读
|
||||
|
||||
- [ADD 指令](7.3_add.md):复制和解压
|
||||
- [WORKDIR 指令](7.10_workdir.md):设置工作目录
|
||||
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md):Dockerfile 入门
|
||||
- [多阶段构建](7.17_multistage_builds.md):优化镜像大小
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 编写指南
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md):编写指南
|
||||
- [安全](../18_security/README.md):容器安全实践
|
||||
- [Compose 模板文件](../11_compose/11.5_compose_file.md):Compose 中的配置
|
||||
---
|
||||
|
||||
| 场景 | 推荐指令 |
|
||||
|------|---------|
|
||||
| 复制普通文件 | `COPY` |
|
||||
| 复制目录 | `COPY` |
|
||||
| 自动解压 tar | `ADD` |
|
||||
| 从 URL 下载 | `RUN curl` |
|
||||
| 保持 tar 不解压 | `COPY` |
|
||||
|
||||
### 7.19.9 延伸阅读
|
||||
|
||||
- [COPY 复制文件](7.2_copy.md):基本复制操作
|
||||
- [多阶段构建](7.17_multistage_builds.md):减少镜像体积
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 编写指南
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 指定容器启动时的默认命令 |
|
||||
| **推荐格式** | exec 格式 `CMD ["程序", "参数"]` |
|
||||
| **覆盖方式** | `docker run image 新命令` |
|
||||
| **与 ENTRYPOINT** | CMD 作为 ENTRYPOINT 的默认参数 |
|
||||
| **核心原则** | 应用必须在前台运行 |
|
||||
|
||||
### 7.19.10 延伸阅读
|
||||
|
||||
- [ENTRYPOINT 入口点](7.5_entrypoint.md):固定的启动命令
|
||||
- [后台运行](../05_container/5.2_daemon.md):容器前台/后台概念
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 编写指南
|
||||
|
||||
| ENTRYPOINT | CMD | 适用场景 |
|
||||
|------------|-----|---------|
|
||||
| ✓ | ✗ | 镜像作为固定命令使用 |
|
||||
| ✗ | ✓ | 简单的默认命令 |
|
||||
| ✓ | ✓ | **推荐**:固定命令 + 可配置参数 |
|
||||
|
||||
### 7.19.11 延伸阅读
|
||||
|
||||
- [CMD 容器启动命令](7.4_cmd.md):默认命令
|
||||
- [最佳实践](../appendix/best_practices.md):启动命令设计
|
||||
- [后台运行](../05_container/5.2_daemon.md):前台/后台概念
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **语法** | `ENV KEY=value` |
|
||||
| **作用范围** | 构建时 + 运行时 |
|
||||
| **覆盖方式** | `docker run -e KEY=value` |
|
||||
| **与 ARG** | ARG 仅构建时,ENV 持久化到运行时 |
|
||||
| **安全** | 不要存储敏感信息 |
|
||||
|
||||
### 7.19.12 延伸阅读
|
||||
|
||||
- [ARG 构建参数](7.7_arg.md):构建时变量
|
||||
- [Compose 环境变量](../11_compose/11.5_compose_file.md):Compose 中的环境变量
|
||||
- [最佳实践](../appendix/best_practices.md):Dockerfile 编写指南
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 定义构建时变量 |
|
||||
| **语法** | `ARG NAME=value` |
|
||||
| **覆盖** | `docker build --build-arg NAME=value` |
|
||||
| **作用域** | FROM 之后需要重新声明 |
|
||||
| **vs ENV** | ARG 仅构建时,ENV 构建+运行时 |
|
||||
| **安全** | 不要存储敏感信息 |
|
||||
|
||||
### 7.19.13 延伸阅读
|
||||
|
||||
- [ENV 设置环境变量](7.6_env.md):运行时环境变量
|
||||
- [FROM 指令](../04_image/4.5_build.md):基础镜像指定
|
||||
- [多阶段构建](7.17_multistage_builds.md):复杂构建场景
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 创建挂载点,标记为外部卷 |
|
||||
| **语法** | `VOLUME /path` |
|
||||
| **默认行为** | 自动创建匿名卷 |
|
||||
| **覆盖方式** | `docker run -v name:/path` |
|
||||
| **注意** | VOLUME 之后的修改会丢失 |
|
||||
|
||||
### 7.19.14 延伸阅读
|
||||
|
||||
- [数据卷](../08_data/8.1_volume.md):卷的管理和使用
|
||||
- [挂载主机目录](../08_data/8.2_bind-mounts.md):Bind Mount
|
||||
- [Compose 数据管理](../11_compose/11.5_compose_file.md):Compose 中的卷配置
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 声明容器提供服务的端口 (文档)|
|
||||
| **不会** | 自动映射端口或开放外部访问 |
|
||||
| **配合** | `docker run -P` 自动映射 |
|
||||
| **外部访问** | 需要 `-p 宿主机端口:容器端口` |
|
||||
| **语法** | `EXPOSE 80` 或 `EXPOSE 80/tcp` |
|
||||
|
||||
### 7.19.15 延伸阅读
|
||||
|
||||
- [网络配置](../09_network/README.md):Docker 网络详解
|
||||
- [端口映射](../09_network/9.5_port_mapping.md):-p 参数详解
|
||||
- [Compose 端口](../11_compose/11.5_compose_file.md):Compose 中的端口配置
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -138,8 +138,11 @@ $ docker run -d \
|
||||
| 特性 | --mount | -v |
|
||||
|------|---------|-----|
|
||||
| 语法 | 键值对,更清晰 | 冒号分隔,更简洁 |
|
||||
| 自动创建卷 | source 不存在会报错 | 自动创建 |
|
||||
| 推荐程度 | ✅ 推荐 (更明确)| 常用 (更简洁)|
|
||||
| **数据卷 (Volume)** 挂载行为 | 卷不存在会自动创建,与 `-v` 结果一致 | 卷不存在会自动创建 |
|
||||
| **绑定挂载 (Bind Mount)** 行为 | ⭐**宿主机路径不存在会报错**,不会自动创建 | 宿主机路径不存在会 **自动创建为目录** |
|
||||
| 推荐程度 | ✅ 推荐 (更明确安全,避免误创建)| 常用 (更简洁)|
|
||||
|
||||
> **提示**:官方更推荐使用 `--mount`。除了语法格式可读性更好之外,最重要的行为差异发生在 **绑定挂载 (Bind Mount)** 时:如果挂载的宿主机源路径尚未存在,`-v` 会擅自将其自动创建为一个空目录;而 `--mount` 则会严格检查并直接报错。这能有效避免因路径拼写错误而在宿主机上留下垃圾目录(以及导致的容器访问空目录问题)。而对于本节的 **数据卷 (Volume)** 挂载而言,两者在目标指定的卷不存在时皆会自动创建卷,产生的结果是 **完全一致** 的。
|
||||
|
||||
#### 只读挂载
|
||||
|
||||
|
||||
@@ -7,18 +7,24 @@ Bind Mount (绑定挂载) 将 **宿主机的目录或文件** 直接挂载到容
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Host ["宿主机"]
|
||||
direction TB
|
||||
Dir1["/home/user/code/<br/>├── index.html<br/>├── style.css<br/>└── app.js"]
|
||||
Dir1["/home/user/code/"]
|
||||
end
|
||||
|
||||
subgraph Container ["容器"]
|
||||
direction TB
|
||||
Dir2["/usr/share/nginx/html/<br/>(同一份文件)"]
|
||||
Dir2["/usr/share/nginx/html/"]
|
||||
end
|
||||
|
||||
Dir1 <-->|Bind Mount| Dir2
|
||||
```
|
||||
|
||||
目录结构(同一份文件):
|
||||
```text
|
||||
/home/user/code/ (或 /usr/share/nginx/html/)
|
||||
├── index.html
|
||||
├── style.css
|
||||
└── app.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8.2.2 Bind Mount vs Volume
|
||||
@@ -68,9 +74,11 @@ $ docker run -d \
|
||||
| 特性 | --mount | -v |
|
||||
|------|---------|-----|
|
||||
| 语法 | 键值对,更清晰 | 冒号分隔,更简洁 |
|
||||
| 路径不存在时 | 报错 | 自动创建目录 |
|
||||
| 路径不存在时 | 直接报错 (Fail Fast) | 静默自动创建 **目录** |
|
||||
| 推荐程度 | ✅ 推荐 | 常用 |
|
||||
|
||||
> **⚠️ 陷阱**:如果不小心挂载了一个不存在的宿主机路径,使用 `-v` 会在宿主机上静默创建一个 **空目录**(即使你本来想挂载的是一个文件),这常常会导致权限错误或应用无法正常读取。这也正是为什么 Docker 官方更推荐使用 `--mount` 的原因:它会遵循“Fail Fast”原则直接报错,避免弄巧成拙。
|
||||
|
||||
---
|
||||
|
||||
### 8.2.4 使用场景
|
||||
|
||||
@@ -10,16 +10,20 @@
|
||||
|
||||
### 8.3.2 基本用法
|
||||
|
||||
```bash
|
||||
$ docker run --tmpfs /run:rw,noexec,nosuid,size=64m nginx
|
||||
```
|
||||
|
||||
也可以使用 `--mount` 语法:
|
||||
使用 `--mount` 语法(推荐):
|
||||
|
||||
```bash
|
||||
$ docker run --mount type=tmpfs,destination=/run,tmpfs-size=67108864 nginx
|
||||
$ docker run --mount type=tmpfs,destination=/run,tmpfs-size=67108864,tmpfs-mode=1770 nginx
|
||||
```
|
||||
|
||||
也可以使用 `--tmpfs` 简写语法:
|
||||
|
||||
```bash
|
||||
$ docker run --tmpfs /run:size=64m nginx
|
||||
```
|
||||
|
||||
> **注意**:`--tmpfs` 支持的选项有限,主要为 `size` 和 `mode`。如果需要更精细的控制(如 `noexec`、`nosuid`),推荐使用 `--mount` 语法并通过 `tmpfs-mode` 参数设置权限。
|
||||
|
||||
### 8.3.3 注意事项
|
||||
|
||||
- 容器停止后,`tmpfs` 数据会丢失。
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||

|
||||
|
||||
图 8-1 Docker 数据挂载类型示意图
|
||||
图 8-1:Docker 数据挂载类型示意图
|
||||
|
||||
这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有两种方式:
|
||||
这一章介绍如何在 Docker 内部以及容器之间管理数据,在容器中管理数据主要有以下几种方式:
|
||||
|
||||
* [数据卷](8.1_volume.md)
|
||||
* [挂载主机目录](8.2_bind-mounts.md)
|
||||
* [tmpfs 挂载](8.3_tmpfs.md)
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
## 本章小结
|
||||
|
||||
| 要点 | 说明 |
|
||||
|------|------|
|
||||
| **作用** | 将宿主机目录挂载到容器 |
|
||||
| **语法** | `-v /宿主机:/容器` 或 `--mount type=bind,...` |
|
||||
| **只读** | 添加 `readonly` 或 `:ro` |
|
||||
| **适用场景** | 开发环境、配置文件、日志 |
|
||||
| **vs Volume** | Bind 更灵活,Volume 更适合生产 |
|
||||
本章介绍了 Docker 的三种数据管理方式:数据卷 (Volume)、绑定挂载 (Bind Mount) 和 tmpfs 挂载。
|
||||
|
||||
### 8.4.1 延伸阅读
|
||||
|
||||
- [数据卷](8.1_volume.md):Docker 管理的持久化存储
|
||||
- [tmpfs 挂载](8.3_tmpfs.md):内存临时存储
|
||||
- [Compose 数据管理](../11_compose/11.5_compose_file.md):Compose 中的挂载配置
|
||||
| 方式 | 特点 | 适用场景 |
|
||||
|------|------|---------|
|
||||
| **数据卷 (Volume)** | Docker 管理,生命周期独立于容器 | 数据库、应用数据(推荐生产环境) |
|
||||
| **绑定挂载 (Bind Mount)** | 挂载宿主机目录,更灵活 | 开发环境、配置文件、日志 |
|
||||
| **tmpfs 挂载** | 仅存储在内存中,容器停止即消失 | 临时敏感数据、高速缓存 |
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
@@ -23,8 +17,13 @@
|
||||
| 清理未用 | `docker volume prune` |
|
||||
| 挂载数据卷 | `-v name:/path` 或 `--mount source=name,target=/path` |
|
||||
|
||||
### 8.4.2 延伸阅读
|
||||
### 延伸阅读
|
||||
|
||||
- [数据卷](8.1_volume.md):Docker 管理的持久化存储
|
||||
- [绑定挂载](8.2_bind-mounts.md):挂载宿主机目录
|
||||
- [tmpfs 挂载](8.3_tmpfs.md):内存中的临时存储
|
||||
- [存储驱动](../12_implementation/12.4_ufs.md):Docker 存储的底层原理
|
||||
- [Compose 数据管理](../11_compose/11.5_compose_file.md):Compose 中的挂载配置
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -4,16 +4,16 @@ Docker 1.10.0 以后,内建了一个 DNS 服务器,使得容器可以直接
|
||||
|
||||
但是使用 Docker DNS 有个前提条件,就是它只能在 **自定义网络** 中使用。也就是说,如果使用的是默认的 `bridge` 网络,是无法使用 DNS 的,所以我们就需要自定义网络。
|
||||
|
||||
### 9.2.1 容器的 DNS 机制
|
||||
### 9.1.1 容器的 DNS 机制
|
||||
|
||||
Docker 容器的 DNS 配置有两种情况:
|
||||
|
||||
1. **默认 Bridge 网络**:继承宿主机的 DNS 配置 (`/etc/resolv.conf`)。
|
||||
2. **自定义网络** (推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。
|
||||
2. **自定义网络**(推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。
|
||||
|
||||
---
|
||||
|
||||
### 9.2.2 嵌入式 DNS
|
||||
### 9.1.2 嵌入式 DNS
|
||||
|
||||
这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过 “名字” 找到彼此,而不需要知道对方的 IP (因为 IP 可能会变)。
|
||||
|
||||
@@ -38,7 +38,7 @@ Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的
|
||||
|
||||
---
|
||||
|
||||
### 9.2.3 配置 DNS 参数
|
||||
### 9.1.3 配置 DNS 参数
|
||||
|
||||
如果你需要手动配置容器的 DNS (例如使用内网 DNS 服务器),可以在 `docker run` 中使用以下参数:
|
||||
|
||||
@@ -69,7 +69,7 @@ $ docker run -h myweb nginx
|
||||
|
||||
---
|
||||
|
||||
### 9.2.4 全局 DNS 配置
|
||||
### 9.1.4 全局 DNS 配置
|
||||
|
||||
如果希望所有容器都使用特定的 DNS 服务器 (而不是继承宿主机),可以修改 `/etc/docker/daemon.json`:
|
||||
|
||||
@@ -86,7 +86,7 @@ $ docker run -h myweb nginx
|
||||
|
||||
---
|
||||
|
||||
### 9.2.5 常见问题
|
||||
### 9.1.5 常见问题
|
||||
|
||||
以下是使用容器 DNS 时常见的问题及解决方法:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
在生产环境中,推荐使用用户自定义网络代替默认的 bridge 网络。自定义网络提供了更好的隔离性和服务发现能力。
|
||||
|
||||
### 9.4.1 为什么要用自定义网络
|
||||
### 9.3.1 为什么要用自定义网络
|
||||
|
||||
默认 bridge 网络存在以下局限,而自定义网络可以很好地解决这些问题:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| 所有容器在同一网络 | 更好的隔离性 |
|
||||
| 需要 --link (已废弃)| 原生支持服务发现 |
|
||||
|
||||
### 9.4.2 创建自定义网络
|
||||
### 9.3.2 创建自定义网络
|
||||
|
||||
使用 `docker network create` 命令可以创建自定义网络:
|
||||
|
||||
@@ -26,7 +26,7 @@ $ docker network create mynet
|
||||
$ docker network inspect mynet
|
||||
```
|
||||
|
||||
### 9.4.3 使用自定义网络
|
||||
### 9.3.3 使用自定义网络
|
||||
|
||||
启动容器时通过 `--network` 参数指定连接的网络:
|
||||
|
||||
@@ -43,7 +43,7 @@ PING db (172.18.0.3): 56 data bytes
|
||||
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.083 ms
|
||||
```
|
||||
|
||||
### 9.4.4 容器名 DNS 解析
|
||||
### 9.3.4 容器名 DNS 解析
|
||||
|
||||
自定义网络自动提供 DNS 服务。Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器,容器内的 DNS 请求会被转发到这里:
|
||||
|
||||
@@ -58,7 +58,7 @@ flowchart LR
|
||||
end
|
||||
```
|
||||
|
||||
### 9.4.5 常用网络命令
|
||||
### 9.3.5 常用网络命令
|
||||
|
||||
以下是 Docker 网络管理中常用的命令:
|
||||
|
||||
@@ -91,3 +91,9 @@ $ docker network rm mynet
|
||||
|
||||
$ docker network prune
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **🔥 踩坑实录**
|
||||
>
|
||||
> 一个新手开发者通过 `docker-compose` 部署了两个容器化服务:服务 A 和服务 B。他在服务 A 的代码中尝试用 `localhost:3000` 访问服务 B,结果始终连接超时。这个错误非常隐蔽——在本地单机开发时看不出问题,因为他可能在同一个进程中测试。排查时他错误地认为是防火墙或网络配置问题。实际原因是:每个容器都有独立的网络命名空间,`localhost` 在容器内部只指向容器自己,不是宿主机也不是其他容器。正确的做法是使用 docker-compose 自动创建的服务名作为主机名:`http://service-b:3000`。`docker-compose` 会自动在网络中注册服务名的 DNS,这样容器间通信才能正确解析。改动仅需一行代码,问题随之消失。
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
容器之间的网络通信是 Docker 网络的核心功能之一。本节介绍容器互联的几种方式。
|
||||
|
||||
### 9.5.1 同一网络内的容器
|
||||
### 9.4.1 同一网络内的容器
|
||||
|
||||
同一自定义网络内的容器可以直接通过容器名通信,这是推荐的容器互联方式:
|
||||
|
||||
@@ -21,7 +21,7 @@ $ docker run -d --name app --network app-net myapp
|
||||
...
|
||||
```
|
||||
|
||||
### 9.5.2 连接到多个网络
|
||||
### 9.4.2 连接到多个网络
|
||||
|
||||
一个容器可以同时连接到多个网络,这对于需要跨网络通信的中间件容器特别有用:
|
||||
|
||||
@@ -39,7 +39,7 @@ $ docker network connect backend multi-net-container
|
||||
$ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks}}'
|
||||
```
|
||||
|
||||
### 9.5.3 ⚠️ --link 已废弃
|
||||
### 9.4.3 ⚠️ --link 已废弃
|
||||
|
||||
`--link` 是 Docker 早期用于容器互联的方式,**已经被废弃**,不建议在新项目中使用。请使用自定义网络替代:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)。为了让外部网络访问容器内的服务,我们需要将容器的端口映射到宿主机的端口。
|
||||
|
||||
### 9.6.1 为什么要映射端口
|
||||
### 9.5.1 为什么要映射端口
|
||||
|
||||
容器的网络访问规则如下:
|
||||
|
||||
@@ -21,7 +21,7 @@ flowchart TD
|
||||
|
||||
---
|
||||
|
||||
### 9.6.2 端口映射方式
|
||||
### 9.5.2 端口映射方式
|
||||
|
||||
Docker 提供了多种方式来指定端口映射。
|
||||
|
||||
@@ -66,7 +66,7 @@ abc123456 0.0.0.0:49153->80/tcp
|
||||
|
||||
---
|
||||
|
||||
### 9.6.3 查看端口映射
|
||||
### 9.5.3 查看端口映射
|
||||
|
||||
可以使用以下命令查看容器的端口映射:
|
||||
|
||||
@@ -92,7 +92,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
|
||||
|
||||
---
|
||||
|
||||
### 9.6.4 最佳实践与安全
|
||||
### 9.5.4 最佳实践与安全
|
||||
|
||||
在配置端口映射时,需要注意以下安全事项:
|
||||
|
||||
@@ -127,7 +127,7 @@ $ docker run -d -p 53:53/udp dns-server
|
||||
|
||||
---
|
||||
|
||||
### 9.6.5 实现原理
|
||||
### 9.5.5 实现原理
|
||||
|
||||
Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内核态) 来实现端口转发。
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Docker 网络提供了天然的隔离能力,不同网络之间的容器默认无法通信。这是 Docker 网络安全的重要基础。
|
||||
|
||||
### 9.7.1 网络隔离原理
|
||||
### 9.6.1 网络隔离原理
|
||||
|
||||
不同网络之间默认隔离,容器只能与同一网络中的容器直接通信:
|
||||
|
||||
@@ -26,7 +26,7 @@ $ docker exec web ping db
|
||||
ping: db: Name or service not known
|
||||
```
|
||||
|
||||
### 9.7.2 安全优势
|
||||
### 9.6.2 安全优势
|
||||
|
||||
这种隔离机制带来以下安全优势:
|
||||
|
||||
@@ -37,7 +37,7 @@ ping: db: Name or service not known
|
||||
| **多租户** | 不同租户的容器在不同网络中完全隔离 |
|
||||
| **最小权限** | 容器只能访问必要的网络资源 |
|
||||
|
||||
### 9.7.3 跨网络通信
|
||||
### 9.6.3 跨网络通信
|
||||
|
||||
如果确实需要某个容器跨网络通信,可以将其同时连接到多个网络:
|
||||
|
||||
@@ -52,7 +52,7 @@ $ docker network connect backend api
|
||||
|
||||
这种方式让你可以精确控制哪些容器可以跨网络通信,遵循最小权限原则。
|
||||
|
||||
### 9.7.4 典型网络架构
|
||||
### 9.6.4 典型网络架构
|
||||
|
||||
一个典型的多层应用网络架构如下:
|
||||
|
||||
|
||||
709
09_network/9.7_advanced_networking.md
Normal file
709
09_network/9.7_advanced_networking.md
Normal file
@@ -0,0 +1,709 @@
|
||||
## 9.7 容器网络高级特性
|
||||
|
||||
深入探讨容器网络的核心机制、Overlay 网络、CNI 插件生态、容器 DNS 解析、网络策略等高级特性,为生产级别的网络架构打下坚实基础。
|
||||
|
||||
### 9.7.1 Overlay 网络原理与配置
|
||||
|
||||
Overlay 网络在现有网络基础上建立虚拟网络,允许容器跨宿主机通信。它是 Kubernetes 和 Swarm 模式的基础。
|
||||
|
||||
#### Overlay 网络工作原理
|
||||
|
||||
Overlay 网络通过隧道封装技术(通常是 VXLAN)将容器网络流量封装在宿主机物理网络的 UDP 数据包中传输。
|
||||
|
||||
```
|
||||
容器 A (192.168.0.2)
|
||||
↓
|
||||
veth 对
|
||||
↓
|
||||
br-net (网桥)
|
||||
↓
|
||||
Docker 引擎 (VXLAN 封装)
|
||||
↓
|
||||
物理网络 (172.16.0.0/24)
|
||||
↓
|
||||
Docker 引擎 (VXLAN 解封装)
|
||||
↓
|
||||
br-net (网桥)
|
||||
↓
|
||||
veth 对
|
||||
↓
|
||||
容器 B (192.168.0.3,不同宿主机)
|
||||
```
|
||||
|
||||
#### 创建和使用 Overlay 网络
|
||||
|
||||
**Docker Swarm 模式下的 Overlay 网络:**
|
||||
|
||||
```bash
|
||||
# 初始化 Swarm(创建集群)
|
||||
docker swarm init
|
||||
|
||||
# 创建 overlay 网络
|
||||
docker network create --driver overlay \
|
||||
--subnet 192.168.0.0/24 \
|
||||
--opt com.docker.network.driver.mtu=1450 \
|
||||
my-overlay-net
|
||||
|
||||
# 验证网络创建
|
||||
docker network ls
|
||||
docker network inspect my-overlay-net
|
||||
|
||||
# 在 Swarm 服务中使用 overlay 网络
|
||||
docker service create --name web \
|
||||
--network my-overlay-net \
|
||||
--replicas 3 \
|
||||
nginx:latest
|
||||
|
||||
# 验证服务跨节点通信
|
||||
docker service ps web
|
||||
```
|
||||
|
||||
**单机 Overlay 网络模拟(Linux 容器):**
|
||||
|
||||
```bash
|
||||
# 创建自定义 overlay 网络
|
||||
docker network create --driver overlay custom-overlay
|
||||
|
||||
# 创建两个容器
|
||||
docker run -d --name container1 --network custom-overlay nginx:latest
|
||||
docker run -d --name container2 --network custom-overlay nginx:latest
|
||||
|
||||
# 测试跨容器通信
|
||||
docker exec container1 ping container2
|
||||
docker exec container1 curl http://container2
|
||||
|
||||
# 检查网络配置
|
||||
docker network inspect custom-overlay
|
||||
```
|
||||
|
||||
#### Overlay 网络性能优化
|
||||
|
||||
```bash
|
||||
# 调整 MTU(Maximum Transmission Unit)避免分片
|
||||
# VXLAN 开销 50 字节,物理 MTU 1500,建议设置为 1450
|
||||
docker network create --driver overlay \
|
||||
--opt com.docker.network.driver.mtu=1450 \
|
||||
optimized-overlay
|
||||
|
||||
# 启用 IP 地址管理(IPAM)自定义
|
||||
docker network create --driver overlay \
|
||||
--subnet 10.0.9.0/24 \
|
||||
--aux-address "my-router=10.0.9.2" \
|
||||
my-custom-overlay
|
||||
|
||||
# 在 Compose 中使用 overlay 网络
|
||||
version: '3.9'
|
||||
services:
|
||||
web:
|
||||
image: nginx
|
||||
networks:
|
||||
- backend
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
networks:
|
||||
- backend
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: overlay
|
||||
driver_opts:
|
||||
com.docker.network.driver.mtu: 1450
|
||||
```
|
||||
|
||||
### 9.7.2 CNI 插件生态概览
|
||||
|
||||
容器网络接口(CNI)是容器编排平台(尤其是 Kubernetes)的标准化网络接口。不同的 CNI 插件提供不同的网络能力。
|
||||
|
||||
#### 主流 CNI 插件对比
|
||||
|
||||
**Calico - 基于 BGP 的网络**
|
||||
|
||||
Calico 使用 BGP 协议进行路由,支持网络策略和 eBPF 加速。
|
||||
|
||||
```yaml
|
||||
# Kubernetes 中安装 Calico
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: calico-config
|
||||
namespace: kube-system
|
||||
data:
|
||||
cni_network_config: |
|
||||
{
|
||||
"name": "k8s-pod-network",
|
||||
"cniVersion": "0.4.0",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "calico",
|
||||
"datastore_type": "kubernetes",
|
||||
"mtu": 1450,
|
||||
"ipam": {
|
||||
"type": "calico-ipam"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "portmap",
|
||||
"snat": true,
|
||||
"capabilities": {"portMappings": true}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Flannel - 简单可靠的 Overlay**
|
||||
|
||||
Flannel 提供简单的 overlay 网络实现,适合小到中等规模的集群。
|
||||
|
||||
```bash
|
||||
# 安装 Flannel
|
||||
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
|
||||
|
||||
# 配置 Flannel 后端(VXLAN、UDP、AWS VPC 等)
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: kube-flannel-cfg
|
||||
namespace: kube-flannel
|
||||
data:
|
||||
cni-conf.json: |
|
||||
{
|
||||
"name": "cbr0",
|
||||
"cniVersion": "0.3.1",
|
||||
"plugins": [
|
||||
{
|
||||
"type": "flannel",
|
||||
"delegate": {
|
||||
"hairpinMode": true,
|
||||
"isDefaultGateway": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "portmap",
|
||||
"capabilities": {
|
||||
"portMappings": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
net-conf.json: |
|
||||
{
|
||||
"Network": "10.244.0.0/16",
|
||||
"Backend": {
|
||||
"Type": "vxlan"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
**Cilium - eBPF 驱动的先进网络**
|
||||
|
||||
Cilium 使用 eBPF 在内核级别实现网络策略和可观测性,性能优异。
|
||||
|
||||
```bash
|
||||
# 安装 Cilium
|
||||
helm repo add cilium https://helm.cilium.io
|
||||
helm install cilium cilium/cilium \
|
||||
--namespace kube-system \
|
||||
--set image.tag=v1.14.0 \
|
||||
--set operator.replicas=1
|
||||
|
||||
# 启用 Hubble(可观测性)
|
||||
helm upgrade cilium cilium/cilium \
|
||||
--namespace kube-system \
|
||||
--reuse-values \
|
||||
--set hubble.enabled=true \
|
||||
--set hubble.ui.enabled=true
|
||||
```
|
||||
|
||||
**Weave - 跨主机网络通信**
|
||||
|
||||
Weave 提供简单的跨主机通信,支持加密和多播。
|
||||
|
||||
```bash
|
||||
# Docker 中使用 Weave 网络
|
||||
docker run -d --name weave \
|
||||
--net=host \
|
||||
--cap-add=NET_ADMIN \
|
||||
--cap-add=SYS_PTRACE \
|
||||
ghcr.io/weaveworks/weave:latest
|
||||
|
||||
# 连接到 Weave 网络
|
||||
docker run -d --network weave --name web nginx:latest
|
||||
```
|
||||
|
||||
**CNI 插件对比表:**
|
||||
|
||||
| 特性 | Calico | Flannel | Cilium | Weave |
|
||||
|------|--------|---------|--------|-------|
|
||||
| 路由方式 | BGP | VXLAN/UDP | eBPF | VxLAN |
|
||||
| 网络策略 | ✓ | ✗ | ✓ (L3-L7) | ✗ |
|
||||
| 性能 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||
| 可观测性 | 中 | 低 | ⭐⭐⭐⭐⭐ | 中 |
|
||||
| 学习曲线 | 中 | 低 | 高 | 低 |
|
||||
| 生产就绪 | ✓ | ✓ | ✓ | ✓ |
|
||||
|
||||
### 9.7.3 容器 DNS 解析机制
|
||||
|
||||
Docker 内置 DNS 服务器,但 DNS 解析涉及多个层面的配置。
|
||||
|
||||
#### DNS 解析流程
|
||||
|
||||
```
|
||||
容器应用 (dig www.example.com)
|
||||
↓
|
||||
容器内 /etc/resolv.conf (127.0.0.11:53)
|
||||
↓
|
||||
Docker 内嵌 DNS 服务器 (127.0.0.11)
|
||||
↓
|
||||
用户自定义 DNS 或宿主机 /etc/resolv.conf
|
||||
↓
|
||||
外部 DNS 服务器 (8.8.8.8 等)
|
||||
↓
|
||||
DNS 响应 → 容器缓存 → 应用
|
||||
```
|
||||
|
||||
#### 配置容器 DNS
|
||||
|
||||
**在运行时指定 DNS:**
|
||||
|
||||
```bash
|
||||
# 单个容器
|
||||
docker run -d \
|
||||
--dns 8.8.8.8 \
|
||||
--dns 1.1.1.1 \
|
||||
--dns-search example.com \
|
||||
nginx:latest
|
||||
|
||||
# DNS 选项
|
||||
docker run -d \
|
||||
--dns-option ndots:2 \
|
||||
--dns-option timeout:1 \
|
||||
--dns-option attempts:3 \
|
||||
nginx:latest
|
||||
|
||||
# 查看容器 DNS 配置
|
||||
docker exec <container_id> cat /etc/resolv.conf
|
||||
```
|
||||
|
||||
**Docker Compose DNS 配置:**
|
||||
|
||||
```yaml
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
web:
|
||||
image: nginx
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 1.1.1.1
|
||||
dns_search:
|
||||
- example.com
|
||||
- local
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
networks:
|
||||
- backend
|
||||
hostname: postgres-db
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: bridge
|
||||
|
||||
# 容器内 /etc/resolv.conf 将被自动配置
|
||||
# search example.com local
|
||||
# nameserver 8.8.8.8
|
||||
# nameserver 1.1.1.1
|
||||
```
|
||||
|
||||
**Docker 守护进程级别配置:**
|
||||
|
||||
```json
|
||||
{
|
||||
"dns": ["8.8.8.8", "1.1.1.1"],
|
||||
"dns-search": ["example.com"],
|
||||
"insecure-registries": [],
|
||||
"registry-mirrors": ["https://mirror.example.com"]
|
||||
}
|
||||
```
|
||||
|
||||
#### 自定义服务发现(Service Discovery)
|
||||
|
||||
**使用 Docker 内建 DNS 的服务发现:**
|
||||
|
||||
```bash
|
||||
# 创建自定义网络
|
||||
docker network create mynet
|
||||
|
||||
# 运行服务
|
||||
docker run -d --name web --network mynet nginx:latest
|
||||
docker run -d --name db --network mynet postgres:latest
|
||||
|
||||
# 在其他容器中通过服务名访问
|
||||
docker run -it --network mynet busybox sh
|
||||
# ping web # 自动解析到 web 容器 IP
|
||||
# ping db # 自动解析到 db 容器 IP
|
||||
```
|
||||
|
||||
**Compose 服务名自动发现:**
|
||||
|
||||
```yaml
|
||||
version: '3.9'
|
||||
|
||||
services:
|
||||
frontend:
|
||||
image: nginx
|
||||
depends_on:
|
||||
- backend
|
||||
environment:
|
||||
BACKEND_URL: http://backend:8080
|
||||
|
||||
backend:
|
||||
image: myapp
|
||||
depends_on:
|
||||
- database
|
||||
|
||||
database:
|
||||
image: postgres
|
||||
environment:
|
||||
POSTGRES_DB: mydb
|
||||
|
||||
# frontend 容器可以直接访问 http://backend:8080
|
||||
# backend 容器可以直接访问 postgres://database:5432
|
||||
```
|
||||
|
||||
#### DNS 性能优化
|
||||
|
||||
```bash
|
||||
# 检查 DNS 延迟
|
||||
time docker exec <container> nslookup www.example.com
|
||||
|
||||
# 优化 DNS 解析
|
||||
docker run -d \
|
||||
--dns 127.0.0.1 \ # 使用本地缓存 DNS (Dnsmasq)
|
||||
nginx:latest
|
||||
|
||||
# 在 Kubernetes 中优化
|
||||
kubectl patch deployment -n kube-system coredns --patch '{
|
||||
"spec": {
|
||||
"template": {
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "coredns",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"memory": "512Mi",
|
||||
"cpu": "500m"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### 9.7.4 网络策略(NetworkPolicy)实践
|
||||
|
||||
网络策略定义了容器间的流量控制规则,是微服务架构中的安全基础。
|
||||
|
||||
#### 基本网络策略
|
||||
|
||||
**默认拒绝所有入站流量的策略:**
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny-ingress
|
||||
namespace: default
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
# 不指定 ingress 规则,表示拒绝所有入站流量
|
||||
```
|
||||
|
||||
**允许特定来源的入站流量:**
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-from-frontend
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
tier: backend
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
tier: frontend
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
```
|
||||
|
||||
**允许出站流量到数据库:**
|
||||
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-backend-to-db
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
tier: backend
|
||||
policyTypes:
|
||||
- Egress
|
||||
egress:
|
||||
# 允许到数据库的流量
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
tier: database
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
# 允许 DNS 查询
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
ports:
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
# 允许到外部 API 的流量
|
||||
- to:
|
||||
- ipBlock:
|
||||
cidr: 0.0.0.0/0
|
||||
except:
|
||||
- 169.254.169.254/32 # 阻止元数据服务
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 443
|
||||
```
|
||||
|
||||
#### 微服务网络策略示例
|
||||
|
||||
```yaml
|
||||
---
|
||||
# 拒绝所有默认
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: default-deny-all
|
||||
spec:
|
||||
podSelector: {}
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
|
||||
---
|
||||
# Frontend 容器策略
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-frontend
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
# 允许来自 Ingress Controller 的流量
|
||||
- from:
|
||||
- namespaceSelector:
|
||||
matchLabels:
|
||||
name: ingress-nginx
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: ingress-controller
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 3000
|
||||
egress:
|
||||
# 允许到 API 的流量
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: api
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
# 允许 DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
|
||||
---
|
||||
# API 容器策略
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-api
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: api
|
||||
policyTypes:
|
||||
- Ingress
|
||||
- Egress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: frontend
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
egress:
|
||||
# 允许到数据库的流量
|
||||
- to:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
# 允许 DNS
|
||||
- to:
|
||||
- namespaceSelector: {}
|
||||
podSelector:
|
||||
matchLabels:
|
||||
k8s-app: kube-dns
|
||||
ports:
|
||||
- protocol: UDP
|
||||
port: 53
|
||||
|
||||
---
|
||||
# 数据库容器策略
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: NetworkPolicy
|
||||
metadata:
|
||||
name: allow-postgres
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: postgres
|
||||
policyTypes:
|
||||
- Ingress
|
||||
ingress:
|
||||
- from:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: api
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 5432
|
||||
```
|
||||
|
||||
#### 使用 Calico/Cilium 的高级网络策略
|
||||
|
||||
**L7 应用层策略(仅 Cilium 支持):**
|
||||
|
||||
```yaml
|
||||
apiVersion: "cilium.io/v2"
|
||||
kind: CiliumNetworkPolicy
|
||||
metadata:
|
||||
name: "api-gateway-policy"
|
||||
spec:
|
||||
description: "L7 policy for API gateway"
|
||||
endpointSelector:
|
||||
matchLabels:
|
||||
app: api
|
||||
ingress:
|
||||
- fromEndpoints:
|
||||
- matchLabels:
|
||||
app: frontend
|
||||
toPorts:
|
||||
- ports:
|
||||
- port: "8080"
|
||||
protocol: TCP
|
||||
rules:
|
||||
http:
|
||||
# 允许 GET /api/users
|
||||
- method: "GET"
|
||||
path: "/api/users/.*"
|
||||
# 允许 POST /api/users 仅从管理员来源
|
||||
- method: "POST"
|
||||
path: "/api/users"
|
||||
sourceIPs:
|
||||
- "10.0.0.0/8"
|
||||
```
|
||||
|
||||
### 9.7.5 跨主机容器通信方案对比
|
||||
|
||||
#### 方案对比表
|
||||
|
||||
| 方案 | 隔离性 | 性能 | 复杂度 | 适用场景 |
|
||||
|------|--------|------|--------|---------|
|
||||
| 主机网络 | ✗ | ⭐⭐⭐⭐⭐ | 低 | 高性能,单主机 |
|
||||
| Bridge + Host Port | 中 | ⭐⭐⭐⭐ | 低 | 小规模集群 |
|
||||
| Overlay (VXLAN) | ✓ | ⭐⭐⭐ | 中 | 跨域通信 |
|
||||
| BGP (Calico) | ✓ | ⭐⭐⭐⭐ | 中 | 大规模集群 |
|
||||
| eBPF (Cilium) | ✓ | ⭐⭐⭐⭐⭐ | 高 | 高性能大集群 |
|
||||
|
||||
#### 选择建议
|
||||
|
||||
```bash
|
||||
# 1. 开发环境:使用 Bridge 网络
|
||||
docker network create my-app
|
||||
docker-compose up # 默认使用 bridge
|
||||
|
||||
# 2. 小规模生产(< 50 节点):使用 Flannel
|
||||
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
|
||||
|
||||
# 3. 中等规模(50-500 节点):使用 Calico
|
||||
kubeadm init --pod-network-cidr=192.168.0.0/16
|
||||
kubectl apply -f https://docs.projectcalico.org/v3.24/manifests/tigera-operator.yaml
|
||||
|
||||
# 4. 大规模(> 500 节点)或需要 L7 策略:使用 Cilium
|
||||
helm install cilium cilium/cilium --namespace kube-system
|
||||
|
||||
# 5. 需要多云/跨域:使用 Weave
|
||||
```
|
||||
|
||||
### 9.7.6 网络故障排查
|
||||
|
||||
**常见网络问题诊断:**
|
||||
|
||||
```bash
|
||||
# 1. 容器无法访问外部网络
|
||||
docker exec <container> ping 8.8.8.8
|
||||
docker exec <container> cat /etc/resolv.conf
|
||||
docker logs <container> | grep -i network
|
||||
|
||||
# 2. 容器间无法通信
|
||||
docker network inspect <network>
|
||||
docker exec <container1> ping <container2>
|
||||
|
||||
# 3. 端口映射失效
|
||||
docker port <container>
|
||||
netstat -tlnp | grep <port>
|
||||
|
||||
# 4. DNS 解析失败
|
||||
docker exec <container> nslookup example.com
|
||||
docker exec <container> cat /etc/hosts
|
||||
|
||||
# 5. 网络延迟
|
||||
docker run --rm --network host iperf3:latest -c <target>
|
||||
docker exec <container> mtr -r example.com
|
||||
|
||||
# 使用 tcpdump 抓包分析
|
||||
docker run --rm --cap-add NET_ADMIN --network host \
|
||||
corfr/tcpdump -i eth0 -n "port 80"
|
||||
```
|
||||
@@ -34,8 +34,9 @@ graph TD
|
||||
## 本章内容
|
||||
|
||||
* [配置 DNS](9.1_dns.md)
|
||||
* [外部访问容器](9.5_port_mapping.md)
|
||||
* [网络类型](9.2_network_types.md)
|
||||
* [自定义网络](9.3_custom_network.md)
|
||||
* [容器互联](9.4_container_linking.md)
|
||||
* [外部访问容器](9.5_port_mapping.md)
|
||||
* [网络隔离](9.6_network_isolation.md)
|
||||
* [高级网络配置](9.7_advanced_networking.md)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| **网络隔离** | 不同网络默认隔离,增强安全性 |
|
||||
| **--link** | 已废弃,使用自定义网络替代 |
|
||||
|
||||
### 9.8.1 延伸阅读
|
||||
### 延伸阅读
|
||||
|
||||
- [配置 DNS](9.1_dns.md):自定义 DNS 设置
|
||||
- [网络类型](9.2_network_types.md):Bridge、Host、None 等网络模式
|
||||
@@ -22,3 +22,6 @@
|
||||
- [网络隔离](9.6_network_isolation.md):网络安全与隔离策略
|
||||
- [EXPOSE 指令](../07_dockerfile/7.9_expose.md):在 Dockerfile 中声明端口
|
||||
- [Compose 网络](../11_compose/11.5_compose_file.md):Compose 中的网络配置
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -38,6 +38,15 @@ $ docker buildx build --sbom=true -t myimage .
|
||||
|
||||
该命令会在构建结果中包含 SPDX 或 CycloneDX 格式的 SBOM 数据。
|
||||
|
||||
> **⚠️ 注意与失败模式**:
|
||||
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见,对底层的存储格式有前置要求:默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构。
|
||||
>
|
||||
> 如果只简单运行上述命令,你可能会面临 **“命令成功执行,但本地镜像中看不到 SBOM”** 的体会落差。
|
||||
>
|
||||
> **正确的解决路径有两条**:
|
||||
> 1. 在 Docker 守护进程中启用 `containerd image store` 特性(现代 Docker Desktop 默认推荐)。
|
||||
> 2. 或者使用 `docker-container` driver 的构建器,并直接 **加上 `--push` 参数** 将产物推送到远端支持 OCI 的镜像仓库,仓库会正确保存这些元数据。
|
||||
|
||||
### 10.2.2 官方文档
|
||||
|
||||
* https://docs.docker.com/engine/reference/commandline/buildx/
|
||||
|
||||
@@ -11,3 +11,6 @@ Docker Buildx 是一个 docker CLI 插件,其扩展了 docker 命令,支持
|
||||
* [使用 BuildKit 构建镜像](10.1_buildkit.md)
|
||||
* [使用 Buildx 构建镜像](10.2_buildx.md)
|
||||
* [构建多种系统架构支持的 Docker 镜像](10.3_multi-arch-images.md)
|
||||
|
||||
> **供应链安全与存储后端前瞻**:现代软件供应链中,镜像来源证明(Provenance,在 BuildKit 中默认以 `mode=min` 添加)和软件物料清单(SBOM,可通过 `--sbom=true` 显式开启)已经成为极其重要的构建产出。这些 Attestations 数据会作为 manifest 附着在 **镜像索引 (Image Index)** 上。
|
||||
> 正是基于此诉求,自 Docker Engine v29 开始默认启用的 `containerd image store` 提供对 Image Index 的完美本地支持能力,解决了传统经典存储后端(Classic Store)无法有效处理带 Attestations 镜像索引的瓶颈。这使得你可以利用 `docker buildx imagetools inspect` 等手段,甚至做到无需拉取完整镜像内容即可在 Registry 或本地高效校验镜像的安全元数据。
|
||||
|
||||
@@ -17,3 +17,6 @@ Docker Buildx 是 Docker 构建系统的重要进化,提供了高效、安全
|
||||
- [Dockerfile 指令详解](../07_dockerfile/README.md):Dockerfile 编写基础
|
||||
- [多阶段构建](../07_dockerfile/7.17_multistage_builds.md):优化镜像体积
|
||||
- [Dockerfile 最佳实践](../appendix/best_practices.md):编写高效 Dockerfile
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
|
||||
### 11.1.1 概述
|
||||
|
||||
Docker Compose 让用户能够以声明式方式定义和管理多容器应用。它的核心价值在于:用一个 YAML 文件取代一连串手动的 `docker run` 命令,使得复杂应用的启动、停止和重建变得一键可达。
|
||||
|
||||
对于开发团队而言,Compose 解决了三个关键问题:环境一致性(“在我机器上能跑”的问题)、服务依赖管理(确保数据库在应用之前启动)、以及开发-测试-生产的配置差异管理(通过 `compose.override.yaml` 实现多环境适配)。
|
||||
|
||||
### 11.1.2 模板文件规范
|
||||
|
||||
Compose 模板文件采用 YAML 格式,扩展名为 `.yml` 或 `.yaml`。
|
||||
|
||||
@@ -18,12 +18,12 @@ Linux 系统请使用以下介绍的方法安装。
|
||||
|
||||
> **提示**:版本更新较快,请访问上述链接获取最新版本号,替换下方命令中的版本号。
|
||||
|
||||
例如,在 Linux 64 位系统上直接下载对应的二进制包 (以 v5.0.2 为例)。
|
||||
例如,在 Linux 64 位系统上直接下载对应的二进制包 (以 v5.1.0 为例)。
|
||||
|
||||
```bash
|
||||
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
|
||||
$ mkdir -p $DOCKER_CONFIG/cli-plugins
|
||||
$ curl -SL https://github.com/docker/compose/releases/download/v5.0.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
$ curl -SL https://github.com/docker/compose/releases/download/v5.1.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
```
|
||||
|
||||
之后,执行
|
||||
@@ -36,13 +36,13 @@ $ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
|
||||
```bash
|
||||
$ docker compose version
|
||||
Docker Compose version v5.0.2
|
||||
Docker Compose version v5.1.0
|
||||
```
|
||||
|
||||
### 11.2.3 bash 补全命令
|
||||
|
||||
```bash
|
||||
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.0.2/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
|
||||
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.1.0/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
|
||||
```
|
||||
|
||||
### 11.2.4 卸载
|
||||
|
||||
@@ -399,8 +399,8 @@ mysql:
|
||||
- my_other_secret
|
||||
|
||||
secrets:
|
||||
my_secret:
|
||||
file: ./my_secret.txt
|
||||
db_root_password:
|
||||
file: ./db_root_password.txt
|
||||
my_other_secret:
|
||||
external: true
|
||||
```
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
### 11.6.1 架构概览
|
||||
|
||||
在开始之前,先看整体架构 (如图 10-1 所示):
|
||||
在开始之前,先看整体架构 (如图 11-1:所示):
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
@@ -31,7 +31,7 @@ flowchart TD
|
||||
Port8000 --> Browser
|
||||
```
|
||||
|
||||
图 10-1 Django + PostgreSQL 的 Compose 架构
|
||||
图 11-1:Django + PostgreSQL 的 Compose 架构
|
||||
|
||||
**关键点**:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
### 11.7.1 架构概览
|
||||
|
||||
如图 10-2 所示,Rails 与 PostgreSQL 在同一 Compose 网络中协同工作。
|
||||
如图 11-2:所示,Rails 与 PostgreSQL 在同一 Compose 网络中协同工作。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
@@ -31,7 +31,7 @@ flowchart TD
|
||||
Port3000 --> Browser
|
||||
```
|
||||
|
||||
图 10-2 Rails + PostgreSQL 的 Compose 架构
|
||||
图 11-2:Rails + PostgreSQL 的 Compose 架构
|
||||
|
||||
### 11.7.2 准备工作
|
||||
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
## 11.9 实战 LNMP
|
||||
|
||||
本项目的维护者 [khs1994](https://github.com/khs1994) 的开源项目 [khs1994-docker/lnmp](https://github.com/khs1994-docker/lnmp) 使用 Docker Compose 搭建了一套 LNMP 环境,各位开发者可以参考该项目在 Docker 或 Kubernetes 中运行 LNMP。
|
||||
### 什么是 LNMP
|
||||
|
||||
LNMP 是一个经典的 Web 应用栈,由以下四个开源软件组合而成:
|
||||
|
||||
- **L**:Linux(操作系统)
|
||||
- **N**:Nginx(Web 服务器)
|
||||
- **M**:MySQL(数据库服务器)
|
||||
- **P**:PHP(脚本语言)
|
||||
|
||||
这个组合被广泛用于构建高性能的 Web 应用。
|
||||
|
||||
### 使用 Docker Compose 部署 LNMP
|
||||
|
||||
本项目的维护者 [khs1994](https://github.com/khs1994) 的开源项目 [khs1994-docker/lnmp](https://github.com/khs1994-docker/lnmp) 使用 Docker Compose 搭建了一套完整的 LNMP 环境。
|
||||
|
||||
### 参考项目
|
||||
|
||||
该项目中包含的服务:
|
||||
|
||||
- **Nginx**:Web 服务器,用于处理 HTTP 请求
|
||||
- **MySQL/MariaDB**:关系型数据库服务
|
||||
- **PHP-FPM**:PHP 处理器,与 Nginx 通过 Fast CGI 协议通信
|
||||
- **Redis**:可选的内存缓存服务(用于会话或缓存)
|
||||
|
||||
### 学习资源
|
||||
|
||||
各位开发者可以参考该项目在以下场景中运行 LNMP:
|
||||
|
||||
- Docker 容器化部署
|
||||
- Kubernetes 集群编排
|
||||
- 开发环境快速搭建
|
||||
- 生产环境配置参考
|
||||
|
||||
项目地址:https://github.com/khs1994-docker/lnmp
|
||||
|
||||
通过该项目,你可以学习到如何使用 Docker Compose 定义多个相互关联的服务,以及如何在容器化环境中管理应用的生命周期。
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
`Docker Compose` 是 Docker 官方编排 (Orchestration) 项目之一,负责快速的部署分布式应用。
|
||||
|
||||
> ⚠️ **重要提示:Compose V1 已停止支持**
|
||||
>
|
||||
> 早期基于 Python 编写的 Compose V1(命令为 `docker-compose`)已于 2023 年中正式停止支持。现已全面升级为基于 Go 编写的 Compose V2,作为 Docker CLI 的官方插件提供(命令为 `docker compose`,中间为空格)。本书强烈推荐且后续章节均以 V2 为核心标准进行讲解。
|
||||
|
||||
本章将介绍 `Compose` 项目情况以及安装和使用。
|
||||
|
||||
* [简介](11.1_introduction.md)
|
||||
|
||||
@@ -13,9 +13,12 @@ Docker Compose 是管理多容器应用的利器,通过 YAML 文件声明式
|
||||
| **查看日志** | `docker compose logs` 查看服务日志 |
|
||||
| **模板文件** | 支持 `services`、`networks`、`volumes` 等顶级配置 |
|
||||
|
||||
### 11.10.1 延伸阅读
|
||||
### 延伸阅读
|
||||
|
||||
- [Compose 模板文件](11.5_compose_file.md):详细模板语法参考
|
||||
- [Compose 命令说明](11.4_commands.md):完整命令列表
|
||||
- [网络配置](../09_network/README.md):Docker 网络基础
|
||||
- [数据管理](../08_data/README.md):数据卷管理
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。
|
||||
|
||||
## 12.2 什么是 Namespace
|
||||
### 12.2.1 什么是 Namespace
|
||||
|
||||
> **Namespace 是 Linux 内核提供的资源隔离机制,它让容器内的进程仿佛运行在独立的操作系统中。** Namespace 是容器技术的核心基础之一。它回答了一个关键问题:**如何让一个进程 “以为” 自己独占整个系统?**
|
||||
> **Namespace 是 Linux 内核提供的资源隔离机制,它让容器内的进程仿佛运行在独立的操作系统中。**Namespace 是容器技术的核心基础之一。它回答了一个关键问题:**如何让一个进程 “以为” 自己独占整个系统?**
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
@@ -26,7 +26,7 @@ flowchart LR
|
||||
H4 -. "(实际是宿主机的 1234)" .- C1
|
||||
```
|
||||
|
||||
### 12.2.1 Namespace 的类型
|
||||
### 12.2.2 Namespace 的类型
|
||||
|
||||
Linux 内核提供了以下几种 Namespace,Docker 容器使用了全部:
|
||||
|
||||
@@ -42,7 +42,7 @@ Linux 内核提供了以下几种 Namespace,Docker 容器使用了全部:
|
||||
|
||||
---
|
||||
|
||||
### 12.2.2 PID Namespace
|
||||
### 12.2.3 PID Namespace
|
||||
|
||||
PID Namespace 负责进程 ID 的隔离,使得容器内的进程彼此不可见。
|
||||
|
||||
@@ -75,7 +75,7 @@ PID USER COMMAND
|
||||
|
||||
---
|
||||
|
||||
### 12.2.3 NET Namespace
|
||||
### 12.2.4 NET Namespace
|
||||
|
||||
NET Namespace 负责网络栈的隔离,包括网卡、路由表和 iptables 规则等。
|
||||
|
||||
@@ -110,7 +110,7 @@ flowchart LR
|
||||
|
||||
---
|
||||
|
||||
### 12.2.4 MNT Namespace
|
||||
### 12.2.5 MNT Namespace
|
||||
|
||||
MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的文件系统视图。
|
||||
|
||||
@@ -143,7 +143,7 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的
|
||||
|
||||
---
|
||||
|
||||
### 12.2.5 UTS Namespace
|
||||
### 12.2.6 UTS Namespace
|
||||
|
||||
UTS Namespace 主要用于隔离主机名和域名。
|
||||
|
||||
@@ -169,7 +169,7 @@ UTS = “UNIX Time-sharing System”,是历史遗留的名称。
|
||||
|
||||
---
|
||||
|
||||
### 12.2.6 IPC Namespace
|
||||
### 12.2.7 IPC Namespace
|
||||
|
||||
IPC Namespace 用于隔离进程间通信资源,如 System V IPC 和 POSIX 消息队列。
|
||||
|
||||
@@ -190,7 +190,7 @@ IPC Namespace 用于隔离进程间通信资源,如 System V IPC 和 POSIX 消
|
||||
|
||||
---
|
||||
|
||||
### 12.2.7 USER Namespace
|
||||
### 12.2.8 USER Namespace
|
||||
|
||||
USER Namespace 允许将容器内的用户 ID 映射到宿主机的不同用户 ID。
|
||||
|
||||
@@ -226,7 +226,7 @@ flowchart LR
|
||||
|
||||
---
|
||||
|
||||
### 12.2.8 动手实验:体验 Namespace
|
||||
### 12.2.9 动手实验:体验 Namespace
|
||||
|
||||
使用 `unshare` 命令可以在不使用 Docker 的情况下体验 Namespace:
|
||||
|
||||
@@ -285,7 +285,7 @@ $ ip addr
|
||||
|
||||
---
|
||||
|
||||
### 12.2.9 Namespace 的局限性
|
||||
### 12.2.10 Namespace 的局限性
|
||||
|
||||
Namespace 提供了隔离但不是安全边界:
|
||||
|
||||
|
||||
@@ -35,10 +35,11 @@ flowchart LR
|
||||
|
||||
| 时间 | 事件 |
|
||||
|------|------|
|
||||
| 2006 | Google 工程师提出 cgroups 概念 |
|
||||
| 2008 | Linux 2.6.24 正式支持 cgroups v1 |
|
||||
| 2006 | Google 工程师提出 “process containers” 概念 |
|
||||
| 2007 | 为避免与 Linux 容器概念混淆,更名为 “control groups” (cgroups) |
|
||||
| 2008 | Linux 2.6.24(2008年1月)正式合并 cgroups v1 |
|
||||
| 2016 | Linux 4.5 引入 cgroups v2 |
|
||||
| 现在 | Docker 默认使用 cgroups v2 (如系统支持)|
|
||||
| 现在 | Docker 在宿主机支持 cgroups v2 时会自动使用 v2,否则回退到 v1 |
|
||||
|
||||
---
|
||||
|
||||
@@ -265,7 +266,7 @@ $ docker run -d --name cadvisor \
|
||||
-v /var/run:/var/run:ro \
|
||||
-v /sys:/sys:ro \
|
||||
-v /var/lib/docker:/var/lib/docker:ro \
|
||||
gcr.io/cadvisor/cadvisor
|
||||
ghcr.io/google/cadvisor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -92,32 +92,33 @@ flowchart LR
|
||||
|
||||
### 12.4.4 Docker 支持的存储驱动
|
||||
|
||||
Docker 可使用多种联合文件系统实现:
|
||||
Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, devicemapper),到被广泛使用的现代经典 graph driver (`overlay2`),再到当下(Engine v29 及以后)**默认启用的 containerd 镜像存储引擎(containerd image store)** 的演进。
|
||||
|
||||
| 存储驱动 | 说明 | 推荐程度 |
|
||||
| 存储后端 / 驱动 | 核心特性说明 | 推荐程度 |
|
||||
|---------|------|---------|
|
||||
| **overlay2**| 现代 Linux 默认驱动,性能优秀 | ✅**推荐** |
|
||||
| **containerd image store**| (v29+ 新一代默认引擎) 基于 containerd 的 snapshotters,原生支持 OCI image index、多架构镜像与 Attestations 构建溯源元数据存储。 | ✅**强烈推荐 (现代默认)** |
|
||||
| **overlay2**| (经典 Graph Driver) 传统架构下的现代 Linux 默认驱动,性能优秀,但在处理复杂溯源元数据(索引)时受限。 | ✅**推荐 (主要后备)** |
|
||||
| **aufs** | 早期默认,兼容性好 | 遗留系统 |
|
||||
| **btrfs** | 使用 Btrfs 子卷 | 特定场景 |
|
||||
| **zfs** | 使用 ZFS 数据集 | 特定场景 |
|
||||
| **devicemapper** | 块设备级存储 | 遗留系统 |
|
||||
| **btrfs**/**zfs** | 使用原生稳定文件系统快照能力 | 特定场景 |
|
||||
| **devicemapper** | 块设备级存储 | 遗留系统 (已被逐步弃用) |
|
||||
| **vfs** | 不使用 CoW,每层完整复制 | 仅测试 |
|
||||
|
||||
#### 各发行版推荐
|
||||
#### Classic Graph Drivers 与 Snapshotters 的核心差异
|
||||
|
||||
| Linux 发行版 | 推荐存储驱动 |
|
||||
|-------------|-------------|
|
||||
| Ubuntu 16.04+ | overlay2 |
|
||||
| Debian Stretch+ | overlay2 |
|
||||
| CentOS 7+ | overlay2 |
|
||||
| RHEL 8+ | overlay2 |
|
||||
| Fedora | overlay2 |
|
||||
传统模型(如 `overlay2`)将镜像拉取解包的过程由 Docker 的 graph drivers 处理。而新的 `containerd image store` 则将这一职责彻底下放给了 `containerd` 自身的 `snapshotters`(底层在 Linux 发行版通常依然利用操作系统的 overlayfs)。这种架构改变带来了:
|
||||
1. 本地免拉取查看多平台镜像 index manifest 与 attestations (SBOM、Provenance)。
|
||||
2. 避免了以前绕过 CRI 获取本地镜像的问题,带来更好的原生 Kubernetes 生态兼容性。
|
||||
|
||||
#### 查看当前存储驱动
|
||||
#### 查看当前存储驱动与后端
|
||||
|
||||
```bash
|
||||
## 查看默认存储驱动 (Storage Driver)
|
||||
$ docker info | grep "Storage Driver"
|
||||
Storage Driver: overlay2
|
||||
|
||||
## 在 Engine v29+ 中,可以通过如下输出验证是否开启了 containerd 镜像后端:
|
||||
$ docker info | grep "containerd image store"
|
||||
containerd image store: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -1,3 +1,50 @@
|
||||
## 12.5 容器格式
|
||||
|
||||
最初,Docker 采用了 `LXC` 中的容器格式。从 0.7 版本以后开始去除 LXC,转而使用自行开发的 [libcontainer](https://github.com/docker/libcontainer),从 1.11 开始,则进一步演进为使用 [runC](https://github.com/opencontainers/runc) 和 [containerd](https://github.com/containerd/containerd)。
|
||||
### Docker 容器格式的演进
|
||||
|
||||
最初,Docker 采用了 `LXC` 中的容器格式。从 0.7 版本以后开始去除 LXC 的依赖,转而使用自行开发的 [libcontainer](https://github.com/docker/libcontainer)。从 1.11 开始,则进一步演进为使用 [runC](https://github.com/opencontainers/runc) 和 [containerd](https://github.com/containerd/containerd)。
|
||||
|
||||
### 关键组件说明
|
||||
|
||||
#### LXC(Linux 容器)
|
||||
|
||||
Docker 早期版本(0.1-0.7)直接使用 LXC 作为容器运行时,利用 Linux Namespaces 和 Cgroups 实现容器隔离。
|
||||
|
||||
#### libcontainer
|
||||
|
||||
- Docker 自行开发的容器库
|
||||
- 提供了容器的通用接口
|
||||
- 不依赖于特定的 Linux 容器实现
|
||||
- 更灵活和可控
|
||||
|
||||
#### runC
|
||||
|
||||
- OCI(Open Container Initiative)标准实现
|
||||
- 轻量级的容器运行时
|
||||
- 独立的二进制文件,可单独使用
|
||||
- 基于 libcontainer 发展而来
|
||||
|
||||
#### containerd
|
||||
|
||||
- Docker 开源的容器运行时
|
||||
- 提供了容器的完整生命周期管理
|
||||
- 支持 runC 和其他 OCI 兼容的运行时
|
||||
- 在 Kubernetes 等编排系统中广泛使用
|
||||
|
||||
### 容器规范标准
|
||||
|
||||
Docker 积极参与 Open Container Initiative (OCI) 的制定,推动了以下规范的发展:
|
||||
|
||||
- **Image Spec**:容器镜像格式规范
|
||||
- **Runtime Spec**:容器运行时接口规范
|
||||
- **Distribution Spec**:容器镜像分发规范
|
||||
|
||||
### 架构演变的优势
|
||||
|
||||
从 LXC → libcontainer → runC/containerd 的演变提供了以下优势:
|
||||
|
||||
1. 减少外部依赖
|
||||
2. 提高运行效率
|
||||
3. 遵循行业标准(OCI)
|
||||
4. 增强可移植性和互操作性
|
||||
5. 支持多种容器运行时选择
|
||||
|
||||
@@ -12,6 +12,8 @@ Docker 底层的核心技术包括 Linux 上的命名空间 (Namespaces)、控
|
||||
|
||||
随着 Linux 系统对于命名空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的命名空间中运行。大家虽然都共用一个内核和某些运行时环境 (例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器 (Container),利用命名空间来做权限的隔离控制,利用 cgroups 来做资源分配。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [基本架构](12.1_arch.md)
|
||||
* [命名空间](12.2_namespace.md)
|
||||
* [控制组](12.3_cgroups.md)
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
## 本章小结
|
||||
|
||||
本章深入介绍了 Docker 的底层实现,包括命名空间、控制组和联合文件系统三大核心技术。
|
||||
|
||||
| 技术 | 作用 | 要点 |
|
||||
|------|------|------|
|
||||
| **Namespace** | 资源隔离 | PID、NET、MNT、UTS、IPC、USER 六种命名空间 |
|
||||
| **Cgroups** | 资源限制 | 限制 CPU、内存、磁盘 I/O、进程数 |
|
||||
| **Union FS** | 分层存储 | overlay2 为推荐驱动,支持 Copy-on-Write |
|
||||
|
||||
| Namespace | 隔离内容 | 一句话说明 |
|
||||
|-----------|---------|-----------|
|
||||
|-----------|---------|-----------|
|
||||
| PID | 进程 ID | 容器有自己的进程树 |
|
||||
| NET | 网络 | 容器有自己的 IP 和端口 |
|
||||
| MNT | 文件系统 | 容器有自己的根目录 |
|
||||
@@ -9,13 +17,6 @@
|
||||
| IPC | 进程间通信 | 容器间 IPC 隔离 |
|
||||
| USER | 用户 ID | 容器 root ≠ 宿主机 root |
|
||||
|
||||
### 12.7.1 延伸阅读
|
||||
|
||||
- [控制组 (Cgroups)](12.3_cgroups.md):资源限制机制
|
||||
- [联合文件系统](12.4_ufs.md):分层存储的实现
|
||||
- [安全](../18_security/README.md):容器安全实践
|
||||
- [Linux Namespace 官方文档](https://man7.org/linux/man-pages/man7/namespaces.7.html)
|
||||
|
||||
| 资源 | 限制参数 | 示例 |
|
||||
|------|---------|------|
|
||||
| **内存** | `-m` | `-m 512m` |
|
||||
@@ -24,21 +25,15 @@
|
||||
| **磁盘 I/O** | `--device-write-bps` | `--device-write-bps /dev/sda:10mb` |
|
||||
| **进程数** | `--pids-limit` | `--pids-limit=100` |
|
||||
|
||||
### 12.7.2 延伸阅读
|
||||
|
||||
- [命名空间](12.2_namespace.md):资源隔离
|
||||
- [安全](../18_security/README.md):容器安全概述
|
||||
- [Docker Stats](../05_container/README.md):监控容器资源
|
||||
|
||||
| 概念 | 说明 |
|
||||
|------|------|
|
||||
| **UnionFS** | 将多层目录联合挂载为一个文件系统 |
|
||||
| **Copy-on-Write** | 写时复制,修改时才复制到可写层 |
|
||||
| **overlay2** | Docker 默认推荐的存储驱动 |
|
||||
| **分层好处** | 镜像复用、快速构建、快速启动 |
|
||||
|
||||
### 12.7.3 延伸阅读
|
||||
### 延伸阅读
|
||||
|
||||
- [命名空间](12.2_namespace.md):资源隔离机制详解
|
||||
- [控制组 (Cgroups)](12.3_cgroups.md):资源限制机制
|
||||
- [联合文件系统](12.4_ufs.md):分层存储的实现
|
||||
- [安全](../18_security/README.md):容器安全实践
|
||||
- [镜像](../02_basic_concept/2.1_image.md):理解镜像分层
|
||||
- [容器](../02_basic_concept/2.2_container.md):容器存储层
|
||||
- [构建镜像](../04_image/4.5_build.md):Dockerfile 层的创建
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||

|
||||
|
||||
图 13-1 Kubernetes 项目标识
|
||||
图 13-1:Kubernetes 项目标识
|
||||
|
||||
### 13.1.1 什么是 Kubernetes
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## 13.2 基本概念
|
||||
|
||||
如图 12-2 所示,Kubernetes 由控制平面与工作节点构成。
|
||||
如图 13-2 所示,Kubernetes 由控制平面与工作节点构成。
|
||||
|
||||

|
||||
|
||||
图 12-2 Kubernetes 基本概念示意图
|
||||
图 13-2:Kubernetes 基本概念示意图
|
||||
|
||||
* 节点 (`Node`):一个节点是一个运行 Kubernetes 中的主机。
|
||||
* 容器组 (`Pod`):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷 (volume)。
|
||||
@@ -39,41 +39,56 @@
|
||||
|
||||
#### 节点管理
|
||||
|
||||
节点并非 Kubernetes 创建,而是由云平台创建,或者就是物理机器、虚拟机。在 Kubernetes 中,节点仅仅是一条记录,节点创建之后,Kubernetes 会检查其是否可用。在 Kubernetes 中,节点用如下结构保存:
|
||||
节点并非 Kubernetes 创建,而是由云平台创建,或者就是物理机器、虚拟机。在 Kubernetes 中,节点仅仅是一条记录,节点创建之后,Kubernetes 会检查其是否可用。可以通过 `kubectl` 查看节点信息:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "10.1.2.3",
|
||||
"kind": "Minion",
|
||||
"apiVersion": "v1beta1",
|
||||
"resources": {
|
||||
"capacity": {
|
||||
"cpu": 1000,
|
||||
"memory": 1073741824
|
||||
},
|
||||
},
|
||||
"labels": {
|
||||
"name": "my-first-k8s-node",
|
||||
},
|
||||
}
|
||||
```bash
|
||||
$ kubectl get nodes
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
control-plane Ready control-plane 10d v1.30.2
|
||||
worker-1 Ready <none> 10d v1.30.2
|
||||
worker-2 Ready <none> 10d v1.30.2
|
||||
```
|
||||
|
||||
Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接口可以用来管理节点:节点控制和 Kube 管理。
|
||||
每个节点的详细信息以如下结构保存:
|
||||
|
||||
#### 节点控制
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Node
|
||||
metadata:
|
||||
name: worker-1
|
||||
labels:
|
||||
kubernetes.io/os: linux
|
||||
status:
|
||||
capacity:
|
||||
cpu: "4"
|
||||
memory: 8Gi
|
||||
conditions:
|
||||
- type: Ready
|
||||
status: "True"
|
||||
```
|
||||
|
||||
在 Kubernetes 主节点中,节点控制器是用来管理节点的组件。主要包含:
|
||||
#### 节点控制器
|
||||
|
||||
* 集群范围内节点同步
|
||||
在 Kubernetes 控制平面中,节点控制器 (Node Controller) 负责管理节点的生命周期,主要包含:
|
||||
|
||||
* 集群范围内节点状态同步
|
||||
* 单节点生命周期管理
|
||||
|
||||
节点控制有一个同步轮询,主要监听所有云平台的虚拟实例,会根据节点状态创建和删除。可以通过 `--node_sync_period` 标志来控制该轮询。如果一个实例已经创建,节点控制将会为其创建一个结构。同样的,如果一个节点被删除,节点控制也会删除该结构。在 Kubernetes 启动时可用通过 `--machines` 标记来显示指定节点。同样可以使用 `kubectl` 来一条一条的添加节点,两者是相同的。通过设置 `--sync_nodes=false` 标记来禁止集群之间的节点同步,你也可以使用 api/kubectl 命令行来增删节点。
|
||||
节点控制器会持续监控节点的健康状态。当节点变为不可达时,控制器会等待一个超时期限,然后将该节点上的 Pod 标记为失败,并触发重新调度。可以使用 `kubectl` 来管理节点,例如标记节点为不可调度或排空节点上的工作负载:
|
||||
|
||||
```bash
|
||||
## 标记节点为不可调度
|
||||
$ kubectl cordon worker-1
|
||||
|
||||
## 排空节点上的 Pod
|
||||
$ kubectl drain worker-1 --ignore-daemonsets
|
||||
```
|
||||
|
||||
### 13.2.2 容器组
|
||||
|
||||
在 Kubernetes 中,使用的最小单位是容器组,容器组是创建,调度,管理的最小单位。一个容器组使用相同的 Docker 容器并共享卷 (挂载点)。一个容器组是一个特定应用的打包集合,包含一个或多个容器。
|
||||
在 Kubernetes 中,使用的最小调度单位是容器组 (Pod),它是创建、调度、管理的最小单位。一个 Pod 包含一个或多个紧密协作的容器,它们共享网络命名空间和存储卷。
|
||||
|
||||
和运行的容器类似,一个容器组被认为只有很短的运行周期。容器组被调度到一组节点运行,直到容器的生命周期结束或者其被删除。如果节点死掉,运行在其上的容器组将会被删除而不是重新调度。(也许在将来的版本中会添加容器组的移动)。
|
||||
Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理。当节点发生故障时,控制器会在其他可用节点上重新创建 Pod。
|
||||
|
||||
#### 容器组设计的初衷
|
||||
|
||||
@@ -93,7 +108,7 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接
|
||||
|
||||
#### 容器组的使用
|
||||
|
||||
容器组可以通过组合来构建复杂的应用,其本来的意义包含:
|
||||
容器组可以通过组合来构建复杂的应用,典型的使用模式包含:
|
||||
|
||||
* 内容管理,文件和数据加载以及本地缓存管理等。
|
||||
* 日志和检查点备份,压缩,快照等。
|
||||
@@ -101,108 +116,154 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接
|
||||
* 代理,网桥
|
||||
* 控制器,管理,配置以及更新
|
||||
|
||||
#### 替代方案
|
||||
#### 为什么不在一个容器里运行多个程序
|
||||
|
||||
为什么不在一个单一的容器里运行多个程序?
|
||||
|
||||
* 1. 透明化。为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。这样设计是为了用户的便利性。
|
||||
* 2. 解耦软件之间的依赖。每个容器都可能重新构建和发布,Kubernetes 必须支持热发布和热更新 (将来)。
|
||||
* 3. 方便使用。用户不必运行独立的程序管理,也不用担心每个应用程序的退出状态。
|
||||
* 4. 高效。考虑到基础设施有更多的职责,容器必须要轻量化。
|
||||
1. **透明化**:为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。
|
||||
2. **解耦依赖**:每个容器都可能独立地重新构建和发布。
|
||||
3. **方便使用**:用户不必运行独立的程序管理,也不用担心每个应用程序的退出状态。
|
||||
4. **高效**:考虑到基础设施有更多的职责,容器必须要轻量化。
|
||||
|
||||
#### 容器组的生命状态
|
||||
|
||||
包括若干状态值:`pending`、`running`、`succeeded`、`failed`。
|
||||
包括若干状态值:`Pending`、`Running`、`Succeeded`、`Failed`。
|
||||
|
||||
##### pending
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| **Pending** | Pod 已被集群接受,但有一个或多个容器还没有运行起来(可能在拉取镜像)。|
|
||||
| **Running** | Pod 已被调度到节点,并且所有容器都已启动。至少有一个容器处于运行状态。|
|
||||
| **Succeeded** | Pod 中的所有容器都正常退出,且不会被重启。|
|
||||
| **Failed** | Pod 中的所有容器都已终止,且至少有一个容器以失败状态退出。|
|
||||
|
||||
容器组已经被节点接受,但有一个或多个容器还没有运行起来。这将包含某些节点正在下载镜像的时间,这种情形会依赖于网络情况。
|
||||
#### 容器组生命周期与重启策略
|
||||
|
||||
##### running
|
||||
Pod 的重启策略 (`restartPolicy`) 决定了容器退出后的行为:
|
||||
|
||||
容器组已经被调度到节点,并且所有的容器都已经启动。至少有一个容器处于运行状态 (或者处于重启状态)。
|
||||
| 重启策略 | 容器正常退出 | 容器异常退出 |
|
||||
|---------|------------|------------|
|
||||
| **Always** (默认) | 重启容器 | 重启容器 |
|
||||
| **OnFailure** | 不重启 | 重启容器 |
|
||||
| **Never** | 不重启 | 不重启 |
|
||||
|
||||
##### succeeded
|
||||
当节点故障或不可达时,节点控制器会将该节点上所有 Pod 的状态标记为 `Failed`。如果这些 Pod 由 Deployment 等控制器管理,控制器会自动在其他节点上重新创建。
|
||||
|
||||
所有的容器都正常退出。
|
||||
### 13.2.3 Deployment 与 ReplicaSet
|
||||
|
||||
##### failed
|
||||
Deployment 是管理无状态应用的推荐方式,它通过 ReplicaSet 来确保指定数量的 Pod 副本始终在运行。
|
||||
|
||||
容器组中所有容器都意外中断了。
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.27
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
#### 容器组生命周期
|
||||
Deployment 的核心能力包括:
|
||||
|
||||
通常来说,如果容器组被创建了就不会自动销毁,除非被某种行为触发,而触发此种情况可能是人为,或者复制控制器所为。唯一例外的是容器组由 succeeded 状态成功退出,或者在一定时间内重试多次依然失败。
|
||||
* **副本管理**:确保始终有指定数量的 Pod 在运行
|
||||
* **滚动更新**:逐步替换旧版本 Pod,实现零停机部署
|
||||
* **回滚**:如果新版本出现问题,可以快速回滚到之前的版本
|
||||
|
||||
如果某个节点死掉或者不能连接,那么节点控制器将会标记其上的容器组的状态为 `failed`。
|
||||
|
||||
举例如下。
|
||||
|
||||
* 容器组状态 `running`,有 1 容器,容器正常退出
|
||||
* 记录完成事件
|
||||
* 如果重启策略为:
|
||||
* 始终:重启容器,容器组保持 `running`
|
||||
* 失败时:容器组变为 `succeeded`
|
||||
* 从不:容器组变为 `succeeded`
|
||||
* 容器组状态 `running`,有 1 容器,容器异常退出
|
||||
* 记录失败事件
|
||||
* 如果重启策略为:
|
||||
* 始终:重启容器,容器组保持 `running`
|
||||
* 失败时:重启容器,容器组保持 `running`
|
||||
* 从不:容器组变为 `failed`
|
||||
* 容器组状态 `running`,有 2 容器,有 1 容器异常退出
|
||||
* 记录失败事件
|
||||
* 如果重启策略为:
|
||||
* 始终:重启容器,容器组保持 `running`
|
||||
* 失败时:重启容器,容器组保持 `running`
|
||||
* 从不:容器组保持 `running`
|
||||
* 当有 2 容器退出
|
||||
* 记录失败事件
|
||||
* 如果重启策略为:
|
||||
* 始终:重启容器,容器组保持 `running`
|
||||
* 失败时:重启容器,容器组保持 `running`
|
||||
* 从不:容器组变为 `failed`
|
||||
* 容器组状态 `running`,容器内存不足
|
||||
* 标记容器错误中断
|
||||
* 记录内存不足事件
|
||||
* 如果重启策略为:
|
||||
* 始终:重启容器,容器组保持 `running`
|
||||
* 失败时:重启容器,容器组保持 `running`
|
||||
* 从不:记录错误事件,容器组变为 `failed`
|
||||
* 容器组状态 `running`,一块磁盘死掉
|
||||
* 杀死所有容器
|
||||
* 记录事件
|
||||
* 容器组变为 `failed`
|
||||
* 如果容器组运行在一个控制器下,容器组将会在其他地方重新创建
|
||||
* 容器组状态 `running`,对应的节点段溢出
|
||||
* 节点控制器等到超时
|
||||
* 节点控制器标记容器组 `failed`
|
||||
* 如果容器组运行在一个控制器下,容器组将会在其他地方重新创建
|
||||
|
||||
### 13.2.3 Replication Controllers
|
||||
|
||||
> 注:Replication Controller (RC) 是早期的控制器类型,现代 Kubernetes 更推荐使用 ReplicaSet/Deployment。
|
||||
> 早期 Kubernetes 使用 Replication Controller (RC) 来管理副本,现已被 ReplicaSet/Deployment 取代。
|
||||
|
||||
### 13.2.4 服务
|
||||
|
||||
> 注:服务 (Service) 定义一组 Pod 的逻辑集合和访问它们的策略。
|
||||
服务 (Service) 定义了一组 Pod 的逻辑集合和访问策略。由于 Pod 的 IP 地址是动态分配的,Service 提供了一个稳定的访问入口。
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: nginx-service
|
||||
spec:
|
||||
selector:
|
||||
app: nginx
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
type: ClusterIP
|
||||
```
|
||||
|
||||
常见的 Service 类型:
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| **ClusterIP** | 默认类型,仅集群内部可访问 |
|
||||
| **NodePort** | 在每个节点上开放固定端口,集群外部可通过 `节点IP:端口` 访问 |
|
||||
| **LoadBalancer** | 通过云平台的负载均衡器暴露服务 |
|
||||
|
||||
### 13.2.5 卷
|
||||
|
||||
> 注:卷 (Volume) 包含可被 Pod 中容器访问的数据的目录。
|
||||
卷 (Volume) 为 Pod 中的容器提供持久化存储。Kubernetes 支持多种卷类型:
|
||||
|
||||
| 卷类型 | 说明 |
|
||||
|-------|------|
|
||||
| **emptyDir** | 临时存储,Pod 删除后数据丢失 |
|
||||
| **hostPath** | 挂载节点上的文件或目录 |
|
||||
| **PersistentVolumeClaim** | 使用持久卷声明,与底层存储解耦 |
|
||||
| **configMap / secret** | 将配置或敏感数据挂载为文件 |
|
||||
|
||||
生产环境中,推荐使用 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 来管理存储,实现存储资源与使用者的解耦。
|
||||
|
||||
### 13.2.6 标签
|
||||
|
||||
> 注:标签 (Label) 是附加到对象 (如 Pods) 上的键值对,用于组织和选择对象子集。
|
||||
标签 (Label) 是附加到 Kubernetes 对象上的键值对,用于组织和选择对象子集。标签是 Kubernetes 中实现松耦合的关键机制。
|
||||
|
||||
### 13.2.7 接口权限
|
||||
```bash
|
||||
## 为 Pod 添加标签
|
||||
$ kubectl label pod my-pod env=production
|
||||
|
||||
> 注:接口权限通过认证、授权和准入控制来保护 Kubernetes API 的访问。
|
||||
## 通过标签选择器查询
|
||||
$ kubectl get pods -l env=production
|
||||
```
|
||||
|
||||
### 13.2.8 web 界面
|
||||
Service、Deployment 等资源都通过标签选择器 (`selector`) 来关联目标 Pod。
|
||||
|
||||
> 注:Kubernetes Dashboard 是一个基于 Web 的用户界面,用于管理集群。
|
||||
### 13.2.7 API 访问控制
|
||||
|
||||
### 13.2.9 命令行操作
|
||||
Kubernetes API 的访问通过三个阶段进行控制:
|
||||
|
||||
> 注:kubectl 是 Kubernetes 的命令行工具,用于与集群进行交互。
|
||||
1. **认证 (Authentication)**:验证请求者的身份(如证书、Token、OIDC)
|
||||
2. **授权 (Authorization)**:判断请求者是否有权限执行操作(通常使用 RBAC)
|
||||
3. **准入控制 (Admission Control)**:在请求被持久化之前对其进行校验或修改
|
||||
|
||||
### 13.2.8 Dashboard
|
||||
|
||||
Kubernetes Dashboard 是一个基于 Web 的用户界面,用于部署容器化应用、监控集群资源和排查问题。Dashboard 的部署方法详见[部署 Dashboard](../14_kubernetes_setup/14.7_dashboard.md) 章节。
|
||||
|
||||
### 13.2.9 命令行工具 kubectl
|
||||
|
||||
`kubectl` 是 Kubernetes 的命令行工具,用于与集群进行交互。常用命令如下:
|
||||
|
||||
```bash
|
||||
## 查看集群中的资源
|
||||
$ kubectl get pods,deployments,services,nodes
|
||||
|
||||
## 创建资源
|
||||
$ kubectl apply -f deployment.yaml
|
||||
|
||||
## 查看 Pod 日志
|
||||
$ kubectl logs my-pod
|
||||
|
||||
## 进入 Pod 执行命令
|
||||
$ kubectl exec -it my-pod -- /bin/sh
|
||||
|
||||
## 查看资源详情
|
||||
$ kubectl describe pod my-pod
|
||||
```
|
||||
|
||||
更多 kubectl 操作详见[kubectl 命令行](../14_kubernetes_setup/14.8_kubectl.md)章节。
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
### 13.3.2 运行原理
|
||||
|
||||
如图 12-3 所示,该图完整展示了 Kubernetes 的运行原理。
|
||||
如图 13-3 所示,该图完整展示了 Kubernetes 的运行原理。
|
||||
|
||||

|
||||
|
||||
图 12-3 Kubernetes 运行原理图
|
||||
图 13-3:Kubernetes 运行原理图
|
||||
|
||||
可见,Kubernetes 首先是一套分布式系统,由多个节点组成,节点分为两类:一类是属于管理平面的主节点/控制节点 (Master Node);一类是属于运行平面的工作节点 (Worker Node)。
|
||||
|
||||
@@ -52,4 +52,4 @@
|
||||
|
||||

|
||||
|
||||
图 12-4 kube-proxy 请求转发示意图
|
||||
图 13-4:kube-proxy 请求转发示意图
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
Kubernetes 的最小调度单位是 `Pod`。一个 `Pod` 由一组紧密协作的容器构成,它们共享网络命名空间、IP 以及部分存储资源,也可以根据需要对 Pod 进行端口映射。
|
||||
|
||||
本章将分为 5 节介绍 `Kubernetes`,包括
|
||||
本章将分为 5 节介绍 `Kubernetes`:
|
||||
|
||||
* 项目简介
|
||||
* 快速入门
|
||||
* 基本概念
|
||||
* 实践例子
|
||||
* 架构分析等高级话题
|
||||
* [简介](13.1_intro.md)
|
||||
* [基本概念](13.2_concepts.md)
|
||||
* [架构设计](13.3_design.md)
|
||||
* [高级特性](13.4_advanced.md)
|
||||
* [实战练习](13.5_practice.md)
|
||||
|
||||
@@ -17,3 +17,6 @@ Kubernetes 是当前最主流的容器编排平台,其声明式管理模型和
|
||||
- [部署 Kubernetes](../14_kubernetes_setup/README.md):搭建 Kubernetes 集群
|
||||
- [Etcd](../15_etcd/README.md):Kubernetes 使用的分布式存储
|
||||
- [底层实现](../12_implementation/README.md):容器技术原理
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## 14.1 使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)
|
||||
## 14.1 使用 kubeadm 部署 Kubernetes
|
||||
|
||||
`kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令,作为快速创建 `Kubernetes` 集群的最佳实践。
|
||||
|
||||
@@ -228,7 +228,7 @@ oom_score = 0
|
||||
async_remove = false
|
||||
```
|
||||
|
||||
### 14.1.3 安装 **kubelet****kubeadm****kubectl****cri-tools****kubernetes-cni**
|
||||
### 14.1.3 安装 **kubelet**、**kubeadm**、**kubectl**、**cri-tools**、**kubernetes-cni**
|
||||
|
||||
需要在每台机器上安装以下的软件包:
|
||||
|
||||
@@ -292,7 +292,6 @@ kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无
|
||||
$ sudo swapoff -a
|
||||
|
||||
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -446,7 +445,7 @@ $ kubectl get node -o yaml | grep CIDR
|
||||
```
|
||||
|
||||
```bash
|
||||
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/Documentation/kube-flannel.yml
|
||||
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
|
||||
```
|
||||
|
||||
### 14.1.10 master 节点默认不能运行 pod
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
`kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令,作为快速创建 `Kubernetes` 集群的最佳实践。
|
||||
|
||||
> ⚠️ **重要说明**:自 Kubernetes 1.24 起,内置 `dockershim` 已被移除,Kubernetes 默认不再直接使用 Docker Engine 作为容器运行时 (CRI)。因此,**更推荐参考** 同目录下的《[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)》。
|
||||
> ⚠️ **强烈提示:Docker 与 Kubernetes 环境的时代分界**
|
||||
>
|
||||
> 本文档主要用于历史环境/学习目的:如果你确实需要在较新版本中继续使用 Docker Engine,通常需要额外部署 `cri-dockerd` 并在 `kubeadm init/join` 中指定 `--cri-socket`。
|
||||
> 自 Kubernetes v1.24 起,内置的 `dockershim` 组件已被正式移除。这意味着 **Kubernetes 不再将 Docker Engine 作为默认内置的容器运行时**。虽然 Docker 仍然是你本地构建、管理镜像的绝佳工具,但它已不再是 kubelet 的默认运行时选项。
|
||||
>
|
||||
> 因此,**强烈推荐** 读者直接参考同目录下的《[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)》作为主要的部署路线。
|
||||
>
|
||||
> 本文档保留,主要用于历史环境维护或特殊需求场景:如果你必须在较新的 Kubernetes 集群中继续使用 Docker Engine 作为底层运行时,你必须理解 CRI 层机制,额外部署并配置第三方兼容层 `cri-dockerd`,同时在部署时手动补充 `--cri-socket` 等参数约束。
|
||||
|
||||
### 14.2.1 安装 Docker
|
||||
|
||||
参考[安装 Docker](../03_install/README.md) 一节安装 Docker。
|
||||
|
||||
### 14.2.2 安装 **kubelet****kubeadm****kubectl**
|
||||
### 14.2.2 安装 **kubelet**、**kubeadm**、**kubectl**
|
||||
|
||||
需要在每台机器上安装以下的软件包:
|
||||
|
||||
@@ -74,7 +78,6 @@ kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无
|
||||
$ sudo swapoff -a
|
||||
|
||||
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -212,7 +215,7 @@ $ kubectl get node -o yaml | grep CIDR
|
||||
```
|
||||
|
||||
```bash
|
||||
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/Documentation/kube-flannel.yml
|
||||
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
|
||||
```
|
||||
|
||||
### 14.2.9 master 节点默认不能运行 pod
|
||||
|
||||
@@ -1,3 +1,67 @@
|
||||
## 14.6 一步步部署 Kubernetes 集群
|
||||
|
||||
可以参考 [opsnull/follow-me-install-kubernetes-cluster](https://github.com/opsnull/follow-me-install-kubernetes-cluster) 项目一步步部署 Kubernetes 集群。
|
||||
### 概述
|
||||
|
||||
部署 Kubernetes 集群涉及多个组件的安装和配置,包括 Master 节点和 Worker 节点。本章介绍如何使用 systemd 管理这些服务的生命周期。
|
||||
|
||||
### Kubernetes 主要组件
|
||||
|
||||
#### Master 节点组件
|
||||
|
||||
- **kube-apiserver**:API 服务器,Kubernetes 集群的中心
|
||||
- **kube-controller-manager**:控制器管理器
|
||||
- **kube-scheduler**:调度器,负责 Pod 调度
|
||||
- **etcd**:分布式键值存储,存储集群数据
|
||||
|
||||
#### Worker 节点组件
|
||||
|
||||
- **kubelet**:节点代理,管理容器生命周期
|
||||
- **kube-proxy**:网络代理,处理服务网络
|
||||
- **Container Runtime**:容器运行时(Docker、containerd 等)
|
||||
|
||||
### 使用 systemd 管理 Kubernetes 服务
|
||||
|
||||
#### 服务单元文件
|
||||
|
||||
为了让 systemd 管理 Kubernetes 服务,需要创建相应的 `.service` 文件,例如:
|
||||
|
||||
```
|
||||
/etc/systemd/system/kubelet.service
|
||||
/etc/systemd/system/kube-proxy.service
|
||||
/etc/systemd/system/kube-apiserver.service
|
||||
```
|
||||
|
||||
#### 常用命令
|
||||
|
||||
```bash
|
||||
# 启动服务
|
||||
sudo systemctl start kubelet
|
||||
|
||||
# 停止服务
|
||||
sudo systemctl stop kubelet
|
||||
|
||||
# 重启服务
|
||||
sudo systemctl restart kubelet
|
||||
|
||||
# 查看服务状态
|
||||
sudo systemctl status kubelet
|
||||
|
||||
# 设置开机自启
|
||||
sudo systemctl enable kubelet
|
||||
```
|
||||
|
||||
### 参考资源
|
||||
|
||||
详细的部署步骤和配置说明,可以参考以下项目:
|
||||
|
||||
- [opsnull/follow-me-install-kubernetes-cluster](https://github.com/opsnull/follow-me-install-kubernetes-cluster):一个完整的 Kubernetes 集群部署指南项目
|
||||
|
||||
该项目提供了详细的步骤说明,涵盖 Master 节点、Worker 节点的安装配置,以及如何使用 systemd 管理这些组件的生命周期。
|
||||
|
||||
### 推荐学习路径
|
||||
|
||||
1. 理解 Kubernetes 架构和各组件的作用
|
||||
2. 准备所需的系统环境(Linux 主机、网络配置等)
|
||||
3. 按步骤安装各个 Kubernetes 组件
|
||||
4. 配置 systemd 服务单元文件
|
||||
5. 验证集群健康状态
|
||||
|
||||
@@ -8,74 +8,74 @@ kubectl [flags]
|
||||
kubectl [command]
|
||||
```
|
||||
|
||||
## 14.8 get
|
||||
### 14.8.1 get
|
||||
|
||||
显示一个或多个资源
|
||||
|
||||
## 14.8 describe
|
||||
### 14.8.2 describe
|
||||
|
||||
显示资源详情
|
||||
|
||||
## 14.8 create
|
||||
### 14.8.3 create
|
||||
|
||||
从文件或标准输入创建资源
|
||||
|
||||
## 14.8 update
|
||||
### 14.8.4 update
|
||||
|
||||
从文件或标准输入更新资源
|
||||
|
||||
## 14.8 delete
|
||||
### 14.8.5 delete
|
||||
|
||||
通过文件名、标准输入、资源名或者 label selector 删除资源
|
||||
|
||||
## 14.8 logs
|
||||
### 14.8.6 logs
|
||||
|
||||
输出 pod 中一个容器的日志
|
||||
|
||||
## 14.8 rollout
|
||||
### 14.8.7 rollout
|
||||
|
||||
对 Deployment 等资源执行滚动更新/回滚
|
||||
|
||||
## 14.8 exec
|
||||
### 14.8.8 exec
|
||||
|
||||
在容器内部执行命令
|
||||
|
||||
## 14.8 port-forward
|
||||
### 14.8.9 port-forward
|
||||
|
||||
将本地端口转发到 Pod
|
||||
|
||||
## 14.8 proxy
|
||||
### 14.8.10 proxy
|
||||
|
||||
为 Kubernetes API server 启动代理服务器
|
||||
|
||||
## 14.8 run
|
||||
### 14.8.11 run
|
||||
|
||||
在集群中使用指定镜像启动容器
|
||||
|
||||
## 14.8 expose
|
||||
### 14.8.12 expose
|
||||
|
||||
将 replication controller service 或 pod 暴露为新的 Kubernetes service
|
||||
|
||||
## 14.8 label
|
||||
### 14.8.13 label
|
||||
|
||||
更新资源的 label
|
||||
|
||||
## 14.8 config
|
||||
### 14.8.14 config
|
||||
|
||||
修改 Kubernetes 配置文件
|
||||
|
||||
## 14.8 cluster-info
|
||||
### 14.8.15 cluster-info
|
||||
|
||||
显示集群信息
|
||||
|
||||
## 14.8 api-versions
|
||||
### 14.8.16 api-versions
|
||||
|
||||
以 “组/版本” 的格式输出服务端支持的 API 版本
|
||||
|
||||
## 14.8 version
|
||||
### 14.8.17 version
|
||||
|
||||
输出服务端和客户端的版本信息
|
||||
|
||||
## 14.8 help
|
||||
### 14.8.18 help
|
||||
|
||||
显示各个命令的帮助信息
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
目前,Kubernetes 支持在多种环境下使用,包括本地主机 (Ubuntu、Debian、CentOS、Fedora 等)、云服务 ([腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)、[阿里云](https://www.aliyun.com/product/kubernetes?source=5176.11533457&userCode=8lx5zmtu&type=copy)、[百度云](https://cloud.baidu.com/product/cce.html)等)。
|
||||
|
||||
你可以使用以下几种方式部署 Kubernetes:
|
||||
你可以使用以下几种方式部署 Kubernetes,接下来的小节会对各种方式进行详细介绍。
|
||||
|
||||
* kubeadm
|
||||
* docker-desktop
|
||||
* k3s
|
||||
|
||||
接下来的小节会对以上几种方式进行详细介绍。
|
||||
* [使用 kubeadm 部署 (CRI 使用 containerd)](14.1_kubeadm.md)
|
||||
* [使用 kubeadm 部署 (使用 Docker)](14.2_kubeadm-docker.md)
|
||||
* [在 Docker Desktop 使用](14.3_docker-desktop.md)
|
||||
* [Kind - Kubernetes IN Docker](14.4_kind.md)
|
||||
* [K3s - 轻量级 Kubernetes](14.5_k3s.md)
|
||||
* [一步步部署 Kubernetes 集群](14.6_systemd.md)
|
||||
* [部署 Dashboard](14.7_dashboard.md)
|
||||
* [Kubernetes 命令行 kubectl](14.8_kubectl.md)
|
||||
|
||||
@@ -15,3 +15,6 @@
|
||||
- [容器编排基础](../13_kubernetes_concepts/README.md):Kubernetes 核心概念
|
||||
- [Dashboard](14.7_dashboard.md):部署可视化管理界面
|
||||
- [kubectl](14.8_kubectl.md):命令行工具使用指南
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## 15.1 简介
|
||||
|
||||
如图 12-5 所示,etcd 项目使用该标识。
|
||||
如图 15-1:所示,etcd 项目使用该标识。
|
||||
|
||||

|
||||
|
||||
图 12-5 etcd 项目标识
|
||||
图 15-1:etcd 项目标识
|
||||
|
||||
`etcd` 是 `CoreOS` 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值 (`key-value`) 数据库,基于 `Go` 语言实现。我们知道,在分布式系统中,各种服务的配置信息的管理分享,服务的发现是一个很基本同时也是很重要的问题。`CoreOS` 项目就希望基于 `etcd` 来解决这一问题。
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
`etcd` 基于 `Go` 语言实现,因此,用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
|
||||
|
||||
>注意:本章节内容基于 etcd `3.4.x` 版本
|
||||
>注意:本章节内容基于 etcd `3.4.x` 版本编写。etcd 3.4 的官方支持将于 **2026 年 5 月 15 日结束**,新部署建议使用 etcd `3.5` 或 `3.6` 版本。请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
|
||||
|
||||
### 15.2.1 二进制文件方式下载
|
||||
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
# 第十五章 Etcd 项目
|
||||
|
||||
`etcd` 是 `CoreOS` 团队发起的一个管理配置信息和服务发现 (`Service Discovery`) 的项目,在这一章里面,我们将基于 `etcd 3.x` 版本介绍该项目的目标,安装和使用,以及实现的技术。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [简介](15.1_intro.md)
|
||||
* [安装](15.2_install.md)
|
||||
* [集群](15.3_cluster.md)
|
||||
* [使用 etcdctl](15.4_etcdctl.md)
|
||||
|
||||
@@ -15,3 +15,6 @@ etcd 是 Kubernetes 的核心存储组件,为分布式系统提供可靠的键
|
||||
|
||||
- [容器编排基础](../13_kubernetes_concepts/README.md):Kubernetes 如何使用 etcd
|
||||
- [部署 Kubernetes](../14_kubernetes_setup/README.md):在集群中部署 etcd
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## 16.2 腾讯云
|
||||
|
||||
如图 13-5 所示,腾讯云提供完整的云基础设施与容器能力。
|
||||
如图 16-1:所示,腾讯云提供完整的云基础设施与容器能力。
|
||||
|
||||

|
||||
|
||||
图 13-5 腾讯云标识
|
||||
图 16-1:腾讯云标识
|
||||
|
||||
[腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=1040\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)在架构方面经过多年积累,并且有着多年对海量互联网服务的经验。不管是社交、游戏还是其他领域,都有多年的成熟产品来提供产品服务。腾讯在云端完成重要部署,为开发者及企业提供云服务、云数据、云运营等整体一站式服务方案。
|
||||
|
||||
@@ -14,4 +14,200 @@
|
||||
|
||||

|
||||
|
||||
图 13-6 腾讯云容器服务示意图
|
||||
图 16-2:腾讯云容器服务示意图
|
||||
|
||||
### 腾讯云容器服务 (TKE) 简介
|
||||
|
||||
腾讯云容器服务 (TKE, Tencent Kubernetes Engine) 是一款容器编排平台,基于原生 Kubernetes 提供,支持自动扩展、负载均衡、多可用区高可用等企业级功能。TKE 帮助开发者快速部署和管理容器化应用,消除集群运维的复杂度。
|
||||
|
||||
### 基本使用步骤
|
||||
|
||||
#### 1. 创建集群
|
||||
|
||||
登录腾讯云控制台,进入容器服务模块:
|
||||
- 选择 “创建集群”,配置集群名称、地域和网络
|
||||
- 选择节点配置(云服务器规格和数量)
|
||||
- 设置 Kubernetes 版本和安全组
|
||||
- 完成创建后获得集群 kubeconfig 文件
|
||||
|
||||
```bash
|
||||
# 下载 kubeconfig 文件后,配置本地环境
|
||||
export KUBECONFIG=/path/to/kubeconfig.yaml
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
#### 2. 部署容器应用
|
||||
|
||||
创建 Deployment 部署应用:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-app
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
|
||||
应用配置文件:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deployment.yaml
|
||||
kubectl get pods
|
||||
kubectl get svc
|
||||
```
|
||||
|
||||
#### 3. 管理镜像
|
||||
|
||||
通过腾讯云容器镜像服务 (TCR) 存储和管理私有镜像:
|
||||
|
||||
```bash
|
||||
# 登录腾讯云镜像仓库
|
||||
docker login ccr.ccs.tencentyun.com -u <username>
|
||||
|
||||
# 标记本地镜像
|
||||
docker tag my-app:latest ccr.ccs.tencentyun.com/namespace/my-app:latest
|
||||
|
||||
# 推送镜像到腾讯云
|
||||
docker push ccr.ccs.tencentyun.com/namespace/my-app:latest
|
||||
```
|
||||
|
||||
### 腾讯云 Docker 镜像加速器配置
|
||||
|
||||
为了加快镜像拉取速度,腾讯云提供了镜像加速服务。配置方法如下:
|
||||
|
||||
#### Linux 系统配置
|
||||
|
||||
编辑 `/etc/docker/daemon.json` 文件(如果不存在则创建):
|
||||
|
||||
```bash
|
||||
# 创建或编辑配置文件
|
||||
sudo mkdir -p /etc/docker
|
||||
sudo nano /etc/docker/daemon.json
|
||||
```
|
||||
|
||||
添加以下内容:
|
||||
|
||||
```json
|
||||
{
|
||||
"registry-mirrors": [
|
||||
"https://mirror.ccs.tencentyun.com"
|
||||
],
|
||||
"insecure-registries": []
|
||||
}
|
||||
```
|
||||
|
||||
重启 Docker 服务:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
验证配置:
|
||||
|
||||
```bash
|
||||
# 查看镜像源是否生效
|
||||
docker info | grep -A 5 "Registry Mirrors"
|
||||
```
|
||||
|
||||
#### Windows/Mac 配置
|
||||
|
||||
对于 Docker Desktop,在设置界面中:
|
||||
1. 打开 Docker Desktop 设置
|
||||
2. 导航到 “Docker Engine”
|
||||
3. 在 JSON 配置中添加上述 `registry-mirrors` 字段
|
||||
4. 点击 “Apply & Restart”
|
||||
|
||||
### 腾讯云容器镜像服务 (TCR)
|
||||
|
||||
腾讯云容器镜像服务 (TCR) 提供企业级容器镜像存储和分发能力:
|
||||
|
||||
- **私有镜像仓库**:支持命名空间隔离,完整的访问权限控制
|
||||
- **镜像扫描**:自动扫描镜像漏洞,提供安全建议
|
||||
- **镜像加速**:支持跨地域镜像分发和加速
|
||||
- **Webhook 通知**:镜像推送时自动触发 CI/CD 流程
|
||||
- **镜像版本管理**:标签管理、镜像清理策略、生命周期管理
|
||||
|
||||
#### 快速开始
|
||||
|
||||
1. 在腾讯云控制台创建个人版或企业版 TCR 实例
|
||||
2. 创建命名空间和镜像仓库
|
||||
3. 配置 Docker 登录凭证
|
||||
4. 本地构建镜像并推送到 TCR
|
||||
5. 在 TKE 集群部署时引用 TCR 镜像地址
|
||||
|
||||
#### 完整推送/拉取示例
|
||||
|
||||
```bash
|
||||
# 登录到腾讯云 TCR(使用 API 密钥)
|
||||
docker login ccr.ccs.tencentyun.com \
|
||||
--username <腾讯云账号ID> \
|
||||
--password <API_KEY>
|
||||
|
||||
# 拉取公开镜像
|
||||
docker pull ccr.ccs.tencentyun.com/library/nginx:latest
|
||||
|
||||
# 构建本地镜像
|
||||
docker build -t my-app:v1.0 .
|
||||
|
||||
# 标记镜像为 TCR 地址
|
||||
docker tag my-app:v1.0 \
|
||||
ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
|
||||
|
||||
# 推送镜像到 TCR
|
||||
docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
|
||||
|
||||
# 在 Dockerfile 中使用 TCR 镜像
|
||||
FROM ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
|
||||
RUN echo "使用腾讯云镜像作为基础镜像"
|
||||
```
|
||||
|
||||
#### TKE 集群中使用 TCR 镜像
|
||||
|
||||
配置镜像拉取凭证后,在 Deployment 中直接引用 TCR 镜像:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-app-deployment
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: my-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: my-app
|
||||
spec:
|
||||
imagePullSecrets:
|
||||
- name: tcr-secret # 需提前创建该 Secret
|
||||
containers:
|
||||
- name: my-app
|
||||
image: ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## 16.3 阿里云
|
||||
|
||||
如图 13-3 所示,阿里云是国内主流云服务平台之一。
|
||||
如图 16-3:所示,阿里云是国内主流云服务平台之一。
|
||||
|
||||

|
||||
|
||||
图 13-3 阿里云标识
|
||||
图 16-3:阿里云标识
|
||||
|
||||
[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。
|
||||
|
||||
@@ -12,6 +12,260 @@
|
||||
|
||||
[阿里云容器服务 Kubernetes 版 ACK](https://www.aliyun.com/product/kubernetes?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
|
||||
|
||||

|
||||
<!-- 注意:原阿里云容器服务截图链接已失效,请参考阿里云官方文档获取最新界面截图 -->
|
||||
<!-- 原链接: https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png -->
|
||||
|
||||
图 13-4 阿里云容器服务示意图
|
||||
图 16-4:阿里云容器服务示意图(请访问 [阿里云容器服务 ACK 官方文档](https://help.aliyun.com/product/85222.html) 查看最新界面)
|
||||
|
||||
### 阿里云容器服务 ACK 简介
|
||||
|
||||
阿里云容器服务 Kubernetes 版 (ACK, Container Service for Kubernetes) 是一款托管式 Kubernetes 服务,基于开源 Kubernetes 构建,提供企业级的容器编排和管理能力。ACK 集成了阿里云存储、网络和安全能力,支持多种应用部署模式和持续交付流程。
|
||||
|
||||
### 基本使用步骤
|
||||
|
||||
#### 1. 创建集群
|
||||
|
||||
登录阿里云控制台,进入容器服务 > Kubernetes 集群:
|
||||
- 点击 “创建集群”,选择集群配置
|
||||
- 配置集群名称、地域、可用区和节点类型
|
||||
- 选择节点规格和数量(支持弹性伸缩)
|
||||
- 配置网络参数和安全设置
|
||||
- 完成创建,下载 kubeconfig 文件
|
||||
|
||||
```bash
|
||||
# 配置本地 kubectl
|
||||
export KUBECONFIG=/path/to/kubeconfig.yaml
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
#### 2. 部署容器应用
|
||||
|
||||
通过 Deployment 部署应用示例:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web-server
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: registry.cn-hangzhou.aliyuncs.com/myapp/web:v1
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
```
|
||||
|
||||
部署应用:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deployment.yaml
|
||||
kubectl get pods -o wide
|
||||
kubectl logs <pod-name>
|
||||
```
|
||||
|
||||
#### 3. 暴露服务
|
||||
|
||||
创建 Service 暴露应用:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: web-service
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: web
|
||||
```
|
||||
|
||||
应用:
|
||||
|
||||
```bash
|
||||
kubectl apply -f service.yaml
|
||||
kubectl get svc web-service
|
||||
```
|
||||
|
||||
### 阿里云 Docker 镜像加速器配置
|
||||
|
||||
为了加快从阿里云镜像源拉取官方镜像的速度,可以配置镜像加速器。阿里云为容器服务 ACK 用户提供了免费的镜像加速服务。
|
||||
|
||||
#### 获取加速器地址
|
||||
|
||||
登录阿里云容器镜像服务控制台,在 “镜像工具” > “镜像加速器” 中可获取个人的加速器地址(类似于 `https://xxxxxx.mirror.aliyuncs.com`)。
|
||||
|
||||
#### Linux 系统配置
|
||||
|
||||
编辑或创建 `/etc/docker/daemon.json` 文件:
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/docker
|
||||
sudo nano /etc/docker/daemon.json
|
||||
```
|
||||
|
||||
添加或修改以下内容(替换为你的加速器地址):
|
||||
|
||||
```json
|
||||
{
|
||||
"registry-mirrors": [
|
||||
"https://xxxxxx.mirror.aliyuncs.com"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
重新加载并重启 Docker:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
||||
验证配置生效:
|
||||
|
||||
```bash
|
||||
docker info | grep -A 5 "Registry Mirrors"
|
||||
```
|
||||
|
||||
#### Windows/Mac 配置
|
||||
|
||||
在 Docker Desktop 的 Settings 中:
|
||||
1. 进入 “Docker Engine” 标签
|
||||
2. 编辑 JSON 配置,添加 `registry-mirrors` 字段
|
||||
3. 点击 “Apply & Restart”
|
||||
|
||||
#### 测试加速效果
|
||||
|
||||
```bash
|
||||
# 从加速器拉取镜像(速度应该明显提升)
|
||||
docker pull nginx:latest
|
||||
time docker pull alpine:latest
|
||||
```
|
||||
|
||||
### 阿里云容器镜像服务 (ACR)
|
||||
|
||||
阿里云容器镜像服务 (ACR, Container Registry) 是企业级的容器镜像存储和分发平台:
|
||||
|
||||
- **私有镜像仓库**:支持多个命名空间,细粒度权限控制
|
||||
- **镜像构建**:云端编译和构建,支持自动化 CI/CD
|
||||
- **镜像扫描**:自动检测镜像中的漏洞和恶意代码
|
||||
- **跨地域复制**:支持镜像在多个地域的同步和加速
|
||||
- **集成 ACK**:与 ACK 无缝集成,自动身份认证
|
||||
- **镜像版本管理**:标签管理、镜像过期清理、保留策略
|
||||
|
||||
#### 完整推送/拉取示例
|
||||
|
||||
```bash
|
||||
# 登录阿里云镜像仓库(使用 Docker 登录)
|
||||
# 使用阿里云账户 ID 和 RAM 访问密钥或密码
|
||||
docker login registry.cn-hangzhou.aliyuncs.com \
|
||||
--username=<阿里云账户ID>
|
||||
|
||||
# 拉取阿里云公开镜像
|
||||
docker pull registry.cn-hangzhou.aliyuncs.com/library/nginx:latest
|
||||
|
||||
# 构建本地镜像
|
||||
docker build -t my-app:v1.0 .
|
||||
|
||||
# 标记镜像为阿里云仓库地址
|
||||
docker tag my-app:v1.0 \
|
||||
registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
|
||||
|
||||
# 推送镜像到阿里云 ACR
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
|
||||
|
||||
# 在 Dockerfile 中使用 ACR 镜像
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
|
||||
COPY . /app
|
||||
RUN echo "已成功使用阿里云镜像"
|
||||
```
|
||||
|
||||
#### ACK 集群中使用 ACR 镜像
|
||||
|
||||
在 ACK 集群中,需要先配置镜像拉取凭证(Secret),然后在 Deployment 中引用:
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web-server
|
||||
namespace: default
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web
|
||||
spec:
|
||||
# 如果是私有镜像,需配置镜像拉取凭证
|
||||
imagePullSecrets:
|
||||
- name: acr-secret
|
||||
containers:
|
||||
- name: web
|
||||
image: registry.cn-hangzhou.aliyuncs.com/myapp/web:v2.0
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
resources:
|
||||
requests:
|
||||
memory: "256Mi"
|
||||
cpu: "100m"
|
||||
limits:
|
||||
memory: "512Mi"
|
||||
cpu: "500m"
|
||||
affinity:
|
||||
# 配置 Pod 反亲和性,分散到不同节点
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- web
|
||||
topologyKey: kubernetes.io/hostname
|
||||
```
|
||||
|
||||
#### 创建镜像拉取凭证
|
||||
|
||||
在 ACK 集群中创建 Secret,用于拉取私有镜像:
|
||||
|
||||
```bash
|
||||
# 创建镜像拉取 Secret
|
||||
kubectl create secret docker-registry acr-secret \
|
||||
--docker-server=registry.cn-hangzhou.aliyuncs.com \
|
||||
--docker-username=<阿里云账户ID> \
|
||||
--docker-password=<RAM访问密钥或密码> \
|
||||
--docker-email=<邮箱地址>
|
||||
|
||||
# 查看创建的 Secret
|
||||
kubectl get secret acr-secret
|
||||
kubectl describe secret acr-secret
|
||||
```
|
||||
|
||||
#### ACR 优势
|
||||
|
||||
- 在 ACK 集群中与镜像仓库无缝集成,简化身份认证
|
||||
- 支持 Helm Chart 存储和版本管理,方便应用交付
|
||||
- 提供完整的图形化镜像仓库管理界面
|
||||
- 完整的审计日志和操作追踪功能
|
||||
- 支持镜像自动扫描和漏洞报告
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## 16.4 亚马逊云
|
||||
|
||||
如图 13-1 所示,AWS 是全球主流云服务平台之一。
|
||||
如图 16-5:所示,AWS 是全球主流云服务平台之一。
|
||||
|
||||

|
||||
|
||||
图 13-1 AWS 标识
|
||||
图 16-5:AWS 标识
|
||||
|
||||
[AWS](https://www.amazonaws.cn),即 Amazon Web Services,是亚马逊 (Amazon) 公司的 IaaS 和 PaaS 平台服务。AWS 提供了一整套基础设施和应用程序服务,使用户几乎能够在云中运行一切应用程序:从企业应用程序和大数据项目,到社交游戏和移动应用程序。AWS 面向用户提供包括弹性计算、存储、数据库、应用程序在内的一整套云计算服务,能够帮助企业降低 IT 投入成本和维护成本。
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
|
||||

|
||||
|
||||
图 13-2 AWS 容器服务示意图
|
||||
图 16-6:AWS 容器服务示意图
|
||||
|
||||
@@ -3,3 +3,11 @@
|
||||
Docker 目前已经得到了众多公有云平台的支持,并成为除虚拟机之外的核心云业务。
|
||||
|
||||
除了 AWS、Google、Azure 等,国内的各大公有云厂商,基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务。有的还推出了其他服务,例如[容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61)让用户在云上享有安全高效的镜像托管、分发等服务。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [简介](16.1_intro.md)
|
||||
* [腾讯云](16.2_tencentCloud.md)
|
||||
* [阿里云](16.3_alicloud.md)
|
||||
* [亚马逊云](16.4_aws.md)
|
||||
* [多云部署策略](16.5_multicloud.md)
|
||||
|
||||
@@ -11,3 +11,6 @@
|
||||
* 利用公有云和 Docker 的特性更加方便的迁移和扩展应用。
|
||||
|
||||
同时,容器将作为与虚拟机类似的业务直接提供给用户使用,极大的丰富了应用开发和部署的场景。
|
||||
---
|
||||
|
||||
> 📝 **发现错误或有改进建议?** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。
|
||||
|
||||
@@ -21,8 +21,3 @@ FCOS 使用 rpm-ostree 系统进行事务性升级。无需像 yum 升级那样
|
||||
#### 容器工具
|
||||
|
||||
对于诸如构建,复制和其他管理容器的任务,FCOS 用一组容器工具代替了 **Docker CLI**。**podman CLI** 工具支持许多容器运行时功能,例如运行,启动,停止,列出和删除容器和镜像。**skopeo CLI** 工具可以复制,认证和签名镜像。您还可以使用 **crictl CLI** 工具来处理 CRI-O 容器引擎中的容器和镜像。
|
||||
|
||||
### 17.1.2 参考文档
|
||||
|
||||
* [官方文档](https://docs.fedoraproject.org/en-US/fedora-coreos/)
|
||||
* [openshift 官方文档](https://docs.openshift.com/container-platform/4.3/architecture/architecture-rhcos.html)
|
||||
|
||||
@@ -47,7 +47,3 @@ $ ssh core@虚拟机IP
|
||||
|
||||
$ docker --version
|
||||
```
|
||||
|
||||
### 17.2.6 参考链接
|
||||
|
||||
* [官方文档](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/)
|
||||
|
||||
Binary file not shown.
88
17_ecosystem/17.4_buildah.md
Normal file
88
17_ecosystem/17.4_buildah.md
Normal file
@@ -0,0 +1,88 @@
|
||||
## 17.4 Buildah - 容器镜像构建工具
|
||||
|
||||
本节介绍 Buildah,包括其基础概念、应用场景以及基本指令。
|
||||
|
||||
### Buildah 简介
|
||||
|
||||
Buildah 是一个用于构建 OCI(Open Container Initiative)兼容格式容器镜像的开源命令行工具。与 Docker 需要一直运行的守护进程(daemon)不同,Buildah 的设计初衷是无需守护进程(daemonless)即可工作,并且也不强制要求 root 权限(rootless)。这使得在持续集成/持续部署(CI/CD)环境中构建镜像时能够更加轻量且安全。
|
||||
|
||||
Buildah 由 Red Hat 主导开发,通常和 Podman、Skopeo 一起使用,被认为是构建、运行和管理容器的一套现代化工具链。在很多需要增强安全性和无需依赖守护进程的场景中,Buildah 是 `docker build` 命令的最佳替代方案。
|
||||
|
||||
### 核心特性
|
||||
|
||||
- **无守护进程(Daemonless)**:Buildah 直接通过系统调用拉取、构建和推送镜像,减少了单点故障的风险和资源开销。
|
||||
- **构建效率高**:可以挂载镜像的根文件系统到本地,并直接利用宿主机的工具对其进行操作,非常灵活。
|
||||
- **兼容性**:不仅支持处理传统的 Dockerfile,还能完全兼容 OCI(Open Container Initiative)标准和 Docker 格式。
|
||||
- **与 Podman 集成**:Podman 自身构建镜像的命令 `podman build` 底层实际上也是依赖 Buildah 库来实现的。
|
||||
|
||||
### 安装 Buildah
|
||||
|
||||
在许多主流的 Linux 发行版中都可以通过包管理器直接安装 Buildah。
|
||||
|
||||
以 Fedora/CentOS/RHEL 为例:
|
||||
|
||||
```bash
|
||||
$ sudo dnf install -y buildah
|
||||
```
|
||||
|
||||
以 Ubuntu/Debian 为例(需引入官方源后):
|
||||
|
||||
```bash
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get -y install buildah
|
||||
```
|
||||
|
||||
### 基础用法示例
|
||||
|
||||
#### 1. 从现有的 Dockerfile 构建镜像
|
||||
|
||||
Buildah 最常见的用法就是像 Docker 一样根据 `Dockerfile` 来构建镜像,可以直接使用 `buildah bud`(或者 `buildah build-using-dockerfile`)命令:
|
||||
|
||||
```bash
|
||||
$ buildah bud -t my-app:latest .
|
||||
```
|
||||
|
||||
可以看到在这点上,它与 `docker build` 的体验完全一致。
|
||||
|
||||
#### 2. 交互式从空镜像开始构建
|
||||
|
||||
除了使用 Dockerfile,Buildah 最强大的功能来自于它的交互式和脚本化构建机制。我们可以从一个极简的镜像(或基础镜像)开始构建:
|
||||
|
||||
```bash
|
||||
# 获取一个基础镜像
|
||||
$ container=$(buildah from alpine:latest)
|
||||
|
||||
# 获取挂载点,并查看其路径
|
||||
$ mnt=$(buildah mount $container)
|
||||
$ echo $mnt
|
||||
/var/lib/containers/storage/overlay/xxx/merged
|
||||
|
||||
# 利用宿主机直接创建文件,而不需要在容器内部运行命令
|
||||
$ echo "Hello Buildah" > $mnt/hello.txt
|
||||
|
||||
# 添加一些配置和命令
|
||||
$ buildah config --cmd "cat /hello.txt" $container
|
||||
|
||||
# 将容器提交为镜像
|
||||
$ buildah commit $container my-hello-image:latest
|
||||
|
||||
# 构建完成后可以卸载并清理容器上下文
|
||||
$ buildah unmount $container
|
||||
$ buildah rm $container
|
||||
```
|
||||
|
||||
这种模式在自动化流水线中极为有用,因为我们可以将上述过程编写成标准的 bash 脚本,无需为了构建镜像而撰写只在其独立语法中运行的 Dockerfile 指令。
|
||||
|
||||
#### 3. 查看和推送镜像
|
||||
|
||||
通过 `buildah images` 可以查看当前环境中的镜像。推送镜像到外部 Registry 也十分安全方便:
|
||||
|
||||
```bash
|
||||
# 查看本地构建的镜像
|
||||
$ buildah images
|
||||
|
||||
# 推送镜像到 Docker Hub(注意需要先登录)
|
||||
$ buildah push my-hello-image:latest docker://docker.io/username/my-hello-image:latest
|
||||
```
|
||||
|
||||
结合其无需特权和灵活脚本的优点,Buildah 正变得越来越受到构建和分发 OCI 镜像的用户喜爱。
|
||||
79
17_ecosystem/17.5_skopeo.md
Normal file
79
17_ecosystem/17.5_skopeo.md
Normal file
@@ -0,0 +1,79 @@
|
||||
## 17.5 Skopeo - 容器镜像管理工具
|
||||
|
||||
本节介绍 Skopeo,包括其基础概念、应用场景以及基本指令。
|
||||
|
||||
### Skopeo 简介
|
||||
|
||||
Skopeo 是一个由 Red Hat 赞助开源的命令行工具,它可以在不需要运行容器守护进程(如 Docker Daemon)的前提下,对容器镜像进行极其高效的操作和管理,包括:检查、复制、删除和签名等操作。
|
||||
|
||||
Skopeo 最大的特点是其可以在“不将镜像拉取到本地”的情况下,直接在远端 Registry(镜像仓库)之间完成检查和搬运,从而大幅度节省带宽和磁盘空间。这也是它在容器运维和分发领域非常受欢迎的原因。
|
||||
|
||||
### 核心特性
|
||||
|
||||
- **远程巡检**:通过 `skopeo inspect` 可以查看远端仓库中镜像的元数据(例如包含哪些层、环境变量信息、入口命令等),而完全无需拉取该镜像。
|
||||
- **镜像复制与同步**:支持各种格式之间的相互传输,如在不同的容器仓库之间、或者从仓库拉取到本地的目录、或者存储为 OCI 布局结构等。
|
||||
- **镜像删除**:可以远程删除仓库中的镜像(需要拥有权限)。
|
||||
- **签名验证**:支持在分发镜像前进行数字签名以保障安全性。
|
||||
|
||||
### 安装 Skopeo
|
||||
|
||||
类似于 Buildah,Skopeo 也直接包含在大部分主流的 Linux 源中。
|
||||
|
||||
在 Fedora/CentOS/RHEL 等发行版中:
|
||||
|
||||
```bash
|
||||
$ sudo dnf install -y skopeo
|
||||
```
|
||||
|
||||
在 Ubuntu/Debian 中:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get -y install skopeo
|
||||
```
|
||||
|
||||
如果是 macOS 环境,可以通过 Homebrew 安装:
|
||||
|
||||
```bash
|
||||
$ brew install skopeo
|
||||
```
|
||||
|
||||
### 基础用法示例
|
||||
|
||||
#### 1. 远程检查镜像
|
||||
|
||||
有时候我们只想知道远端镜像的详细信息,并不想拉取它。下面是检查 Docker Hub 上的 Alpine 镜像的例子:
|
||||
|
||||
```bash
|
||||
$ skopeo inspect docker://docker.io/library/alpine:latest
|
||||
```
|
||||
|
||||
这个命令会返回一段 JSON 格式的数据,其中包含了诸如镜像摘要(Digest)、创建时间、架构(Architecture)、标签(Tags)等丰富信息。在自动化的工具和系统审查环境中,这是一个不可或缺的利器。
|
||||
|
||||
#### 2. 同步与复制镜像
|
||||
|
||||
`skopeo copy` 是使用最为广泛的命令。它可以在不同的仓库、不同的格式之间无缝搬运镜像。
|
||||
|
||||
例如,从一个公共仓库直接搬运镜像到一个私有企业仓库(无需将其先 `docker pull` 到本地,再 `docker push`):
|
||||
|
||||
```bash
|
||||
$ skopeo copy docker://docker.io/library/alpine:latest docker://registry.example.com/library/alpine:latest
|
||||
```
|
||||
|
||||
又或者,你可以将远程镜像拉取到本地,只为了检查其拆解后的格式,比如将镜像解压到本地某个目录下以 OCI 规范存放:
|
||||
|
||||
```bash
|
||||
$ skopeo copy docker://docker.io/library/alpine:latest oci:alpine-oci
|
||||
```
|
||||
|
||||
如果我们要将本地的某个目录下的打包好的镜像再次推向 Registry 或转换为其它存储类型也是完全支持的,诸如:
|
||||
- `docker://` 远端 Registry
|
||||
- `docker-archive:` / `docker-daemon:` Docker 对应的归档文件或本地守护进程
|
||||
- `oci:` / `oci-archive:` OCI 相关文件格式
|
||||
- `dir:` 本地纯目录
|
||||
|
||||
#### 3. 校验机制与安全
|
||||
|
||||
如果你不信任公开仓库上的镜像,或是需要通过特定的 TLS 证书和鉴权,Skopeo 的功能也是能很好的支持的,比如它可以直接传递诸如 `--src-creds` 或 `--dest-tls-verify=false` 等参数,这在进行网络隔离的复杂镜像搬运操作中常常会用到。
|
||||
|
||||
对于复杂的容器环境或那些纯粹用于镜像资产管理的节点来说,Skopeo 提供了一个直接而强大的数据“搬运工”。
|
||||
69
17_ecosystem/17.6_containerd.md
Normal file
69
17_ecosystem/17.6_containerd.md
Normal file
@@ -0,0 +1,69 @@
|
||||
## 17.6 containerd - 核心容器运行时
|
||||
|
||||
本节介绍 containerd,它是现代容器技术栈中最为核心的基础组件之一。了解 containerd 有助于更深入地理解 Docker 和 Kubernetes 的底层运行机制。
|
||||
|
||||
### containerd 简介
|
||||
|
||||
[containerd](https://containerd.io/) 是一个行业标准的容器运行时,它最初是由 Docker 引擎中剥离出来的一个核心组件,后来 Docker 将其捐赠给了云原生计算基金会(CNCF),目前已经是一个 CNCF 毕业(Graduated)项目。
|
||||
|
||||
它的主要职责是管理单个宿主机上完整的容器生命周期,包括:
|
||||
- 镜像的传输和存储
|
||||
- 容器执行和管理
|
||||
- 存储和网络接口的管理
|
||||
|
||||
简单来说,当你在使用 Docker 或者 Kubernetes 时,真正去底层调用操作系统接口(如 Linux 的 Namespace 和 Cgroups)来启动和管理容器进程的,往往是 containerd(及它所调用的 runc 组件)。
|
||||
|
||||
### 与 Docker 和 Kubernetes 的关系
|
||||
|
||||
理解 containerd,首先要理清它与用户日常操作的 Docker 以及 Kubernetes 的关系。
|
||||
|
||||
#### Docker 的架构
|
||||
|
||||
在早期,Docker 引擎是一个包含了所有功能的单体架构。随着技术的发展和标准化要求,Docker 将底层关于容器运行时的部分解耦出来,形成了 `containerd` 和 `runc`。
|
||||
|
||||
当你执行一个 `docker run` 命令时,调用链路大致如下:
|
||||
1. Docker Client 发送请求给 Docker Daemon(`dockerd`)。
|
||||
2. `dockerd` 将请求转发给 `containerd`。
|
||||
3. `containerd` 准备好镜像和容器的必要环境,然后调用 `runc`。
|
||||
4. `runc` 负责按照 OCI(Open Container Initiative)标准,拉起并运行真正的容器进程。
|
||||
|
||||
因此,Docker 现在实际上是构建在 containerd 之上的一个包含更多开发者友好特性(如构建镜像、Compose 管理等)的增强平台。
|
||||
|
||||
#### Kubernetes 与 CRI
|
||||
|
||||
Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行时的实现差异,引入了 CRI(Container Runtime Interface)标准。
|
||||
|
||||
- 早期版本中,Kubernetes 默认使用 docker 作为运行时,通过一个名为 `dockershim` 的桥接组件对接 Docker,Docker 再对接 containerd。
|
||||
- 随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了 `dockershim` 和 `dockerd` 的中间层。这就是为什么从 Kubernetes v1.24 开始“弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用 `dockershim`,底层依然在使用从 Docker 基因中诞生的 containerd。
|
||||
|
||||
### 为什么直接使用 containerd?
|
||||
|
||||
对普通应用开发者来说,Docker 依然是本地开发和测试的首选。但对于构建云平台、自动化流水线或深度管理 Kubernetes 集群的系统工程师来说,直接使用 containerd 可以带来:
|
||||
- **更高的性能与更少的开销**:去掉了 Docker Daemon 等附加组件的资源占用,链路更短。
|
||||
- **更强的稳定性**:作为专注于运行时的底层组件,它的核心功能极为稳定且更新受控。
|
||||
- **直接符合 Kubernetes CRI 标准**:在生产级 Kubernetes 集群中作为标准配置。
|
||||
|
||||
### 基础用法与工具介绍
|
||||
|
||||
不同于 `docker` 命令行工具,containerd 提供了不同的客户端来满足不同的使用场景:
|
||||
|
||||
- **ctr**:containerd 自带的调试用客户端。它功能比较基础,主要用于开发者在开发 containerd 时进行快速调试,一般不作为最终用户的日常管理工具。
|
||||
- **crictl**:Kubernetes 提供的 CRI 命令行工具。它用于排查 Kubernetes 节点上的容器和沙箱(Pod)问题。
|
||||
- **nerdctl**:这是一个由系统社区成员(主要是 containerd 项目的维护者)开发的,完全兼容 Docker CLI 体验的 containerd 命令行客户端。对于习惯了 `docker run/ps/build` 命令的用户来说,`nerdctl` 可以作为直接操作 containerd 的理想替代品,并且它还支持直接构建镜像(依赖 BuildKit)。
|
||||
|
||||
#### nerdctl 使用示例
|
||||
|
||||
安装完 containerd 和 nerdctl 后,你可以体验到几乎与 Docker 完全一致的命令行:
|
||||
|
||||
```bash
|
||||
# 启动一个 nginx 容器
|
||||
$ nerdctl run -d -p 8080:80 --name my-nginx nginx:alpine
|
||||
|
||||
# 查看运行中的容器
|
||||
$ nerdctl ps
|
||||
|
||||
# 查看本地镜像
|
||||
$ nerdctl images
|
||||
```
|
||||
|
||||
对于那些希望在生产服务器上剥离 Docker 庞大体积,但又想要保留类似 Docker 方便的命令行体验的用户,`containerd` + `nerdctl` 是一个极佳的组合。
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user