mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-08-10 08:27:25 +00:00
fix(content): harden Docker practice guide
This commit is contained in:
@@ -11,12 +11,9 @@
|
||||
"forwardPorts": [
|
||||
4000
|
||||
],
|
||||
"runArgs": [
|
||||
"--cap-add=SYS_ADMIN"
|
||||
],
|
||||
"postStartCommand": [
|
||||
"sh",
|
||||
"-cx",
|
||||
"pwd ; cd /workspaces/docker_practice ; mkdir -p ${PWD}/node_modules; mkdir -p ${PWD}/_book; mount --bind /srv/gitbook/node_modules ${PWD}/node_modules ; mount --bind /mnt ${PWD}/_book"
|
||||
"pwd ; cd /workspaces/docker_practice ; mkdir -p ${PWD}/node_modules ${PWD}/_book"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Check project rules
|
||||
run: python3 check_project_rules.py
|
||||
|
||||
- name: Check release metadata
|
||||
run: npm test
|
||||
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
|
||||
@@ -18,6 +18,8 @@ jobs:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Check project rules
|
||||
run: python3 check_project_rules.py
|
||||
- name: Check release metadata
|
||||
run: npm test
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
|
||||
@@ -22,6 +22,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Check project rules
|
||||
run: python3 check_project_rules.py
|
||||
|
||||
- name: Check release metadata
|
||||
run: npm test
|
||||
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
|
||||
@@ -14,6 +14,7 @@ package-lock.json
|
||||
|
||||
docker-compose.override.yml
|
||||
06_repository/demo/auth/nginx.htpasswd
|
||||
11_compose/demo/wordpress/secrets/
|
||||
|
||||
# Editor configs
|
||||
.obsidian/
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
> **版本说明**:本节示例基于 Docker v29.x 编写。示例中使用的 `nginx:alpine` 镜像标签为演示用途,请查阅 [Docker Hub - nginx](https://hub.docker.com/_/nginx) 确认最新可用版本。
|
||||
|
||||
开始前请先完成 [第 3 章安装 Docker](../03_install/README.md),并确认 `docker version` 与 `docker run hello-world` 可以正常执行。若你只是先浏览流程,可以读完本节后再回到安装章实践。
|
||||
|
||||
本节将通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。
|
||||
|
||||
### 为什么选择 Nginx + HTML 作为入门例子?
|
||||
|
||||
在学习 Docker 之前,我们先来理解为什么这个例子是最适合初学者的。Docker 的核心价值在于**一致性交付**——无论你在本地、云端还是他人的机器上运行容器,应用的行为都是完全一致的。这个 Nginx + 静态 HTML 的例子之所以被广泛采用,是因为它展现了 Docker 工作流的三个核心阶段:
|
||||
在学习 Docker 之前,我们先来理解为什么这个例子适合初学者。Docker 的核心价值在于**一致性交付**:在相同镜像、CPU 架构、内核能力、配置和外部依赖都满足的前提下,应用行为可以保持高度一致。这个 Nginx + 静态 HTML 的例子之所以被广泛采用,是因为它展现了 Docker 工作流的三个核心阶段:
|
||||
|
||||
1. **镜像定义(Image Layer)**:通过 Dockerfile 描述如何把应用打包成一个自包含的单元
|
||||
2. **镜像构建(Build)**:执行 `docker build`,Docker 根据 Dockerfile 逐层构建镜像
|
||||
|
||||
@@ -4,11 +4,11 @@ Docker 是彻底改变了软件开发和交付方式的革命性技术。本节
|
||||
|
||||
### 1.2.1 一句话理解 Docker
|
||||
|
||||
> **Docker 是一种轻量级的虚拟化技术,它让应用程序及其依赖环境可以被打包成一个标准化的单元,在任何地方都能一致地运行。** 如果用一个生活中的类比:**Docker 之于软件,就像集装箱之于货物**。
|
||||
> **Docker 是一种轻量级的虚拟化技术,它让应用程序及其依赖环境可以被打包成一个标准化的单元,在满足架构、内核能力和外部依赖前提的环境中高度一致地运行。** 如果用一个生活中的类比:**Docker 之于软件,就像集装箱之于货物**。
|
||||
|
||||
在集装箱发明之前,货物的运输是一件麻烦的事情——不同的货物需要不同的包装、不同的装卸方式,换一种运输工具就要重新装卸。集装箱的出现改变了这一切:无论里面装的是什么,集装箱的外形是标准的,可以用同样的方式装卸、堆放和运输。
|
||||
|
||||
Docker 做的事情类似:无论你的应用是用 Python、Java、Node.js 还是其他语言写的,无论它需要什么样的依赖库和环境,一旦被打包成 Docker 镜像,就可以用同样的方式在任何支持 Docker 的机器上运行。
|
||||
Docker 做的事情类似:无论你的应用是用 Python、Java、Node.js 还是其他语言写的,无论它需要什么样的依赖库和环境,一旦被打包成 Docker 镜像,就可以用同样的方式在兼容的 Docker 环境中运行。
|
||||
|
||||
### 1.2.2 Docker 的核心价值
|
||||
|
||||
|
||||
@@ -63,10 +63,10 @@ flowchart LR
|
||||
|
||||
#### 1. 环境一致性
|
||||
|
||||
Docker 镜像包含了应用运行所需的 **一切**:代码、运行时、系统工具、库、配置。这意味着:
|
||||
Docker 镜像包含了应用运行所需的大部分用户态依赖:代码、运行时、系统工具、库和默认配置。它不包含宿主机内核,也不能消除 CPU 架构、内核能力、外部服务、网络、卷和运行时配置差异。这意味着:
|
||||
|
||||
- ✅ 开发环境和生产环境完全一致
|
||||
- ✅ 不会再有 “在我机器上能跑” 的问题
|
||||
- ✅ 开发环境和生产环境可以显著减少差异
|
||||
- ✅ 大幅降低 “在我机器上能跑” 的问题
|
||||
- ✅ 新人入职,一条命令就能启动开发环境
|
||||
|
||||
```bash
|
||||
|
||||
@@ -50,9 +50,7 @@ $ sudo dnf -y install dnf-plugins-core
|
||||
执行下面的命令添加 `dnf` 软件源:
|
||||
|
||||
```bash
|
||||
$ sudo dnf config-manager \
|
||||
--add-repo \
|
||||
https://download.docker.com/linux/fedora/docker-ce.repo
|
||||
$ sudo dnf config-manager addrepo --from-repofile https://download.docker.com/linux/fedora/docker-ce.repo
|
||||
```
|
||||
如果需要测试版本的 Docker 请使用以下命令:
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ Registry Mirrors:
|
||||
|
||||
### 3.9.6 Kubernetes 官方镜像地址迁移
|
||||
|
||||
可以登录 [阿里云容器镜像服务](https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu&type=copy),在 **镜像中心** -> **镜像搜索** 中查找。
|
||||
可以登录 [阿里云容器镜像服务](https://www.aliyun.com/product/acr),在 **镜像中心** -> **镜像搜索** 中查找。
|
||||
|
||||
Kubernetes 社区已将官方镜像地址从 `k8s.gcr.io` 迁移到 `registry.k8s.io`。建议优先使用新地址。
|
||||
|
||||
@@ -108,4 +108,4 @@ $ docker pull registry.k8s.io/xxx
|
||||
|
||||
某些云服务商提供了 **仅供内部** 访问的镜像服务,当您的 Docker 运行在云平台时可以选择它们。
|
||||
|
||||
* [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)
|
||||
* [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/product/tke)
|
||||
|
||||
@@ -18,7 +18,7 @@ Docker Engine 主要提供 `stable` 和 `test` 两个更新频道;`test.docker
|
||||
|
||||
**开发环境**(本地开发机、测试服务器):
|
||||
|
||||
- 使用**脚本自动安装**或**包管理器直接安装**
|
||||
- 配置 **Docker 官方源后** 使用包管理器安装,或在一次性测试环境使用官方脚本自动安装
|
||||
- 如果你想快速上手,官方脚本(`get.docker.com`)是最便捷的选择
|
||||
- 国内用户注意:这一步一定要选对镜像源,否则网络卡顿会严重影响体验
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# syntax = docker/dockerfile:experimental
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM node:alpine as builder
|
||||
|
||||
@@ -6,24 +6,16 @@ WORKDIR /app
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
--mount=type=cache,target=/root/.npm,id=npm_cache \
|
||||
npm i --registry=https://registry.npmmirror.com
|
||||
RUN --mount=type=cache,target=/root/.npm,id=npm_cache \
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
COPY src /app/src
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
# --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
|
||||
npm run build
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
# COPY --from=builder /app/dist /app/dist
|
||||
|
||||
# 为了更直观的说明 from 和 source 指令,这里使用 RUN 指令
|
||||
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
|
||||
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
|
||||
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
|
||||
COPY --from=builder /app/dist /app/dist
|
||||
|
||||
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
|
||||
cat /docker-php-entrypoint
|
||||
@@ -32,6 +24,6 @@ RUN --mount=type=tmpfs,target=/temp \
|
||||
mount | grep /temp
|
||||
|
||||
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
|
||||
cat /root/.aws/credentials
|
||||
test -s /root/.aws/credentials && echo "credentials mounted"
|
||||
|
||||
# docker build -t test --secret id=aws,src=$PWD/aws.txt --progress=plain -f Dockerfile.buildkit .
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
本节介绍如何使用本地仓库。
|
||||
|
||||
[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文内容基于 [distribution/distribution](https://github.com/distribution/distribution) v2.x 版本。
|
||||
[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文示例沿用 [distribution/distribution](https://github.com/distribution/distribution) v2.x 兼容路径;新生产部署应评估 Distribution 3.x,并核对配置路径、迁移说明和生态兼容性。
|
||||
|
||||
### 6.2.1 安装运行 docker-registry
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
|
||||
```
|
||||
|
||||
> **版本说明**:使用 `registry:2` 表示 Docker Registry 2.x 版本,这是当前推荐的版本。旧版本 Registry 1.x 已停止维护,不建议使用。
|
||||
> **版本说明**:使用 `registry:2` 表示 Docker Registry 2.x 兼容示例。Distribution 3.x 已发布稳定版本;不要直接把本章 v2 配置原样套到 v3 生产环境,升级前应阅读迁移说明并做兼容测试。旧版本 Registry 1.x 已停止维护,不建议使用。
|
||||
这将使用官方的 `registry` 镜像来启动私有仓库。默认情况下,仓库会被创建在容器的 `/var/lib/registry` 目录下。你可以通过 `-v` 参数来将镜像文件存放在本地的指定路径。例如下面的例子将上传的镜像放到本地的 `/opt/data/registry` 目录。
|
||||
|
||||
```bash
|
||||
|
||||
@@ -116,7 +116,7 @@ health:
|
||||
storagedriver:
|
||||
enabled: true
|
||||
interval: 10s
|
||||
threshold: 3
|
||||
threshold: 3
|
||||
```
|
||||
|
||||
### 6.3.3 生成 http 认证文件
|
||||
@@ -156,7 +156,7 @@ volumes:
|
||||
|
||||
本书配套的 `06_repository/demo/` 也采用同样约定:容器内 registry 监听 `:5000`,宿主机通过 `443:5000` 暴露 HTTPS 服务。这样可以避免在容器内占用特权端口,同时仍让客户端使用 `https://docker.domain.com` 访问。
|
||||
|
||||
> **版本说明**:Compose 配置中明确指定 `registry:2` 版本。生产环境建议固定版本号(如 `registry:2.8.3`)而非使用 `latest`,以保证部署的可重复性。
|
||||
> **版本说明**:Compose 配置中明确指定 `registry:2` 版本。生产环境建议固定具体补丁版本(如 `registry:2.8.x`),并在新部署时评估 Distribution 3.x;不要使用 `latest`,以保证部署的可重复性。
|
||||
|
||||
### 6.3.5 修改 Hosts 文件
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
本章涉及的 Registry 和相关工具版本说明:
|
||||
|
||||
- **Docker Registry**:使用 `registry:2` 推荐版本,已停止维护的 `registry:1` 不建议使用
|
||||
- **Docker Registry / CNCF Distribution**:本章示例使用 `registry:2` 兼容路径;新生产部署应评估 Distribution 3.x,并核对配置路径、迁移说明和生态兼容性。已停止维护的 `registry:1` 不建议使用
|
||||
- **Nexus 3**:建议指定具体版本(如 `sonatype/nexus3:3.69`)而非 `latest`,避免自动升级带来的兼容性问题
|
||||
- **镜像标签规范**:
|
||||
- 生产环境推送至仓库时应明确指定版本号(如 `myapp:v1.0.0`)
|
||||
|
||||
@@ -59,7 +59,7 @@ LABEL maintainer="user@example.com" \
|
||||
|
||||
```docker
|
||||
LABEL org.opencontainers.image.authors="yeasy" \
|
||||
org.opencontainers.image.documentation="https://yeasy.gitbooks.io" \
|
||||
org.opencontainers.image.documentation="https://yeasy.gitbook.io/docker_practice/" \
|
||||
org.opencontainers.image.source="https://github.com/yeasy/docker_practice" \
|
||||
org.opencontainers.image.licenses="MIT"
|
||||
```
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
### 官方文档
|
||||
|
||||
* `Dockerfile` 官方参考手册:https://docs.docker.com/engine/reference/builder/
|
||||
* `Dockerfile` 官方参考手册:https://docs.docker.com/reference/dockerfile/
|
||||
|
||||
* `Dockerfile` 最佳实践指南:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
|
||||
* `Dockerfile` 最佳实践指南:https://docs.docker.com/build/building/best-practices/
|
||||
|
||||
* `Docker` 官方镜像 `Dockerfile` 库:https://github.com/docker-library/docs
|
||||
|
||||
|
||||
+29
-28
@@ -4,12 +4,12 @@
|
||||
|
||||
在开始前,让我们直言不讳:**在大多数情况下,你应该使用 COPY,而不是 ADD**。
|
||||
|
||||
`ADD` 在 `COPY` 基础上增加了两个额外功能,但这些功能往往引入复杂性而非便利:
|
||||
`ADD` 在 `COPY` 基础上增加了两个额外功能。它不是 `COPY` 的通用替代品,但在少数场景中更合适:
|
||||
|
||||
1. 自动解压 tar 压缩包(有时你想复制一个 .tar.gz 本身,而 ADD 会意外地解压它)
|
||||
2. 支持从 URL 下载文件(这个功能由于网络不稳定已被广泛认为是反模式)
|
||||
2. 支持从 URL 下载公开远程文件,并可配合 `--checksum` 做校验
|
||||
|
||||
**实践中的建议**:除非你明确需要自动解压功能(比如官方基础镜像构建根文件系统),否则始终使用 COPY。原因很简单——显式优于隐式。你的 Dockerfile 在 6 个月后被接手维护时,清晰的意图会让团队少走很多弯路。
|
||||
**实践中的建议**:本地普通文件默认用 COPY;本地 tar 自动解压或公开远程 artifact 下载并校验时用 ADD;需要认证、请求头、重试或自定义解压流程时用 `RUN curl/wget`。
|
||||
|
||||
### 7.3.1 基本语法
|
||||
|
||||
@@ -20,7 +20,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||||
`ADD` 在 `COPY` 基础上增加了两个功能:
|
||||
|
||||
1. 自动解压 tar 压缩包
|
||||
2. 支持从 URL 下载文件 (不推荐)
|
||||
2. 支持从 URL 下载文件
|
||||
|
||||
---
|
||||
|
||||
@@ -30,11 +30,11 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||||
|------|------|-----|
|
||||
| 复制本地文件 | ✅ | ✅ |
|
||||
| 自动解压 tar | ❌ | ✅ |
|
||||
| 支持 URL | ❌ | ✅ (不推荐)|
|
||||
| 支持 URL | ❌ | ✅ (公开 artifact 可配合校验使用)|
|
||||
| 行为可预测性 | ✅ 高 | ⚠️ 低 |
|
||||
| 推荐程度 | ✅ **优先使用** | 仅解压场景 |
|
||||
| 推荐程度 | ✅ **普通复制优先使用** | 解压、本地 Git/公开远程 artifact |
|
||||
|
||||
> **笔者建议**:除非需要自动解压 tar 文件,否则始终使用 COPY。明确的行为比隐式的魔法更好。
|
||||
> **笔者建议**:普通复制始终优先 COPY;只有当你明确需要 ADD 的额外语义时再使用 ADD,并把意图写清楚。
|
||||
|
||||
---
|
||||
|
||||
@@ -79,7 +79,7 @@ app.tar.gz 包含: /app/ 目录结果:
|
||||
```
|
||||
---
|
||||
|
||||
### 7.3.4 URL 下载功能:不推荐
|
||||
### 7.3.4 URL 下载功能:谨慎使用
|
||||
|
||||
#### 基本用法
|
||||
|
||||
@@ -89,32 +89,29 @@ app.tar.gz 包含: /app/ 目录结果:
|
||||
ADD https://example.com/app.zip /app/app.zip
|
||||
```
|
||||
|
||||
#### 为什么不推荐
|
||||
#### 使用边界
|
||||
|
||||
| 问题 | 说明 |
|
||||
| 场景 | 建议 |
|
||||
|------|------|
|
||||
| 权限固定 | 下载的文件权限为 600,通常需要额外 RUN 修改 |
|
||||
| 不会解压 | URL 下载的压缩包不会自动解压 |
|
||||
| 缓存问题 | URL 内容变化时不会重新下载 |
|
||||
| 层数增加 | 需要额外 RUN 清理 |
|
||||
| 公开、版本固定的远程 artifact | 使用 `ADD --checksum=sha256:... URL dest` |
|
||||
| 需要认证、请求头或复杂重试 | 使用 `RUN curl/wget` |
|
||||
| 下载后需要复杂解压、校验或清理 | 使用 `RUN curl/wget`,把流程显式写出 |
|
||||
| URL 内容可变但无校验 | 不建议直接写入 Dockerfile |
|
||||
|
||||
#### 推荐替代方案
|
||||
#### 推荐写法
|
||||
|
||||
```docker
|
||||
## ❌ 不推荐:使用 ADD 下载
|
||||
## ✅ 公开 artifact:使用 ADD 并固定校验值
|
||||
|
||||
ADD https://example.com/app.tar.gz /tmp/
|
||||
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
|
||||
RUN tar -xzf /tmp/app.tar.gz -C /app && rm /tmp/app.tar.gz
|
||||
|
||||
## ✅ 推荐:使用 RUN + curl
|
||||
## ✅ 需要认证、请求头或特殊处理:使用 RUN + curl
|
||||
|
||||
RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app
|
||||
```
|
||||
优势:
|
||||
`ADD --checksum` 的优势是缓存更精确,并且校验值直接绑定到 Dockerfile。`RUN curl/wget` 的优势是控制力更强,适合企业内网、认证下载或复杂处理。
|
||||
|
||||
- 一条 RUN 完成下载、解压、清理
|
||||
- 减少镜像层数
|
||||
- 更清晰的构建意图
|
||||
|
||||
---
|
||||
|
||||
@@ -139,6 +136,10 @@ ADD rootfs.tar.gz /
|
||||
## 解压应用包
|
||||
|
||||
ADD dist.tar.gz /app/
|
||||
|
||||
## 下载公开 artifact 并校验
|
||||
|
||||
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
|
||||
```
|
||||
|
||||
#### ❌ 不适合使用 ADD
|
||||
@@ -149,9 +150,9 @@ ADD dist.tar.gz /app/
|
||||
ADD package.json /app/ # ❌
|
||||
COPY package.json /app/ # ✅
|
||||
|
||||
## 下载文件(用 RUN + curl)
|
||||
## 需要认证或复杂下载逻辑(用 RUN + curl/wget)
|
||||
|
||||
ADD https://example.com/file / # ❌
|
||||
ADD https://example.com/file / # ❌ 无法传认证信息,也没有显式处理
|
||||
RUN curl -fsSL ... -o /file # ✅
|
||||
|
||||
## 需要保留 tar 不解压(用 COPY)
|
||||
@@ -203,14 +204,14 @@ COPY . /app/
|
||||
ADD app.tar.gz /app/
|
||||
```
|
||||
|
||||
#### 3. 不要用 ADD 下载文件
|
||||
#### 3. 远程 artifact 使用 ADD 时必须固定校验值
|
||||
|
||||
```docker
|
||||
## ❌ 避免
|
||||
## ✅ 公开 artifact
|
||||
|
||||
ADD https://example.com/file.tar.gz /tmp/
|
||||
ADD --checksum=sha256:<digest> https://example.com/file.tar.gz /tmp/file.tar.gz
|
||||
|
||||
## ✅ 推荐
|
||||
## ✅ 认证下载或复杂处理
|
||||
|
||||
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
|
||||
```
|
||||
|
||||
@@ -65,7 +65,7 @@ CMD echo $HOME
|
||||
|
||||
CMD ["sh", "-c", "echo $HOME"]
|
||||
```
|
||||
**优点**:可以使用环境变量、管道等 shell 特性
|
||||
**优点**:可以使用 `$HOME` 这类 shell 变量展开、管道等 shell 特性
|
||||
|
||||
**缺点**:主进程是 sh,信号无法正确传递给应用
|
||||
|
||||
@@ -77,7 +77,7 @@ CMD ["sh", "-c", "echo $HOME"]
|
||||
|------|----------|-----------|
|
||||
| 主进程 | 指定的程序 | `/bin/sh` |
|
||||
| 信号传递 | ✅ 正确 | ❌ 无法传递 |
|
||||
| 环境变量 | ❌ 需要 shell 包装 | ✅ 自动解析 |
|
||||
| `$VAR` shell 展开 | ❌ 不自动展开;环境变量仍会传入进程 | ✅ 自动展开 |
|
||||
| 推荐使用 | ✅ 大多数场景 | 需要 shell 特性时 |
|
||||
|
||||
#### 信号传递问题示例
|
||||
|
||||
@@ -212,7 +212,7 @@ ENV HOST=localhost \
|
||||
|
||||
#### Q:环境变量在 CMD 中不展开
|
||||
|
||||
exec 格式不会自动展开环境变量:
|
||||
exec 格式不会自动执行 shell 展开,因此命令参数里的 `$PORT` 会按字面值传给进程;但环境变量本身仍会注入进程环境,应用可以通过语言运行时读取。
|
||||
|
||||
```docker
|
||||
## ❌ 不会展开 $PORT
|
||||
|
||||
@@ -88,17 +88,17 @@ $ docker run -v /my/data:/var/lib/mysql mysql:8.4
|
||||
|
||||
### 7.8.5 VOLUME 在构建时的特殊行为
|
||||
|
||||
> ⚠️ **重要**:VOLUME 之后对该目录的修改会被丢弃!
|
||||
> ⚠️ **重要**:`VOLUME` 之后再写入该目录的构建语义取决于 builder。legacy builder 会丢弃这些修改;BuildKit 会保留。但运行容器时,一旦该路径挂载了卷,卷会遮蔽镜像内同路径的内容。
|
||||
|
||||
```docker
|
||||
FROM ubuntu
|
||||
VOLUME /data
|
||||
|
||||
## ❌ 这个文件不会出现在镜像中!
|
||||
## ⚠️ legacy builder 会丢弃;BuildKit 会保留,但运行时挂载卷会遮蔽它
|
||||
|
||||
RUN echo "hello" > /data/test.txt
|
||||
```
|
||||
**原因**:在构建过程中,VOLUME 指令会为该目录创建一个临时的匿名卷。后续 RUN 指令对该目录的写入实际发生在这个临时卷中,而非镜像层。当该 RUN 指令结束后,临时卷被丢弃,因此写入的内容不会保存到最终镜像中。注意:这与容器运行时创建的匿名卷是不同的——运行时创建的卷会在容器生命周期内持续存在。
|
||||
**原因**:旧 builder 会在构建过程中为该目录创建临时匿名卷,后续写入发生在临时卷中;BuildKit 则会把修改保留在镜像层。为了避免不同 builder 下出现不同结果,也为了避免运行时卷遮蔽镜像内初始化数据,不要把必须存在的初始化文件写在 `VOLUME` 之后。
|
||||
|
||||
#### 正确做法
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
| **FROM** | 指定基础镜像 | 必须是第一条指令 |
|
||||
| **RUN** | 在新层执行命令 | 合并命令、清理缓存以减小体积 |
|
||||
| **COPY** | 复制文件 | 优先使用,支持 `--from` |
|
||||
| **ADD** | 更高级的复制 | 自动解压 tar,不推荐用于下载 |
|
||||
| **ADD** | 更高级的复制 | 自动解压 tar;公开远程 artifact 应配合 `--checksum` |
|
||||
| **CMD** | 容器启动默认命令 | 可被 `docker run` 参数覆盖 |
|
||||
| **ENTRYPOINT** | 容器入口点 | 固定启动命令,CMD 作为默认参数 |
|
||||
| **ENV** | 设置环境变量 | 构建时 + 运行时均生效 |
|
||||
| **ARG** | 构建参数 | 仅构建时生效,FROM 后需重新声明 |
|
||||
| **VOLUME** | 定义匿名卷 | VOLUME 之后的修改会丢失 |
|
||||
| **VOLUME** | 定义匿名卷 | 运行时挂载会遮蔽镜像内目录;构建后续写入语义依赖 builder |
|
||||
| **EXPOSE** | 声明端口 | 仅文档作用,不自动映射 |
|
||||
| **WORKDIR** | 指定工作目录 | 替代 `RUN cd`,目录不存在会自动创建 |
|
||||
| **USER** | 指定运行用户 | 用户必须已存在,推荐 gosu |
|
||||
|
||||
@@ -122,6 +122,8 @@ $ docker run -d \
|
||||
|
||||
#### 场景四:共享 SSH 密钥
|
||||
|
||||
只读挂载可以防止容器修改主机密钥,但不能防止容器读取并外传密钥。只有在镜像完全可信、密钥作用域很窄且可随时轮换时,才考虑这种做法。更稳妥的方式是使用 SSH agent socket 转发、一次性 deploy key,或在 CI/构建场景中使用 BuildKit `--ssh`。
|
||||
|
||||
```bash
|
||||
## 挂载 SSH 密钥(只读)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ ghi789... none null local
|
||||
| **host** | 容器直接使用宿主机网络栈 | 需要最高网络性能时 |
|
||||
| **none** | 禁用网络 | 完全隔离的容器 |
|
||||
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
|
||||
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
|
||||
| **macvlan** | 容器拥有独立 MAC 地址 | Linux 主机上需要直接接入物理网络 |
|
||||
| **ipvlan** | 容器共享父接口 MAC,独享 IP | 同网段大量容器、对 MAC 数量受限的网络 |
|
||||
|
||||
### 9.2.2 Bridge 网络:默认
|
||||
@@ -45,6 +45,8 @@ $ docker run -d --network host nginx
|
||||
```
|
||||
这种模式下网络性能最高,但容器之间和宿主机之间没有网络隔离。
|
||||
|
||||
> 注意:host 网络优先用于明确需要高性能或大量端口的 Linux 主机场景。Docker Desktop 仅在较新版本中支持,且需要在设置中启用;使用 host 网络时 `-p` / `--publish` 端口映射不会生效。普通 Web 服务默认仍建议使用 bridge 网络并显式发布端口。
|
||||
|
||||
### 9.2.4 None 网络
|
||||
|
||||
使用 `--network none` 参数启动的容器只有 `lo` 回环网卡,完全没有外部网络连接。适用于只需要运行计算任务、不需要网络的容器。
|
||||
@@ -55,7 +57,11 @@ $ docker run -it --network none alpine ip addr
|
||||
inet 127.0.0.1/8 scope host lo
|
||||
```
|
||||
|
||||
### 9.2.5 数据流向
|
||||
### 9.2.5 Macvlan 与平台限制
|
||||
|
||||
Macvlan 适合少数需要让容器像物理主机一样直接出现在二层网络中的场景。它只支持 Linux 主机,不支持 Docker Desktop for Mac / Windows,也不支持 rootless 模式;多数云厂商网络会阻断或限制 macvlan。默认情况下,macvlan 容器与宿主机直接通信也需要额外路由或接口配置。
|
||||
|
||||
### 9.2.6 数据流向
|
||||
|
||||
容器网络中的数据流向可以分为以下几种情况:
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ $ docker run -d -p 8080:80 nginx
|
||||
|
||||
| 格式 | 含义 | 示例 |
|
||||
|------|------|------|
|
||||
| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80` (仅本机访问) |
|
||||
| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80` (仅 IPv4 本机访问) |
|
||||
| `ip::containerPort` | 绑定指定 IP 的随机端口 | `-p 127.0.0.1::80` |
|
||||
| `hostPort:containerPort` | 绑定所有 IP (0.0.0.0) 的特定端口 | `-p 8080:80` (默认) |
|
||||
| `containerPort` | 绑定所有 IP 的随机端口 | `-p 80` |
|
||||
| `hostPort:containerPort` | 绑定所有地址(通常包括 `0.0.0.0` 和 `[::]`)的特定端口 | `-p 8080:80` (默认) |
|
||||
| `containerPort` | 绑定所有地址的随机端口 | `-p 80` |
|
||||
|
||||
#### 2. 随机映射
|
||||
|
||||
@@ -93,14 +93,15 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
|
||||
|
||||
#### 1. 限制监听 IP
|
||||
|
||||
默认情况下,`-p 8080:80` 会监听 `0.0.0.0:8080`,这意味着任何人只要能连接你的宿主机 IP,就能访问该服务。
|
||||
默认情况下,`-p 8080:80` 会监听所有可用地址,常见输出包括 `0.0.0.0:8080` 和 `[::]:8080`。这意味着任何人只要能连接你的宿主机 IP,就能访问该服务。
|
||||
|
||||
如果不希望对外暴露 (例如数据库服务),应绑定到 `127.0.0.1`:
|
||||
如果不希望对外暴露 (例如数据库服务),应绑定到回环地址。IPv4 使用 `127.0.0.1`,IPv6 使用 `[::1]`:
|
||||
|
||||
```bash
|
||||
## 仅允许本机访问
|
||||
|
||||
$ docker run -d -p 127.0.0.1:3306:3306 mysql
|
||||
$ docker run -d -p '[::1]:3306:3306' mysql
|
||||
```
|
||||
|
||||
#### 2. 避免端口冲突
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**BuildKit** 是下一代的镜像构建组件,在 [moby/buildkit](https://github.com/moby/buildkit) 开源。
|
||||
|
||||
> **重要**:自 Docker 23 起,BuildKit 已成为 **默认稳定构建器**,无需手动启用。Docker Engine 29 进一步将 Containerd 镜像存储设为默认,提升与 Kubernetes 的互操作性。
|
||||
> **重要**:自 Docker 23 起,BuildKit 已成为 **默认稳定构建器**,无需手动启用。Docker Engine 29 在新安装场景中进一步将 containerd image store 设为默认,提升多平台镜像、SBOM/Provenance 等 OCI 元数据能力。
|
||||
|
||||
目前,Docker Hub 自动构建已经支持 BuildKit,具体请参考 [docker-practice/docker-hub-buildx](https://github.com/docker-practice/docker-hub-buildx)。
|
||||
|
||||
@@ -46,7 +46,7 @@ COPY --from=builder /app/dist /app/dist
|
||||
```
|
||||
使用多阶段构建,构建的镜像中只包含了目标文件夹 `dist`,但仍然存在一些问题,当 `package.json` 文件变动时,`RUN npm i && rm -rf ~/.npm` 这一层会重新执行,变更多次后,生成了大量的中间层镜像。
|
||||
|
||||
为解决这个问题,进一步的我们可以设想一个类似 **数据卷** 的功能,在镜像构建时把 `node_modules` 文件夹挂载上去,在构建完成后,这个 `node_modules` 文件夹会自动卸载,实际的镜像中并不包含 `node_modules` 这个文件夹,这样我们就省去了每次获取依赖的时间,大大增加了镜像构建效率,同时也避免了生成了大量的中间层镜像。
|
||||
为解决这个问题,可以把包管理器的下载缓存挂载到构建步骤中,例如 npm 的 `/root/.npm`。注意:`type=cache` 只能作为性能优化,不能成为构建正确性的前提。缓存目录可能被并发构建改写,也可能被 GC 清理,所以不要把 `node_modules`、编译产物等必须存在的内容只放在 cache mount 里。
|
||||
|
||||
`BuildKit` 提供了 `RUN --mount=type=cache` 指令,可以实现上边的设想。
|
||||
|
||||
@@ -59,35 +59,23 @@ WORKDIR /app
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
--mount=type=cache,target=/root/.npm,id=npm_cache \
|
||||
npm i --registry=https://registry.npmmirror.com
|
||||
RUN --mount=type=cache,target=/root/.npm,id=npm_cache \
|
||||
npm install --registry=https://registry.npmmirror.com
|
||||
|
||||
COPY src /app/src
|
||||
|
||||
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
|
||||
|
||||
## --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
|
||||
|
||||
npm run build
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
## COPY --from=builder /app/dist /app/dist
|
||||
|
||||
## 为了更直观的说明 from 和 source 指令,这里使用 RUN 指令
|
||||
|
||||
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
|
||||
# --mount=type=cache,target=/tmp/dist,from=my_app_dist,sharing=locked \
|
||||
|
||||
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
|
||||
COPY --from=builder /app/dist /app/dist
|
||||
```
|
||||
|
||||
第一个 `RUN` 指令执行后,`id` 为 `my_app_npm_module` 的缓存文件夹挂载到了 `/app/node_modules` 文件夹中。多次执行也不会产生多个中间层镜像。
|
||||
第一个 `RUN` 指令执行后,`id` 为 `npm_cache` 的缓存文件夹挂载到了 `/root/.npm`,后续构建可复用下载缓存。
|
||||
|
||||
第二个 `RUN` 指令执行时需要用到 `node_modules` 文件夹,`node_modules` 已经挂载,命令也可以正确执行。
|
||||
第二个 `RUN` 指令执行时,`node_modules` 已经作为上一层真实写入到 builder 阶段的文件系统中,构建不依赖缓存目录内容。
|
||||
|
||||
第三个 `RUN` 指令将上一阶段产生的文件复制到指定位置,`from` 指明缓存的来源,这里 `builder` 表示缓存来源于构建的第一阶段,`source` 指明缓存来源的文件夹。
|
||||
最后使用 `COPY --from=builder` 将上一阶段产生的文件复制到最终镜像。跨阶段复制构建产物应使用 `COPY --from`;如果只是临时读取上一阶段文件,可使用 `RUN --mount=type=bind,from=builder,source=/app/dist,target=/tmp/dist,ro`。
|
||||
|
||||
上面的 `Dockerfile` 中 `--mount=type=cache,...` 中指令作用如下:
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ Buildx 支持在构建时直接生成 SBOM (Software Bill of Materials),这对
|
||||
```bash
|
||||
$ docker buildx build --sbom=true -t myimage .
|
||||
```
|
||||
该命令会在构建结果中包含 SPDX 或 CycloneDX 格式的 SBOM 数据。
|
||||
该命令会把 SBOM 作为构建 attestation 附加到构建结果中;BuildKit 默认使用 SPDX SBOM attestation。需要 CycloneDX 文件时,可使用 Syft、Docker Scout 等工具另行生成或转换。
|
||||
|
||||
> **⚠️ 注意与失败模式**:
|
||||
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见,对底层的存储格式有前置要求:默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构。
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
## 11.2 安装与卸载
|
||||
|
||||
`Compose` 是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。
|
||||
`Compose` 是 Docker 官方的开源项目,负责实现本地或单机多容器应用的快速编排。跨主机集群编排应使用 Swarm、Kubernetes 或云厂商托管服务。
|
||||
|
||||
当前的 Compose 以 `docker compose` 子命令的形式提供。Docker Desktop 在 macOS、Windows 和 Linux 上默认包含它;如果你已经在 Linux 上单独安装了 Docker Engine 和 Docker CLI,也可以再安装 Compose CLI 插件。
|
||||
|
||||
### 11.2.1 Linux
|
||||
|
||||
在 Linux 上,你可以通过 Docker 官方发布页安装 Compose CLI 插件。把二进制文件保存到 `$DOCKER_CONFIG/cli-plugins/docker-compose`,并赋予执行权限即可。
|
||||
在 Linux 上,默认建议通过 Docker 官方软件仓库安装 Compose CLI 插件,这样可以随系统包管理器更新。
|
||||
|
||||
Ubuntu / Debian:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get update
|
||||
$ sudo apt-get install docker-compose-plugin
|
||||
```
|
||||
|
||||
Fedora / CentOS / RHEL 兼容发行版:
|
||||
|
||||
```bash
|
||||
$ sudo dnf install docker-compose-plugin
|
||||
```
|
||||
|
||||
如果是离线环境、需要锁定特定版本,或包管理器暂不覆盖你的架构,可以从 Docker 官方发布页手工安装。手工安装不会自动更新;下载 URL 中的版本号和架构(如 `x86_64`、`aarch64`)需要按目标机器替换。
|
||||
|
||||
```bash
|
||||
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
|
||||
$ mkdir -p $DOCKER_CONFIG/cli-plugins
|
||||
$ curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
$ curl -SL https://github.com/docker/compose/releases/download/v5.1.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
$ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
```
|
||||
|
||||
@@ -24,8 +39,12 @@ Docker Compose version v5.x.x
|
||||
|
||||
### 11.2.3 卸载
|
||||
|
||||
如果是二进制包方式安装的,删除二进制文件即可。
|
||||
如果是仓库方式安装,使用包管理器卸载;如果是二进制包方式安装,删除二进制文件即可。
|
||||
|
||||
```bash
|
||||
$ sudo apt-get remove docker-compose-plugin
|
||||
# 或
|
||||
$ sudo dnf remove docker-compose-plugin
|
||||
|
||||
$ rm $DOCKER_CONFIG/cli-plugins/docker-compose
|
||||
```
|
||||
|
||||
@@ -228,7 +228,7 @@ $ docker compose run --no-deps web python manage.py shell
|
||||
|
||||
#### `scale`
|
||||
|
||||
在当前 Compose CLI 中,更稳妥的扩缩容写法是通过 `docker compose up --scale` 完成。
|
||||
当前 Compose CLI 仍支持 `docker compose scale`。实际使用中,更常见也更便于和创建/重建流程放在一起的写法是通过 `docker compose up --scale` 完成。
|
||||
|
||||
例如:
|
||||
|
||||
@@ -238,7 +238,7 @@ $ docker compose up -d --scale web=3 --scale db=2
|
||||
|
||||
将启动 3 个容器运行 `web` 服务,2 个容器运行 `db` 服务。
|
||||
|
||||
> **说明**:有些旧环境或实验性入口中仍可能出现 `docker compose scale`,但它不应再被视为当前 Compose 的通用稳定默认命令。
|
||||
> **说明**:如果 Compose 文件为服务指定了 `container_name`,该服务无法扩展到多个容器。需要扩缩容的服务应使用 Compose 自动生成的容器名,并通过服务名做 DNS 访问。
|
||||
|
||||
一般的,当指定数目多于该服务当前实际运行容器,将新创建并启动容器;反之,将停止容器。
|
||||
|
||||
|
||||
@@ -582,6 +582,14 @@ $ docker compose --profile debug up # 启动 web + debug
|
||||
$ docker compose up # 仅启动 web
|
||||
```
|
||||
|
||||
也可以通过环境变量激活:
|
||||
|
||||
```bash
|
||||
$ COMPOSE_PROFILES=debug,test docker compose up
|
||||
```
|
||||
|
||||
如果在命令行里显式指定某个带 profile 的服务,Compose 会自动启动这个目标服务及其声明的依赖;但不会自动启动同一 profile 下的其它服务,除非也显式指定或通过 `--profile` / `COMPOSE_PROFILES` 启用。
|
||||
|
||||
### 11.5.35 读取变量
|
||||
|
||||
Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 `.env` 文件中的变量。
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
> - MySQL:8.4(可替换为其他 8.x 版本,或使用 MariaDB 替代)
|
||||
> - WordPress:latest(建议在生产环境指定具体版本,如 6.x)
|
||||
|
||||
WordPress 是全球最流行的内容管理系统 (CMS)。使用 Docker Compose 可以在几分钟内搭建一个包含数据库、Web 服务和持久化存储的生产级 WordPress 环境。
|
||||
WordPress 是全球最流行的内容管理系统 (CMS)。使用 Docker Compose 可以在几分钟内搭建一个包含数据库、Web 服务和持久化存储的本地练习/单机演示环境。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 第十一章 Docker Compose
|
||||
|
||||
`Docker Compose` 是 Docker 官方编排 (Orchestration) 项目之一,负责快速的部署分布式应用。
|
||||
`Docker Compose` 是 Docker 官方编排 (Orchestration) 项目之一,负责快速定义和启动本地或单机多容器应用。跨主机集群编排应交给 Swarm、Kubernetes 或云厂商托管服务。
|
||||
|
||||
> ⚠️ **重要提示:Compose V1 已停止支持**
|
||||
>
|
||||
|
||||
@@ -2,9 +2,18 @@
|
||||
services:
|
||||
|
||||
db:
|
||||
image: postgres
|
||||
image: postgres:16
|
||||
environment:
|
||||
POSTGRES_DB: django_db
|
||||
POSTGRES_USER: django_user
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U django_user -d django_db"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
web:
|
||||
build: .
|
||||
@@ -13,6 +22,13 @@ services:
|
||||
- .:/code
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
# 与书中 11.6 节一致:settings.py 从环境变量读取数据库密码
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
DATABASE_URL: postgres://django_user:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@db:5432/django_db
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
@@ -24,7 +24,7 @@ services:
|
||||
- db
|
||||
image: wordpress:latest
|
||||
ports:
|
||||
- "8000:80"
|
||||
- "127.0.0.1:8000:80"
|
||||
restart: always
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: db:3306
|
||||
|
||||
@@ -100,7 +100,7 @@ flowchart TD
|
||||
从 Docker Engine v29.x 开始,架构进一步简化和标准化:
|
||||
|
||||
- **Containerd 镜像存储 (Image Store)**:在 v29.x 的新安装场景中默认启用。Docker 直接使用 Containerd 的镜像管理能力,不再维护自己的一套 graphdriver。
|
||||
- **优势**:多平台镜像支持更好、镜像拉取更快 (lazy pulling)、与 K8s 共享镜像。
|
||||
- **优势**:多平台镜像支持更好,可保存 SBOM/Provenance 等 attestations,并可使用 containerd snapshotters 的 lazy pulling 等能力。
|
||||
- **实验性 nftables 支持**:随着主流 Linux 发行版逐步弃用 iptables,Docker v29.x 引入了实验性 nftables 后端。启用方式为 `dockerd --firewall-backend=nftables`,可直接创建 nftables 规则而无需依赖 iptables-nft 转换层。生产环境请谨慎使用。
|
||||
|
||||
---
|
||||
|
||||
@@ -92,11 +92,11 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device
|
||||
|
||||
| 存储后端 / 驱动 | 核心特性说明 | 推荐程度 |
|
||||
|---------|------|---------|
|
||||
| **containerd image store**| (v29.x 新一代默认后端,新装默认) 基于 containerd 的 snapshotters,原生支持 OCI image index、多架构镜像与 Attestations 构建溯源元数据存储。 | ✅**强烈推荐 (现代默认)** |
|
||||
| **containerd image store**| (v29.x 新一代默认后端,新装默认) 基于 containerd 的 snapshotters,原生支持 OCI image index、多架构镜像与 Attestations 构建溯源元数据存储;启用 `userns-remap` 时不可用。 | ✅**强烈推荐 (现代默认)** |
|
||||
| **overlay2**| (经典 Graph Driver) 传统架构下的现代 Linux 默认驱动,性能优秀,但在处理复杂溯源元数据(索引)时受限。 | ✅**推荐 (主要后备)** |
|
||||
| **aufs** | 早期默认,兼容性好 | 遗留系统 |
|
||||
| **aufs** | 早期默认,已从现代 Docker Engine 移除 | 历史资料 |
|
||||
| **btrfs**/**zfs** | 使用原生稳定文件系统快照能力 | 特定场景 |
|
||||
| **devicemapper** | 块设备级存储 | 遗留系统 (已被逐步弃用) |
|
||||
| **devicemapper** | 块设备级存储,已从现代 Docker Engine 移除 | 历史资料 |
|
||||
| **vfs** | 不使用 CoW,每层完整复制 | 仅测试 |
|
||||
|
||||
#### Classic Graph Drivers 与 Snapshotters 的核心差异
|
||||
@@ -104,7 +104,7 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device
|
||||
传统模型(如 `overlay2`)将镜像拉取解包的过程由 Docker 的 graph drivers 处理。而新的 `containerd image store` 则将这一职责彻底下放给了 `containerd` 自身的 `snapshotters`(底层在 Linux 发行版通常依然利用操作系统的 overlayfs)。这种架构改变带来了:
|
||||
|
||||
1. 本地免拉取查看多平台镜像 index manifest 与 attestations (SBOM、Provenance)。
|
||||
2. 避免了以前绕过 CRI 获取本地镜像的问题,带来更好的原生 Kubernetes 生态兼容性。
|
||||
2. 允许 Docker 使用 containerd snapshotters 管理镜像层,便于与现代 OCI 生态能力对齐。它不表示 kubelet/containerd 会自动复用 Docker 本地镜像;Kubernetes 镜像分发仍应以 registry、镜像拉取策略和运行时配置为准。
|
||||
|
||||
#### 查看当前存储驱动与后端
|
||||
|
||||
@@ -114,14 +114,14 @@ $ docker info | grep "Storage Driver"
|
||||
Storage Driver: overlay2
|
||||
|
||||
## 在 Engine v29.x 中,可以通过如下输出验证是否开启了 containerd 镜像后端:
|
||||
$ docker info | grep "containerd image store"
|
||||
containerd image store: true
|
||||
$ docker info -f '{{ .DriverStatus }}'
|
||||
[[driver-type io.containerd.snapshotter.v1]]
|
||||
```
|
||||
---
|
||||
|
||||
### 12.4.5 overlay2 工作原理
|
||||
|
||||
overlay2 是目前最推荐的存储驱动:
|
||||
在经典 graph driver 体系下,overlay2 仍是 Linux 上的主要推荐驱动;Docker Engine 29 新安装场景默认走 containerd image store/snapshotter。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
| 技术 | 作用 | 要点 |
|
||||
|------|------|------|
|
||||
| **Namespace** | 资源隔离 | PID、NET、MNT、UTS、IPC、USER 六种命名空间 |
|
||||
| **Namespace** | 资源隔离 | 常见核心包括 PID、NET、MNT、UTS、IPC、USER、Cgroup;Time namespace 通常默认不启用 |
|
||||
| **Cgroups** | 资源限制 | 限制 CPU、内存、磁盘 I/O、进程数 |
|
||||
| **Union FS** | 分层存储 | overlay2 为推荐驱动,支持 Copy-on-Write |
|
||||
| **Union FS** | 分层存储 | 镜像分层与 Copy-on-Write 是核心;Engine 29 新装默认 containerd image store,overlay2 是经典 graph driver 场景的主要后备 |
|
||||
|
||||
| Namespace | 隔离内容 | 一句话说明 |
|
||||
|-----------|---------|-----------|
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
图 13-2:Kubernetes 基本概念示意图
|
||||
|
||||
* 节点 (`Node`):一个节点是一个运行 Kubernetes 中的主机。
|
||||
* 容器组 (`Pod`):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷 (volume)。
|
||||
* 容器组 (`Pod`):Kubernetes 中最小的可部署和调度单元;一个 Pod 包含一个或多个紧密协作的容器,共享网络身份,并可共享一个或多个卷 (volume)。
|
||||
* 容器组生命周期 (`pod-states`):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略。
|
||||
* 服务 (`services`):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。
|
||||
* 卷 (`volumes`):一个卷就是一个目录,容器对其有访问权限。
|
||||
* 标签 (`labels`):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。
|
||||
* 接口权限 (`accessing_the_api`):端口,IP 地址和代理的防火墙规则。
|
||||
* web 界面 (`ux`):用户可以通过 web 界面操作 Kubernetes。
|
||||
* web 界面 (`ux`):用户可以通过 Headlamp 等仍在维护的 web 界面观察和操作 Kubernetes;历史 Dashboard 已停止维护。
|
||||
* 命令行操作 (`cli`):`kubectl` 命令。
|
||||
|
||||
### 13.2.1 节点
|
||||
@@ -82,7 +82,7 @@ $ kubectl drain worker-1 --ignore-daemonsets
|
||||
|
||||
### 13.2.2 容器组
|
||||
|
||||
在 Kubernetes 中,使用的最小调度单位是容器组 (Pod),它是创建、调度、管理的最小单位。一个 Pod 包含一个或多个紧密协作的容器,它们共享网络命名空间和存储卷。
|
||||
在 Kubernetes 中,使用的最小调度单位是容器组 (Pod),它是创建、调度、管理的最小单位。一个 Pod 包含一个或多个紧密协作的容器,它们共享网络命名空间,并可共享一个或多个存储卷。
|
||||
|
||||
Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理。当节点发生故障时,控制器会在其他可用节点上重新创建 Pod。
|
||||
|
||||
@@ -96,7 +96,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
|
||||
|
||||
在一个容器组中,容器都使用相同的网络地址和端口,可以通过本地网络来相互通信。每个容器组都有独立的 IP,可以通过网络来和其他物理主机或者容器通信。
|
||||
|
||||
容器组有一组存储卷 (挂载点),主要是为了让容器在重启之后可以不丢失数据。
|
||||
容器组可以挂载一组存储卷 (挂载点)。卷不只用于持久化,也可用于 `emptyDir` 临时交换、ConfigMap/Secret 投射、日志旁路收集等场景。真正需要跨 Pod 生命周期保留的数据,应使用 PersistentVolume / PersistentVolumeClaim 等持久化机制。
|
||||
|
||||
#### 容器组管理
|
||||
|
||||
@@ -121,7 +121,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
|
||||
|
||||
#### 容器组的生命状态
|
||||
|
||||
包括若干状态值:`Pending`、`Running`、`Succeeded`、`Failed`。
|
||||
Pod phase 包括若干状态值:`Pending`、`Running`、`Succeeded`、`Failed`、`Unknown`。
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
@@ -129,6 +129,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
|
||||
| **Running** | Pod 已被调度到节点,并且所有容器都已启动。至少有一个容器处于运行状态。|
|
||||
| **Succeeded** | Pod 中的所有容器都正常退出,且不会被重启。|
|
||||
| **Failed** | Pod 中的所有容器都已终止,且至少有一个容器以失败状态退出。|
|
||||
| **Unknown** | 集群无法获取 Pod 状态,常见原因是节点失联。|
|
||||
|
||||
#### 容器组生命周期与重启策略
|
||||
|
||||
@@ -140,7 +141,7 @@ Pod 的重启策略 (`restartPolicy`) 决定了容器退出后的行为:
|
||||
| **OnFailure** | 不重启 | 重启容器 |
|
||||
| **Never** | 不重启 | 不重启 |
|
||||
|
||||
当节点故障或不可达时,节点控制器会将该节点上所有 Pod 的状态标记为 `Failed`。如果这些 Pod 由 Deployment 等控制器管理,控制器会自动在其他节点上重新创建。
|
||||
当节点故障或不可达时,Pod 可能先表现为 `Unknown`,之后根据控制器、驱逐策略和垃圾回收机制转为 `Failed` 或被重新创建。如果这些 Pod 由 Deployment 等控制器管理,控制器会自动在其他节点上重新创建。
|
||||
|
||||
### 13.2.3 Deployment 与 ReplicaSet
|
||||
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
## 13.5 实战练习
|
||||
|
||||
本章将通过一个具体的案例:部署一个 Nginx 网站,并为其配置 Service 和 Ingress,来串联前面学到的知识。
|
||||
本章将通过一个具体的案例:部署一个 Nginx 网站,并为其配置 Service,来串联前面学到的知识。
|
||||
|
||||
开始前请先准备好可用的 Kubernetes 集群和 `kubectl` 上下文。你可以先完成 [14.3 Docker Desktop](../14_kubernetes_setup/14.3_docker-desktop.md) 或 [14.4 Kind](../14_kubernetes_setup/14.4_kind.md),并确认:
|
||||
|
||||
```bash
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
### 13.5.1 目标
|
||||
|
||||
1. 部署一个 Nginx Deployment。
|
||||
2. 创建一个 Service 暴露 Nginx。
|
||||
3. (可选) 通过 Ingress 访问服务。
|
||||
3. 通过端口转发或 NodePort 访问服务。
|
||||
|
||||
### 13.5.2 步骤 1:创建 Deployment
|
||||
|
||||
@@ -69,7 +75,15 @@ kubectl apply -f nginx-service.yaml
|
||||
```bash
|
||||
kubectl get svc nginx-service
|
||||
```
|
||||
如果输出端口是 `80:30080/TCP`,你可以通过 `http://<NodeIP>:30080` 访问 Nginx。
|
||||
如果输出端口是 `80:30080/TCP`,你可以通过 `http://<NodeIP>:30080` 访问 Nginx。Docker Desktop、Kind 等本地集群中,NodePort 到宿主机的可达性取决于集群实现;更稳定的本地访问方式是端口转发:
|
||||
|
||||
```bash
|
||||
kubectl port-forward svc/nginx-service 8080:80
|
||||
```
|
||||
|
||||
然后访问 `http://localhost:8080`。
|
||||
|
||||
> Ingress 只有在集群中已安装 Ingress controller 且配置了 IngressClass 时才会生效。当前练习只覆盖 Service;Ingress/Gateway API 建议在完成第 14 章后再单独练习。
|
||||
|
||||
### 13.5.4 步骤 3:模拟滚动更新
|
||||
|
||||
|
||||
@@ -171,13 +171,13 @@ $ sudo systemctl enable containerd
|
||||
$ sudo systemctl start containerd
|
||||
|
||||
$ sudo kubeadm init \
|
||||
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
|
||||
--pod-network-cidr 10.244.0.0/16 \
|
||||
--cri-socket unix:///run/containerd/containerd.sock \
|
||||
--v 5
|
||||
```
|
||||
|
||||
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关,这里以 `flannel` 为例,若后续部署其他类型的网络插件请更改此参数。
|
||||
* kubeadm 默认使用 `registry.k8s.io` 拉取 Kubernetes 控制平面镜像。受限网络环境可通过 kubeadm 配置文件中的 `imageRepository` 指向受信任镜像仓库;不要把第三方镜像仓库当成通用默认值。
|
||||
|
||||
> 若 `kubeadm` 预检失败,应按提示修复缺失依赖、内核参数、swap 或运行时配置。实验环境确需忽略预检时,只忽略明确理解且可接受的单项检查,不建议使用 `--ignore-preflight-errors=all`。
|
||||
|
||||
|
||||
@@ -197,14 +197,14 @@ $ sudo systemctl daemon-reload
|
||||
#### master
|
||||
|
||||
```bash
|
||||
$ sudo kubeadm init --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
|
||||
--pod-network-cidr 10.244.0.0/16 \
|
||||
$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16 \
|
||||
--cri-socket unix:///var/run/cri-dockerd.sock \
|
||||
--v 5
|
||||
```
|
||||
|
||||
* `--cri-socket unix:///var/run/cri-dockerd.sock` 参数指定使用 cri-dockerd 作为容器运行时接口。
|
||||
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关,这里以 `flannel` 为例,若后续部署其他类型的网络插件请更改此参数。
|
||||
* kubeadm 默认使用 `registry.k8s.io` 拉取 Kubernetes 控制平面镜像。受限网络环境可通过 kubeadm 配置文件中的 `imageRepository` 指向受信任镜像仓库;不要把第三方镜像仓库当成通用默认值。
|
||||
|
||||
> 若 `kubeadm` 预检失败,应按提示修复缺失依赖、内核参数、swap 或运行时配置。实验环境确需忽略预检时,只忽略明确理解且可接受的单项检查,不建议使用 `--ignore-preflight-errors=all`。
|
||||
|
||||
|
||||
@@ -4,15 +4,17 @@
|
||||
|
||||
### 14.3.1 启用 Kubernetes
|
||||
|
||||
在 Docker Desktop 设置页面,点击 `Kubernetes`,选择 `Enable Kubernetes`,稍等片刻,看到左下方 `Kubernetes` 变为 `running`,Kubernetes 启动成功。
|
||||
在 Docker Desktop 设置页面,进入 `Kubernetes`,创建或启用集群。较新的 Docker Desktop 可选择 `kind` 或 `kubeadm` 作为集群创建方式;日常本地开发优先选择 `kind`,因为它支持多节点和版本选择。
|
||||
|
||||

|
||||
|
||||
> 注意:Kubernetes 的镜像存储在 `registry.k8s.io`,如果国内网络无法直接访问,可以在 Docker Desktop 配置中的 `Docker Engine` 处配置镜像加速器,或者利用国内云服务商的镜像仓库手动拉取镜像并 retag。
|
||||
> 注意:Docker Desktop Kubernetes 的控制平面镜像默认从 Docker Hub 拉取,例如 `docker.io/docker/desktop-*` 或 `docker.io/kindest/node:<tag>`。如果企业网络不能访问 Docker Hub,应按 Docker Desktop 的 `KubernetesImagesRepository` 设置镜像仓库,并用 `docker desktop kubernetes images list`(Docker Desktop 4.44+)或 `docker ps` 确认实际镜像标签。普通 Docker Engine 的 `registry-mirrors` 不会自动改写这些控制平面镜像。
|
||||
|
||||
### 14.3.2 测试
|
||||
|
||||
```bash
|
||||
$ kubectl version
|
||||
$ kubectl config use-context docker-desktop
|
||||
$ kubectl get nodes
|
||||
```
|
||||
如果正常输出信息,则证明 Kubernetes 成功启动。
|
||||
如果 `kubectl get nodes` 显示节点为 `Ready`,则证明 Kubernetes 成功启动。
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
## 14.7 部署 Dashboard
|
||||
## 14.7 可视化管理界面
|
||||
|
||||
[Kubernetes Dashboard](https://github.com/kubernetes/dashboard) 是基于网页的 Kubernetes 用户界面。
|
||||
[Kubernetes Dashboard](https://github.com/kubernetes-retired/dashboard) 是历史上常用的 Kubernetes Web UI,但项目已停止维护。
|
||||
|
||||
> **注意**:原 `kubernetes/dashboard` 项目已于 2026 年 1 月 21 日归档停止维护。推荐使用 [Headlamp](https://headlamp.dev/) 等替代方案。以下内容仅供历史参考,基于归档前的最新 Helm 安装方式。
|
||||
> **注意**:Kubernetes 官方文档已将 Dashboard 标记为 deprecated and unmaintained,新安装建议考虑 [Headlamp](https://headlamp.dev/) 等仍在维护的替代方案。以下 Dashboard 内容仅供历史迁移或存量环境参考。
|
||||
|
||||

|
||||
|
||||
### 14.7.1 部署
|
||||
### 14.7.1 推荐替代:Headlamp
|
||||
|
||||
Headlamp 是 Kubernetes SIG UI 下的现代 Web UI,可通过 Helm 安装:
|
||||
|
||||
```bash
|
||||
$ helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
|
||||
$ helm install headlamp headlamp/headlamp --namespace kube-system
|
||||
```
|
||||
|
||||
本地访问时优先使用端口转发,避免直接把管理界面暴露到公网:
|
||||
|
||||
```bash
|
||||
$ kubectl -n kube-system port-forward svc/headlamp 4466:80
|
||||
```
|
||||
|
||||
### 14.7.2 历史 Dashboard 部署
|
||||
|
||||
Dashboard 7.0+ 版本仅支持通过 Helm 安装:
|
||||
|
||||
@@ -17,7 +32,7 @@ $ helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-da
|
||||
--create-namespace --namespace kubernetes-dashboard
|
||||
```
|
||||
|
||||
### 14.7.2 访问
|
||||
### 14.7.3 访问
|
||||
|
||||
通过端口转发访问 Dashboard:
|
||||
|
||||
@@ -27,19 +42,15 @@ $ kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-pro
|
||||
|
||||
然后在浏览器打开 `https://localhost:8443` 即可访问。
|
||||
|
||||
### 14.7.3 登录
|
||||
### 14.7.4 登录
|
||||
|
||||
为历史 Dashboard 创建只读服务账户并获取短期登录令牌。不要为 Dashboard 创建 `cluster-admin` 绑定;如果确实需要临时管理员权限,应走单独的 break-glass 审批和审计流程。
|
||||
|
||||
```bash
|
||||
$ kubectl create sa dashboard-readonly -n kubernetes-dashboard
|
||||
|
||||
$ kubectl create clusterrole dashboard-readonly \
|
||||
--verb=get,list,watch \
|
||||
--resource=pods,deployments,services,configmaps,namespaces,nodes
|
||||
|
||||
$ kubectl create clusterrolebinding dashboard-readonly \
|
||||
--clusterrole=dashboard-readonly \
|
||||
--clusterrole=view \
|
||||
--serviceaccount=kubernetes-dashboard:dashboard-readonly
|
||||
|
||||
$ kubectl create token dashboard-readonly -n kubernetes-dashboard --duration=1h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 第十四章 部署 Kubernetes
|
||||
|
||||
目前,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 支持在多种环境下使用,包括本地主机 (Ubuntu、Debian、CentOS、Fedora 等)、云服务 ([腾讯云 TKE](https://cloud.tencent.com/product/tke)、[阿里云 ACK](https://cn.aliyun.com/product/ack)、[百度云](https://cloud.baidu.com/product/cce.html)等)。
|
||||
|
||||
你可以使用以下几种方式部署 Kubernetes,接下来的小节会对各种方式进行详细介绍。
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* [Kind - Kubernetes IN Docker](14.4_kind.md)
|
||||
* [K3s - 轻量级 Kubernetes](14.5_k3s.md)
|
||||
* [一步步部署 Kubernetes 集群](14.6_systemd.md)
|
||||
* [部署 Dashboard](14.7_dashboard.md)
|
||||
* [可视化管理界面:Headlamp 与历史 Dashboard](14.7_dashboard.md)
|
||||
* [Kubernetes 命令行 kubectl](14.8_kubectl.md)
|
||||
|
||||
除了上述方式,企业生产环境中还有两个常见的部署工具值得关注:
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
### 延伸阅读
|
||||
|
||||
- [容器编排基础](../13_kubernetes_concepts/README.md):Kubernetes 核心概念
|
||||
- [Dashboard](14.7_dashboard.md):部署可视化管理界面
|
||||
- [可视化管理界面](14.7_dashboard.md):Headlamp 与历史 Dashboard 迁移参考
|
||||
- [kubectl](14.8_kubectl.md):命令行工具使用指南
|
||||
---
|
||||
|
||||
|
||||
@@ -136,7 +136,17 @@ docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
|
||||
|
||||
#### TKE 集群中使用 TCR 镜像
|
||||
|
||||
配置镜像拉取凭证后,在 Deployment 中直接引用 TCR 镜像:
|
||||
配置镜像拉取凭证后,在 Deployment 中直接引用 TCR 镜像。Secret 必须创建在使用它的 namespace 中;下面示例使用 `default` namespace。
|
||||
|
||||
```bash
|
||||
$ kubectl create secret docker-registry tcr-secret \
|
||||
--docker-server=ccr.ccs.tencentyun.com \
|
||||
--docker-username=<username> \
|
||||
--docker-password=<token-or-password> \
|
||||
--namespace=default
|
||||
```
|
||||
|
||||
> 安全提示:在命令行直接输入密码或 token 可能进入 shell 历史记录。生产环境可先 `docker login`,再基于受保护的 `~/.docker/config.json` 创建 `kubernetes.io/dockerconfigjson` Secret,或使用云厂商提供的托管凭据集成。
|
||||
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
图 16-3:阿里云标识
|
||||
|
||||
[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。
|
||||
[阿里云](https://www.aliyun.com/)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。
|
||||
|
||||
[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。
|
||||
[阿里云](https://www.aliyun.com/)的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。
|
||||
|
||||
[阿里云容器服务 Kubernetes 版 ACK](https://www.aliyun.com/product/kubernetes?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
|
||||
[阿里云容器服务 Kubernetes 版 ACK](https://cn.aliyun.com/product/ack) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
|
||||
|
||||
<!-- 注意:原阿里云容器服务截图链接已失效,请参考阿里云官方文档获取最新界面截图 -->
|
||||
<!-- 原链接: https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png -->
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
Docker 目前已经得到了众多公有云平台的支持,并成为除虚拟机之外的核心云业务。
|
||||
|
||||
除了 AWS、Google、Azure 等,国内的各大公有云厂商,基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务。有的还推出了其他服务,例如[容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61)让用户在云上享有安全高效的镜像托管、分发等服务。
|
||||
除了 AWS、Google、Azure 等,国内的各大公有云厂商,基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务。有的还推出了其他服务,例如[容器镜像服务](https://cloud.tencent.com/document/product/1141)让用户在云上享有安全高效的镜像托管、分发等服务。
|
||||
|
||||
## 本章内容
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
## 17.1 Fedora CoreOS 简介
|
||||
|
||||
> **版本说明**:Fedora CoreOS 定期发布更新。建议访问 [官方下载页面](https://getfedora.org/coreos/download/) 获取最新版本和兼容性信息。
|
||||
> **版本说明**:Fedora CoreOS 定期发布更新。建议访问 [官方下载页面](https://fedoraproject.org/coreos/download/) 获取最新版本和兼容性信息。
|
||||
|
||||
[Fedora CoreOS](https://getfedora.org/coreos/) 是一个自动更新的,最小的,整体的,以容器为中心的操作系统,不仅适用于集群,而且可独立运行,并针对运行 Kubernetes 进行了优化。它旨在结合 CoreOS Container Linux 和 Fedora Atomic Host 的优点,将 Container Linux 中的 [Ignition](https://github.com/coreos/ignition) 与 [rpm-ostree](https://github.com/coreos/rpm-ostree) 和 Project Atomic 中的 SELinux 强化等技术相集成。其目标是提供最佳的容器主机,以安全,大规模地运行容器化的工作负载。
|
||||
[Fedora CoreOS](https://fedoraproject.org/coreos/) 是一个自动更新的,最小的,整体的,以容器为中心的操作系统,不仅适用于集群,而且可独立运行,并针对运行 Kubernetes 进行了优化。它旨在结合 CoreOS Container Linux 和 Fedora Atomic Host 的优点,将 Container Linux 中的 [Ignition](https://github.com/coreos/ignition) 与 [rpm-ostree](https://github.com/coreos/rpm-ostree) 和 Project Atomic 中的 SELinux 强化等技术相集成。其目标是提供最佳的容器主机,以安全,大规模地运行容器化的工作负载。
|
||||
|
||||
### 17.1.1 FCOS 特性
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### 17.2.1 下载 ISO
|
||||
|
||||
在[下载页面](https://getfedora.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。
|
||||
在[下载页面](https://fedoraproject.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。
|
||||
|
||||
### 17.2.2 编写 Butane 配置
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
|
||||
> 为了缓解内核漏洞带来的威胁,生产环境务必保持宿主机 Linux 内核的及时修补与更新,或者借助诸如 gVisor、Kata Containers 等提供了独立内核的安全容器技术。同时,需要及时修补容器运行时(如 runC)的漏洞。2025 年 11 月披露的一系列 runC 容器逃逸漏洞(CVE-2025-31133、CVE-2025-52565、CVE-2025-52881)就表明,即使内核保持更新,运行时层的缺陷仍然可能导致容器隔离被突破。
|
||||
|
||||
通过命名空间,Docker 也能限制进程从外部环境获取信息。
|
||||
例如,由于进程环境被隔离,进程在内部其实是无法感知到外部宿主机的存在的。它既不能获取其他容器的进程列表,也无法通过网络与其他系统进行交互(除非经过配置)。
|
||||
例如,由于进程环境被隔离,进程在内部通常无法直接感知外部宿主机的进程和挂载命名空间。网络命名空间隔离的是网络栈;默认 bridge 网络通常允许容器主动访问外部网络,限制的是外部直接访问容器服务。若要限制出站访问,需要使用 `none` 网络、防火墙、Kubernetes NetworkPolicy 或运行时策略。
|
||||
|
||||
### 18.1.3 用户命名空间与提权防护
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ grype sbom:sbom.json --add-cpes-if-none
|
||||
|
||||
### 18.6.3 镜像签名与验证
|
||||
|
||||
镜像签名确保镜像的来源可信且未被篡改。两种主流方案是 Cosign 和 Notary。
|
||||
镜像签名确保镜像的来源可信且未被篡改。新项目通常优先评估 Cosign (Sigstore) 或 Notary Project 的 Notation;Docker Content Trust / Notary v1 属于历史路径。
|
||||
|
||||
#### Cosign - 现代签名解决方案
|
||||
|
||||
@@ -269,13 +269,25 @@ cosign verify --key cosign.pub "$IMAGE_DIGEST"
|
||||
# 在 GitHub Actions 等 CI 中无需存储密钥
|
||||
cosign sign --yes "$IMAGE_DIGEST"
|
||||
|
||||
# 验证时自动使用 OIDC 令牌验证身份
|
||||
# 验证时检查签名证书中的 OIDC 身份声明是否匹配预期 workflow 与 issuer
|
||||
cosign verify "$IMAGE_DIGEST" \
|
||||
--certificate-identity https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
|
||||
--certificate-oidc-issuer https://token.actions.githubusercontent.com
|
||||
```
|
||||
|
||||
#### Docker Content Trust 与 Notary
|
||||
#### Notary Project / Notation
|
||||
|
||||
Notation 是 Notary Project 的 OCI 签名工具,适合希望采用 CNCF Notary Project 规范、或使用 registry/云厂商原生集成的团队。与 Cosign 类似,生产环境应围绕不可变 digest 做签名和策略校验。
|
||||
|
||||
```bash
|
||||
# 签名已推送的镜像 digest
|
||||
notation sign myregistry.com/myapp@sha256:<digest>
|
||||
|
||||
# 验证签名
|
||||
notation verify myregistry.com/myapp@sha256:<digest>
|
||||
```
|
||||
|
||||
#### Docker Content Trust 与 Notary v1
|
||||
|
||||
> **注意:DCT 退役时间线**
|
||||
>
|
||||
@@ -283,7 +295,7 @@ cosign verify "$IMAGE_DIGEST" \
|
||||
>
|
||||
> 新项目应优先使用上文介绍的 **Cosign (Sigstore)** 或 registry 原生签名/证明能力;现有 DCT 用户应先盘点依赖、验证替代方案,再制定迁移计划。
|
||||
|
||||
Docker Content Trust 使用 Notary 实现镜像签名,是 Docker 官方的传统签名解决方案。
|
||||
Docker Content Trust 使用 Notary v1 实现镜像签名,是 Docker 官方的传统签名解决方案,不建议新项目采用。
|
||||
|
||||
**历史用法示例(不建议新项目采用):**
|
||||
|
||||
@@ -353,17 +365,7 @@ trivy image --scanners vuln,misconfig registry:5000/myapp:latest
|
||||
|
||||
**Harbor(私有镜像仓库)的安全扫描:**
|
||||
|
||||
```yaml
|
||||
# harbor.yml 配置示例
|
||||
trivy:
|
||||
enabled: true
|
||||
# 启用镜像扫描
|
||||
image_source: "Official"
|
||||
|
||||
# 默认扫描配置
|
||||
scan_on_push: true # 推送时自动扫描
|
||||
scan_all: true # 扫描仓库中的所有镜像
|
||||
```
|
||||
Harbor 的扫描器应在管理界面的 **Interrogation Services / Scanner** 中配置;推送自动扫描通常在项目级 **Configuration** 中启用。不要把扫描策略误写成通用 `harbor.yml` 顶层字段。实际部署时应按所用 Harbor 版本文档配置 scanner、项目策略和漏洞阻断阈值。
|
||||
|
||||
#### 5. 政策执行
|
||||
|
||||
@@ -427,13 +429,33 @@ jobs:
|
||||
if: github.event_name == 'push'
|
||||
uses: sigstore/cosign-installer@v3
|
||||
|
||||
- name: Build Docker image for scan
|
||||
- name: Login to Registry
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker image
|
||||
if: github.event_name == 'push'
|
||||
id: build-push
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
|
||||
- name: Build Docker image for pull request scan
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
load: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
tags: local/${{ env.IMAGE_NAME }}:pr
|
||||
|
||||
- name: Run Trivy vulnerability scan
|
||||
# 安全提醒:2026 年 3 月 19 日 Trivy GitHub Actions 遭受供应链攻击,
|
||||
@@ -441,7 +463,7 @@ jobs:
|
||||
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
|
||||
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
image-ref: ${{ github.event_name == 'push' && format('{0}/{1}@{2}', env.REGISTRY, env.IMAGE_NAME, steps.build-push.outputs.digest) || format('local/{0}:pr', env.IMAGE_NAME) }}
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
severity: 'HIGH,CRITICAL'
|
||||
@@ -454,7 +476,7 @@ jobs:
|
||||
- name: Generate SBOM
|
||||
uses: anchore/sbom-action@v0
|
||||
with:
|
||||
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
image: ${{ github.event_name == 'push' && format('{0}/{1}@{2}', env.REGISTRY, env.IMAGE_NAME, steps.build-push.outputs.digest) || format('local/{0}:pr', env.IMAGE_NAME) }}
|
||||
format: cyclonedx-json
|
||||
output-file: sbom-cyclonedx.json
|
||||
|
||||
@@ -464,23 +486,6 @@ jobs:
|
||||
name: sbom
|
||||
path: sbom-cyclonedx.json
|
||||
|
||||
- name: Login to Registry and Push
|
||||
if: github.event_name == 'push'
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Push image
|
||||
if: github.event_name == 'push'
|
||||
id: build-push
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
- name: Sign image with Cosign
|
||||
if: github.event_name == 'push'
|
||||
run: |
|
||||
@@ -529,7 +534,9 @@ generate:sbom:
|
||||
- syft docker-archive://image.tar -o cyclonedx > sbom.xml
|
||||
artifacts:
|
||||
reports:
|
||||
sbom: sbom.xml
|
||||
cyclonedx: sbom.xml
|
||||
|
||||
# 如需让 GitLab 安全面板摄取容器扫描结果,应输出 GitLab 兼容的 container_scanning 报告。
|
||||
|
||||
push:
|
||||
stage: push
|
||||
|
||||
@@ -66,7 +66,7 @@ services:
|
||||
- ./rules.yml:/etc/prometheus/rules.yml
|
||||
- prometheus_data:/prometheus
|
||||
ports:
|
||||
- "9090:9090"
|
||||
- "127.0.0.1:9090:9090"
|
||||
command:
|
||||
- --config.file=/etc/prometheus/prometheus.yml
|
||||
- --storage.tsdb.path=/prometheus
|
||||
@@ -77,9 +77,9 @@ services:
|
||||
grafana:
|
||||
image: grafana/grafana:13.0.1
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "127.0.0.1:3000:3000"
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD}
|
||||
networks:
|
||||
- monitoring
|
||||
depends_on:
|
||||
@@ -88,14 +88,14 @@ services:
|
||||
node-exporter:
|
||||
image: prom/node-exporter:v1.11.1
|
||||
ports:
|
||||
- "9100:9100"
|
||||
- "127.0.0.1:9100:9100"
|
||||
networks:
|
||||
- monitoring
|
||||
|
||||
cadvisor:
|
||||
image: ghcr.io/google/cadvisor:v0.56.2
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "127.0.0.1:8080:8080"
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
@@ -119,7 +119,9 @@ $ docker compose up -d
|
||||
启动后,访问以下地址:
|
||||
|
||||
* Prometheus: `http://localhost:9090`
|
||||
* Grafana:`http://localhost:3000` (默认账号密码:admin/admin,首次登录后务必立即修改密码)
|
||||
* Grafana:`http://localhost:3000` (账号为 `admin`,密码来自 `GRAFANA_ADMIN_PASSWORD`)
|
||||
|
||||
> 安全提示:cAdvisor 需要读取宿主机 `/sys`、`/var/run`、Docker 数据目录等路径才能采集容器指标;即使是只读挂载,也会暴露宿主机和容器元数据。只在受控监控节点使用,并把 Prometheus、Grafana、cAdvisor 端口绑定到本机或受保护网络。
|
||||
|
||||
### 19.1.3 配置 Grafana 面板
|
||||
|
||||
|
||||
@@ -42,8 +42,6 @@ services:
|
||||
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
|
||||
ports:
|
||||
- "5601:5601"
|
||||
links:
|
||||
- elasticsearch
|
||||
networks:
|
||||
- logging
|
||||
|
||||
@@ -59,8 +57,6 @@ services:
|
||||
ports:
|
||||
- "24224:24224"
|
||||
- "24224:24224/udp"
|
||||
links:
|
||||
- elasticsearch
|
||||
volumes:
|
||||
- ./fluentd/conf:/fluentd/etc
|
||||
networks:
|
||||
|
||||
@@ -6,44 +6,18 @@
|
||||
|
||||
#### 核心性能指标体系
|
||||
|
||||
容器性能监控涉及以下关键指标:
|
||||
容器性能监控涉及 Docker CLI、Prometheus/cAdvisor 指标和底层 cgroup 文件。现代 Linux 与 Kubernetes 新版本通常使用 cgroup v2;旧系统或兼容环境仍可能看到 cgroup v1 名称。
|
||||
|
||||
**CPU 相关指标:**
|
||||
|
||||
- `cpu.usage_usec`:容器 CPU 使用时间(微秒)
|
||||
- `cpu.stat.nr_throttled`:CPU 限流发生次数
|
||||
- `cpu.stat.throttled_usec`:CPU 限流总时间
|
||||
- `cpu_percent`:CPU 使用百分比
|
||||
- `cpu_quota`:CPU 配额设置(微秒)
|
||||
|
||||
**内存相关指标:**
|
||||
|
||||
- `memory.usage_bytes`:当前内存使用量
|
||||
- `memory.max_usage_bytes`:内存使用峰值
|
||||
- `memory.limit_in_bytes`:内存限制
|
||||
- `memory.fail_cnt`:OOM(Out of Memory)失败次数
|
||||
- `memory.stat.cache`:页面缓存占用
|
||||
- `memory.stat.rss`:实际内存占用(RSS)
|
||||
- `memory.stat.swap`:SWAP 使用量
|
||||
|
||||
**网络相关指标:**
|
||||
|
||||
- `rx_bytes`:接收字节数
|
||||
- `tx_bytes`:发送字节数
|
||||
- `rx_packets`:接收包数
|
||||
- `tx_packets`:发送包数
|
||||
- `rx_errors`:接收错误数
|
||||
- `tx_errors`:发送错误数
|
||||
- `rx_dropped`:接收丢包数
|
||||
- `tx_dropped`:发送丢包数
|
||||
|
||||
**I/O 相关指标:**
|
||||
|
||||
- `io_service_bytes`:I/O 操作字节数
|
||||
- `io_service_time`:I/O 操作耗时
|
||||
- `io_queued`:I/O 队列长度
|
||||
- `fs_limit_bytes`:文件系统限制
|
||||
- `fs_usage_bytes`:文件系统使用量
|
||||
| 类型 | Docker / Prometheus 常见指标 | cgroup v2 文件 | cgroup v1 兼容名 |
|
||||
|------|------------------------------|----------------|------------------|
|
||||
| CPU 使用 | `CPU %`、`container_cpu_usage_seconds_total` | `cpu.stat` 中的 `usage_usec` | `cpuacct.usage` |
|
||||
| CPU 限流 | `container_cpu_cfs_throttled_periods_total` | `cpu.stat` 中的 `nr_throttled`、`throttled_usec` | `cpu.stat.nr_throttled`、`cpu.stat.throttled_time` |
|
||||
| 内存使用 | `MEM USAGE`、`container_memory_working_set_bytes` | `memory.current` | `memory.usage_in_bytes` |
|
||||
| 内存限制 | `MEM USAGE / LIMIT` | `memory.max` | `memory.limit_in_bytes` |
|
||||
| OOM 次数 | `container_oom_events_total` 或运行时事件 | `memory.events` 中的 `oom` / `oom_kill` | `memory.failcnt` |
|
||||
| 网络收发 | `NET I/O`、`container_network_receive_bytes_total` / `transmit_bytes_total` | 网络命名空间接口计数 | `rx_bytes` / `tx_bytes` |
|
||||
| 块 I/O | `BLOCK I/O`、`container_fs_*` / `container_blkio_*` | `io.stat` | `blkio.throttle.io_service_bytes` |
|
||||
| 文件系统 | `container_fs_usage_bytes` / `container_fs_limit_bytes` | 运行时或文件系统采集 | `fs_usage_bytes` / `fs_limit_bytes` |
|
||||
|
||||
### 19.3.2 使用 docker stats 实时监控
|
||||
|
||||
@@ -246,6 +220,16 @@ networks:
|
||||
```
|
||||
**Prometheus 配置文件(prometheus.yml):**
|
||||
|
||||
如果需要采集 Docker daemon 自身指标,需要先在 Docker daemon 配置中开启 metrics:
|
||||
|
||||
```json
|
||||
{
|
||||
"metrics-addr": "127.0.0.1:9323"
|
||||
}
|
||||
```
|
||||
|
||||
Prometheus 运行在容器里并使用 `host.docker.internal:9323` 抓取时,daemon 必须监听容器可达的主机地址;若改为 `0.0.0.0:9323`,会把指标端口暴露给更大网络,必须配合防火墙和可信网络边界。
|
||||
|
||||
```yaml
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
|
||||
@@ -72,6 +72,8 @@ jobs:
|
||||
ghcr.io/${{ github.repository }}:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
provenance: mode=max
|
||||
sbom: true
|
||||
```
|
||||
|
||||
关键说明:
|
||||
@@ -79,6 +81,7 @@ jobs:
|
||||
* `docker/login-action` 负责认证,支持 Docker Hub、GHCR、ECR 等主流 Registry。
|
||||
* `cache-from` / `cache-to` 使用 GitHub Actions 原生缓存(`type=gha`),无需额外配置即可加速增量构建。
|
||||
* 标签同时使用 commit hash 和 `latest`,兼顾版本追溯与部署便利。
|
||||
* `provenance: mode=max` 和 `sbom: true` 会把构建来源证明和 SBOM 附加到推送的镜像上;只做本地 `load: true` 的构建无法完整保留这些 attestation。
|
||||
|
||||
### 21.2.3 最佳实践
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
本小节以 `GitHub` + `Drone` 来演示 `Drone` 的工作流程。
|
||||
当然在实际开发过程中,你的代码也许不在 GitHub 托管,那么你可以尝试使用 `Gogs` + `Drone` 来进行 CI/CD。
|
||||
|
||||
> 安全提示:Docker runner 如果挂载宿主机 `/var/run/docker.sock`,流水线就具备近似宿主机 root 的控制能力。下面配置只适合可信代码、单租户、本地演示环境;生产环境应使用隔离的临时 runner/虚拟机、Kubernetes runner、rootless 方案或更严格的权限边界,并为不同项目隔离密钥。
|
||||
|
||||
### 21.3.1 关联项目
|
||||
|
||||
在 GitHub 新建一个名为 `drone-demo` 的仓库。
|
||||
|
||||
@@ -557,6 +557,8 @@ client-output-buffer-limit pubsub 32mb 8mb 60
|
||||
|
||||
**三层微服务架构示例:**
|
||||
|
||||
> 下面示例聚焦服务拓扑、网络、健康检查和资源限制。为便于阅读,密码仍通过环境变量串接;生产环境应改用 Compose secrets、外部密钥系统或云厂商密钥服务,并避免把敏感值写入 `DATABASE_URL` / `REDIS_URL`。
|
||||
|
||||
```yaml
|
||||
services:
|
||||
# 前端服务
|
||||
@@ -564,7 +566,6 @@ services:
|
||||
build:
|
||||
context: ./frontend
|
||||
dockerfile: Dockerfile
|
||||
container_name: frontend
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
@@ -586,7 +587,6 @@ services:
|
||||
build:
|
||||
context: ./api
|
||||
dockerfile: Dockerfile
|
||||
container_name: api
|
||||
ports:
|
||||
- "8000:8000"
|
||||
environment:
|
||||
@@ -619,7 +619,6 @@ services:
|
||||
# PostgreSQL 数据库
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: postgres
|
||||
environment:
|
||||
POSTGRES_DB: myappdb
|
||||
POSTGRES_USER: appuser
|
||||
@@ -641,7 +640,6 @@ services:
|
||||
# Redis 缓存
|
||||
redis:
|
||||
image: redis:8-alpine
|
||||
container_name: redis
|
||||
command: ["sh", "-c", "redis-server --appendonly yes --requirepass \"$$REDIS_PASSWORD\""]
|
||||
environment:
|
||||
REDIS_PASSWORD: ${REDIS_PASSWORD:?set REDIS_PASSWORD}
|
||||
@@ -659,7 +657,6 @@ services:
|
||||
# Nginx 反向代理
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
|
||||
@@ -25,6 +25,7 @@ services:
|
||||
depends_on:
|
||||
- drone-server
|
||||
volumes:
|
||||
# Trusted single-tenant demo only: Docker socket access is host-root equivalent.
|
||||
- /var/run/docker.sock:/var/run/docker.sock:rw
|
||||
environment:
|
||||
- DRONE_RPC_PROTO=http
|
||||
|
||||
@@ -48,10 +48,10 @@
|
||||
graph LR
|
||||
Start[Docker 学习入口] --> Ch1[第1章:Docker 简介]
|
||||
|
||||
Ch1 --> Role1["运维新手<br/>第1-4章"]
|
||||
Ch1 --> Role2["开发者<br/>第1-3章 → 第5-8章"]
|
||||
Ch1 --> Role3["DevOps 工程师<br/>第1章 → 第9-14章 → 第18章"]
|
||||
Ch1 --> Role4["架构师<br/>第1章 → 第15-21章"]
|
||||
Ch1 --> Role1["运维新手<br/>第1-6章"]
|
||||
Ch1 --> Role2["开发者<br/>第1-8章 → 第11章"]
|
||||
Ch1 --> Role3["DevOps 工程师<br/>第1-11章 → 第13-14章 → 第18-21章"]
|
||||
Ch1 --> Role4["架构师<br/>第1-6章 → 第12-17章 → 第18-19章"]
|
||||
|
||||
Role1 --> End1["掌握基本操作"]
|
||||
Role2 --> End2["构建与部署应用"]
|
||||
@@ -60,14 +60,14 @@ graph LR
|
||||
```
|
||||
| 读者角色 | 学习重点 | 核心成果 |
|
||||
|---------|---------|---------|
|
||||
| **运维新手** | 第1-4章 | 掌握容器的基本概念与操作 |
|
||||
| **开发者** | 第1-3章 → 第5-8章 | 学会容器化应用的构建与部署 |
|
||||
| **DevOps 工程师** | 第1章 → 第9-14章 → 第18章 | 实现容器编排与自动化部署流程 |
|
||||
| **架构师** | 第1章 → 第15-21章 | 设计高可用、高性能的容器基础设施 |
|
||||
| **运维新手** | 第1-6章 | 掌握容器的基本概念与操作 |
|
||||
| **开发者** | 第1-8章 → 第11章 | 学会容器化应用的构建与部署 |
|
||||
| **DevOps 工程师** | 第1-11章 → 第13-14章 → 第18-21章 | 实现容器编排与自动化部署流程 |
|
||||
| **架构师** | 第1-6章 → 第12-17章 → 第18-19章 | 设计高可用、高性能的容器基础设施 |
|
||||
|
||||
## 在线阅读
|
||||
|
||||
本书在线阅读,可直接访问 [GitBook](https://yeasy.gitbook.io/docker_practice/)。也可访问 [GitHub 仓库目录](https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md) 或 [镜像站点](https://vuepress.mirror.docker-practice.com/)。
|
||||
本书在线阅读,可直接访问 [GitBook](https://yeasy.gitbook.io/docker_practice/)。也可访问 [GitHub 仓库目录](https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md)。
|
||||
|
||||
## 下载离线版本
|
||||
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@
|
||||
* [14.4 Kind - Kubernetes IN Docker](14_kubernetes_setup/14.4_kind.md)
|
||||
* [14.5 K3s - 轻量级 Kubernetes](14_kubernetes_setup/14.5_k3s.md)
|
||||
* [14.6 一步步部署 Kubernetes 集群](14_kubernetes_setup/14.6_systemd.md)
|
||||
* [14.7 部署 Dashboard](14_kubernetes_setup/14.7_dashboard.md)
|
||||
* [14.7 可视化管理界面](14_kubernetes_setup/14.7_dashboard.md)
|
||||
* [14.8 Kubernetes 命令行 kubectl](14_kubernetes_setup/14.8_kubectl.md)
|
||||
* [本章小结](14_kubernetes_setup/summary.md)
|
||||
* [第十五章 Etcd 项目](15_etcd/README.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## 附录四:Dockerfile 最佳实践
|
||||
|
||||
本附录是笔者对 Docker 官方文档中 [Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) 的理解与翻译。
|
||||
本附录是笔者对 Docker 官方文档中 [Building best practices](https://docs.docker.com/build/building/best-practices/) 的理解与翻译。
|
||||
|
||||
### 一般性的指南和建议
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ $ docker network create -d bridge --subnet 172.25.0.0/16 my-net
|
||||
$ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox
|
||||
```
|
||||
|
||||
这个固定 IP 主要用于同一 Docker daemon 内的容器间通信。Docker Desktop 上不要依赖宿主机直接访问 Linux 容器 IP;宿主机访问容器服务仍应使用端口映射或 `host.docker.internal` 等机制。
|
||||
|
||||
### 如何临时退出一个正在交互的容器的终端,而不终止它?
|
||||
|
||||
答:按 `Ctrl-p Ctrl-q`。如果按 `Ctrl-c` 往往会让容器内应用进程终止,进而会终止容器。
|
||||
|
||||
@@ -116,8 +116,8 @@ Docker Compose
|
||||
**学习资源:**
|
||||
|
||||
- 本书第 4-11 章:进阶篇
|
||||
- [Docker 官方最佳实践](https://docs.docker.com/develop/dev-best-practices/)
|
||||
- [Dockerfile 参考](https://docs.docker.com/engine/reference/builder/)
|
||||
- [Docker 官方最佳实践](https://docs.docker.com/build/building/best-practices/)
|
||||
- [Dockerfile 参考](https://docs.docker.com/reference/dockerfile/)
|
||||
|
||||
**时间投入:**
|
||||
|
||||
@@ -477,7 +477,7 @@ Kubernetes 进阶 (Week 24-36)
|
||||
# 1. 学习本书第 1-11 章(基础到中级)
|
||||
# 2. 完成 20+ 个实战项目
|
||||
# 3. 参考官方学习指南
|
||||
# 参考 KodeKloud DCA 认证指南:https://kodekloud.com/blog/docker-certified-associate-guide/
|
||||
# 参考 Docker 官方学习入口:https://www.docker.com/resources/
|
||||
|
||||
# 4. 模拟考试
|
||||
- Linux Academy DCA 练习题
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
```bash
|
||||
$ docker run --name some-redis -d -p 6379:6379 redis
|
||||
```
|
||||
另外还可以启用[持久存储](https://redis.io/topics/persistence)。
|
||||
另外还可以启用[持久存储](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)。
|
||||
|
||||
```bash
|
||||
$ docker run --name some-redis -d -p 6379:6379 redis redis-server --appendonly yes
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* [Docker CLI 参考](https://docs.docker.com/engine/reference/commandline/docker/)
|
||||
* [Dockerfile 参考](https://docs.docker.com/reference/dockerfile/)
|
||||
* [Docker 构建最佳实践](https://docs.docker.com/build/building/best-practices/)
|
||||
* [Docker 远端应用 API](https://docs.docker.com/develop/sdk/)
|
||||
* [Docker 远端应用 API](https://docs.docker.com/reference/api/engine/sdk/)
|
||||
* [Docker 存储文档](https://docs.docker.com/engine/storage/)
|
||||
* [Docker 网络文档](https://docs.docker.com/engine/network/)
|
||||
|
||||
|
||||
@@ -24,15 +24,3 @@ services:
|
||||
vuepress-offline:
|
||||
<< : *mdpress-offline
|
||||
image: dockerpracticesig/docker_practice:vuepress
|
||||
|
||||
# developer test docker image
|
||||
|
||||
development:
|
||||
build: ./.travis
|
||||
image: yeasy/docker_practice:latest
|
||||
ports:
|
||||
- 4000:4000
|
||||
volumes:
|
||||
- ./:/srv/gitbook-src
|
||||
command: server
|
||||
# command: build
|
||||
|
||||
Reference in New Issue
Block a user