mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-08-16 19:37:27 +00:00
Compare commits
64
Commits
v1.9.2
..
32f5c53d76
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32f5c53d76 | ||
|
|
109112d146 | ||
|
|
233b0ca96f | ||
|
|
11369ba10a | ||
|
|
0dadce28d9 | ||
|
|
9de6b523c4 | ||
|
|
abd4f6e5cd | ||
|
|
8f13ff9dfa | ||
|
|
89a66c645a | ||
|
|
89bbbe94a5 | ||
|
|
2917ec2f27 | ||
|
|
423b6c7060 | ||
|
|
0aba9e50a9 | ||
|
|
109733421f | ||
|
|
e641ff3c90 | ||
|
|
8440b48566 | ||
|
|
12070a093d | ||
|
|
b16aa3976e | ||
|
|
396cdf0744 | ||
|
|
e3861040ec | ||
|
|
f4fa272dc5 | ||
|
|
57b203832f | ||
|
|
b0408f633b | ||
|
|
73f29570d4 | ||
|
|
73d230f3b7 | ||
|
|
7d2ab6cd28 | ||
|
|
a101822a00 | ||
|
|
dacb3d9c7e | ||
|
|
b34cb3c9ba | ||
|
|
b628da8dba | ||
|
|
1ee3a4f97f | ||
|
|
67695cd45b | ||
|
|
e6459efb63 | ||
|
|
2d7740ffb5 | ||
|
|
771d75ac03 | ||
|
|
9c47ee5dd4 | ||
|
|
2392090f8b | ||
|
|
1836416263 | ||
|
|
7cb55a0dd6 | ||
|
|
d57fb34102 | ||
|
|
258ef59727 | ||
|
|
14851771a8 | ||
|
|
787c2adf57 | ||
|
|
029da9f946 | ||
|
|
b0d4b23744 | ||
|
|
6a876694a9 | ||
|
|
69d46f78d5 | ||
|
|
969f371091 | ||
|
|
dd4e7c91e8 | ||
|
|
456918e31f | ||
|
|
5c225e6c58 | ||
|
|
ecd1e696eb | ||
|
|
78ae7ad641 | ||
|
|
e9f315147c | ||
|
|
dd0368e926 | ||
|
|
80772a1e97 | ||
|
|
6eecb5118d | ||
|
|
ce466273be | ||
|
|
ec2897feab | ||
|
|
0455c5e233 | ||
|
|
28f49b6dc1 | ||
|
|
d0e1a20411 | ||
|
|
fae0a7a092 | ||
|
|
9074524eaa |
@@ -16,13 +16,9 @@ jobs:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
chrome-version: stable
|
||||
- name: Install CJK fonts
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
|
||||
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
|
||||
|
||||
- name: Install mdpress (latest)
|
||||
run: |
|
||||
|
||||
@@ -17,13 +17,9 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
chrome-version: stable
|
||||
- name: Install CJK fonts
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
|
||||
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
|
||||
- name: Install mdpress (latest)
|
||||
run: |
|
||||
LATEST_TAG=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" https://api.github.com/repos/yeasy/mdpress/releases/latest | jq -r .tag_name)
|
||||
|
||||
@@ -23,13 +23,9 @@ jobs:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Install Chromium and CJK fonts
|
||||
uses: browser-actions/setup-chrome@v2
|
||||
with:
|
||||
chrome-version: stable
|
||||
- name: Install CJK fonts
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
|
||||
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
|
||||
|
||||
- name: Install mdpress (latest)
|
||||
run: |
|
||||
|
||||
@@ -172,7 +172,7 @@ registry.example.com/myproject/myapp:v1.2.3
|
||||
|
||||
## 简写(使用 Docker Hub)
|
||||
|
||||
nginx:1.28
|
||||
nginx:1.25
|
||||
ubuntu:24.04
|
||||
|
||||
## 省略标签(默认使用 latest)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## 2.3 仓库
|
||||
|
||||
> **版本说明**:本节示例基于 Docker v29.x 和常见镜像版本编写。示例中的版本号(如 `nginx:1.28`、`mysql:8.4`、`mysql:5.7` 等)为演示用途。实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
|
||||
> **版本说明**:本节示例基于 Docker v29.x 和常见镜像版本编写。示例中的版本号(如 `nginx:1.25`、`mysql:8.0`、`mysql:5.7` 等)为演示用途。实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
|
||||
|
||||
Docker Registry 是镜像分发和管理的核心组件。本节将介绍 Registry 的基本概念、公共和私有服务的选择,以及镜像的安全管理。
|
||||
|
||||
@@ -25,8 +25,8 @@ flowchart TB
|
||||
subgraph RepoNginx ["Repository(仓库): nginx"]
|
||||
direction LR
|
||||
N1(":latest (tag)")
|
||||
N2(":1.28 (tag)")
|
||||
N3(":1.26 (tag)")
|
||||
N2(":1.25 (tag)")
|
||||
N3(":1.24 (tag)")
|
||||
N4(":alpine (tag)")
|
||||
N5("...")
|
||||
N1 ~~~ N2 ~~~ N3 ~~~ N4 ~~~ N5
|
||||
@@ -50,7 +50,7 @@ flowchart TB
|
||||
|------|------|------|
|
||||
| **Registry** | 存储镜像的服务 | Docker Hub、ghcr.io |
|
||||
| **Repository (仓库)** | 同一软件的镜像集合 | `nginx`、`mysql`、`mycompany/myapp` |
|
||||
| **Tag (标签)** | 仓库内的版本标识 | `latest`、`1.28`、`alpine` |
|
||||
| **Tag (标签)** | 仓库内的版本标识 | `latest`、`1.25`、`alpine` |
|
||||
|
||||
#### 镜像的完整名称
|
||||
|
||||
@@ -73,7 +73,7 @@ registry.example.com/mycompany/myapp:v1.2.3
|
||||
|
||||
## Docker Hub 官方镜像(省略 registry 和用户名)
|
||||
|
||||
nginx:1.28
|
||||
nginx:1.25
|
||||
ubuntu:24.04
|
||||
|
||||
## Docker Hub 用户镜像
|
||||
@@ -131,7 +131,7 @@ Google 的 Container Registry 已废弃并完成下线,当前应优先使用 A
|
||||
|
||||
由于网络原因,在国内直接访问 Docker Hub 可能会很慢。可以配置 **镜像加速器** (Registry Mirror) 来加速下载。配置示例如下:
|
||||
|
||||
```jsonc
|
||||
```json
|
||||
// /etc/docker/daemon.json
|
||||
{
|
||||
"registry-mirrors": [
|
||||
@@ -217,7 +217,7 @@ $ docker login registry.example.com # 登录其他 Registry
|
||||
|
||||
## 拉取镜像
|
||||
|
||||
$ docker pull nginx:1.28
|
||||
$ docker pull nginx:1.25
|
||||
|
||||
## 标记镜像(准备推送)
|
||||
|
||||
@@ -261,9 +261,9 @@ someuser/myapp # ⚠️ 需要评估
|
||||
|
||||
```bash
|
||||
## 准备一个你有写权限的镜像地址
|
||||
$ export IMAGE=<你的仓库名>/nginx:1.28
|
||||
$ docker pull nginx:1.28
|
||||
$ docker tag nginx:1.28 $IMAGE
|
||||
$ export IMAGE=<你的仓库名>/nginx:1.27
|
||||
$ docker pull nginx:1.27
|
||||
$ docker tag nginx:1.27 $IMAGE
|
||||
$ docker push $IMAGE
|
||||
|
||||
## 生成签名密钥(会生成 cosign.key / cosign.pub)
|
||||
|
||||
@@ -39,7 +39,7 @@ $ sudo dnf remove docker \
|
||||
|
||||
### 3.3.2 使用 dnf 安装
|
||||
|
||||
使用 dnf 包管理器安装是推荐的方式,便于后续的更新和管理。
|
||||
使用 dnf 包管理器安装是推荐的方式,便于后续的更行和管理。
|
||||
|
||||
执行以下命令安装依赖包:
|
||||
|
||||
|
||||
+15
-15
@@ -4,7 +4,7 @@
|
||||
|
||||
> **版本号最佳实践**
|
||||
>
|
||||
> - **永远指定版本号**:避免使用 `latest` 标签,应指定具体的版本(如 `ubuntu:24.04`、`nginx:1.28`),以确保镜像内容稳定一致。
|
||||
> - **永远指定版本号**:避免使用 `latest` 标签,应指定具体的版本(如 `ubuntu:24.04`、`nginx:1.27`),以确保镜像内容稳定一致。
|
||||
> - **在生产环境使用摘要**:优先使用镜像摘要(SHA256)而非标签,如 `nginx@sha256:abc123...`,因为摘要不可变。
|
||||
> - **定期评估依赖**:即使指定了版本号,仍应定期检查依赖的基础镜像是否有安全更新。
|
||||
|
||||
@@ -13,24 +13,24 @@
|
||||
从镜像仓库获取镜像的命令是 `docker pull`:
|
||||
|
||||
```bash
|
||||
docker pull [选项] [Registry地址/]仓库名[:标签]
|
||||
docker pull [选项] [Registry地址/][命名空间/]仓库名[:标签|@摘要]
|
||||
```
|
||||
|
||||
#### 镜像名称格式
|
||||
|
||||
Docker 镜像名称由 Registry 地址、用户名、仓库名和标签组成。其标准格式如下:
|
||||
Docker 镜像名称通常由 Registry 地址、命名空间、仓库名和标签(或摘要)组成。其常见格式如下:
|
||||
|
||||
```bash
|
||||
docker.io / library / ubuntu : 24.04
|
||||
────┬──── ───┬─── ──┬─── ──┬──
|
||||
│ │ │ │
|
||||
Registry地址 用户名 仓库名 标签
|
||||
(可省略) (可省略)
|
||||
docker.io/library/ubuntu:24.04
|
||||
────┬──── ─────┬──── ──┬─── ──┬──
|
||||
│ │ │ │
|
||||
Registry地址 命名空间 仓库名 标签
|
||||
(可省略) (可省略)
|
||||
```
|
||||
| 组成部分 | 说明 | 默认值 |
|
||||
|---------|------|--------|
|
||||
| Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)|
|
||||
| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)|
|
||||
| 命名空间 | 镜像所属用户/组织;官方镜像常为 `library` | `library` (官方镜像)|
|
||||
| 仓库名 | 镜像名称 | 必须指定 |
|
||||
| 标签 | 版本标识 | `latest` |
|
||||
|
||||
@@ -89,19 +89,19 @@ docker.io/library/ubuntu:24.04
|
||||
|
||||
#### 分层下载
|
||||
|
||||
从输出可以看到,镜像是 **分层下载** 的:
|
||||
从输出可以看到,镜像是 **按层拉取** 的:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph Image ["ubuntu:24.04 镜像"]
|
||||
direction TB
|
||||
L3["第3层 c8299583700a<br/>(已存在,跳过下载)"]
|
||||
L2["第2层 be13a9d27eb8<br/>(下载中... 完成)"]
|
||||
L1["第1层 92dc2a97ff99<br/>(下载中... 完成)"]
|
||||
L3["第3层 c8299583700a<br/>(拉取完成)"]
|
||||
L2["第2层 be13a9d27eb8<br/>(拉取完成)"]
|
||||
L1["第1层 92dc2a97ff99<br/>(拉取完成)"]
|
||||
L3 --- L2 --- L1
|
||||
end
|
||||
```
|
||||
如果本地已有相同的层,Docker 会跳过下载,节省带宽和时间。
|
||||
如果本地已有相同的层,Docker 通常会显示 `Already exists`;本例中三层都显示 `Pull complete`,表示此次拉取流程都完成了相应的层处理。
|
||||
|
||||
---
|
||||
|
||||
@@ -160,7 +160,7 @@ root@e7009c6ce357:/# exit
|
||||
|
||||
从 Docker Hub 下载可能较慢。可以配置镜像加速器:
|
||||
|
||||
```jsonc
|
||||
```json
|
||||
// /etc/docker/daemon.json (Linux)
|
||||
// ~/.docker/daemon.json (Docker Desktop)
|
||||
{
|
||||
|
||||
+11
-11
@@ -46,21 +46,21 @@ Docker 镜像的大小可能与我们通常理解的文件大小有所不同,
|
||||
|
||||
| 位置 | 显示大小 | 说明 |
|
||||
|------|---------|------|
|
||||
| Docker Hub | 29MB | 压缩后的网络传输大小 |
|
||||
| docker image ls | 78MB | 本地解压后的实际大小 |
|
||||
| Registry / Docker Hub 页面 | 常见为压缩后的分发大小或单平台视角 | 便于传输与分发 |
|
||||
| `docker image ls` | 本地镜像及其父层累计占用大小 | 更接近主机上的实际展开占用 |
|
||||
|
||||
#### 实际磁盘占用
|
||||
|
||||
由于镜像是分层存储,不同镜像可能共享相同的层:
|
||||
由于镜像是分层存储,**只有基于相同父层构建** 的镜像才会共享相同层:
|
||||
|
||||
```bash
|
||||
ubuntu:24.04 nginx:latest redis:latest
|
||||
│ │ │
|
||||
└───────┬───────┘ │
|
||||
▼ │
|
||||
共享基础层 ◄───────────────────┘
|
||||
python:3.12-slim myapp:web myapp:worker
|
||||
│ │ │
|
||||
└───────┬───────┘ │
|
||||
▼ │
|
||||
共享父层与依赖层 ◄──────────┘
|
||||
```
|
||||
因此,`docker image ls` 中各镜像大小之和 > 实际磁盘占用。
|
||||
因此,`docker image ls` 中各镜像大小之和通常会大于实际磁盘占用;共享层只会在磁盘上保存一次。
|
||||
|
||||
#### 查看实际空间占用
|
||||
|
||||
@@ -164,9 +164,9 @@ $ docker image prune
|
||||
```bash
|
||||
$ docker images -a
|
||||
```
|
||||
会显示很多无标签镜像——这些是构建过程中产生的中间层,被其他镜像依赖。
|
||||
会显示默认隐藏的中间层和虚悬镜像,其中一部分可能来自构建过程并被其他镜像复用。
|
||||
|
||||
> ⚠️ 不要删除中间层镜像。它们是其他镜像的依赖,删除会导致上层镜像无法使用。删除顶层镜像时会自动清理不再需要的中间层。
|
||||
> ⚠️ 一般不要手动逐个处理这些无标签项。优先删除顶层镜像或使用 `docker image prune` 清理无用镜像,让 Docker 自行回收不再被引用的层。
|
||||
|
||||
---
|
||||
|
||||
|
||||
+23
-8
@@ -19,7 +19,7 @@ $ docker image rm [选项] <镜像1> [<镜像2> ...]
|
||||
|
||||
| 方式 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| **短 ID** | ID 的前几位 (通常 3-4 位)| `docker rmi 501` |
|
||||
| **短 ID** | ID 的前几位,只要足够唯一即可 | `docker rmi 501` |
|
||||
| **长 ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` |
|
||||
| **镜像名:标签** | 仓库名和标签 | `docker rmi redis:7.0` |
|
||||
| **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` |
|
||||
@@ -144,7 +144,7 @@ $ docker image prune -f
|
||||
|
||||
$ docker image prune -a
|
||||
|
||||
## 保留最近 24 小时的
|
||||
## 只清理 24 小时前的未使用镜像
|
||||
|
||||
$ docker image prune -a --filter "until=24h"
|
||||
```
|
||||
@@ -152,13 +152,17 @@ $ docker image prune -a --filter "until=24h"
|
||||
#### 按条件删除
|
||||
|
||||
```bash
|
||||
## 删除所有 redis 镜像
|
||||
## 先列出所有 redis 相关镜像引用
|
||||
|
||||
$ docker rmi $(docker images -q redis)
|
||||
$ docker image ls --filter reference='redis*'
|
||||
|
||||
## 删除 mongo:8.0 之前的所有镜像
|
||||
## 确认后,按仓库名:标签逐个删除需要的镜像
|
||||
|
||||
$ docker rmi $(docker images -q -f before=mongo:8.0)
|
||||
$ docker image rm redis:7 redis:7-alpine
|
||||
|
||||
## 先列出所有比 mongo:8.0 更早创建的镜像
|
||||
|
||||
$ docker image ls --filter before=mongo:8.0
|
||||
|
||||
## 删除某个时间之前的镜像
|
||||
|
||||
@@ -217,14 +221,25 @@ Error: image has dependent child images
|
||||
|
||||
### 4.3.6 常用过滤条件
|
||||
|
||||
不同命令支持的过滤条件并不相同。最常见的是 `docker image ls` 用来筛选查看对象,`docker image prune` 用来清理未使用镜像。
|
||||
|
||||
#### `docker image ls` 常用过滤条件
|
||||
|
||||
| 过滤条件 | 说明 | 示例 |
|
||||
|---------|------|------|
|
||||
| `dangling=true` | 虚悬镜像 | `-f dangling=true` |
|
||||
| `before=镜像` | 在某镜像之前 | `-f before=mongo:3.2` |
|
||||
| `since=镜像` | 在某镜像之后 | `-f since=mongo:3.2` |
|
||||
| `before=镜像` | 仅匹配比某镜像更早创建的镜像 | `-f before=mongo:3.2` |
|
||||
| `since=镜像` | 仅匹配比某镜像更晚创建的镜像 | `-f since=mongo:3.2` |
|
||||
| `label=key=value` | 按标签过滤 | `-f label=version=1.0` |
|
||||
| `reference=pattern` | 按名称模式 | `-f reference='*:latest'` |
|
||||
|
||||
#### `docker image prune` 常用过滤条件
|
||||
|
||||
| 过滤条件 | 说明 | 示例 |
|
||||
|---------|------|------|
|
||||
| `until=<时间>` | 仅清理某个时间点之前创建的未使用镜像 | `--filter "until=24h"` |
|
||||
| `label=key=value` | 仅清理带指定标签的未使用镜像 | `--filter "label=stage=temp"` |
|
||||
|
||||
---
|
||||
|
||||
### 4.3.7 清理策略
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
现在让我们以定制一个 Web 服务器为例子,来讲解镜像是如何构建的。
|
||||
|
||||
> **版本提示**:以下示例中 `nginx` 镜像使用默认 `latest` 标签。生产环境建议指定具体版本号(如 `nginx:1.28`),以避免镜像更新带来的不兼容性。
|
||||
> **版本提示**:以下示例中 `nginx` 镜像使用默认 `latest` 标签。生产环境建议指定具体版本号(如 `nginx:1.27`),以避免镜像更新带来的不兼容性。
|
||||
|
||||
```bash
|
||||
$ docker run --name webserver -d -p 8080:80 nginx
|
||||
@@ -89,11 +89,11 @@ sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
|
||||
$ docker image ls nginx
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx v2 07e334659748 9 seconds ago 181.5 MB
|
||||
nginx 1.30 05a60462f8ba 12 days ago 181.5 MB
|
||||
nginx 1.27 05a60462f8ba 12 days ago 181.5 MB
|
||||
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB
|
||||
```
|
||||
|
||||
> **版本说明**:上面示例中 `nginx:1.30` 代表 1.30 系列的最新 patch 版本。在实际应用中应根据需求选择确切的版本号,而不是盲目使用 `latest`。
|
||||
> **版本说明**:上面示例中 `nginx:1.27` 代表 1.27 系列的最新 patch 版本。在实际应用中应根据需求选择确切的版本号,而不是盲目使用 `latest`。
|
||||
|
||||
我们还可以用 `docker history` 具体查看镜像内的历史记录。例如先执行 `docker history nginx:v2`,再对比 `docker history nginx:latest`,就能看到我们刚刚提交出来的新层。
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ $ touch Dockerfile
|
||||
```
|
||||
其内容为:
|
||||
|
||||
> **版本提示**:下面示例中 `FROM nginx` 使用的是 `latest` 标签。在实际应用中应使用明确的版本号(如 `FROM nginx:1.28`),以确保 Dockerfile 的可重现性和稳定性。
|
||||
> **版本提示**:下面示例中 `FROM nginx` 使用的是 `latest` 标签。在实际应用中应使用明确的版本号(如 `FROM nginx:1.27`),以确保 Dockerfile 的可重现性和稳定性。
|
||||
|
||||
```docker
|
||||
FROM nginx
|
||||
@@ -86,7 +86,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
$ docker build -t nginx:v3 .
|
||||
```
|
||||
|
||||
在当前版本的 Docker 中,`docker build` 默认会通过 Buildx 调用 BuildKit,因此你更常看到的是 `[+] Building ...` 这类输出。为了帮助理解“每一步如何形成镜像历史”,下面仍展示一种较容易阅读的经典输出形式:
|
||||
在当前版本的 Docker 中,`docker build` 默认会通过 Buildx 调用 BuildKit;但如果你显式设置了 `DOCKER_BUILDKIT=0`,或正在使用 Windows container mode,行为会回到 legacy builder。因此你更常看到的是 `[+] Building ...` 这类输出。为了帮助理解“每一步如何形成镜像历史”,下面仍展示一种较容易阅读的 legacy builder 经典输出形式:
|
||||
|
||||
```bash
|
||||
Sending build context to Docker daemon 2.048 kB
|
||||
@@ -98,7 +98,7 @@ Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
|
||||
Removing intermediate container 9cdc27646c7b
|
||||
Successfully built 44aa4490ce2c
|
||||
```
|
||||
从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 `Step 2` 中,如同我们之前所说的那样,`RUN` 指令启动了一个容器 `9cdc27646c7b`,执行了所要求的命令,并最后提交了这一层 `44aa4490ce2c`,随后删除了所用到的这个容器 `9cdc27646c7b`。
|
||||
这段输出清晰展示了 legacy builder 的构建过程。在 `Step 2` 中,`RUN` 指令对应一次临时构建容器:执行命令、生成新的镜像层,再删除中间容器。默认的 BuildKit 后端通常不会把这些中间容器和中间镜像以这种形式暴露给用户,但“每条会改文件系统的指令都会生成新的层”这一点并没有改变。
|
||||
|
||||
这里我们使用了 `docker build` 命令进行镜像构建。其格式为:
|
||||
|
||||
@@ -111,7 +111,7 @@ docker build [选项] <上下文路径/URL/->
|
||||
|
||||
如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定 **上下文路径**。那么什么是上下文呢?
|
||||
|
||||
首先要理解 `docker build` 的工作原理。今天的 `docker build` 默认会通过 Buildx 向 BuildKit 后端发起构建请求;无论后端运行在本机还是远端,位置参数指定的都是 **构建上下文**,也就是构建器可以访问到的文件集合。
|
||||
首先要理解 `docker build` 的工作原理。今天的 `docker build` 通常会通过 Buildx 向 BuildKit 后端发起构建请求;无论后端运行在本机还是远端,位置参数指定的都是 **构建上下文**,也就是构建器可以访问到的文件集合。
|
||||
|
||||
当我们进行镜像构建的时候,并非所有定制都会通过 `RUN` 指令完成,经常还需要把本地文件复制进镜像,比如通过 `COPY` 指令、`ADD` 指令等。因此,构建器必须能够访问这些文件,而它能访问的范围正是你传给 `docker build` 的那个上下文。
|
||||
|
||||
@@ -124,7 +124,7 @@ COPY ./package.json /app/
|
||||
```
|
||||
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制 **上下文 (context)** 目录下的 `package.json`。
|
||||
|
||||
因此,`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解。对于 legacy builder,像 `COPY ../package.json /app` 这样的写法会直接报错;而在 BuildKit 下,前导的越界 `../` 会被剥离并重新解释为上下文内路径。无论是哪种情况,构建器都无法读取上下文之外的宿主机文件;如果真的需要那些文件,应该先把它们放进上下文目录,或重新选择合适的上下文。
|
||||
因此,`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解。像 `COPY ../package.json /app` 这样的写法,前导的越界 `../` 会被规范化掉,最终仍只能在上下文根内解析;换句话说,构建器并不能借此读取上下文之外的宿主机文件。如果真的需要那些文件,应该先把它们放进上下文目录,或重新选择合适的上下文。
|
||||
|
||||
现在就可以理解刚才的命令 `docker build -t nginx:v3 .` 中的这个 `.`,实际上是在指定上下文目录,而不是单纯指定 `Dockerfile` 所在目录。
|
||||
|
||||
|
||||
+22
-20
@@ -6,44 +6,44 @@
|
||||
|
||||
格式:`docker import [选项] <文件>|<URL>|- [<仓库名>[:<标签>]]`
|
||||
|
||||
压缩包可以是本地文件、远程 Web 文件,甚至是从标准输入中得到。压缩包将会在镜像 `/` 目录展开,并直接作为镜像第一层提交。
|
||||
压缩包可以是本地文件、远程 Web 文件,甚至是从标准输入中得到。压缩包将会在镜像 `/` 目录展开,并直接作为镜像的文件系统内容导入。若还需要补充 `CMD`、`ENV` 等元数据,可以通过 `--change` 追加;但它不支持 `RUN`、`COPY` 这类依赖构建上下文或会生成新文件系统层的 Dockerfile 指令。
|
||||
|
||||
比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 16.04 [模板](https://wiki.openvz.org/Download/template/precreated)的镜像:
|
||||
例如在 Debian/Ubuntu 主机上,可以先用 `debootstrap` 生成 Ubuntu 24.04(`noble`)的 rootfs,再通过标准输入导入为基础镜像:
|
||||
|
||||
> **版本提示**:示例中的 Ubuntu 16.04 (Xenial) 已于 2021 年 4 月停止支持。如果用于生产环境,建议更新至 Ubuntu 22.04 LTS 或更新版本。
|
||||
|
||||
```bash
|
||||
$ docker import \
|
||||
http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz \
|
||||
openvz/ubuntu:16.04
|
||||
$ sudo debootstrap noble noble > /dev/null
|
||||
$ sudo tar -C noble -c . | docker import - ubuntu:noble
|
||||
|
||||
Downloading from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz
|
||||
sha256:412b8fc3e3f786dca0197834a698932b9c51b69bd8cf49e100c35d38c9879213
|
||||
sha256:81ec9a55a92a5618161f68ae691d092bf14d700129093158297b3d01593f4ee3
|
||||
```
|
||||
这条命令自动下载了 `ubuntu-16.04-x86_64.tar.gz` 文件,并且作为根文件系统展开导入,并保存为镜像 `openvz/ubuntu:16.04`。
|
||||
这组命令会先得到 `noble/` 目录下的 rootfs,再把它打包后导入成镜像 `ubuntu:noble`。这种方式更适合制作自定义基础镜像或把现成的根文件系统快速封装成镜像。
|
||||
|
||||
导入成功后,我们可以用 `docker image ls` 看到这个导入的镜像:
|
||||
|
||||
```bash
|
||||
$ docker image ls openvz/ubuntu
|
||||
$ docker image ls ubuntu
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
openvz/ubuntu 16.04 412b8fc3e3f7 55 seconds ago 505MB
|
||||
ubuntu noble 81ec9a55a92a 5 seconds ago 78MB
|
||||
```
|
||||
如果我们查看其历史的话,会看到描述中有导入的文件链接:
|
||||
如果需要在导入时补上镜像元数据,可以配合 `--change` 选项:
|
||||
|
||||
```bash
|
||||
$ docker history openvz/ubuntu:16.04
|
||||
IMAGE CREATED CREATED BY SIZE COMMENT
|
||||
f477a6e18e98 About a minute ago 214.9 MB Imported from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz
|
||||
$ docker import \
|
||||
--change 'CMD ["/bin/bash"]' \
|
||||
--change 'ENV LANG=C.UTF-8' \
|
||||
rootfs.tar \
|
||||
custom/base:noble
|
||||
```
|
||||
|
||||
### 4.6.2 Docker 镜像的导入和导出 `docker save` 和 `docker load`
|
||||
|
||||
Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个文件,然后传输到另一个位置上,再加载进来。这是在没有 Docker Registry 时的做法,现在已经不推荐,镜像迁移应该直接使用 Docker Registry,无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以。
|
||||
Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个归档文件,然后传输到另一个位置上,再加载进来。它们仍然适合离线备份、气隙环境分发,或在两台主机之间手工迁移镜像;如果是团队常规分发、版本管理和协作,优先使用 Docker Registry(无论是 Docker Hub 还是内网私有 Registry)会更合适。
|
||||
|
||||
#### 保存镜像
|
||||
|
||||
使用 `docker save` 命令可以将镜像保存为归档文件。
|
||||
使用 `docker save` 命令可以将镜像保存为归档文件。归档中会包含镜像的父层以及所指定的标签;如果本地镜像仓库里已有多个平台变体,还可以通过 `--platform` 仅导出某个平台版本。
|
||||
|
||||
比如我们希望保存这个 `alpine` 镜像。
|
||||
|
||||
@@ -57,7 +57,7 @@ alpine latest baa5d63471ea 5 weeks ago
|
||||
保存镜像的命令为:
|
||||
|
||||
```bash
|
||||
$ docker save alpine -o filename
|
||||
$ docker image save -o filename alpine
|
||||
$ file filename
|
||||
filename: POSIX tar archive
|
||||
```
|
||||
@@ -68,14 +68,16 @@ filename: POSIX tar archive
|
||||
若使用 `gzip` 压缩:
|
||||
|
||||
```bash
|
||||
$ docker save alpine | gzip > alpine-latest.tar.gz
|
||||
$ docker image save alpine | gzip > alpine-latest.tar.gz
|
||||
```
|
||||
然后我们将 `alpine-latest.tar.gz` 文件复制到了到了另一个机器上,可以用下面这个命令加载镜像:
|
||||
然后我们将 `alpine-latest.tar.gz` 文件复制到了另一个机器上,可以用下面这个命令加载镜像:
|
||||
|
||||
```bash
|
||||
$ docker load -i alpine-latest.tar.gz
|
||||
$ docker image load -i alpine-latest.tar.gz
|
||||
Loaded image: alpine:latest
|
||||
```
|
||||
`docker load` 会恢复归档中的镜像和标签;同样地,在需要时也可以通过 `--platform` 只加载其中一个平台变体。
|
||||
|
||||
如果我们结合这两个命令以及 `ssh` 甚至 `pv` 的话,利用 Linux 强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -40,8 +40,8 @@ flowchart TD
|
||||
```
|
||||
|
||||
* **读取文件**:当容器需要读取文件时,Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找,直到找到该文件为止。
|
||||
* **修改文件**:当容器需要修改某个文件时,Docker 会从下层镜像中将该文件复制到上层的容器层,然后对副本进行修改。这被称为 **写时复制 (Copy-on-Write,CoW)** 策略。
|
||||
* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它 (因为下层是只读的),而是在容器层创建一个特殊的 “白障 (Whiteout)” 文件,用来标记该文件已被删除,从而在容器视图中隐藏它。
|
||||
* **修改文件**:当容器需要修改某个文件时,底层存储后端会以 **写时复制 (Copy-on-Write,CoW)** 的方式记录变化。在 `overlay2` 这类联合文件系统后端上,常见表现是先把文件 `copy_up` 到容器层再修改;而 `btrfs`、`zfs` 等 CoW 文件系统的内部实现会有所不同。
|
||||
* **删除文件**:当容器删除某个文件时,Docker 不会直接改写下层只读层,而是由当前存储后端在上层记录“把下层内容屏蔽掉”的元数据。在 `overlay2` 中,这常表现为 whiteout 或 opaque directory;其他后端会用各自的机制达到相同效果。
|
||||
|
||||
这就是为什么:
|
||||
|
||||
@@ -58,10 +58,10 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的
|
||||
|
||||
### 4.7.4 联合文件系统
|
||||
|
||||
Docker 使用联合文件系统 (Union FS) 与写时复制思路来实现这种分层挂载。传统的实现方式常见于 `overlay2`、`aufs`、`btrfs`、`zfs` 等存储驱动;而在 Docker Engine 29.0 及之后的全新安装中,默认镜像后端已经变为 containerd image store,它使用 snapshotter 来管理这些层。
|
||||
Docker 用“分层 + CoW”的思路来实现镜像与容器层叠加,但具体后端并不完全相同。`overlay2`、`aufs` 这类后端属于联合文件系统;`btrfs`、`zfs` 更接近具备快照/克隆能力的 CoW 文件系统;而在 Docker Engine 29.0 及之后的全新安装中,默认镜像后端已经变为 containerd image store,它使用 snapshotter 来管理这些层。
|
||||
|
||||
> **版本背景**:Docker Engine 29.0(发布于 2025 年 11 月)是一个重要版本分界点,在全新安装场景下默认启用 containerd image store 作为镜像存储后端。这对镜像管理、OCI 合规性和供应链安全都有深远影响。如果你的 Docker 版本低于 29.0,镜像存储仍使用传统的 classic store 路径。
|
||||
> **版本背景**:Docker Engine 29.0(发布于 2024 年 2 月)是一个重要版本分界点,引入了 containerd image store 作为默认镜像存储后端。这对镜像管理、OCI 合规性和供应链安全都有深远影响。如果你的 Docker 版本低于 29.0,镜像存储仍使用传统的 classic store 路径。
|
||||
|
||||
虽然底层实现细节不同,但它们都遵循上述的 **分层 + CoW** 模型;因此,无论你看到的是 `overlay2` 还是 containerd snapshotter,理解镜像层、容器层和写时复制的方式都是一样重要的。
|
||||
虽然底层实现细节不同,但它们都遵循“下层只读、上层记录差异”的总体模型;因此,无论你看到的是 `overlay2`、`zfs` 还是 containerd snapshotter,理解镜像层、容器层和写时复制的核心思想都是一样重要的。
|
||||
|
||||
> 想要深入了解 Overlay2 等文件系统的具体实现原理,包括 WorkDir、UpperDir、LowerDir 等底层细节,请阅读 **[第十二章 底层实现](../12_implementation/README.md)** 中的 **[联合文件系统](../12_implementation/12.4_ufs.md)** 章节。
|
||||
|
||||
@@ -126,14 +126,14 @@ $ docker run -d -p 80:80 nginx:latest
|
||||
|
||||
## 数据库
|
||||
|
||||
$ docker run -d -p 3306:3306 mysql:8.4
|
||||
$ docker run -d -p 3306:3306 mysql:8.0
|
||||
|
||||
## 缓存服务
|
||||
|
||||
$ docker run -d -p 6379:6379 redis:latest
|
||||
```
|
||||
|
||||
> **版本说明**:示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.4`。具体版本可根据需求调整,生产环境建议明确指定版本号(如 `mysql:8.4.4`)而非使用 `latest`。
|
||||
> **版本说明**:示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.0`。具体版本可根据需求调整,生产环境建议明确指定版本号(如 `mysql:8.0.35`)而非使用 `latest`。
|
||||
|
||||
#### 2. 调试时先用前台模式
|
||||
|
||||
@@ -196,9 +196,9 @@ $ docker logs -t myapp
|
||||
|
||||
3. **以交互模式调试**:
|
||||
```bash
|
||||
# /bin/sh 覆盖镜像原本的启动命令,避免容器再次崩溃退出
|
||||
# 进入 shell 后可手动执行原启动命令,定位具体报错原因
|
||||
$ docker run -it myimage:v1.0.0 /bin/sh
|
||||
# 进入容器手动执行命令,查找问题
|
||||
|
||||
```
|
||||
|
||||
#### Q:容器在后台运行但无法访问服务
|
||||
|
||||
@@ -212,7 +212,7 @@ FROM node:22-alpine
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
> **版本说明**:示例使用 `node:22-alpine`,这是一个精简的 Node.js 22 版本镜像。可根据需求替换为其他版本(如 `node:24-alpine`、`node:latest`)。
|
||||
> **版本说明**:示例使用 `node:22-alpine`,这是一个精简的 Node.js 22 版本镜像。可根据需求替换为其他版本(如 `node:20-alpine`、`node:latest`)。
|
||||
|
||||
#### Q:容器无法停止
|
||||
|
||||
|
||||
@@ -249,11 +249,10 @@ $ docker exec myapp python manage.py migrate
|
||||
$ docker exec -it myapp bash
|
||||
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found
|
||||
|
||||
## 解决方案:使用调试容器(需要 Docker Desktop Pro/Team/Business 订阅)
|
||||
## 解决方案:使用调试容器
|
||||
|
||||
$ docker debug myapp
|
||||
```
|
||||
> **注意**:`docker debug` 是 Docker Desktop 4.33+ 提供的功能,需要 Pro、Team 或 Business 订阅。它会附加一个包含常用调试工具(vim、curl、htop 等)的工具箱到目标容器,即使目标镜像基于 `scratch` 也能使用。
|
||||
---
|
||||
|
||||
### 5.4.7 常见问题
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
本章示例涉及多个 Docker 镜像,遵循以下版本号最佳实践:
|
||||
|
||||
- **官方镜像**(如 `ubuntu`、`nginx`、`mysql`):使用具体大版本号(如 `ubuntu:24.04`、`mysql:8.4`)而非 `latest`,确保示例的可重复性
|
||||
- **官方镜像**(如 `ubuntu`、`nginx`、`mysql`):使用具体大版本号(如 `ubuntu:24.04`、`mysql:8.0`)而非 `latest`,确保示例的可重复性
|
||||
- **镜像标签约定**:
|
||||
- `latest` 或 `v1.0.0` 等:带标签的自定义镜像,示例中指定具体版本
|
||||
- `24.04`、`8.4`:官方镜像的稳定版本分支
|
||||
- 生产环境建议:指定确切版本号(如 `nginx:1.28.0`、`mysql:8.4.4`)而非仅大版本号
|
||||
- `24.04`、`8.0`:官方镜像的稳定版本分支
|
||||
- 生产环境建议:指定精确版本号(如 `nginx:1.24.0`、`mysql:8.0.35`)而非仅大版本号
|
||||
|
||||
* [启动容器](5.1_run.md)
|
||||
* [守护态运行](5.2_daemon.md)
|
||||
|
||||
@@ -75,7 +75,7 @@ Docker Hub 对不同类型用户实施拉取速率限制(基于 6 小时周期
|
||||
| **免费账户** (已登录) | 每 6 小时 200 次请求 |
|
||||
| **Pro/Team/Business 账户** | 无限制(公平使用政策) |
|
||||
|
||||
> **注意**:Docker 曾计划于 2025 年 4 月调整拉取限制策略,但在 2025 年 2 月宣布取消该计划。目前付费订阅用户享有无限制拉取额度,匿名用户和免费账户的限制保持不变。建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度。
|
||||
> **注意**:自 2025 年 4 月起,所有付费订阅用户享有无限制拉取额度。匿名用户和免费账户的限制保持不变,建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度。
|
||||
|
||||
#### 滥用限流
|
||||
|
||||
|
||||
@@ -126,8 +126,6 @@ $ docker run --rm \
|
||||
-Bbn username password > auth/nginx.htpasswd
|
||||
```
|
||||
> 将上面的 `username` `password` 替换为你自己的用户名和密码。
|
||||
>
|
||||
> **安全提示**:上述命令会将密码明文暴露在 shell 历史记录和进程列表中。生产环境建议使用交互式方式输入密码(不带 `-b` 参数),或通过环境变量/文件传入。
|
||||
|
||||
> **版本说明**:使用 `httpd:2.4-alpine` 基于 Apache 2.4 的精简镜像。如需其他版本,可替换为 `httpd:latest` 或指定具体版本号如 `httpd:2.4.58-alpine`。
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ server {
|
||||
ssl_certificate_key key/example.key;
|
||||
|
||||
ssl_session_timeout 5m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
large_client_header_buffers 4 32k;
|
||||
|
||||
@@ -82,9 +82,9 @@ RUN pwd # 输出 /app
|
||||
|
||||
```docker
|
||||
## 构建阶段
|
||||
## 建议使用 node:22 或 node: 等具体版本标签,避免使用 latest
|
||||
## 建议使用 node:20 或 node: 等具体版本标签,避免使用 latest
|
||||
|
||||
FROM node:22 AS builder
|
||||
FROM node:20 AS builder
|
||||
WORKDIR /build
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
@@ -105,8 +105,8 @@ COPY --from=builder /build/dist .
|
||||
#### 1. 尽早设置 WORKDIR
|
||||
|
||||
```docker
|
||||
# 建议使用 node:22 等主/次版本号标签
|
||||
FROM node:22
|
||||
# 建议使用 node:20 等主/次版本号标签
|
||||
FROM node:20
|
||||
WORKDIR /app # 尽早设置
|
||||
|
||||
COPY package*.json ./
|
||||
|
||||
@@ -35,7 +35,7 @@ flowchart LR
|
||||
#### 创建并切换用户
|
||||
|
||||
```docker
|
||||
FROM node:22-alpine
|
||||
FROM node:20-alpine
|
||||
|
||||
## 1. 创建用户和组
|
||||
|
||||
@@ -173,7 +173,7 @@ $ docker run -u root myimage
|
||||
切换用户后,确保应用有权访问文件:
|
||||
|
||||
```docker
|
||||
FROM node:22-alpine
|
||||
FROM node:20-alpine
|
||||
|
||||
## 创建用户
|
||||
|
||||
@@ -229,14 +229,14 @@ USER 1000:1000
|
||||
```docker
|
||||
## 构建阶段可以用 root
|
||||
|
||||
FROM node:22 AS builder
|
||||
FROM node:20 AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN npm install && npm run build
|
||||
|
||||
## 生产阶段用非 root
|
||||
|
||||
FROM node:22-alpine
|
||||
FROM node:20-alpine
|
||||
RUN adduser -D appuser
|
||||
WORKDIR /app
|
||||
COPY --from=builder --chown=appuser:appuser /app/dist .
|
||||
|
||||
@@ -34,7 +34,7 @@ Starting ──成功──> Healthy ──失败N次──> Unhealthy
|
||||
#### Web 服务检查
|
||||
|
||||
```docker
|
||||
# 注:nginx 镜像推荐使用具体的版本标签(如 nginx:1.28-alpine)
|
||||
# 注:nginx 镜像推荐使用具体的版本标签(如 nginx:1.25-alpine)
|
||||
FROM nginx
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ ONBUILD <其它指令>
|
||||
**基础镜像 (my-node-base)**:
|
||||
|
||||
```docker
|
||||
FROM node:22-alpine
|
||||
FROM node:20-alpine
|
||||
WORKDIR /app
|
||||
|
||||
## 这些指令将在子镜像构建时执行
|
||||
@@ -126,7 +126,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
|
||||
建议在镜像标签中添加 `-onbuild` 后缀,明确告知使用者该镜像包含触发器。
|
||||
|
||||
```bash
|
||||
node:22-onbuild
|
||||
node:20-onbuild
|
||||
python:3.12-onbuild
|
||||
```
|
||||
|
||||
|
||||
@@ -14,20 +14,12 @@ Dockerfile 中的常用指令包括:
|
||||
|
||||
- **FROM**: 指定基础镜像,必须是第一条指令
|
||||
- **RUN**: 在镜像中执行命令,用于安装软件包等
|
||||
- **COPY**: 复制文件到镜像中
|
||||
- **ADD**: 更高级的复制文件(支持 URL 和自动解压)
|
||||
- **CMD**: 容器默认执行的命令
|
||||
- **ENTRYPOINT**: 容器启动时的入口点
|
||||
- **ENV**: 设置环境变量
|
||||
- **ARG**: 构建时的参数变量
|
||||
- **VOLUME**: 定义匿名卷挂载点
|
||||
- **EXPOSE**: 声明容器监听的端口
|
||||
- **WORKDIR**: 设置工作目录
|
||||
- **USER**: 指定运行容器时的用户
|
||||
- **HEALTHCHECK**: 配置容器健康检查
|
||||
- **ONBUILD**: 设置触发器指令,在子镜像构建时执行
|
||||
- **LABEL**: 为镜像添加元数据标签
|
||||
- **SHELL**: 指定 RUN 等指令使用的 shell
|
||||
- **COPY/ADD**: 复制文件到镜像中
|
||||
- **EXPOSE**: 声明容器监听的端口
|
||||
- **ENV**: 设置环境变量
|
||||
- **ENTRYPOINT**: 容器启动时的入口点
|
||||
- **CMD**: 容器默认执行的命令
|
||||
|
||||
### 最佳实践建议
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ WORKDIR /go/src/github.com/go/helloworld/
|
||||
COPY app.go .
|
||||
|
||||
RUN go mod init helloworld \
|
||||
&& go get github.com/go-sql-driver/mysql \
|
||||
&& go get -d -v github.com/go-sql-driver/mysql \
|
||||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \
|
||||
&& cp /go/src/github.com/go/helloworld/app /root
|
||||
|
||||
@@ -62,8 +62,7 @@ WORKDIR /go/src/github.com/go/helloworld
|
||||
|
||||
COPY app.go .
|
||||
|
||||
RUN go mod init helloworld \
|
||||
&& go get github.com/go-sql-driver/mysql \
|
||||
RUN go get -d -v github.com/go-sql-driver/mysql \
|
||||
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
|
||||
```
|
||||
编写 `Dockerfile.copy` 文件
|
||||
@@ -126,8 +125,7 @@ RUN apk --no-cache add git
|
||||
|
||||
WORKDIR /go/src/github.com/go/helloworld/
|
||||
|
||||
RUN go mod init helloworld \
|
||||
&& go get github.com/go-sql-driver/mysql
|
||||
RUN go get -d -v github.com/go-sql-driver/mysql
|
||||
|
||||
COPY app.go .
|
||||
|
||||
@@ -160,15 +158,6 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
|
||||
```
|
||||
很明显使用多阶段构建的镜像体积小,同时也完美解决了上边提到的问题。
|
||||
|
||||
> **Go Modules 最佳实践**:上述示例为简化演示在 Dockerfile 中临时执行 `go mod init`。在实际项目中,通常已在代码仓库中维护好 `go.mod` 和 `go.sum` 文件。推荐的 Dockerfile 写法是先拷贝这两个文件并执行 `go mod download` 以利用 Docker 层缓存,再拷贝源码并构建:
|
||||
>
|
||||
> ```docker
|
||||
> COPY go.mod go.sum ./
|
||||
> RUN go mod download
|
||||
> COPY . .
|
||||
> RUN go build -o app .
|
||||
> ```
|
||||
|
||||
### 7.17.4 只构建某一阶段的镜像
|
||||
|
||||
我们可以使用 `as` 来为某一阶段命名,例如
|
||||
@@ -187,5 +176,5 @@ $ docker build --target builder -t username/imagename:tag .
|
||||
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
|
||||
|
||||
```docker
|
||||
COPY --from=nginx:1.28-alpine /etc/nginx/nginx.conf /nginx.conf
|
||||
COPY --from=nginx:1.25-alpine /etc/nginx/nginx.conf /nginx.conf
|
||||
```
|
||||
|
||||
@@ -60,8 +60,8 @@ server {
|
||||
第一阶段进行前端构建。
|
||||
|
||||
```docker
|
||||
# 注:node 镜像推荐使用具体的版本标签(如 node:22-alpine)
|
||||
FROM node:22-alpine as frontend
|
||||
# 注:node 镜像推荐使用具体的版本标签(如 node:20-alpine)
|
||||
FROM node:20-alpine as frontend
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
@@ -128,8 +128,8 @@ RUN set -x ; cd ${LARAVEL_PATH} \
|
||||
### 7.18.5 最后一个阶段构建 NGINX 镜像
|
||||
|
||||
```docker
|
||||
# 注:nginx 镜像推荐使用具体的版本标签(如 nginx:1.28-alpine)
|
||||
FROM nginx:1.28-alpine as nginx
|
||||
# 注:nginx 镜像推荐使用具体的版本标签(如 nginx:1.25-alpine)
|
||||
FROM nginx:1.25-alpine as nginx
|
||||
|
||||
ARG LARAVEL_PATH=/app/laravel
|
||||
|
||||
@@ -179,8 +179,8 @@ $ docker run -dit --rm --network=laravel -p 8080:80 my/nginx
|
||||
完整的 `Dockerfile` 文件如下。
|
||||
|
||||
```docker
|
||||
# 注:生产环境推荐使用具体的版本标签,如 node:22-alpine、composer:2.x、php:8.3-fpm-alpine、nginx:1.28-alpine
|
||||
FROM node:22-alpine as frontend
|
||||
# 注:生产环境推荐使用具体的版本标签,如 node:20-alpine、composer:2.x、php:8.3-fpm-alpine、nginx:1.25-alpine
|
||||
FROM node:20-alpine as frontend
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
@@ -229,7 +229,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
|
||||
&& chmod -R 777 storage \
|
||||
&& php artisan package:discover
|
||||
|
||||
FROM nginx:1.28-alpine as nginx
|
||||
FROM nginx:1.25-alpine as nginx
|
||||
|
||||
ARG LARAVEL_PATH=/app/laravel
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ ADD app.tar.gz /app/
|
||||
```docker
|
||||
## 构建阶段
|
||||
|
||||
FROM node:22 AS builder
|
||||
FROM node:20 AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
这是 Dockerfile 使用中最常见的困惑之一。简单的答案是:
|
||||
|
||||
- **CMD**:定义容器的“默认命令”。如果用户在 `docker run` 时提供命令,CMD 会被覆盖
|
||||
- **ENTRYPOINT**:定义容器的“入口脚本”。通常用于启动应用的某个特定部分
|
||||
- **CMD**:定义容器的”默认命令”。如果用户在 `docker run` 时提供命令,CMD 会被覆盖
|
||||
- **ENTRYPOINT**:定义容器的”入口脚本”。通常用于启动应用的某个特定部分
|
||||
|
||||
**决策树**:
|
||||
|
||||
|
||||
@@ -158,15 +158,15 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp .
|
||||
```docker
|
||||
## ✅ 好:版本集中管理
|
||||
|
||||
ENV NGINX_VERSION=1.30 \
|
||||
NODE_VERSION=22 \
|
||||
ENV NGINX_VERSION=1.25 \
|
||||
NODE_VERSION=20 \
|
||||
PYTHON_VERSION=3.12
|
||||
|
||||
RUN apt-get install nginx=${NGINX_VERSION}
|
||||
|
||||
## ❌ 差:版本分散在各处
|
||||
|
||||
RUN apt-get install nginx=1.30
|
||||
RUN apt-get install nginx=1.25
|
||||
```
|
||||
|
||||
#### 2. 不要存储敏感信息
|
||||
|
||||
@@ -93,14 +93,14 @@ RUN echo "Node version: $NODE_VERSION"
|
||||
```docker
|
||||
ARG BASE_VERSION=alpine
|
||||
|
||||
FROM node:22-${BASE_VERSION} AS builder
|
||||
FROM node:20-${BASE_VERSION} AS builder
|
||||
|
||||
## 需要重新声明
|
||||
|
||||
ARG NODE_VERSION=20
|
||||
RUN echo "Building with Node $NODE_VERSION"
|
||||
|
||||
FROM node:22-${BASE_VERSION}
|
||||
FROM node:20-${BASE_VERSION}
|
||||
|
||||
## 每个阶段都需要重新声明
|
||||
|
||||
@@ -125,8 +125,8 @@ $ docker build --build-arg ALPINE_VERSION=3.19 .
|
||||
#### 2. 设置软件版本
|
||||
|
||||
```docker
|
||||
# 使用次版本号 (1.30) 而非完整版本号 (1.30.0),以便自动更新到最新补丁版本
|
||||
ARG NGINX_VERSION=1.30
|
||||
# 使用次版本号 (1.25) 而非完整版本号 (1.25.0),以便自动更新到最新补丁版本
|
||||
ARG NGINX_VERSION=1.25
|
||||
|
||||
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
|
||||
```
|
||||
|
||||
@@ -44,7 +44,7 @@ flowchart LR
|
||||
#### 定义单个卷
|
||||
|
||||
```docker
|
||||
FROM mysql:8.4
|
||||
FROM mysql:8.0
|
||||
VOLUME /var/lib/mysql
|
||||
```
|
||||
|
||||
@@ -63,7 +63,7 @@ VOLUME ["/data", "/logs", "/config"]
|
||||
如果运行时未指定挂载,Docker 会自动创建匿名卷:
|
||||
|
||||
```bash
|
||||
$ docker run mysql:8.4
|
||||
$ docker run mysql:8.0
|
||||
$ docker volume ls
|
||||
DRIVER VOLUME NAME
|
||||
local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
@@ -74,7 +74,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
```bash
|
||||
## 使用命名卷替代匿名卷
|
||||
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
```
|
||||
|
||||
#### 3. 可被 Bind Mount 覆盖
|
||||
@@ -82,7 +82,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.4
|
||||
```bash
|
||||
## 使用宿主机目录替代
|
||||
|
||||
$ docker run -v /my/data:/var/lib/mysql mysql:8.4
|
||||
$ docker run -v /my/data:/var/lib/mysql mysql:8.0
|
||||
```
|
||||
---
|
||||
|
||||
@@ -145,7 +145,7 @@ VOLUME /app/uploads
|
||||
```bash
|
||||
## 查看镜像定义的 VOLUME
|
||||
|
||||
$ docker inspect mysql:8.4 --format '{{json .Config.Volumes}}' | jq
|
||||
$ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq
|
||||
{
|
||||
"/var/lib/mysql": {}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ volumes:
|
||||
```bash
|
||||
## 使用 --rm 运行的容器,匿名卷会在容器删除时一起删除
|
||||
|
||||
$ docker run --rm mysql:8.4
|
||||
$ docker run --rm mysql:8.0
|
||||
|
||||
## 容器停止后,数据丢失!
|
||||
|
||||
@@ -205,7 +205,7 @@ $ docker run --rm mysql:8.4
|
||||
**解决**:始终使用命名卷
|
||||
|
||||
```bash
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
```
|
||||
---
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ docker build -t my-image:1.0 .
|
||||
本章中的 Dockerfile 示例使用的基础镜像标签遵循以下原则:
|
||||
|
||||
- **通用标签**(如 `ubuntu:24.04`、`alpine`、`nginx`):保持原样,无需修改
|
||||
- **基础镜像版本号**(如 `node:22`、`python:3.12`):使用主或次版本号而非完整版本号(patch),这样可以自动获取最新的补丁版本,确保获得安全更新
|
||||
- **基础镜像版本号**(如 `node:20`、`python:3.12`):使用主或次版本号而非完整版本号(patch),这样可以自动获取最新的补丁版本,确保获得安全更新
|
||||
- **避免**:不建议使用 `latest` 标签和完整的 patch 版本号(如 `20.10.0`)作为基础镜像,因为这会导致构建的不可重现性或安全风险
|
||||
|
||||
读者在使用这些示例时,应根据实际生产环境需求选择合适的版本号。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:22-alpine as frontend
|
||||
FROM node:20-alpine as frontend
|
||||
|
||||
COPY package.json /app/
|
||||
|
||||
@@ -47,7 +47,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
|
||||
&& chmod -R 777 storage \
|
||||
&& php artisan package:discover
|
||||
|
||||
FROM nginx:1.30-alpine as nginx
|
||||
FROM nginx:1.25-alpine as nginx
|
||||
|
||||
ARG LARAVEL_PATH=/app/laravel
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ $ docker run -u $(id -u):$(id -g) ...
|
||||
在 Docker Desktop 上,Bind Mount 性能通常不如 Volume,因为数据需要在宿主机文件系统和 Linux VM 之间同步:
|
||||
|
||||
```bash
|
||||
## 使用 :cached 或 :delegated 提高性能(macOS,仅 Docker Desktop 4.5 及更早版本)
|
||||
## 使用 :cached 或 :delegated 提高性能(macOS)
|
||||
|
||||
$ docker run -v /host/path:/container/path:cached myapp
|
||||
```
|
||||
@@ -248,8 +248,6 @@ $ docker run -v /host/path:/container/path:cached myapp
|
||||
| `:delegated` | 容器权威,宿主机读取可能延迟 |
|
||||
| `:consistent` | 默认,完全一致 (最慢)|
|
||||
|
||||
> **注意**:Docker Desktop 4.6+ 默认使用 VirtioFS 文件共享引擎,上述 `:cached`/`:delegated` 选项已被静默忽略。如需优化文件同步性能,请参考 Docker Desktop 的 [Synchronized file shares](https://docs.docker.com/desktop/synchronized-file-sharing/) 功能。
|
||||
|
||||
---
|
||||
|
||||
### 8.2.9 最佳实践
|
||||
|
||||
@@ -21,7 +21,6 @@ ghi789... none null local
|
||||
| **none** | 禁用网络 | 完全隔离的容器 |
|
||||
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
|
||||
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
|
||||
| **ipvlan** | 容器共享父接口 MAC,独享 IP | 同网段大量容器、对 MAC 数量受限的网络 |
|
||||
|
||||
### 9.2.2 Bridge 网络:默认
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ docker network inspect my-overlay-net
|
||||
docker service create --name web \
|
||||
--network my-overlay-net \
|
||||
--replicas 3 \
|
||||
nginx # 确保与环境兼容的 Nginx 版本
|
||||
nginx
|
||||
|
||||
# 单机环境下也可以让普通容器加入 attachable overlay 网络
|
||||
docker run -d --name container1 --network my-overlay-net busybox sleep 1d
|
||||
@@ -111,14 +111,14 @@ docker run -d \
|
||||
--dns 8.8.8.8 \
|
||||
--dns 1.1.1.1 \
|
||||
--dns-search example.com \
|
||||
nginx # 确保与环境兼容的 Nginx 版本
|
||||
nginx
|
||||
|
||||
# DNS 选项
|
||||
docker run -d \
|
||||
--dns-option ndots:2 \
|
||||
--dns-option timeout:1 \
|
||||
--dns-option attempts:3 \
|
||||
nginx # 确保与环境兼容的 Nginx 版本
|
||||
nginx
|
||||
|
||||
# 查看容器 DNS 配置
|
||||
docker exec <container_id> cat /etc/resolv.conf
|
||||
@@ -171,8 +171,8 @@ networks:
|
||||
docker network create mynet
|
||||
|
||||
# 运行服务
|
||||
docker run -d --name web --network mynet nginx # 确保与环境兼容的 Nginx 版本
|
||||
docker run -d --name db --network mynet postgres # 确保与环境兼容的 PostgreSQL 版本
|
||||
docker run -d --name web --network mynet nginx
|
||||
docker run -d --name db --network mynet postgres
|
||||
|
||||
# 在其他容器中通过服务名访问
|
||||
docker run -it --network mynet busybox sh
|
||||
|
||||
@@ -39,7 +39,7 @@ $ docker buildx build --sbom=true -t myimage .
|
||||
> **⚠️ 注意与失败模式**:
|
||||
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见,对底层的存储格式有前置要求:默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构。
|
||||
>
|
||||
> 如果只简单运行上述命令,你可能会面临 **“命令成功执行,但本地镜像中看不到 SBOM”** 的体会落差。
|
||||
> 如果只简单运行上述命令,你可能会面临 **”命令成功执行,但本地镜像中看不到 SBOM”** 的体会落差。
|
||||
>
|
||||
> **正确的解决路径有两条**:
|
||||
> 1. **推送到远端仓库**:使用 `docker buildx build --sbom=true --push -t myimage:tag` 时,SBOM 会正确保存到远端仓库。远端 OCI 兼容的镜像仓库能够完整存储这些元数据。
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
Docker Buildx 是一个 docker CLI 插件,其扩展了 docker 命令,支持 [Moby BuildKit](10.1_buildkit.md) 提供的功能。提供了与 docker build 相同的用户体验,并增加了许多新功能。
|
||||
|
||||
> Buildx 需要 Docker v23.0+(该版本起 BuildKit 成为默认构建引擎)。推荐使用 Docker v28 及以上版本以获得最完整的 Buildx 功能支持。
|
||||
> Buildx 需要 Docker v19.03+ (Docker 19.03 及以上版本)。在较新版本中已更常用且功能更完整。
|
||||
|
||||
## 本章内容
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Docker Compose 提供了丰富的命令来管理项目和容器。本节将详
|
||||
|
||||
**配置验证**:
|
||||
|
||||
- `docker compose config`:验证 docker-compose.yml 格式是否正确
|
||||
- `docker compose config`:验证 compose.yaml (或 docker-compose.yml) 格式是否正确
|
||||
|
||||
### 11.4.1 命令对象与格式
|
||||
|
||||
@@ -46,7 +46,7 @@ docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
|
||||
|
||||
* `-p, --project-name NAME` 指定项目名称,默认将使用所在目录名称作为项目名。
|
||||
|
||||
* `--verbose` 输出更多调试信息。(**已弃用**:在 Docker Compose V2 中,请改用 `docker --log-level debug compose ...` 或设置环境变量 `COMPOSE_DEBUG=1`。)
|
||||
* `--verbose` 输出更多调试信息。
|
||||
|
||||
* `-v, --version` 打印版本并退出。
|
||||
|
||||
|
||||
@@ -490,7 +490,7 @@ volumes:
|
||||
```yaml
|
||||
services:
|
||||
my_src:
|
||||
image: mysql:8.4
|
||||
image: mysql:8.0
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
|
||||
|
||||
@@ -106,11 +106,6 @@ services:
|
||||
POSTGRES_PASSWORD: password
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
web:
|
||||
build: .
|
||||
@@ -120,8 +115,7 @@ services:
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
- db
|
||||
environment:
|
||||
DATABASE_URL: postgres://postgres:password@db:5432/myapp_development
|
||||
|
||||
@@ -134,7 +128,7 @@ volumes:
|
||||
|--------|------|
|
||||
| `rm -f tmp/pids/server.pid` | 清理上次异常退出留下的 PID 文件 |
|
||||
| `volumes: .:/myapp` | 挂载代码目录,支持热更新 |
|
||||
| `depends_on` + `condition` | 等待数据库健康检查通过后再启动 |
|
||||
| `depends_on: db` | 确保数据库先启动 |
|
||||
| `DATABASE_URL` | Rails 12-factor 风格的数据库配置 |
|
||||
|
||||
### 11.7.6 步骤 4:生成 Rails 项目
|
||||
|
||||
@@ -28,13 +28,13 @@ services:
|
||||
# 数据库服务
|
||||
|
||||
db:
|
||||
image: mysql:8.4
|
||||
image: mysql:8.0
|
||||
container_name: wordpress_db
|
||||
restart: always
|
||||
command:
|
||||
# 启用原生密码认证(MySQL 8.4 默认禁用,旧版 WP 兼容性需要)
|
||||
# 使用原生密码认证(旧版 WP 兼容性)
|
||||
|
||||
- --mysql-native-password=ON
|
||||
- --default-authentication-plugin=mysql_native_password
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
environment:
|
||||
|
||||
@@ -5,6 +5,11 @@ services:
|
||||
image: postgres
|
||||
environment:
|
||||
POSTGRES_PASSWORD: 'postgres'
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
web:
|
||||
build: .
|
||||
@@ -13,3 +18,6 @@ services:
|
||||
- .:/code
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
services:
|
||||
|
||||
db:
|
||||
image: mysql:8.4
|
||||
image: mysql:8.0
|
||||
command:
|
||||
- --mysql-native-password=ON
|
||||
- --default_authentication_plugin=mysql_native_password
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
volumes:
|
||||
|
||||
@@ -198,7 +198,7 @@ $ docker run --rm --cpus=1 stress --cpu 4
|
||||
|
||||
#### Docker 对 cgroups v2 的支持
|
||||
|
||||
Docker 20.10+ 开始支持 cgroups v2(如果系统支持),提供更好的性能和资源隔离。如果需要明确控制或回退到 v1,可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数:
|
||||
Docker 19.03+ 默认优先使用 cgroups v2(如果系统支持),提供更好的性能和资源隔离。如果需要明确控制或回退到 v1,可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ flowchart TD
|
||||
每个 Dockerfile 指令创建一层,只有变化的层需要重建:
|
||||
|
||||
```docker
|
||||
FROM node:22 # 层1:基础镜像
|
||||
FROM node:20 # 层1:基础镜像
|
||||
COPY package.json ./ # 层2:依赖定义
|
||||
RUN npm install # 层3:安装依赖
|
||||
COPY . . # 层4:应用代码
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
##### 节点状态
|
||||
|
||||
节点的状态通过一组条件(Conditions)来描述。主要条件包括 `Ready`(kubelet 健康且可以接收 Pod)、`MemoryPressure`(内存不足)、`DiskPressure`(磁盘不足)和 `PIDPressure`(进程数过多)等。其中 `Ready` 条件最为关键:值为 `True` 表示节点健康可调度,`False` 表示节点异常,`Unknown` 表示节点控制器超过一定时间未收到心跳。
|
||||
节点的状态主要是用来描述处于 `Running` 的节点。当前可用的有 `NodeReachable` 和 `NodeReady`。以后可能会增加其他状态。`NodeReachable` 表示集群可达。`NodeReady` 表示 kubelet 返回 Status Ok 并且 HTTP 状态检查健康。
|
||||
|
||||
#### 节点管理
|
||||
|
||||
@@ -166,7 +166,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.28
|
||||
image: nginx:1.30
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
@@ -200,7 +200,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: mysql
|
||||
image: mysql:8.4
|
||||
image: mysql:8.0
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/mysql
|
||||
|
||||
@@ -31,7 +31,7 @@ spec:
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.28
|
||||
image: nginx:1.30
|
||||
ports:
|
||||
- containerPort: 80
|
||||
```
|
||||
@@ -73,7 +73,7 @@ kubectl get svc nginx-service
|
||||
|
||||
### 13.5.4 步骤 3:模拟滚动更新
|
||||
|
||||
修改 `nginx-deployment.yaml`,将镜像版本改为 `nginx:1.28-alpine`。
|
||||
修改 `nginx-deployment.yaml`,将镜像版本改为 `nginx:1.30-alpine`。
|
||||
|
||||
```bash
|
||||
kubectl apply -f nginx-deployment.yaml
|
||||
|
||||
@@ -138,14 +138,12 @@ $ sysctl --system
|
||||
|
||||
为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。
|
||||
|
||||
#### 修改 `kubelet.service`(可选:IPVS 模式)
|
||||
|
||||
> **注意**:kube-proxy 的 IPVS 模式已在 Kubernetes 1.35 中被标记为弃用,并在 **Kubernetes 1.36 中正式移除**。新部署应使用默认的 iptables 模式或 nftables 模式(Kubernetes 1.31+ 可用)。以下 IPVS 配置仅供 1.35 及更早版本的旧环境参考。
|
||||
#### 修改 `kubelet.service`
|
||||
|
||||
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
|
||||
|
||||
```bash
|
||||
# 启用 ipvs 相关内核模块(已弃用,建议迁移至 nftables)
|
||||
# 启用 ipvs 相关内核模块
|
||||
|
||||
[Service]
|
||||
ExecStartPre=-/sbin/modprobe ip_vs
|
||||
|
||||
@@ -169,14 +169,12 @@ $ sysctl --system
|
||||
|
||||
为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。
|
||||
|
||||
#### 修改 `kubelet.service`(可选:IPVS 模式)
|
||||
|
||||
> **注意**:kube-proxy 的 IPVS 模式已在 Kubernetes 1.35 中被标记为弃用,并在 **Kubernetes 1.36 中正式移除**。新部署应使用默认的 iptables 模式或 nftables 模式(Kubernetes 1.31+ 可用)。以下 IPVS 配置仅供 1.35 及更早版本的旧环境参考。
|
||||
#### 修改 `kubelet.service`
|
||||
|
||||
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
|
||||
|
||||
```bash
|
||||
# 启用 ipvs 相关内核模块(已弃用,建议迁移至 nftables)
|
||||
# 启用 ipvs 相关内核模块
|
||||
|
||||
[Service]
|
||||
ExecStartPre=-/sbin/modprobe ip_vs
|
||||
@@ -242,8 +240,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
|
||||
|
||||
```bash
|
||||
$ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
|
||||
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
|
||||
--cri-socket unix:///var/run/cri-dockerd.sock
|
||||
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
|
||||
```
|
||||
|
||||
### 14.2.7 查看服务
|
||||
|
||||
@@ -193,10 +193,10 @@ $ kubectl label pods -l app=nginx version=v1
|
||||
|
||||
```bash
|
||||
# 添加注解
|
||||
$ kubectl annotate pod my-pod description="Production pod"
|
||||
$ kubectl annotate pod my-pod description=”Production pod”
|
||||
|
||||
# 修改注解
|
||||
$ kubectl annotate pod my-pod description="Staging pod" --overwrite
|
||||
$ kubectl annotate pod my-pod description=”Staging pod” --overwrite
|
||||
|
||||
# 删除注解
|
||||
$ kubectl annotate pod my-pod description-
|
||||
@@ -240,10 +240,8 @@ $ kubectl config set-context --current --namespace=my-namespace
|
||||
# 显示集群信息
|
||||
$ kubectl cluster-info
|
||||
|
||||
# 显示完整的集群状态(注:componentstatuses 自 1.19 起已弃用,建议使用下方替代命令)
|
||||
# 显示完整的集群状态(包括所有组件)
|
||||
$ kubectl get componentstatuses
|
||||
# 推荐替代:
|
||||
$ kubectl get --raw='/readyz?verbose'
|
||||
```
|
||||
|
||||
### 14.8.15 version
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## 15.1 简介
|
||||
|
||||
> **版本说明:** 本章内容基于 etcd 3.5 系列版本编写。官方维护最新两个次版本(当前为 3.5 和 3.6)。请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
|
||||
> **版本说明:** 本章内容基于 etcd 3.5 系列版本编写(当前最新为 v3.5.x)。请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
|
||||
|
||||
如图 15-1 所示,etcd 项目使用该标识。
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
`etcd` 基于 `Go` 语言实现,因此,用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
|
||||
|
||||
> 注意:etcd 官方仅维护最新两个次版本(当前为 3.5 和 3.6)。etcd 3.4 已于 2026 年 5 月结束支持(EOL),仍在使用 3.4 的用户应尽快升级。本章示例基于 etcd `3.5.x` 版本编写。etcd 3.6.x 可用于新部署。请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
|
||||
> 注意:etcd 官方仅维护最新两个次版本(当前为 3.5 和 3.6)。本章示例基于 etcd `3.5.x` 版本编写。etcd 3.6.x 可用于新部署。请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
|
||||
|
||||
### 15.2.1 二进制文件方式下载
|
||||
|
||||
|
||||
@@ -111,11 +111,9 @@ hello
|
||||
```
|
||||
支持的选项为
|
||||
|
||||
`--sort-by` 指定排序字段(CREATE / KEY / MODIFY / VALUE / VERSION)
|
||||
`--sort` 对结果进行排序
|
||||
|
||||
`--order` 指定排序顺序(ASCEND / DESCEND)
|
||||
|
||||
`--consistency` 指定一致性级别(`l` 线性一致,`s` 串行)
|
||||
`--consistent` 将请求发给主节点,保证获取内容的一致性
|
||||
|
||||
#### del
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ version: "3.6"
|
||||
services:
|
||||
|
||||
node1:
|
||||
image: quay.io/coreos/etcd:v3.5.29
|
||||
image: quay.io/coreos/etcd:v3.5.17
|
||||
volumes:
|
||||
- node1-data:/etcd-data
|
||||
expose:
|
||||
@@ -34,7 +34,7 @@ services:
|
||||
- docker-etcd
|
||||
|
||||
node2:
|
||||
image: quay.io/coreos/etcd:v3.5.29
|
||||
image: quay.io/coreos/etcd:v3.5.17
|
||||
volumes:
|
||||
- node2-data:/etcd-data
|
||||
networks:
|
||||
@@ -66,7 +66,7 @@ services:
|
||||
- docker-etcd
|
||||
|
||||
node3:
|
||||
image: quay.io/coreos/etcd:v3.5.29
|
||||
image: quay.io/coreos/etcd:v3.5.17
|
||||
volumes:
|
||||
- node3-data:/etcd-data
|
||||
networks:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Skopeo 是一个由 Red Hat 赞助开源的命令行工具,它可以在不需要运行容器守护进程(如 Docker Daemon)的前提下,对容器镜像进行极其高效的操作和管理,包括:检查、复制、删除和签名等操作。
|
||||
|
||||
Skopeo 最大的特点是其可以在“不将镜像拉取到本地”的情况下,直接在远端 Registry(镜像仓库)之间完成检查和搬运,从而大幅度节省带宽和磁盘空间。这也是它在容器运维和分发领域非常受欢迎的原因。
|
||||
Skopeo 最大的特点是其可以在”不将镜像拉取到本地”的情况下,直接在远端 Registry(镜像仓库)之间完成检查和搬运,从而大幅度节省带宽和磁盘空间。这也是它在容器运维和分发领域非常受欢迎的原因。
|
||||
|
||||
### 17.5.2 核心特性
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行时的实现差异,引入了 CRI(Container Runtime Interface)标准。
|
||||
|
||||
- 早期版本中,Kubernetes 默认使用 docker 作为运行时,通过一个名为 `dockershim` 的桥接组件对接 Docker,Docker 再对接 containerd。
|
||||
- 随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了 `dockershim` 和 `dockerd` 的中间层。这就是为什么从 Kubernetes 1.24+ 开始“弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用 `dockershim`,底层依然在使用从 Docker 基因中诞生的 containerd。参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。
|
||||
- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 1.26+ 仅支持 CRI v1)。如果集群中仍有依赖 CRI v1alpha2 的组件,升级 containerd 2.x 前需先完成迁移。containerd 2.3+ 是 2.x 系列首个 LTS 版本,支持从 1.7 LTS 直接升级,生产环境推荐使用。详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。
|
||||
- 随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了 `dockershim` 和 `dockerd` 的中间层。这就是为什么从 Kubernetes 1.24+ 开始”弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用 `dockershim`,底层依然在使用从 Docker 基因中诞生的 containerd。参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。
|
||||
- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 1.26+ 仅支持 CRI v1)。containerd 2.3+ 是 2.x 系列首个 LTS 版本,支持从 1.7 LTS 直接升级,生产环境推荐使用。详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。
|
||||
|
||||
### 17.6.3 为什么直接使用 containerd?
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
尽管这种方式在性能和启动速度上拥有巨大优势,但也带来了一个显著的缺点:**隔离性(Isolation)不足**。如果某个容器内的恶意进程利用了宿主机内核的漏洞完成了越狱(Privilege Escalation),它将对整个宿主机以及其上运行的所有其他容器造成毁灭性威胁。
|
||||
|
||||
如果在公有云环境(多租户场景)或运行不可信的第三方代码时,共享内核显然是不够安全的。为了解决这一问题,社区推出了“安全容器(Secure Containers/Sandboxed Containers)”的概念。安全容器的核心理念是:提供类似虚拟机的强隔离性,同时保持类似容器的轻量、快速启动和标准化管理。
|
||||
如果在公有云环境(多租户场景)或运行不可信的第三方代码时,共享内核显然是不够安全的。为了解决这一问题,社区推出了”安全容器(Secure Containers/Sandboxed Containers)”的概念。安全容器的核心理念是:提供类似虚拟机的强隔离性,同时保持类似容器的轻量、快速启动和标准化管理。
|
||||
|
||||
### 17.7.2 什么是 Kata Containers?
|
||||
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
# 第十七章 容器其它生态
|
||||
|
||||
> **版本说明(核验日期:2026-05-16)**:本章介绍的工具和运行时(Podman、Buildah、Skopeo、containerd、Kata Containers、gVisor、WasmEdge 等)都保持活跃的开发。建议:
|
||||
> **版本说明**:本章介绍的工具和运行时(Podman、Buildah、Skopeo、containerd、Kata Containers、gVisor、WasmEdge 等)都保持活跃的开发。建议:
|
||||
> - 查阅各项目官方文档获取最新版本
|
||||
> - 在生产环境使用前验证版本兼容性
|
||||
> - 关注官方发布说明了解重大变更
|
||||
|
||||
本章将介绍 Docker 和 Kubernetes 之外的容器生态技术。
|
||||
|
||||
同时,Docker 自身的生态也在向云构建、AI 本地推理和企业级桌面安全扩展。当前需要额外关注:
|
||||
|
||||
* **Docker Model Runner**:在 Docker Desktop / Docker Engine 中管理、运行和服务本地 AI 模型,支持 OpenAI 与 Ollama 兼容 API,并可将 GGUF、Safetensors 等模型文件作为 OCI Artifact 管理。
|
||||
* **Docker Build Cloud**:通过远程 BuildKit 和共享构建缓存加速本地与 CI 构建,适合多平台镜像和团队共享缓存场景。
|
||||
* **Docker Offload**:把容器构建和运行卸载到云端,适合 VDI、受限本机或不支持嵌套虚拟化的开发环境。
|
||||
* **Hardened Docker Desktop / Enhanced Container Isolation (ECI)**:通过更强的命名空间隔离、敏感挂载保护和系统调用限制降低桌面容器逃逸风险。
|
||||
|
||||
## 本章内容
|
||||
|
||||
* [Fedora CoreOS 简介](17.1_coreos_intro.md)
|
||||
|
||||
@@ -14,7 +14,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
|
||||
|
||||
尽管命名空间提供了很好的隔离性,但我们必须认识到:**所有的容器依然共享同一个宿主机的 Linux 内核**。
|
||||
|
||||
这意味着,一旦宿主机的内核存在提权漏洞(如著名的 Dirty COW 漏洞),攻击者有可能通过突破 Namespace 的限制,直接在内核层面执行恶意代码,从而实现“容器逃逸”。
|
||||
这意味着,一旦宿主机的内核存在提权漏洞(如著名的 Dirty COW 漏洞),攻击者有可能通过突破 Namespace 的限制,直接在内核层面执行恶意代码,从而实现”容器逃逸”。
|
||||
|
||||
> [!WARNING]
|
||||
> 为了缓解内核漏洞带来的威胁,生产环境务必保持宿主机 Linux 内核的及时修补与更新,或者借助诸如 gVisor、Kata Containers 等提供了独立内核的安全容器技术。同时,需要及时修补容器运行时(如 runC)的漏洞。2025 年 11 月披露的一系列 runC 容器逃逸漏洞(CVE-2025-31133、CVE-2025-52565、CVE-2025-52881)就表明,即使内核保持更新,运行时层的缺陷仍然可能导致容器隔离被突破。
|
||||
|
||||
@@ -50,7 +50,7 @@ dockerd \
|
||||
|
||||
### 18.3.3 Rootless 模式:非特权运行
|
||||
|
||||
为了从根本上解决“拥有 Docker socket 就是 root”的问题,Docker 自 19.03 版本(2019 年)起提供了 **Rootless 模式**。
|
||||
为了从根本上解决“拥有 Docker socket 就是 root”的问题,Docker 在近年推出了 **Rootless 模式**。
|
||||
|
||||
Rootless 模式允许在完全局限于非 `root` 用户的环境中运行 Docker 守护进程(`dockerd`)和容器。该模式利用了现代 Linux 内核的 User Namespace 技术和非特权网络命名空间实现。
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
一个普通的 Linux 内核提供了 300 多个系统调用,而一个正常运行的容器化应用(例如 Nginx 服务)通常只会用到几十个调用,这就给攻击者留下了大量的闲置入口点来进行内核层的缓冲区溢出攻击。
|
||||
|
||||
Docker 默认启用了 Seccomp 并利用预置的 [默认配置文件](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 将可以利用的系统调用缩减到了不足一半(默认禁用了 44 个危险的系统调用,比如修改时区或重启系统)。
|
||||
Docker 默认启用了 Seccomp 并利用预置的 [默认配置文件](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 将可以利用的系统调用缩减到了不足一半(默认禁用了 44 个危险的统调用,比如修改时区或重启系统)。
|
||||
|
||||
如果你对应用的系统调用特征了如指掌,你可以为容器定制专属规则。
|
||||
|
||||
|
||||
@@ -434,8 +434,8 @@ jobs:
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
- name: Run Trivy vulnerability scan
|
||||
# 安全提醒:2026 年 3 月 19 日 Trivy GitHub Actions 遭受供应链攻击,
|
||||
# 76 个版本标签被劫持。务必使用不可变的 commit SHA 引用,而非可变标签。
|
||||
# 安全提醒:2026 年 3 月 Trivy GitHub Actions 遭受供应链攻击,
|
||||
# 75 个版本标签被劫持。务必使用不可变的 commit SHA 引用,而非可变标签。
|
||||
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
|
||||
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
|
||||
with:
|
||||
|
||||
@@ -22,7 +22,7 @@ ELK (Elasticsearch,Logstash,Kibana) 是目前业界最流行的开源日志
|
||||
```yaml
|
||||
services:
|
||||
elasticsearch:
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:9.4.0
|
||||
image: docker.elastic.co/elasticsearch/elasticsearch:9.3.3
|
||||
container_name: elasticsearch
|
||||
environment:
|
||||
- "discovery.type=single-node"
|
||||
@@ -36,7 +36,7 @@ services:
|
||||
- logging
|
||||
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:9.4.0
|
||||
image: docker.elastic.co/kibana/kibana:9.3.3
|
||||
container_name: kibana
|
||||
environment:
|
||||
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
- **容器监控**:以 Prometheus 为主,讲解如何采集和展示容器性能指标。
|
||||
- **日志管理**:以 ELK (Elasticsearch, Logstash, Kibana) 套件为例,介绍集中式日志收集平台。
|
||||
|
||||
为了让读者能够在生产环境中真正用起来,本章会补齐以下“最小闭环”:
|
||||
为了让读者能够在生产环境中真正用起来,本章会补齐以下”最小闭环”:
|
||||
|
||||
* 关键指标与日志的验证方法
|
||||
* 常见故障排查路径
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* **指标监控**:以 Prometheus + Grafana 为主,完成指标采集、存储与可视化。
|
||||
* **日志管理**:以 EFK/ELK 为例,完成容器日志的集中采集、检索与分析。
|
||||
|
||||
生产环境中,建议将“可观测性”当成一个完整闭环:**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**。
|
||||
生产环境中,建议将”可观测性”当成一个完整闭环:**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**。
|
||||
|
||||
## 扩展阅读:Docker 日志驱动
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Debian 是一个常用的基础镜像。
|
||||
```bash
|
||||
$ docker run -it debian bash
|
||||
root@668e178d8d69:/# cat /etc/issue
|
||||
Debian GNU/Linux 13
|
||||
Debian GNU/Linux 12
|
||||
```
|
||||
`Debian` 镜像很适合作为基础镜像,构建自定义镜像。
|
||||
|
||||
@@ -43,18 +43,18 @@ Debian GNU/Linux 13
|
||||
Ubuntu 是目前最流行的 Linux 发行版之一。
|
||||
|
||||
|
||||
下面以 `ubuntu:26.04` 为例,演示如何使用该镜像安装一些常用软件。
|
||||
下面以 `ubuntu:24.04` 为例,演示如何使用该镜像安装一些常用软件。
|
||||
|
||||
首先使用 `-ti` 参数启动容器,登录 `bash`,查看 `ubuntu` 的发行版本号。
|
||||
|
||||
```bash
|
||||
$ docker run -ti ubuntu:26.04 /bin/bash
|
||||
$ docker run -ti ubuntu:24.04 /bin/bash
|
||||
root@7d93de07bf76:/# cat /etc/os-release
|
||||
PRETTY_NAME="Ubuntu 26.04 LTS"
|
||||
PRETTY_NAME="Ubuntu 24.04 LTS"
|
||||
NAME="Ubuntu"
|
||||
VERSION_ID="26.04"
|
||||
VERSION="26.04 LTS (Resolute Raccoon)"
|
||||
VERSION_CODENAME=resolute
|
||||
VERSION_ID="24.04"
|
||||
VERSION="24.04 LTS (Noble Numbat)"
|
||||
VERSION_CODENAME=noble
|
||||
ID=ubuntu
|
||||
ID_LIKE=debian
|
||||
HOME_URL="https://www.ubuntu.com/"
|
||||
|
||||
@@ -50,7 +50,7 @@ latest: Pulling from library/fedora
|
||||
Digest: sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e
|
||||
Status: Downloaded newer image for fedora:latest
|
||||
[root@196ca341419b /]# cat /etc/redhat-release
|
||||
Fedora release 43 (Forty Three)
|
||||
Fedora release 39 (Thirty Nine)
|
||||
```
|
||||
|
||||
### 20.4.3 相关资源
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
本章示例中使用的操作系统镜像版本遵循以下原则:
|
||||
|
||||
- **Alpine、Debian、Ubuntu、CentOS** 等操作系统镜像采用大版本或次版本标签(如 `alpine:3.21`、`ubuntu:26.04`),避免使用 `latest` 标签确保构建的可再现性
|
||||
- **Alpine、Debian、Ubuntu、CentOS** 等操作系统镜像采用大版本或次版本标签(如 `alpine:3.21`、`ubuntu:24.04`),避免使用 `latest` 标签确保构建的可再现性
|
||||
- **OS 大版本保留**,以便获得最新的安全补丁和修复
|
||||
- 在生产环境中,建议根据实际需求选择合适的版本,并定期更新以获得安全修复
|
||||
|
||||
|
||||
@@ -54,9 +54,9 @@ unit_test:
|
||||
|
||||
build_image:
|
||||
stage: build
|
||||
image: docker:29
|
||||
image: docker:27
|
||||
services:
|
||||
- docker:29-dind
|
||||
- docker:27-dind
|
||||
script:
|
||||
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
|
||||
|
||||
@@ -543,7 +543,7 @@ logfile ""
|
||||
|
||||
# 客户端输出缓冲限制
|
||||
client-output-buffer-limit normal 0 0 0
|
||||
client-output-buffer-limit replica 256mb 64mb 60
|
||||
client-output-buffer-limit slave 256mb 64mb 60
|
||||
client-output-buffer-limit pubsub 32mb 8mb 60
|
||||
```
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
## DevOps 背景介绍
|
||||
|
||||
DevOps 是一种重要的开发和运维文化,强调开发团队和运维团队之间的协作和自动化。它致力于通过自动化和流程优化,加快软件交付速度,同时提高系统的稳定性和可靠性。Docker 作为容器化技术的领导者,已成为现代 DevOps 工作流中不可或缺的工具。通过容器化应用,开发团队可以确保“一次构建,处处运行”,消除开发、测试和生产环境的差异,大大简化了部署流程。
|
||||
DevOps 是一种重要的开发和运维文化,强调开发团队和运维团队之间的协作和自动化。它致力于通过自动化和流程优化,加快软件交付速度,同时提高系统的稳定性和可靠性。Docker 作为容器化技术的领导者,已成为现代 DevOps 工作流中不可或缺的工具。通过容器化应用,开发团队可以确保”一次构建,处处运行”,消除开发、测试和生产环境的差异,大大简化了部署流程。
|
||||
|
||||
## Docker 在 DevOps 中的角色
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#### 使用多阶段构建
|
||||
|
||||
在现代 Docker 版本中,你可以使用[多阶段构建](../07_dockerfile/7.17_multistage_builds.md)来减少所构建镜像的大小。该能力最早在 Docker 17.05 引入,如今已是编写生产镜像的默认实践之一;新项目还应结合 BuildKit 缓存挂载、secret 挂载和多平台构建能力一起评估。
|
||||
在 Docker 17.05 以上版本中,你可以使用[多阶段构建](../07_dockerfile/7.17_multistage_builds.md)来减少所构建镜像的大小。
|
||||
|
||||
#### 避免安装不必要的包
|
||||
|
||||
@@ -190,7 +190,7 @@ ENV PG_MAJOR 9.3
|
||||
|
||||
ENV PG_VERSION 9.3.4
|
||||
|
||||
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgres && …
|
||||
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
|
||||
|
||||
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
|
||||
```
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
```bash
|
||||
$ sudo kill -SIGHUP $(pidof dockerd)
|
||||
```
|
||||
此时 dockerd 会在日志中输出更多信息供分析。
|
||||
此时 dockerd 会在日志中输入更多信息供分析。
|
||||
|
||||
### 检查内核日志
|
||||
|
||||
|
||||
@@ -421,7 +421,7 @@ Kubernetes 进阶 (Week 24-36)
|
||||
- [Docker 官方博客](https://www.docker.com/blog/)
|
||||
- [Kubernetes 官方博客](https://kubernetes.io/blog/)
|
||||
- [CNCF 博客](https://www.cncf.io/blog/)
|
||||
- [DZone Cloud Architecture](https://dzone.com/cloud-architecture)
|
||||
- [DZone](https://dzone.com/containers-cloud)
|
||||
|
||||
### 认证指南
|
||||
|
||||
@@ -435,7 +435,7 @@ Kubernetes 进阶 (Week 24-36)
|
||||
- 时间限制:90 分钟
|
||||
- 及格分数:73%(约 41 道题)
|
||||
- 费用:$199 USD
|
||||
- 有效期:2 年
|
||||
- 有效期:3 年
|
||||
|
||||
考试内容比例:
|
||||
```text
|
||||
@@ -478,7 +478,7 @@ Kubernetes 进阶 (Week 24-36)
|
||||
# 1. 学习本书第 1-11 章(基础到中级)
|
||||
# 2. 完成 20+ 个实战项目
|
||||
# 3. 参考官方学习指南
|
||||
# 参考 KodeKloud DCA 认证指南:https://kodekloud.com/blog/docker-certified-associate-guide/
|
||||
curl https://docker.training.kodekloud.com/dca-guide
|
||||
|
||||
# 4. 模拟考试
|
||||
- Linux Academy DCA 练习题
|
||||
@@ -587,7 +587,7 @@ A(要点):
|
||||
A(要点):
|
||||
```text
|
||||
1. 选择合适的基础镜像:
|
||||
scratch < alpine:3.21 < python:3.14-slim < python:3.14
|
||||
scratch < alpine:3.17 < python:3.14-slim < python:3.14
|
||||
|
||||
2. 多阶段构建:
|
||||
- 构建阶段只保留编译工具
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
> 2026 年了,对于任何新项目,**强烈建议** 使用以下生产级替代方案:
|
||||
> - [Rocky Linux](https://hub.docker.com/_/rockylinux):CentOS 原创始人发起的社区驱动项目,目前主流为 Rocky Linux 9。
|
||||
> - [AlmaLinux](https://hub.docker.com/_/almalinux):由 CloudLinux 支持的企业级发行版,提供长期支持。
|
||||
> - [CentOS Stream](https://quay.io/repository/centos/centos):RHEL 的上游开发分支,镜像已迁移至 Quay.io (适合开发测试,不建议用于生产环境)。
|
||||
> - [CentOS Stream](https://hub.docker.com/r/centos/centos):RHEL 的上游开发分支 (适合开发测试,不建议用于生产环境)。
|
||||
|
||||
该仓库位于 [Docker Hub 的 CentOS 官方镜像页](https://hub.docker.com/_/centos),提供了 CentOS 从 5 ~ 8 各个版本的镜像(仅作为历史归档,不再更新)。
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ $ docker run --name some-mongo -d --network my-mongo-net mongo
|
||||
```bash
|
||||
$ docker run --name some-app -d --network my-mongo-net application-that-uses-mongo
|
||||
```
|
||||
或者通过 `mongosh`(MongoDB 6.0+ 已移除旧版 `mongo` 命令行工具)
|
||||
或者通过 `mongosh`(MongoDB 6.0+ 已弃用 `mongo`,请使用 `mongosh`)
|
||||
|
||||
```bash
|
||||
$ docker run -it --rm \
|
||||
--network my-mongo-net \
|
||||
mongo \
|
||||
mongosh "some-mongo:27017/test"
|
||||
sh -c 'exec mongosh "mongodb://some-mongo:27017/test"'
|
||||
```
|
||||
|
||||
### Dockerfile
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
在项目中创建一个 Dockerfile。
|
||||
|
||||
```docker
|
||||
FROM node:22
|
||||
FROM node:20
|
||||
|
||||
## replace this with your application's default port
|
||||
|
||||
@@ -28,11 +28,9 @@ $ docker run -it --rm --name my-running-app my-nodejs-app
|
||||
```bash
|
||||
$ docker run -it --rm \
|
||||
--name my-running-script \
|
||||
# -v "$ ":/usr/src/myapp \
|
||||
|
||||
--mount type=bind,src="$(pwd)",target=/usr/src/myapp \
|
||||
-w /usr/src/myapp \
|
||||
node:22-alpine \
|
||||
node:20-alpine \
|
||||
node your-daemon-or-script.js
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user