Add blank lines around headers

This commit is contained in:
yeasy
2026-03-24 09:27:04 -07:00
parent 2f7985225a
commit 76c2ae50fe
112 changed files with 468 additions and 0 deletions
+2
View File
@@ -9,6 +9,7 @@
```html
<h1>Hello, Docker!</h1>
```
### 1.1.2 编写 Dockerfile
在同级目录下创建一个名为 `Dockerfile` (无后缀) 的文件
@@ -17,6 +18,7 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```
### 1.1.3 构建镜像
打开终端进入该目录执行构建命令
+1
View File
@@ -40,6 +40,7 @@ flowchart LR
end
A == 一致 ==> C
```
### 1.2.3 Docker vs 虚拟机
很多人第一次接触 Docker 时会问**这不就是虚拟机吗** 答案是**不是而且差别很大**
+6
View File
@@ -33,6 +33,7 @@
├── Day 4:问老同事怎么配的,他也忘了
└── Day 5:终于能跑起来了!但不知道为什么……
```
#### 场景三服务器迁移的恐惧
```bash
@@ -41,6 +42,7 @@
运维:"当时是一个已经离职的同事配的……"
所有人:😱
```
### 1.3.2 Docker 如何解决这些问题
Docker 的出现为上述问题提供了完美的解决方案它通过 一次构建到处运行 的核心理念从根本上改变了软件交付的方式
@@ -54,6 +56,7 @@ flowchart LR
test -- "有问题<br/>反馈修改和更新" --> dev
test -- "没问题<br/>发布" --> prod["生产环境"]
```
### 1.3.3 Docker 的核心优势
除了解决上述痛点Docker 还拥有诸多显著的技术优势包括环境一致性秒级启动高效的资源利用等
@@ -76,6 +79,7 @@ $ docker compose up
...
```
#### 2. 秒级启动
传统虚拟机启动需要几分钟 (引导操作系统) Docker 容器启动通常只需要 **几秒甚至几百毫秒**
@@ -126,6 +130,7 @@ flowchart TD
Server2 --- Containers
end
```
#### 4. 持续交付和部署
Docker 完美契合 DevOps 的工作流程
@@ -182,6 +187,7 @@ flowchart TD
Worker --> DB
end
```
### 1.3.4 Docker 不适合的场景
笔者认为技术选型要客观Docker 并非银弹以下场景可能不太适合
+5
View File
@@ -79,6 +79,7 @@ flowchart TD
AppC --> Ubuntu
end
```
#### 分层是如何工作的
笔者用一个实际的 Dockerfile 来解释分层
@@ -135,6 +136,7 @@ RUN apt-get update && \
## 在同一层完成安装、使用、清理
```
#### 查看镜像的分层
```bash
@@ -150,6 +152,7 @@ a6bd71f48f68 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
<missing> 2 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB
...
```
### 2.1.5 镜像的标识
Docker 镜像有多种标识方式
@@ -172,6 +175,7 @@ ubuntu:24.04
nginx # 等同于 nginx:latest
```
#### 2. 镜像 IDContent-Addressable 标识
每个镜像有一个基于内容计算的唯一 ID
@@ -182,6 +186,7 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a6bd71f48f68 2 weeks ago 187MB
ubuntu 24.04 ca2b0f26964c 3 weeks ago 78.1MB
```
#### 3. 镜像摘要
更精确的标识基于镜像内容的 SHA256 哈希
+4
View File
@@ -92,6 +92,7 @@ flowchart TD
ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1
```
#### Copy-on-Write写时复制
当容器需要修改镜像层中的文件时
@@ -104,6 +105,7 @@ flowchart TD
读取文件:直接从镜像层读取(共享,高效)
修改文件:复制到容器层,然后修改(只有这个容器能看到修改)
```
#### 容器存储层的生命周期
> **笔者特别强调**这是新手最容易踩的坑**容器存储层与容器生命周期绑定容器删除数据就没了**
@@ -122,6 +124,7 @@ $ docker rm abc123
## 数据丢了!没有任何办法恢复!
```
#### 正确的数据持久化方式
按照 Docker 最佳实践容器存储层应该保持 **无状态**需要持久化的数据应该使用
@@ -190,6 +193,7 @@ $ docker unpause abc123 # 恢复
$ docker rm abc123 # 删除已停止的容器
$ docker rm -f abc123 # 强制删除运行中的容器
```
### 2.2.6 容器与进程的关系
> **核心概念**容器的生命周期 = 主进程 (PID 1) 的生命周期
+5
View File
@@ -110,6 +110,7 @@ $ docker pull bitnami/redis # 第三方镜像
$ docker login
$ docker push username/myapp:v1.0
```
#### 其他公共 Registry
除了 Docker Hub还有以下几个常见的公共 Registry
@@ -160,6 +161,7 @@ $ docker push localhost:5000/myapp:v1.0
$ docker pull localhost:5000/myapp:v1.0
```
#### 企业级解决方案
官方 Registry 功能较为基础企业环境常用以下方案
@@ -225,6 +227,7 @@ $ docker push registry.example.com/myteam/myapp:v1.0
$ docker logout
```
### 2.3.7 镜像的安全性
在使用公共镜像或维护私有镜像时安全性是不容忽视的重要环节
@@ -245,6 +248,7 @@ redis # ✅ 官方
bitnami/redis # ⚠️ 需要评估
someuser/myapp # ⚠️ 需要评估
```
#### 镜像签名
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证`Docker Content Trust (DCT)` 已进入退场阶段不建议作为新项目主方案
@@ -265,6 +269,7 @@ $ cosign generate-key-pair
$ cosign sign --key cosign.key $IMAGE
$ cosign verify --key cosign.pub $IMAGE
```
#### 漏洞扫描
```bash
+3
View File
@@ -36,6 +36,7 @@ do
sudo apt remove $pkg;
done
```
### 3.1.2 使用 APT 安装
由于 `apt` 源使用 HTTPS 以确保软件下载过程中不被篡改因此我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书
@@ -83,6 +84,7 @@ $ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
```
### 3.1.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Ubuntu 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
@@ -105,6 +107,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.1.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
+3
View File
@@ -25,6 +25,7 @@ $ sudo apt-get remove docker \
docker-engine \
docker.io
```
### 3.2.2 使用 APT 安装
由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改因此我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书
@@ -74,6 +75,7 @@ $ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
### 3.2.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Debian 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
@@ -96,6 +98,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.2.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
+4
View File
@@ -32,6 +32,7 @@ $ sudo dnf remove docker \
docker-engine-selinux \
docker-engine
```
### 3.3.2 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式便于后续的更行和管理
@@ -67,6 +68,7 @@ $ sudo dnf config-manager --set-enabled docker-ce-test
```bash
$ sudo dnf config-manager --set-disabled docker-ce-test
```
#### 安装 Docker
更新 `dnf` 软件源缓存并安装 `docker-ce`
@@ -84,6 +86,7 @@ docker-ce.x86_64 18.06.1.ce-3.fc28 docker-ce-stable
$ sudo dnf -y install docker-ce-18.06.1.ce
```
### 3.3.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Fedora 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
@@ -106,6 +109,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.3.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
+6
View File
@@ -34,6 +34,7 @@ $ sudo yum remove docker \
docker-ce-cli \
containerd.io
```
### 3.4.2 使用 yum 安装
使用 yum/dnf 安装是管理 Docker 生命周期的标准方式
@@ -64,6 +65,7 @@ $ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.r
```bash
$ sudo dnf config-manager --set-enabled docker-ce-test
```
#### 安装 Docker
更新 `dnf` 软件源缓存并安装 `docker-ce`
@@ -71,6 +73,7 @@ $ sudo dnf config-manager --set-enabled docker-ce-test
```bash
$ sudo dnf install docker-ce docker-ce-cli containerd.io
```
### 3.4.3 CentOS8 额外设置
CentOS 8/Stream 默认使用 `nftables`Docker 在新版本中已提供 `nftables` 实验支持但在一些环境下仍可能遇到兼容性问题若你遇到容器网络异常可以先切换回 `iptables` 后端
@@ -89,6 +92,7 @@ $ firewall-cmd --permanent --zone=trusted --add-interface=docker0
$ firewall-cmd --reload
```
### 3.4.4 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本CentOS 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
@@ -112,6 +116,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.4.6 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
@@ -192,6 +197,7 @@ EOF
```bash
$ sudo sysctl -p
```
### 3.4.10 参考文档
* [Docker 官方 CentOS 安装文档](https://docs.docker.com/engine/install/centos/)。
+3
View File
@@ -89,6 +89,7 @@ $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docke
# $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian $(lsb_release -cs) stable" | sudo tee -a /etc/apt/sources.list
```
#### 安装 Docker
更新 apt 软件包缓存并安装 `docker-ce`
@@ -98,6 +99,7 @@ $ sudo apt-get update
$ sudo apt-get install docker-ce
```
### 3.5.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程提供了一套便捷的安装脚本Raspberry Pi OS 系统上可以使用这套脚本安装另外可以通过 `--mirror` 选项使用国内源进行安装
@@ -121,6 +123,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
### 3.5.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
+9
View File
@@ -41,6 +41,7 @@ docker-ce.x86_64 3:19.03.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable
....
```
##### 下载到指定文件夹
```bash
@@ -74,6 +75,7 @@ Background downloading packages, then exiting:
Total 118 MB/s | 87 MB 00:00:00
exiting because "Download Only" specified
```
##### 复制到目标服务器之后进入文件夹安装C-N
* 离线安装时必须使用 rpm 命令不检查依赖的方式安装
@@ -81,6 +83,7 @@ exiting because "Download Only" specified
```bash
rpm -Uvh *.rpm --nodeps --force
```
##### 锁定软件版本C-N
**下载锁定版本软件**
@@ -130,6 +133,7 @@ versionlock deleted: 1
```bash
sudo yum versionlock delete all
```
#### YUM 本地源服务器搭建安装 Docker
##### 挂载 ISO 镜像搭建本地 File
@@ -161,6 +165,7 @@ EOF
yum clean all
yum install createrepo -y
```
##### 根据本地文件搭建 BASE 网络源
```bash
@@ -183,6 +188,7 @@ createrepo /var/www/html/base/
systemctl enable httpd
systemctl start httpd
```
##### 下载 Docker-CE 镜像仓库
在有网络的服务器上下载 Docker-ce 镜像
@@ -202,6 +208,7 @@ mkdir /tmp/docker-ce/
reposync -r docker-ce-stable -p /tmp/docker-ce/
```
##### 创建仓库索引
把下载的 docker-ce 文件夹复制到离线的服务器
@@ -213,6 +220,7 @@ reposync -r docker-ce-stable -p /tmp/docker-ce/
createrepo /var/www/html/docker-ce/
```
##### YUM 客户端设置C...N
```bash
@@ -239,6 +247,7 @@ proxy=_none_
EOF
```
##### Docker 安装C...N
```bash
+2
View File
@@ -18,6 +18,7 @@ Docker Desktop 为 Mac 用户提供了无缝的 Docker 体验。你可以选择
```bash
$ brew install --cask docker
```
#### 手动下载安装
如果需要手动下载请点击以下[链接](https://desktop.docker.com/mac/main/amd64/Docker.dmg)下载 Docker Desktop for Mac。
@@ -63,6 +64,7 @@ $ docker run -d -p 80:80 --name webserver nginx
$ docker stop webserver
$ docker rm webserver
```
### 3.7.4 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢可以配置 Docker [国内镜像加速](3.9_mirror.md)
+1
View File
@@ -22,6 +22,7 @@
```powershell
$ winget install Docker.DockerDesktop
```
### 3.8.3 WSL2 运行 Docker
若你的 Windows 版本为 Windows 10 专业版或家庭版 v1903 及以上版本可以使用 WSL2 运行 Docker具体请查看 [Docker Desktop WSL 2 backend](https://docs.docker.com/docker-for-windows/wsl/)。
+1
View File
@@ -19,6 +19,7 @@ Docker 支持在多种平台上安装和使用,选择合适的安装方式是
$ docker version
$ docker run --rm hello-world
```
### 延伸阅读
- [镜像加速器](3.9_mirror.md)解决国内拉取镜像慢的问题
+3
View File
@@ -9,6 +9,7 @@
```bash
docker pull [选项] [Registry地址/]仓库名[:标签]
```
#### 镜像名称格式
Docker 镜像名称由 Registry 地址用户名仓库名和标签组成其标准格式如下
@@ -70,6 +71,7 @@ Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
```
#### 输出解读
| 输出内容 | 说明 |
@@ -180,6 +182,7 @@ $ docker images --digests ubuntu
REPOSITORY TAG DIGEST IMAGE ID
ubuntu 24.04 sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26 ca2b0f26964c
```
#### 使用摘要拉取
用摘要拉取可确保获取完全相同的镜像
+7
View File
@@ -87,6 +87,7 @@ ubuntu 24.04 329ed837d508 78MB
ubuntu noble 329ed837d508 78MB
ubuntu 22.04 a1b2c3d4e5f6 72MB
```
#### 按仓库名和标签过滤
```bash
@@ -94,6 +95,7 @@ $ docker images ubuntu:24.04
REPOSITORY TAG IMAGE ID SIZE
ubuntu 24.04 329ed837d508 78MB
```
#### 使用过滤器 --filter
| 过滤条件 | 说明 | 示例 |
@@ -132,6 +134,7 @@ $ docker images
REPOSITORY TAG IMAGE ID SIZE
<none> <none> 00285df0df87 342MB
```
#### 产生原因
1. **镜像重新构建**新镜像使用了旧镜像的标签旧镜像标签被移除
@@ -188,11 +191,13 @@ $ docker rmi $(docker images -q)
$ docker rmi $(docker images -q redis)
```
#### 显示完整 ID
```bash
$ docker images --no-trunc
```
#### 显示摘要
```bash
@@ -200,6 +205,7 @@ $ docker images --digests
REPOSITORY TAG DIGEST IMAGE ID
nginx latest sha256:b4f0e0bdeb5... e43d811ce2f4
```
#### 自定义格式
使用 Go 模板语法自定义输出
@@ -220,6 +226,7 @@ redis latest 183MB
nginx latest 181MB
ubuntu 24.04 78MB
```
#### 可用模板字段
| 字段 | 说明 |
+8
View File
@@ -38,6 +38,7 @@ $ docker rmi 501
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
#### 使用镜像名删除
```bash
@@ -45,6 +46,7 @@ $ docker rmi redis:alpine
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
#### 使用摘要删除
摘要删除最精确适用于 CI/CD 场景
@@ -76,6 +78,7 @@ Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
```
#### Untagged vs Deleted
| 操作 | 含义 |
@@ -131,6 +134,7 @@ $ docker image prune
$ docker image prune -f
```
#### 删除所有未使用的镜像
```bash
@@ -142,6 +146,7 @@ $ docker image prune -a
$ docker image prune -a --filter "until=24h"
```
#### 按条件删除
```bash
@@ -182,6 +187,7 @@ $ docker rmi nginx
$ docker rmi -f nginx
```
#### 原因二多个标签指向同一镜像
```bash
@@ -234,6 +240,7 @@ $ docker image prune -f
$ docker system prune -a
```
#### CI/CD 环境
```bash
@@ -241,6 +248,7 @@ $ docker system prune -a
$ docker image prune -a --filter "until=72h" -f
```
#### 查看空间占用
```bash
+1
View File
@@ -34,6 +34,7 @@ $ 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
```
### 4.6.2 Docker 镜像的导入和导出 `docker save` `docker load`
Docker 还提供了 `docker save` `docker load` 命令用以将镜像保存为一个文件然后传输到另一个位置上再加载进来这是在没有 Docker Registry 时的做法现在已经不推荐镜像迁移应该直接使用 Docker Registry无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以
+9
View File
@@ -18,6 +18,7 @@
```bash
docker run [选项] 镜像 [命令] [参数...]
```
#### 最简单的例子
输出 Hello World 后容器自动终止
@@ -53,6 +54,7 @@ root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@af8bae53bdd3:/# exit # 退出容器
```
### 5.1.3 docker run 的完整流程
执行 `docker run` Docker 在后台完成以下操作
@@ -73,6 +75,7 @@ flowchart TD
Step4["4. 启动容器,执行指定命令"] --> Step5
Step5["5. 命令执行完毕,容器停止"]
```
### 5.1.4 常用启动选项
#### 基础选项
@@ -99,6 +102,7 @@ $ docker run -d -P nginx
$ docker run -d -p 127.0.0.1:8080:80 nginx
```
#### 数据卷挂载
```bash
@@ -114,6 +118,7 @@ $ docker run -v /host/path:/container/path nginx
$ docker run -v /host/path:/container/path:ro nginx
```
#### 环境变量
```bash
@@ -125,6 +130,7 @@ $ docker run -e MYSQL_ROOT_PASSWORD=secret mysql
$ docker run --env-file .env myapp
```
#### 资源限制
```bash
@@ -136,6 +142,7 @@ $ docker run -m 512m nginx
$ docker run --cpus=1.5 nginx
```
### 5.1.5 启动已终止容器
使用 `docker start` 重新启动已停止的容器
@@ -155,6 +162,7 @@ $ docker start myubuntu
$ docker start -ai myubuntu
```
### 5.1.6 容器内进程的特点
容器内只运行指定的应用程序及其必需资源
@@ -199,6 +207,7 @@ $ docker run -d nginx
$ docker run -d -p 80:80 nginx
```
#### Q容器内修改的文件丢失
**原因**未使用数据卷数据保存在容器存储层
+6
View File
@@ -92,6 +92,7 @@ $ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77b2dc01fe0f ubuntu:24.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright
```
#### 查看容器输出日志
```bash
@@ -106,6 +107,7 @@ hello world
```bash
$ docker container logs -f 77b2dc01fe0f
```
#### 查看已停止的容器
```bash
@@ -130,6 +132,7 @@ $ docker run -d -p 3306:3306 mysql:8
$ docker run -d -p 6379:6379 redis
```
#### 2. 调试时先用前台模式
当容器启动有问题时**去掉 `-d` 参数** 可以直接看到输出和错误
@@ -139,6 +142,7 @@ $ docker run -d -p 6379:6379 redis
$ docker run myimage:latest
```
#### 3. 使用 --rm 自动清理
对于一次性任务使用 `--rm` 参数让容器退出后自动删除
@@ -151,6 +155,7 @@ Hello, World!
...
```
#### 4. 配合日志查看
```bash
@@ -170,6 +175,7 @@ $ docker logs -f myapp
$ docker logs -t myapp
```
### 5.2.6 常见问题排查
#### Q容器启动后立即退出
+8
View File
@@ -21,6 +21,7 @@
```bash
$ docker stop 容器名或ID
```
#### 工作原理
```mermaid
@@ -29,6 +30,7 @@ flowchart TD
A --> B["2. 等待容器优雅退出 (默认 10 秒)"]
B --> C["3. 如果超时仍未退出,发送 SIGKILL 强制终止"]
```
#### 自定义超时时间
```bash
@@ -40,6 +42,7 @@ $ docker stop -t 30 mycontainer
$ docker stop -t 0 mycontainer
```
#### 停止多个容器
```bash
@@ -60,6 +63,7 @@ $ docker stop $(docker ps -q)
```bash
$ docker kill 容器名或ID
```
#### stop 的区别
| 命令 | 信号 | 使用场景 |
@@ -127,6 +131,7 @@ $ docker start 容器名或ID
$ docker start -ai 容器名
```
#### 重启运行中的容器
```bash
@@ -166,11 +171,13 @@ stateDiagram-v2
```bash
$ docker stop $(docker ps -q)
```
#### 删除所有已停止的容器
```bash
$ docker container prune
```
#### 停止并删除所有容器
```bash
@@ -204,6 +211,7 @@ FROM node:22
CMD ["node", "server.js"]
```
#### Q容器无法停止
```bash
+8
View File
@@ -35,6 +35,7 @@ $ docker exec -it 容器名 /bin/bash
$ docker exec -it 容器名 /bin/sh
```
#### 参数说明
| 参数 | 作用 |
@@ -67,6 +68,7 @@ $ docker ps
CONTAINER ID IMAGE STATUS NAMES
69d137adef7a ubuntu Up 2 minutes myubuntu
```
#### 执行单条命令
不进入交互模式直接执行命令
@@ -84,6 +86,7 @@ $ docker exec myubuntu cat /etc/nginx/nginx.conf
$ docker exec -u root myubuntu apt update
```
#### 只用 -i 不用 -t 的区别
```bash
@@ -112,6 +115,7 @@ root@69d137adef7a:/# # 有提示符
```bash
$ docker attach 容器名
```
#### 工作原理
`attach` 会附加到容器的 **主进程** (PID 1) 的标准输入输出
@@ -126,6 +130,7 @@ flowchart LR
end
Attach["docker attach"] -->|"附加到这里"| P1
```
#### docker attach 示例
```bash
@@ -139,6 +144,7 @@ $ docker run -dit --name myubuntu ubuntu
$ docker attach myubuntu
root@243c32535da7:/#
```
#### 重要警告
** attach 会话中输入 `exit` 或按 `Ctrl+D` 会导致容器停止**
@@ -224,6 +230,7 @@ $ docker exec myapp tail -f /var/log/app.log
$ docker exec myapp python manage.py migrate
```
#### 2. 生产环境避免进入容器
笔者建议生产环境应尽量避免进入容器直接操作而是通过
@@ -261,6 +268,7 @@ $ docker debug myapp
```bash
$ docker exec -it myapp /bin/sh
```
#### Q需要 root 权限
```bash
+6
View File
@@ -27,6 +27,7 @@ $ docker rm 容器名或ID
$ docker rm mycontainer
mycontainer
```
#### 强制删除运行中的容器
```bash
@@ -73,6 +74,7 @@ Total reclaimed space: 150MB
$ docker container prune -f
```
#### 删除所有容器包括运行中的
```bash
@@ -85,6 +87,7 @@ $ docker rm $(docker ps -aq)
$ docker rm -f $(docker ps -aq)
```
#### 按条件删除
```bash
@@ -158,6 +161,7 @@ $ docker container prune -f
$ docker system prune -f
```
#### 生产环境
```bash
@@ -171,6 +175,7 @@ $ docker run --rm ubuntu echo "Hello"
$ docker container prune --filter "until=168h" # 保留 7 天内的
```
#### 完整清理脚本
```bash
@@ -212,6 +217,7 @@ $ docker rm mycontainer
$ docker rm -f mycontainer
```
#### Q删除后磁盘空间没释放
可能原因
+2
View File
@@ -37,6 +37,7 @@ centos The official build of CentOS. 7000+ [OK]
```bash
$ docker pull nginx:alpine
```
#### 3. 推送镜像
需要先登录
@@ -108,6 +109,7 @@ $ docker push username/myapp:v1
```bash
$ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin
```
#### 3. 关注镜像漏洞
Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描在镜像标签页可以看到漏洞扫描结果
+2
View File
@@ -25,6 +25,7 @@ $ docker run -d \
-v /opt/data/registry:/var/lib/registry \
registry
```
### 6.2.2 在私有仓库上传搜索下载镜像
创建好私有仓库之后就可以使用 `docker tag` 来标记一个镜像然后推送它到仓库例如私有仓库地址为 `127.0.0.1:5000`
@@ -86,6 +87,7 @@ $ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
```
### 6.2.3 配置非 https 仓库地址
如果你不想使用 `127.0.0.1:5000` 作为仓库地址比如想让本网段的其他主机也能把镜像推送到私有仓库你就得把例如 `192.168.199.100:5000` 这样的内网地址作为私有仓库地址这时你会发现无法成功推送镜像
+3
View File
@@ -114,6 +114,7 @@ health:
interval: 10s
threshold: 3
```
### 6.3.3 生成 http 认证文件
```bash
@@ -143,6 +144,7 @@ services:
volumes:
registry-data:
```
### 6.3.5 修改 Hosts 文件
编辑 `/etc/hosts`
@@ -150,6 +152,7 @@ volumes:
```bash
127.0.0.1 docker.domain.com
```
### 6.3.6 启动
```bash
+1
View File
@@ -107,6 +107,7 @@ server {
error_page 500 502 503 504 /50x.html;
}
```
### 6.4.5 Docker 主机访问镜像仓库
如果不启用 SSL 加密可以通过[前面章节](6.2_registry.md)的方法添加非 https 仓库地址到 Docker 的配置文件中然后重启 Docker
+4
View File
@@ -30,6 +30,7 @@ COPY . . # 复制到 /app/
RUN cd /app
RUN echo "hello" > world.txt # 文件在根目录
```
#### 原因分析
```dockerfile
@@ -110,6 +111,7 @@ RUN npm install
COPY . .
CMD ["node", "server.js"]
```
#### 2. 使用绝对路径
```docker
@@ -121,6 +123,7 @@ WORKDIR /app
WORKDIR app
```
#### 3. 不要用 RUN cd
```docker
@@ -133,6 +136,7 @@ RUN cd /app && echo "hello" > world.txt
WORKDIR /app
RUN echo "hello" > world.txt
```
#### 4. 适时重置 WORKDIR
```docker
+6
View File
@@ -55,6 +55,7 @@ USER appuser
CMD ["node", "server.js"]
```
#### 使用 UID/GID
```docker
@@ -80,6 +81,7 @@ USER nonexistent
RUN useradd -r -s /bin/false appuser
USER appuser
```
#### 创建用户的方式
**Debian/Ubuntu**
@@ -139,6 +141,7 @@ chown -R redis:redis /data
exec gosu redis "$@"
```
#### 为什么不用 su/sudo
| 问题 | su/sudo | gosu |
@@ -208,6 +211,7 @@ CMD ["myapp"]
CMD ["myapp"] # root 运行
```
#### 2. 使用固定 UID/GID
便于在宿主机和容器间共享文件
@@ -219,6 +223,7 @@ RUN addgroup -g 1000 -S appgroup && \
adduser -u 1000 -S -G appgroup appuser
USER 1000:1000
```
#### 3. 多阶段构建中的 USER
```docker
@@ -252,6 +257,7 @@ permission denied: '/app/data.log'
```docker
RUN mkdir -p /app/data && chown appuser:appuser /app/data
```
#### Q无法绑定低于 1024 的端口
root 用户无法绑定 80443 等端口
+4
View File
@@ -40,6 +40,7 @@ RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -fs http://localhost/ || exit 1
```
#### 命令返回值
- `0`成功 (healthy)
@@ -82,6 +83,7 @@ HEALTHCHECK CMD curl -f http://localhost/ || exit 1
HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
```
#### 数据库
```docker
@@ -93,6 +95,7 @@ HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
HEALTHCHECK CMD redis-cli ping || exit 1
```
#### 自定义脚本
```docker
@@ -178,6 +181,7 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
```
#### 4. 只检查核心依赖
健康检查应主要关注 **当前服务** 是否可用而不是检查其下游依赖 (数据库等)下游依赖的检查应由应用逻辑处理
+3
View File
@@ -76,6 +76,7 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行
ONBUILD COPY requirements.txt ./
ONBUILD RUN pip install -r requirements.txt
```
#### 2. 自动编译代码
```docker
@@ -84,6 +85,7 @@ ONBUILD RUN pip install -r requirements.txt
ONBUILD COPY . .
ONBUILD RUN go build -o app main.go
```
#### 3. 处理静态资源
```docker
@@ -127,6 +129,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
node:20-onbuild
python:3.12-onbuild
```
#### 2. 避免执行耗时操作
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件)这会让子镜像构建变得缓慢且不可控
+2
View File
@@ -26,6 +26,7 @@ LABEL <key>=<value> <key>=<value> ...
LABEL version="1.0"
LABEL description="这是一个 Web 应用服务器"
```
#### 定义多个标签推荐
```docker
@@ -119,6 +120,7 @@ $ docker inspect nginx --format '{{json .Config.Labels}}' | jq
"maintainer": "NGINX Docker Maintainers <docker-maint@nginx.com>"
}
```
#### 过滤器
可以使用标签过滤镜像
+3
View File
@@ -31,6 +31,7 @@ SHELL ["/bin/bash", "-c"]
RUN echo {a..z}
```
#### 2. 增强错误处理
默认情况下管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功整个指令就视为成功这可能掩盖构建错误
@@ -51,6 +52,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN wget -O - https://invalid-url | tar xz
```
#### 3. Windows 环境
Windows 容器中经常需要在 `cmd` `powershell` 之间切换
@@ -122,6 +124,7 @@ RUN echo "Using sh again"
```docker
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
```
#### 2. 明确意图
如果由于脚本需求必须更改 shell最好在 Dockerfile 中显式声明而不是依赖默认行为
+3
View File
@@ -46,6 +46,7 @@ CMD ["./app"]
```bash
$ docker build -t go/helloworld:1 -f Dockerfile.one .
```
### 7.17.2 分散到多个 Dockerfile
另一种方式就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后再将其拷贝到运行环境中这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来这种方式虽然可以很好地规避第一种方式存在的风险但明显部署过程较复杂
@@ -110,6 +111,7 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
### 7.17.3 使用多阶段构建
为解决以上问题Docker v17.05 开始支持多阶段构建 (`multistage builds`)使用多阶段构建我们就可以很容易解决前面提到的问题并且只需要编写一个 `Dockerfile`
@@ -168,6 +170,7 @@ FROM golang:alpine as builder
```bash
$ docker build --target builder -t username/imagename:tag .
```
### 7.17.5 构建时从其他镜像复制文件
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件我们也可以复制任意镜像中的文件
@@ -54,6 +54,7 @@ server {
}
}
```
### 7.18.2 前端构建
第一阶段进行前端构建
@@ -74,6 +75,7 @@ RUN set -x ; cd /app \
&& mkdir -p public \
&& npm run production
```
### 7.18.3 安装 Composer 依赖
第二阶段安装 Composer 依赖
@@ -93,6 +95,7 @@ RUN set -x ; cd /app \
--no-scripts \
--prefer-dist
```
### 7.18.4 整合以上阶段所生成的文件
第三阶段对以上阶段生成的文件进行整合
@@ -118,6 +121,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
```
### 7.18.5 最后一个阶段构建 NGINX 镜像
```docker
@@ -128,6 +132,7 @@ ARG LARAVEL_PATH=/app/laravel
COPY laravel.conf /etc/nginx/conf.d/
COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public
```
### 7.18.6 构建 Laravel Nginx 镜像
使用 `docker build` 命令构建镜像
@@ -137,6 +142,7 @@ $ docker build -t my/laravel --target=laravel .
$ docker build -t my/nginx --target=nginx .
```
### 7.18.7 启动容器并测试
新建 Docker 网络
+3
View File
@@ -55,6 +55,7 @@ RUN apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/*
```
#### 2. 清理缓存
在安装完软件后立即清除缓存可以显著减小镜像体积
@@ -103,6 +104,7 @@ RUN touch hello.txt
WORKDIR /app
RUN touch hello.txt
```
#### Q环境变量不生效
```docker
@@ -136,6 +138,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
RUN --mount=type=cache,target=/go/pkg/mod \
go build -o app
```
#### 2. 挂载密钥
安全地使用 SSH 密钥或 Token而不将其记录在镜像中
+7
View File
@@ -23,6 +23,7 @@ COPY package.json /app/
COPY config.json /app/settings.json
```
#### 复制多个文件
```docker
@@ -35,6 +36,7 @@ COPY package.json package-lock.json /app/
COPY *.json /app/
COPY src/*.js /app/src/
```
#### 复制目录
```docker
@@ -77,6 +79,7 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js
```docker
COPY app.js /usr/src/app/
```
#### 相对路径基于 WORKDIR
```docker
@@ -84,6 +87,7 @@ WORKDIR /app
COPY package.json ./ # 复制到 /app/package.json
COPY src/ ./src/ # 复制到 /app/src/
```
#### 自动创建目录
如果目标目录不存在Docker 会自动创建
@@ -174,6 +178,7 @@ RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
```
#### 使用 --link 优化缓存
```docker
@@ -227,6 +232,7 @@ COPY . .
COPY . .
RUN npm install
```
#### 2. 使用 .dockerignore
```docker
@@ -238,6 +244,7 @@ COPY . .
...
```
#### 3. 明确复制路径
```docker
+6
View File
@@ -51,6 +51,7 @@ ADD 会识别并解压以下格式:
FROM scratch
ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz /
```
#### 解压过程
```bash
@@ -76,6 +77,7 @@ app.tar.gz 包含: /app/ 目录结果:
ADD https://example.com/app.zip /app/app.zip
```
#### 为什么不推荐
| 问题 | 说明 |
@@ -127,6 +129,7 @@ ADD rootfs.tar.gz /
ADD dist.tar.gz /app/
```
#### 不适合使用 ADD
```docker
@@ -180,6 +183,7 @@ ADD app.tar.gz /app/
COPY . /app/
```
#### 2. 仅在需要解压时使用 ADD
```docker
@@ -187,6 +191,7 @@ COPY . /app/
ADD app.tar.gz /app/
```
#### 3. 不要用 ADD 下载文件
```docker
@@ -198,6 +203,7 @@ ADD https://example.com/file.tar.gz /tmp/
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
```
#### 4. 解压后清理
```docker
+8
View File
@@ -111,6 +111,7 @@ CMD ["/bin/bash"] + cat /etc/os-release
CMD service nginx start
```
#### 原因分析
```bash
@@ -126,6 +127,7 @@ CMD service nginx start
6. 容器主进程sh退出 容器停止
```
#### 正确做法
```docker
@@ -153,6 +155,7 @@ CMD ["curl", "-s", "http://example.com"]
$ docker run myimage # 执行默认命令
$ docker run myimage curl -v ... # 完全覆盖
```
#### 搭配 ENTRYPOINT
```docker
@@ -182,6 +185,7 @@ CMD ["python", "app.py"]
CMD ["sh", "-c", "echo $PATH && python app.py"]
```
#### 2. 确保应用在前台运行
```docker
@@ -196,6 +200,7 @@ CMD ["java", "-jar", "app.jar"]
CMD service nginx start
CMD systemctl start nginx
```
#### 3. 使用双引号
```docker
@@ -207,6 +212,7 @@ CMD ["node", "server.js"]
CMD ['node', 'server.js']
```
#### 4. 配合 ENTRYPOINT 使用
```docker
@@ -233,6 +239,7 @@ $ docker run myapp --port 9000
CMD ["echo", "first"]
CMD ["echo", "second"] # 只有这个生效
```
#### Q如何在 CMD 中使用环境变量
```docker
@@ -244,6 +251,7 @@ CMD echo "Port is $PORT"
CMD ["sh", "-c", "echo Port is $PORT"]
```
#### Q为什么我的容器不响应 Ctrl+C
可能是使用了 shell 格式信号被 sh 吃掉了
+7
View File
@@ -95,6 +95,7 @@ exec: "-i": executable file not found
...
```
#### 使用 ENTRYPOINT 解决
```docker
@@ -111,6 +112,7 @@ HTTP/1.1 200 OK
...
当前 IP61.148.226.66
```
#### 交互图示
```bash
@@ -160,6 +162,7 @@ fi
exec "$@"
```
#### 工作流程
```bash
@@ -173,6 +176,7 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash
exec gosu redis redis-server exec bash
( redis 用户运行) ( root 用户运行)
```
#### 关键点
1. **exec $@**用传入的参数替换当前进程确保信号正确传递
@@ -261,12 +265,14 @@ ENTRYPOINT ["python", "app.py"]
ENTRYPOINT python app.py
```
#### 2. 提供有意义的默认参数
```docker
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
```
#### 3. 入口脚本使用 exec
```bash
@@ -278,6 +284,7 @@ CMD ["-g", "daemon off;"]
exec "$@"
```
#### 4. 处理信号
确保 ENTRYPOINT 脚本能正确传递信号
+8
View File
@@ -21,6 +21,7 @@ ENV <key1>=<value1> <key2>=<value2> ...
ENV NODE_VERSION 20.10.0
ENV APP_ENV production
```
#### 设置多个变量
```docker
@@ -53,6 +54,7 @@ WORKDIR $APP_HOME
COPY . $APP_HOME
```
#### 2. 容器运行时使用
```docker
@@ -106,6 +108,7 @@ $ docker run -e APP_ENV=development -e DEBUG=true myimage
$ docker run --env-file .env myimage
```
#### .env 文件格式
```bash
@@ -165,6 +168,7 @@ RUN apt-get install nginx=${NGINX_VERSION}
RUN apt-get install nginx=1.25.0
```
#### 2. 不要存储敏感信息
```docker
@@ -178,6 +182,7 @@ ENV DB_PASSWORD=secret123
...
```
#### 3. 为应用提供合理默认值
```docker
@@ -185,6 +190,7 @@ ENV APP_ENV=production \
APP_PORT=8080 \
LOG_LEVEL=info
```
#### 4. 使用有意义的变量名
```docker
@@ -215,12 +221,14 @@ CMD ["python", "app.py", "--port", "$PORT"]
CMD ["sh", "-c", "python app.py --port $PORT"]
```
#### Q如何查看容器的环境变量
```bash
$ docker inspect mycontainer --format '{{json .Config.Env}}'
$ docker exec mycontainer env
```
#### Q多行 ENV 还是多个 ENV
```docker
+8
View File
@@ -43,6 +43,7 @@ ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
RUN echo "Using Node.js $NODE_VERSION"
```
#### 构建时覆盖
```bash
@@ -72,6 +73,7 @@ FROM ${REGISTRY}/${IMAGE_NAME}:20
RUN echo $REGISTRY # 输出空
```
#### FROM 之后重新声明
```docker
@@ -84,6 +86,7 @@ FROM node:${NODE_VERSION}-alpine
ARG NODE_VERSION
RUN echo "Node version: $NODE_VERSION"
```
#### 多阶段构建中的 ARG
```docker
@@ -116,6 +119,7 @@ FROM alpine:${ALPINE_VERSION}
```bash
$ docker build --build-arg ALPINE_VERSION=3.18 .
```
#### 2. 设置软件版本
```docker
@@ -123,6 +127,7 @@ ARG NGINX_VERSION=1.25.0
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
```
#### 3. 配置构建环境
```docker
@@ -135,6 +140,7 @@ RUN if [ "$ENABLE_DEBUG" = "true" ]; then \
npm install --production; \
fi
```
#### 4. 配置私有仓库
```docker
@@ -199,6 +205,7 @@ ARG NODE_VERSION=20
ARG NODE_VERSION
```
#### 2. 不要用 ARG 存储敏感信息
```docker
@@ -211,6 +218,7 @@ RUN echo "password=$DB_PASSWORD" > /app/.env
...
```
#### 3. 使用 ARG 提高构建灵活性
```docker
+7
View File
@@ -47,6 +47,7 @@ flowchart LR
FROM mysql:8.0
VOLUME /var/lib/mysql
```
#### 定义多个卷
```docker
@@ -67,6 +68,7 @@ $ docker volume ls
DRIVER VOLUME NAME
local a1b2c3d4e5f6... # 自动创建的匿名卷
```
#### 2. 可被命名卷覆盖
```bash
@@ -74,6 +76,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
#### 3. 可被 Bind Mount 覆盖
```bash
@@ -120,12 +123,14 @@ VOLUME /data
FROM postgres:16
VOLUME /var/lib/postgresql/data
```
#### 日志目录
```docker
FROM nginx
VOLUME /var/log/nginx
```
#### 上传文件目录
```docker
@@ -212,6 +217,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
FROM postgres:16
VOLUME /var/lib/postgresql/data
```
#### 2. 不要在 VOLUME 后修改目录
```docker
@@ -225,6 +231,7 @@ RUN cp init-data.json /app/data/
RUN mkdir -p /app/data && cp init-data.json /app/data/
VOLUME /app/data
```
#### 3. 文档中说明 VOLUME 用途
```docker
+4
View File
@@ -44,6 +44,7 @@ EXPOSE 80 443
$ docker inspect nginx --format '{{.Config.ExposedPorts}}'
map[80/tcp:{}]
```
#### 2. 配合 -P 使用
使用 `docker run -P` Docker 会自动映射 EXPOSE 的端口到宿主机随机端口
@@ -75,6 +76,7 @@ flowchart TD
Run["docker run -p<br/>实际端口映射<br/>宿主机 ←→ 容器"]
Expose ~~~ Run
```
#### 没有 EXPOSE 也能 -p
```docker
@@ -145,6 +147,7 @@ EXPOSE 5432
FROM redis
EXPOSE 6379
```
#### 2. 使用明确的协议
```docker
@@ -160,6 +163,7 @@ EXPOSE 53/udp
EXPOSE 53/tcp 53/udp
```
#### 3. 与应用实际端口保持一致
```docker
+8
View File
@@ -41,6 +41,7 @@ graph TD
Lifecycle[生命周期 = 容器生命周期] -.-> Container
Delete[容器删除] -->|导致| DataLost[数据丢失 ]
```
#### 数据卷推荐
```mermaid
@@ -65,6 +66,7 @@ graph TD
```bash
$ docker volume create my-vol
```
#### 列出所有数据卷
```bash
@@ -74,6 +76,7 @@ local my-vol
local postgres_data
local redis_data
```
#### 查看数据卷详情
```bash
@@ -182,6 +185,7 @@ $ docker run -d \
-v postgres_data:/var/lib/postgresql/data \
postgres:16
```
#### 场景二多容器共享数据
```bash
@@ -201,6 +205,7 @@ $ docker run --rm \
-v shared-data:/data \
alpine cat /data/log.txt
```
#### 场景三配置文件持久化
```bash
@@ -227,6 +232,7 @@ $ docker volume rm my-vol
$ docker rm -v container_name
```
#### 清理未使用的数据卷
```bash
@@ -279,6 +285,7 @@ $ docker run --rm \
-v $(pwd):/backup:ro \
alpine tar xzf /backup/my-vol-backup.tar.gz -C /target
```
#### 备份脚本示例
```bash
@@ -331,6 +338,7 @@ $ docker run -v /host/path:/app/data nginx
```bash
$ docker inspect container_name --format '{{json .Mounts}}' | jq
```
#### Q数据卷的数据在哪里
```bash
+9
View File
@@ -58,6 +58,7 @@ $ docker run -d \
--mount type=bind,source=/宿主机路径,target=/容器路径 \
nginx
```
#### 使用 -v简写
```bash
@@ -65,6 +66,7 @@ $ docker run -d \
-v /宿主机路径:/容器路径 \
nginx
```
#### 两种语法对比
| 特性 | --mount | -v |
@@ -97,6 +99,7 @@ $ echo "Hello" > src/index.html
...
```
#### 场景二配置文件挂载
```bash
@@ -106,6 +109,7 @@ $ docker run -d \
--mount type=bind,source=/path/to/nginx.conf,target=/etc/nginx/nginx.conf,readonly \
nginx
```
#### 场景三日志收集
```bash
@@ -115,6 +119,7 @@ $ docker run -d \
--mount type=bind,source=/var/log/myapp,target=/app/logs \
myapp
```
#### 场景四共享 SSH 密钥
```bash
@@ -227,6 +232,7 @@ $ docker run -u root ...
$ docker run -u $(id -u):$(id -g) ...
```
#### QmacOS/Windows 性能问题
Docker Desktop Bind Mount 性能较差 (需要跨文件系统同步)
@@ -253,6 +259,7 @@ $ docker run -v /host/path:/container/path:cached myapp
$ docker run -v $(pwd):/app -p 3000:3000 node npm run dev
```
#### 2. 生产环境使用 Volume
```bash
@@ -260,11 +267,13 @@ $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev
$ docker run -v mysql_data:/var/lib/mysql mysql
```
#### 3. 配置文件使用只读挂载
```bash
$ docker run -v /config/nginx.conf:/etc/nginx/nginx.conf:ro nginx
```
#### 4. 注意路径安全
```bash
+2
View File
@@ -49,6 +49,7 @@ Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的
$ docker run -it --dns=114.114.114.114 ubuntu cat /etc/resolv.conf
nameserver 114.114.114.114
```
#### 2. --dns-search
指定 DNS 搜索域例如设置为 `example.com` `ping host` 会尝试解析 `host.example.com`
@@ -56,6 +57,7 @@ nameserver 114.114.114.114
```bash
$ docker run --dns-search=example.com myapp
```
#### 3. --hostname -h
设置容器的主机名
+2
View File
@@ -9,6 +9,7 @@ abc123... bridge bridge local
def456... host host local
ghi789... none null local
```
### 9.2.1 网络类型对比
各网络类型的特点和适用场景如下
@@ -52,6 +53,7 @@ $ docker run -it --network none alpine ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> ...
inet 127.0.0.1/8 scope host lo
```
### 9.2.5 数据流向
容器网络中的数据流向可以分为以下几种情况
+3
View File
@@ -25,6 +25,7 @@ $ docker network create mynet
$ docker network inspect mynet
```
### 9.3.3 使用自定义网络
启动容器时通过 `--network` 参数指定连接的网络
@@ -41,6 +42,7 @@ $ docker exec web ping db
PING db (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.083 ms
```
### 9.3.4 容器名 DNS 解析
自定义网络自动提供 DNS 服务Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器容器内的 DNS 请求会被转发到这里
@@ -55,6 +57,7 @@ flowchart LR
Web["web<br/>172.18.0.2"] -- "DNS: 'db' → 172.18.0.3" --> DB["db<br/>172.18.0.3"]
end
```
### 9.3.5 常用网络命令
以下是 Docker 网络管理中常用的命令
+2
View File
@@ -20,6 +20,7 @@ $ docker run -d --name app --network app-net myapp
...
```
### 9.4.2 连接到多个网络
一个容器可以同时连接到多个网络这对于需要跨网络通信的中间件容器特别有用
@@ -37,6 +38,7 @@ $ docker network connect backend multi-net-container
$ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks}}'
```
### 9.4.3 --link 已废弃
`--link` Docker 早期用于容器互联的方式**已经被废弃**不建议在新项目中使用请使用自定义网络替代
+2
View File
@@ -75,6 +75,7 @@ $ docker port mycontainer
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080
```
#### docker ps
运行 `docker ps` 可以查看到所有容器的端口映射列表
@@ -101,6 +102,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
$ docker run -d -p 127.0.0.1:3306:3306 mysql
```
#### 2. 避免端口冲突
如果宿主机 8080 已经被占用了容器将无法启动
+1
View File
@@ -25,6 +25,7 @@ $ docker run -d --name db --network backend postgres
$ docker exec web ping db
ping: db: Name or service not known
```
### 9.6.2 安全优势
这种隔离机制带来以下安全优势
+11
View File
@@ -29,6 +29,7 @@ veth 对
容器 B (192.168.0.3不同宿主机)
```
#### 创建和使用 Overlay 网络
**Docker Swarm 模式下的 Overlay 网络**
@@ -73,6 +74,7 @@ docker exec container1 curl http://container2
# 检查网络配置
docker network inspect custom-overlay
```
#### Overlay 网络性能优化
```bash
@@ -107,6 +109,7 @@ networks:
driver_opts:
com.docker.network.driver.mtu: 1450
```
### 9.7.2 CNI 插件生态概览
容器网络接口CNI是容器编排平台尤其是 Kubernetes的标准化网络接口不同的 CNI 插件提供不同的网络能力
@@ -255,6 +258,7 @@ Docker 内嵌 DNS 服务器 (127.0.0.11)
DNS 响应 容器缓存 应用
```
#### 配置容器 DNS
**在运行时指定 DNS**
@@ -317,6 +321,7 @@ networks:
"registry-mirrors": ["https://mirror.example.com"]
}
```
#### 自定义服务发现
**使用 Docker 内建 DNS 的服务发现**
@@ -361,6 +366,7 @@ services:
# frontend 容器可以直接访问 http://backend:8080
# backend 容器可以直接访问 postgres://database:5432
```
#### DNS 性能优化
```bash
@@ -393,6 +399,7 @@ kubectl patch deployment -n kube-system coredns --patch '{
}
}'
```
### 9.7.4 网络策略实践
网络策略定义了容器间的流量控制规则是微服务架构中的安全基础
@@ -473,6 +480,7 @@ spec:
- protocol: TCP
port: 443
```
#### 微服务网络策略示例
```yaml
@@ -597,6 +605,7 @@ spec:
- protocol: TCP
port: 5432
```
#### 使用 Calico/Cilium 的高级网络策略
**L7 应用层策略 Cilium 支持**
@@ -630,6 +639,7 @@ spec:
sourceIPs:
- "10.0.0.0/8"
```
### 9.7.5 跨主机容器通信方案对比
#### 方案对比表
@@ -661,6 +671,7 @@ helm install cilium cilium/cilium --namespace kube-system
# 5. 需要多云/跨域使用 Weave
```
### 9.7.6 网络故障排查
**常见网络问题诊断**
+4
View File
@@ -110,6 +110,7 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
cat /docker-php-entrypoint
```
#### `RUN --mount=type=tmpfs`
该指令可以将一个 `tmpfs` 文件系统挂载到指定位置
@@ -120,6 +121,7 @@ RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoin
RUN --mount=type=tmpfs,target=/temp \
mount | grep /temp
```
#### `RUN --mount=type=secret`
该指令可以将一个文件 (例如密钥) 挂载到指定位置
@@ -133,6 +135,7 @@ RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
```bash
$ docker build -t test --secret id=aws,src=$HOME/.aws/credentials .
```
#### `RUN --mount=type=ssh`
该指令可以挂载 `ssh` 密钥
@@ -151,6 +154,7 @@ $ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ docker build -t test --ssh default=$SSH_AUTH_SOCK .
```
### 10.1.2 使用 `docker compose build` BuildKit
Docker Compose 同样支持 BuildKit这使得多服务应用的构建更加高效
+1
View File
@@ -26,6 +26,7 @@ $ docker buildx bake
$ docker buildx bake web
```
#### 生成 SBOM
Buildx 支持在构建时直接生成 SBOM (Software Bill of Materials)这对于软件供应链安全至关重要
+4
View File
@@ -39,6 +39,7 @@ $ docker manifest inspect hello-world
]
}
```
### 10.3.2 使用 `docker buildx` 构建多架构镜像
`docker buildx` 是构建多架构镜像的最佳实践工具它屏蔽了底层的复杂性提供了一键构建多架构镜像的能力
@@ -53,6 +54,7 @@ $ docker manifest inspect hello-world
$ docker buildx create --name mybuilder --use
$ docker buildx inspect --bootstrap
```
#### 构建和推送
使用 `docker buildx build` 命令并指定 `--platform` 参数可以同时构建支持多种架构的镜像`--push` 参数会将构建好的镜像和 manifest list 推送到 Docker 仓库
@@ -96,6 +98,7 @@ COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist
ENTRYPOINT ["/dist"]
```
### 10.3.3 使用 `docker manifest`底层工具
除了 `docker buildx`我们也可以直接操作 Manifest List 来手动组合不同架构的镜像
@@ -120,6 +123,7 @@ $ docker manifest create your-username/my-app:latest \
$ docker manifest push your-username/my-app:latest
```
#### 检查 manifest list
你可以使用 `docker manifest inspect` 来查看一个 manifest list 的详细信息如上文所示
+3
View File
@@ -30,17 +30,20 @@ $ curl -SL https://github.com/docker/compose/releases/download/v5.1.0/docker-com
```bash
$ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```
### 11.2.2 测试安装
```bash
$ docker compose version
Docker Compose version v5.1.0
```
### 11.2.3 bash 补全命令
```bash
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.1.0/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
```
### 11.2.4 卸载
如果是二进制包方式安装的删除二进制文件即可
+11
View File
@@ -37,6 +37,7 @@ def hello():
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
#### Dockerfile
编写 `Dockerfile` 文件内容为
@@ -48,6 +49,7 @@ WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
```
#### compose.yaml
编写 `compose.yaml` 文件这是 Compose 推荐使用的主模板文件 (也兼容 `docker-compose.yml` 等历史文件名)
@@ -62,6 +64,7 @@ services:
redis:
image: "redis:alpine"
```
#### 运行 compose 项目
```bash
@@ -77,11 +80,13 @@ $ docker compose up
```bash
$ docker compose up -d
```
#### 停止
```bash
$ docker compose stop
```
#### 进入服务
```bash
@@ -90,31 +95,37 @@ $ docker compose exec redis sh
127.0.0.1:6379> get hits
"9"
```
#### 查看日志
```bash
$ docker compose logs -f
```
#### 构建镜像
```bash
$ docker compose build
```
#### 启动服务
```bash
$ docker compose start
```
#### 运行一次性命令
```bash
$ docker compose run web python app.py
```
#### 验证 Compose 文件
```bash
$ docker compose config
```
#### 删除项目
```bash
+2
View File
@@ -13,6 +13,7 @@ Docker Compose 提供了丰富的命令来管理项目和容器。本节将详
```bash
docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
```
### 11.4.2 命令选项
* `-f, --file FILE` 指定使用的 Compose 模板文件默认会自动识别 `compose.yaml` (也兼容 `docker-compose.yml` )并且可以多次指定
@@ -74,6 +75,7 @@ docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
```bash
$ docker compose kill -s SIGINT
```
#### `logs`
格式为 `docker compose logs [options] [SERVICE...]`
+27
View File
@@ -52,6 +52,7 @@ build:
- alpine:latest
- corp/web_app:3.14
```
### 11.5.2 `cap_add, cap_drop`
指定容器的内核能力 (capacity) 分配
@@ -68,6 +69,7 @@ cap_add:
cap_drop:
- NET_ADMIN
```
### 11.5.3 `command`
覆盖容器启动后默认执行的命令
@@ -75,6 +77,7 @@ cap_drop:
```yaml
command: echo "hello world"
```
### 11.5.4 `configs`
`configs` 来自 Compose Specification它在 Swarm 中是原生对象在本地 `docker compose` 模式下通常以文件挂载的形式实现具体能力取决于 Compose 版本与运行平台
@@ -88,6 +91,7 @@ command: echo "hello world"
```yaml
cgroup_parent: cgroups_1
```
### 11.5.6 `container_name`
指定容器名称默认将会使用 `项目名称_服务名称_序号` 这样的格式
@@ -109,6 +113,7 @@ container_name: docker-web-container
devices:
- "/dev/ttyUSB1:/dev/ttyUSB0"
```
### 11.5.9 `depends_on`
解决容器的依赖启动先后的问题以下例子中会先启动 `redis` `db` 再启动 `web`
@@ -140,6 +145,7 @@ dns:
- 8.8.8.8
- 114.114.114.114
```
### 11.5.11 `dns_search`
配置 `DNS` 搜索域可以是一个值也可以是一个列表
@@ -151,6 +157,7 @@ dns_search:
- domain1.example.com
- domain2.example.com
```
### 11.5.12 `tmpfs`
挂载一个 tmpfs 文件系统到容器
@@ -161,6 +168,7 @@ tmpfs:
- /run
- /tmp
```
### 11.5.13 `env_file`
从文件中获取环境变量可以为单独的文件路径或列表
@@ -184,6 +192,7 @@ env_file:
PROG_ENV=development
```
### 11.5.14 `environment`
设置环境变量你可以使用数组或字典两种格式
@@ -204,6 +213,7 @@ environment:
```bash
y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF
```
### 11.5.15 `expose`
暴露端口但不映射到宿主机只被连接的服务访问
@@ -215,6 +225,7 @@ expose:
- "3000"
- "8000"
```
### 11.5.16 `external_links`
> 注意不建议使用该指令
@@ -227,6 +238,7 @@ external_links:
- project_db_1:mysql
- project_db_1:postgresql
```
### 11.5.17 `extra_hosts`
类似 Docker 中的 `--add-host` 参数指定额外的 host 名称映射信息
@@ -242,6 +254,7 @@ extra_hosts:
8.8.8.8 googledns
52.1.157.61 dockerhub
```
### 11.5.18 `healthcheck`
通过命令检查容器是否健康运行
@@ -253,6 +266,7 @@ healthcheck:
timeout: 10s
retries: 3
```
### 11.5.19 `image`
指定为镜像名称或镜像 ID如果镜像在本地不存在`Compose` 将会尝试拉取这个镜像
@@ -262,6 +276,7 @@ image: ubuntu
image: orchardup/postgresql
image: a4bc65fd
```
### 11.5.20 `labels`
为容器添加 Docker 元数据 (metadata) 信息例如可以为容器添加辅助说明信息
@@ -272,6 +287,7 @@ labels:
com.startupteam.department: "devops department"
com.startupteam.release: "rc3 for v1.0"
```
### 11.5.21 `links`
> 注意不推荐使用该指令容器之间应通过 Docker 网络 (networks) 进行互联
@@ -300,6 +316,7 @@ options:
max-size: "200k"
max-file: "10"
```
### 11.5.23 `network_mode`
设置网络模式使用和 `docker run` `--network` 参数一样的值
@@ -311,6 +328,7 @@ network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
```
### 11.5.24 `networks`
配置容器连接的网络
@@ -327,6 +345,7 @@ networks:
some-network:
other-network:
```
### 11.5.25 `pid`
跟主机系统共享进程命名空间打开该选项的容器之间以及容器和宿主机系统之间可以通过进程 ID 来相互访问和操作
@@ -334,6 +353,7 @@ networks:
```yaml
pid: "host"
```
### 11.5.26 `ports`
暴露端口信息
@@ -370,6 +390,7 @@ secrets:
my_other_secret:
external: true
```
### 11.5.28 `security_opt`
指定容器模板标签 (label) 机制的默认属性 (用户角色类型级别等)例如配置标签的用户名和角色名
@@ -379,6 +400,7 @@ security_opt:
- label:user:USER
- label:role:ROLE
```
### 11.5.29 `stop_signal`
设置另一个信号来停止容器在默认情况下使用的是 SIGTERM 停止容器
@@ -386,6 +408,7 @@ security_opt:
```yaml
stop_signal: SIGUSR1
```
### 11.5.30 `sysctls`
配置容器内核参数
@@ -399,6 +422,7 @@ sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
```
### 11.5.31 `ulimits`
指定容器的 ulimits 限制值
@@ -412,6 +436,7 @@ sysctls:
soft: 20000
hard: 40000
```
### 11.5.32 `volumes`
数据卷所挂载路径设置可以设置为宿主机路径 (`HOST:CONTAINER`) 或者数据卷名称 (`VOLUME:CONTAINER`)并且可以设置访问模式 (`HOST:CONTAINER:ro`)
@@ -436,6 +461,7 @@ services:
volumes:
mysql_data:
```
### 11.5.33 其它指令
此外还有包括 `domainname, entrypoint, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir` 等指令基本跟 `docker run` 中对应参数的功能一致
@@ -487,6 +513,7 @@ stdin_open: true
```yaml
tty: true
```
### 11.5.34 读取变量
Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 `.env` 文件中的变量
+3
View File
@@ -298,6 +298,7 @@ $ docker compose exec db psql -U django_user -d django_db
$ docker compose ps
$ docker compose logs db
```
#### Q2代码修改没有生效
**可能原因**
@@ -313,6 +314,7 @@ $ docker compose logs db
$ sudo chown -R $USER:$USER .
```
### 11.6.11 开发 vs 生产关键差异
笔者特别提醒本节的配置是 **开发环境** 配置生产环境需要以下调整
@@ -340,6 +342,7 @@ services:
# ...
```
### 11.6.12 延伸阅读
- [Compose 模板文件详解](11.5_compose_file.md)深入理解 Compose 文件的所有配置项
+7
View File
@@ -88,6 +88,7 @@ gem 'rails', '~> 7.1'
```bash
$ touch Gemfile.lock
```
### 11.7.5 步骤 3创建 compose.yaml
配置如下
@@ -157,6 +158,7 @@ compose.yaml bin db public
```bash
$ docker compose build
```
### 11.7.8 步骤 6配置数据库连接
修改 `config/database.yml`
@@ -196,6 +198,7 @@ web-1 | => Run `bin/rails server --help` for more startup options
web-1 | Puma starting in single mode...
web-1 | * Listening on http://0.0.0.0:3000
```
### 11.7.10 步骤 8创建数据库
在另一个终端执行
@@ -230,6 +233,7 @@ $ docker compose exec web rails generate scaffold Post title:string body:text
$ docker compose exec web bash
```
### 11.7.12 常见问题
#### Q数据库连接失败
@@ -240,6 +244,7 @@ $ docker compose exec web bash
$ docker compose ps
$ docker compose logs db
```
#### Qserver.pid 文件导致启动失败
错误信息`A server is already running`
@@ -249,6 +254,7 @@ $ docker compose logs db
```bash
$ docker compose exec web rm -f tmp/pids/server.pid
```
#### QGem 安装失败
可能需要更新 bundler 或清理缓存
@@ -256,6 +262,7 @@ $ docker compose exec web rm -f tmp/pids/server.pid
```bash
$ docker compose run --rm web bundle update
```
### 11.7.13 开发 vs 生产
| 配置项 | 开发环境 | 生产环境 |
+1
View File
@@ -154,6 +154,7 @@ $ docker exec wordpress_db mysqldump -u wordpress -pwordpress wordpress > backup
networks:
- wp_net
```
#### 2. 使用 Nginx 反向代理
在生产环境中不要直接暴露 WordPress 端口而是通过 Nginx 进行反向代理并配置 SSL
+7
View File
@@ -25,6 +25,7 @@ flowchart LR
H4 -. "(实际是宿主机的 1234" .- C1
```
### 12.2.2 Namespace 的类型
Linux 内核提供了以下几种 NamespaceDocker 容器使用了全部
@@ -65,6 +66,7 @@ PID USER COMMAND
1 root nginx: master process 在容器内是 PID 1
2 root nginx: worker process
```
#### PID 关键点
- 容器内的 PID 1 进程特殊重要它是容器的主进程退出则容器停止
@@ -99,6 +101,7 @@ flowchart LR
H2 <--> C2
```
#### NET 关键点
- 每个容器有独立的网卡IP路由表iptables 规则
@@ -129,6 +132,7 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的
merged/ 这个目录成为容器的 /
... ...
```
#### chroot 的区别
| 特性 | chroot | MNT Namespace |
@@ -212,6 +216,7 @@ flowchart LR
C1 -- 映射 --> H1
C2 -- 映射 --> H2
```
#### 安全意义
容器内的 root 用户可以映射为宿主机上的普通用户即使容器被突破攻击者在宿主机上也只有普通权限
@@ -243,6 +248,7 @@ $ exit
$ hostname
my-server
```
#### 实验 2PID Namespace
```bash
@@ -261,6 +267,7 @@ USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 8960 4516 pts/0 S 10:00 0:00 /bin/bash
root 8 0.0 0.0 10072 3200 pts/0 R+ 10:00 0:00 ps aux
```
#### 实验 3NET Namespace
```bash
+4
View File
@@ -117,6 +117,7 @@ $ docker run --device-read-bps /dev/sda:10mb myapp
$ docker run --device-write-iops /dev/sda:100 myapp
```
#### 进程数限制
```bash
@@ -165,6 +166,7 @@ abc123 Exited (137) 5 seconds ago hopeful_darwin
...
```
#### CPU 限制验证
```bash
@@ -253,11 +255,13 @@ services:
$ docker run -m 1g myapp
```
#### 2. 为关键应用设置 CPU 保证
```bash
$ docker run --cpus=2 --cpu-shares=2048 critical-app
```
#### 3. 监控资源使用
```bash
+1
View File
@@ -197,6 +197,7 @@ RUN apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/*
```
#### 2. 避免在容器中写入大量数据
容器层的写入性能低于直接写入大量数据应使用
+2
View File
@@ -65,6 +65,7 @@ status:
- type: Ready
status: "True"
```
#### 节点控制器
Kubernetes 控制平面中节点控制器 (Node Controller) 负责管理节点的生命周期主要包含
@@ -81,6 +82,7 @@ $ kubectl cordon worker-1
## 排空节点上的 Pod
$ kubectl drain worker-1 --ignore-daemonsets
```
### 13.2.2 容器组
Kubernetes 使用的最小调度单位是容器组 (Pod)它是创建调度管理的最小单位一个 Pod 包含一个或多个紧密协作的容器它们共享网络命名空间和存储卷
+1
View File
@@ -52,6 +52,7 @@ spec:
type: Utilization
averageUtilization: 50
```
### 13.4.5 ConfigMap Secret
* **ConfigMap**存储非机密的配置数据 (配置文件环境变量)
+2
View File
@@ -40,6 +40,7 @@ spec:
```bash
kubectl apply -f nginx-deployment.yaml
```
### 13.5.3 步骤 2创建 Service
创建一个名为 `nginx-service.yaml` 的文件
@@ -82,6 +83,7 @@ kubectl apply -f nginx-deployment.yaml
```bash
kubectl rollout status deployment/nginx-deployment
```
### 13.5.5 步骤 4清理资源
练习结束后记得清理资源
+12
View File
@@ -17,6 +17,7 @@ $ sudo apt install containerd.io
$ sudo yum install containerd.io
```
### 14.1.2 配置 containerd
新建 `/etc/systemd/system/cri-containerd.service` 文件
@@ -230,6 +231,7 @@ oom_score = 0
base_image_size = ""
async_remove = false
```
### 14.1.3 安装 **kubelet****kubeadm****kubectl****cri-tools****kubernetes-cni**
需要在每台机器上安装以下的软件包
@@ -253,6 +255,7 @@ $ sudo apt-get install -y kubelet kubeadm kubectl cri-tools kubernetes-cni
$ sudo apt-mark hold kubelet kubeadm kubectl
```
#### CentOS/Fedora
```bash
@@ -270,6 +273,7 @@ EOF
$ sudo yum install -y kubelet kubeadm kubectl cri-tools kubernetes-cni
```
### 14.1.4 修改内核的运行参数
#### 加载内核模块
@@ -283,6 +287,7 @@ EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
```
#### 禁用 swap必须
kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无法加入集群
@@ -303,6 +308,7 @@ EOF
$ sysctl --system
```
### 14.1.5 配置 kubelet
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
@@ -325,6 +331,7 @@ ExecStartPre=-/sbin/modprobe ip_vs_sh
```bash
$ sudo systemctl daemon-reload
```
### 14.1.6 部署
安装配置完成后我们将分别在 Master 节点和 Worker 节点上进行部署操作
@@ -373,6 +380,7 @@ Then you can join any number of worker nodes by running the following on each as
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
#### node 工作节点
**另一主机** 重复 **部署** 小节以前的步骤安装配置好 kubelet根据提示加入到集群
@@ -387,6 +395,7 @@ $ kubeadm join 192.168.199.100:6443 \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
--cri-socket /run/cri-containerd/cri-containerd.sock
```
### 14.1.7 查看服务
所有服务启动后通过 `crictl` 查看本地实际运行的容器这些服务大概分为三类主节点服务工作节点服务和其它服务
@@ -394,6 +403,7 @@ $ kubeadm join 192.168.199.100:6443 \
```bash
CONTAINER_RUNTIME_ENDPOINT=/run/cri-containerd/cri-containerd.sock crictl ps -a
```
#### 主节点服务
* `apiserver` 是整个系统的对外接口提供 RESTful 方式供客户端和其它组件调用
@@ -437,6 +447,7 @@ $ kubectl get node -o yaml | grep CIDR
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
### 14.1.10 master 节点默认不能运行 pod
如果用 `kubeadm` 部署一个单节点集群默认情况下无法使用请执行以下命令解除限制
@@ -454,6 +465,7 @@ $ kubectl taint nodes --all node-role.kubernetes.io/master-
...
```
### 14.1.11 参考文档
* [官方文档](https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)
@@ -44,6 +44,7 @@ $ sudo systemctl start cri-docker
$ sudo /usr/local/bin/cri-dockerd --version
```
#### CentOS/Fedora
```bash
@@ -66,6 +67,7 @@ $ sudo systemctl daemon-reload
$ sudo systemctl enable cri-docker
$ sudo systemctl start cri-docker
```
### 14.2.3 安装 **kubelet****kubeadm****kubectl**
需要在每台机器上安装以下的软件包
@@ -89,6 +91,7 @@ $ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl
```
#### CentOS/Fedora
```bash
@@ -106,6 +109,7 @@ EOF
$ sudo yum install -y kubelet kubeadm kubectl
```
### 14.2.4 修改内核的运行参数
#### 加载内核模块
@@ -119,6 +123,7 @@ EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
```
#### 禁用 swap必须
kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无法加入集群
@@ -139,6 +144,7 @@ EOF
$ sysctl --system
```
### 14.2.5 配置 kubelet
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
@@ -161,6 +167,7 @@ ExecStartPre=-/sbin/modprobe ip_vs_sh
```bash
$ sudo systemctl daemon-reload
```
### 14.2.6 部署
安装配置完成后我们将分别在 Master 节点和 Worker 节点上进行部署操作
@@ -205,6 +212,7 @@ Then you can join any number of worker nodes by running the following on each as
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
#### node 工作节点
**另一主机** 重复 **部署** 小节以前的步骤安装配置好 kubelet根据提示加入到集群
@@ -213,6 +221,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
$ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
### 14.2.7 查看服务
所有服务启动后查看本地实际运行的 Docker 容器这些服务大概分为三类主节点服务工作节点服务和其它服务
@@ -260,6 +269,7 @@ $ kubectl get node -o yaml | grep CIDR
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
### 14.2.10 master 节点默认不能运行 pod
如果用 `kubeadm` 部署一个单节点集群默认情况下无法使用请执行以下命令解除限制
@@ -277,6 +287,7 @@ $ kubectl taint nodes --all node-role.kubernetes.io/master-
...
```
### 14.2.11 参考文档
* [官方文档](https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)
+5
View File
@@ -20,6 +20,7 @@ Kind 是一个二进制文件,并在 PATH 中即可使用。以下是不同系
```bash
brew install kind
```
#### Linux / Windows
可以下载二进制文件
@@ -31,6 +32,7 @@ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
```
### 14.4.3 创建集群
最简单的创建方式
@@ -43,6 +45,7 @@ kind create cluster
```bash
kind create cluster --name my-cluster
```
### 14.4.4 与集群交互
Kind 会自动将 kubeconfig 合并到 `~/.kube/config`
@@ -51,6 +54,7 @@ Kind 会自动将 kubeconfig 合并到 `~/.kube/config`。
kubectl cluster-info --context kind-kind
kubectl get nodes
```
### 14.4.5 高级用法配置集群
创建一个 `kind-config.yaml` 来定制集群例如映射端口到宿主机
@@ -72,6 +76,7 @@ nodes:
```bash
kind create cluster --config kind-config.yaml
```
### 14.4.6 删除集群
```bash
+2
View File
@@ -32,6 +32,7 @@ sudo k3s kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-master Ready control-plane,master 1m v1.35.1+k3s1
```
### 14.5.3 快速使用
K3s 内置了 `kubectl` 命令 (通过 `k3s kubectl` 调用)为了方便通常会建立别名或配置 `KUBECONFIG`
@@ -45,6 +46,7 @@ export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get pods -A
```
### 14.5.4 清理卸载
```bash
+2
View File
@@ -30,6 +30,7 @@
/etc/systemd/system/kube-proxy.service
/etc/systemd/system/kube-apiserver.service
```
#### 常用命令
```bash
@@ -48,6 +49,7 @@ sudo systemctl status kubelet
# 设置开机自启
sudo systemctl enable kubelet
```
### 参考资源
详细的部署步骤和配置说明可以参考以下项目
+1
View File
@@ -11,6 +11,7 @@
```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
```
### 14.7.2 访问
通过命令行代理访问执行以下命令
+1
View File
@@ -7,6 +7,7 @@
kubectl [flags]
kubectl [command]
```
### 14.8.1 get
显示一个或多个资源
+4
View File
@@ -80,6 +80,7 @@ OPTIONS:
--user="" username[:password] for authentication (prompt if password is not supplied)
-w, --write-out="simple" set the output format (fields, json, protobuf, simple, table)
```
### 15.4.1 数据库操作
数据库操作围绕对键值和目录的 CRUD (符合 REST 风格的一套操作Create) 完整生命周期的管理
@@ -94,6 +95,7 @@ etcd 在键的组织上采用了层次化的空间结构 (类似于文件系统
$ etcdctl put /testdir/testkey "Hello world"
OK
```
#### get
获取指定键的值例如
@@ -119,6 +121,7 @@ hello
$ etcdctl del testkey
1
```
### 15.4.2 非数据库操作
#### watch
@@ -133,6 +136,7 @@ PUT
testkey
2
```
#### member
通过 `list``add``update``remove` 命令列出添加更新删除 etcd 实例到 etcd 集群中
+5
View File
@@ -35,6 +35,7 @@
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl cluster-info
```
#### 2. 部署容器应用
创建 Deployment 部署应用
@@ -67,6 +68,7 @@ kubectl apply -f deployment.yaml
kubectl get pods
kubectl get svc
```
#### 3. 管理镜像
通过腾讯云容器镜像服务 (TCR) 存储和管理私有镜像
@@ -81,6 +83,7 @@ docker tag my-app:latest ccr.ccs.tencentyun.com/namespace/my-app:latest
# 推送镜像到腾讯云
docker push ccr.ccs.tencentyun.com/namespace/my-app:latest
```
### 腾讯云 Docker 镜像加速器配置
为了加快镜像拉取速度腾讯云提供了镜像加速服务配置方法如下
@@ -116,6 +119,7 @@ sudo systemctl restart docker
# 查看镜像源是否生效
docker info | grep -A 5 "Registry Mirrors"
```
#### Windows/Mac 配置
对于 Docker Desktop在设置界面中
@@ -167,6 +171,7 @@ docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
FROM ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
RUN echo "使用腾讯云镜像作为基础镜像"
```
#### TKE 集群中使用 TCR 镜像
配置镜像拉取凭证后 Deployment 中直接引用 TCR 镜像
+8
View File
@@ -37,6 +37,7 @@
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl get nodes
```
#### 2. 部署容器应用
通过 Deployment 部署应用示例
@@ -73,6 +74,7 @@ kubectl apply -f deployment.yaml
kubectl get pods -o wide
kubectl logs <pod-name>
```
#### 3. 暴露服务
创建 Service 暴露应用
@@ -96,6 +98,7 @@ spec:
kubectl apply -f service.yaml
kubectl get svc web-service
```
### 阿里云 Docker 镜像加速器配置
为了加快从阿里云镜像源拉取官方镜像的速度可以配置镜像加速器阿里云为容器服务 ACK 用户提供了免费的镜像加速服务
@@ -132,6 +135,7 @@ sudo systemctl restart docker
```bash
docker info | grep -A 5 "Registry Mirrors"
```
#### Windows/Mac 配置
Docker Desktop Settings
@@ -146,6 +150,7 @@ docker info | grep -A 5 "Registry Mirrors"
docker pull nginx:latest
time docker pull alpine:latest
```
### 阿里云容器镜像服务ACR
阿里云容器镜像服务 (ACR, Container Registry) 是企业级的容器镜像存储和分发平台
@@ -183,6 +188,7 @@ FROM registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
COPY . /app
RUN echo "已成功使用阿里云镜像"
```
#### ACK 集群中使用 ACR 镜像
ACK 集群中需要先配置镜像拉取凭证Secret然后在 Deployment 中引用
@@ -233,6 +239,7 @@ spec:
- web
topologyKey: kubernetes.io/hostname
```
#### 创建镜像拉取凭证
ACK 集群中创建 Secret用于拉取私有镜像
@@ -249,6 +256,7 @@ kubectl create secret docker-registry acr-secret \
kubectl get secret acr-secret
kubectl describe secret acr-secret
```
#### ACR 优势
- ACK 集群中与镜像仓库无缝集成简化身份认证
+1
View File
@@ -26,6 +26,7 @@ passwd:
```bash
$ docker run -i --rm quay.io/coreos/fcct:v0.5.0 --pretty --strict < example.fcc > example.ign
```
### 17.2.4 挂载 ISO 启动虚拟机并安装
> 虚拟机需要分配 3GB 以上内存否则会无法启动
+8
View File
@@ -22,6 +22,7 @@ Podman 支持多种操作系统,安装过程也相对简单。
```bash
$ sudo yum -y install podman
```
#### macOS
macOS 上需要安装 Podman Desktop 或通过 Homebrew 安装
@@ -31,6 +32,7 @@ $ brew install podman
$ podman machine init
$ podman machine start
```
### 17.3.3 基本使用
`podman` 的命令行几乎与 `docker` 完全兼容大多数情况下你只需将 `docker` 替换为 `podman` 即可
@@ -42,16 +44,19 @@ $ podman machine start
$ podman run -d -p 80:80 nginx:alpine
```
#### 列出容器
```bash
$ podman ps
```
#### 构建镜像
```bash
$ podman build -t myimage .
```
### 17.3.4 Pods 的概念
Docker 不同Podman 支持Pod的概念 (类似于 Kubernetes Pod)允许你在同一个网络命名空间中运行多个容器
@@ -65,6 +70,7 @@ $ podman pod create --name mypod -p 8080:80
$ podman run -d --pod mypod --name webbing nginx
```
### 17.3.5 迁移到 Podman
如果你习惯使用 `docker` 命令可以简单地设置别名
@@ -72,6 +78,7 @@ $ podman run -d --pod mypod --name webbing nginx
```bash
$ alias docker=podman
```
#### Systemd 集成
Podman 可以生成 systemd 单元文件让容器像普通系统服务一样管理
@@ -89,6 +96,7 @@ $ podman generate systemd --name myweb --files --new
$ systemctl --user enable --now container-myweb.service
```
#### Podman Compose
虽然 Podman 兼容 Docker Compose但在某些场景下你可能需要明确使用 `podman-compose`
+1
View File
@@ -30,6 +30,7 @@ $ sudo dnf install -y buildah
$ sudo apt-get update
$ sudo apt-get -y install buildah
```
### 基础用法示例
#### 1. 从现有的 Dockerfile 构建镜像
+1
View File
@@ -35,6 +35,7 @@ $ sudo apt-get -y install skopeo
```bash
$ brew install skopeo
```
### 基础用法示例
#### 1. 远程检查镜像
+1
View File
@@ -60,6 +60,7 @@ dockremap:165536:65536
```bash
$ sudo systemctl restart docker
```
#### 验证映射效果
我们可以运行一个简单的容器并执行 `sleep` 命令同时在宿主机上观察进程的所有者
+1
View File
@@ -53,6 +53,7 @@ $ docker run --rm -it \
--security-opt apparmor=custom-nginx-profile \
nginx
```
### 18.5.3 容器镜像漏洞静态扫描
现代防护的防御已经不仅仅在运行阶段而向延伸至了构建与分发时期控制很多安全隐患并不是用户代码中的直接逻辑异常而是打包环境或者引入库的基础 `APT` 安装层面潜伏了开源界众所周知的历史漏洞
+13
View File
@@ -41,6 +41,7 @@ trivy image --severity HIGH,CRITICAL \
--exit-code 1 \
myregistry.com/myapp:v1.0.0
```
#### Grype - 支持多种软件包的扫描器
Grype Anchore 开发支持更广泛的软件包管理器和语言
@@ -67,6 +68,7 @@ grype sbom:sbom.json
# 扫描特定目录
grype dir:/path/to/app
```
#### Snyk - 完整的安全平台
Snyk 提供了商业级的安全扫描服务特别适合企业环境
@@ -130,6 +132,7 @@ syft dir:/path/to/app -o json > sbom.json
# OCI 镜像档案生成
syft oci-archive:image.tar -o json > sbom.json
```
#### CycloneDX SPDX 格式
两种主流的 SBOM 格式
@@ -173,6 +176,7 @@ syft oci-archive:image.tar -o json > sbom.json
]
}
```
#### SBOM 的应用场景
**漏洞关联**
@@ -249,6 +253,7 @@ cosign verify myregistry.com/myapp:v1.0.0 \
--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
Docker Content Trust 使用 Notary 实现镜像签名 Docker 官方的签名解决方案
@@ -276,6 +281,7 @@ docker push --disable-content-trust myregistry.com/myapp:v1.0.0
# 查看签名信息
docker inspect --format='{{.RepoDigests}}' myregistry.com/myapp:v1.0.0
```
### 18.6.4 供应链安全最佳实践
#### 1. 基础镜像安全
@@ -289,6 +295,7 @@ RUN apt-get update && apt-get install -y curl
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e6e0e14...完整 64 位哈希
RUN apt-get update && apt-get install -y curl=7.68.0-1ubuntu1
```
#### 2. 构建时扫描
Dockerfile 中集成安全扫描
@@ -308,6 +315,7 @@ RUN go build -o app .
FROM alpine:3.17@sha256:abcd1234...请替换为实际完整的 64 位摘要哈希
COPY --from=builder /app/app /app
```
#### 3. 运行时镜像扫描策略
```bash
@@ -320,6 +328,7 @@ trivy image --severity HIGH,CRITICAL \
# 定期扫描已部署的镜像
trivy image --scanners vuln,misconfig registry:5000/myapp:latest
```
#### 4. 镜像仓库安全配置
**Harbor私有镜像仓库的安全扫描**
@@ -335,6 +344,7 @@ trivy:
scan_on_push: true # 推送时自动扫描
scan_all: true # 扫描仓库中的所有镜像
```
#### 5. 政策执行
Kubernetes 环境中使用 Admission Webhook 强制镜像签名和扫描
@@ -359,6 +369,7 @@ webhooks:
admissionReviewVersions: ["v1"]
sideEffects: None
```
### 18.6.5 CI/CD 中集成安全扫描
#### GitHub Actions 工作流示例
@@ -445,6 +456,7 @@ jobs:
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
#### GitLab CI 工作流示例
```yaml
@@ -509,6 +521,7 @@ push:
only:
- main
```
### 18.6.6 常见问题与最佳实践
**Q: 扫描报告中有过时的 CVE如何处理**
+1
View File
@@ -23,6 +23,7 @@ flowchart LR
Proc --> Mech
end
```
## 本章内容
本章涵盖 Docker 安全的多个层面从内核隔离机制到运行时防护和供应链安全
+2
View File
@@ -48,6 +48,7 @@ scrape_configs:
rule_files:
- /etc/prometheus/rules.yml
```
#### 2. 编写 Docker Compose 文件
创建 `compose.yaml` ( `docker-compose.yml`)
@@ -105,6 +106,7 @@ networks:
volumes:
prometheus_data:
```
#### 3. 启动服务
```bash
+2
View File
@@ -71,6 +71,7 @@ volumes:
networks:
logging:
```
#### 2. 配置 Fluentd
创建 `fluentd/conf/fluent.conf`
@@ -101,6 +102,7 @@ networks:
</store>
</match>
```
#### 3. 配置应用容器使用 fluentd 驱动
启动一个测试容器指定日志驱动为 `fluentd`
@@ -91,6 +91,7 @@ done
# MEM % 接近 100%容器即将 OOM需要增加内存或排查内存泄漏
# 如果 NET I/O dropped 为非零网络拥塞或丢包
```
### 19.3.3 cAdvisor 容器监控系统
cAdvisor Google 开发的容器监控工具提供比 `docker stats` 更详细的性能数据
@@ -150,6 +151,7 @@ scrape_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
```
### 19.3.4 Prometheus 容器监控配置
使用 Prometheus node-exporter 进行长期的容器性能监控
@@ -275,6 +277,7 @@ container_memory_cache_bytes / container_memory_usage_bytes
# 按镜像统计容器数
count(container_memory_usage_bytes) by (image)
```
### 19.3.5 容器 OOM 排查与内存限制调优
#### OOM 问题诊断
@@ -293,6 +296,7 @@ docker logs <container_id> 2>&1 | grep -i "out of memory\|oom"
dmesg | grep -i "oom\|kill"
journalctl -u docker -n 100 | grep -i "oom"
```
#### 内存泄漏检测
使用专项工具分析应用内存使用
@@ -347,6 +351,7 @@ jstat -gc <pid> 1000 # 每秒采样一次
# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU
# 6144 6144 0 6144 39424 12288 149504 84320 50552 47689 6464 5989
```
#### 内存限制最佳实践
```bash
@@ -385,6 +390,7 @@ services:
memory: 2G
memory_reservation: 1G # 预留 1GB允许突发到 2GB
```
### 19.3.6 镜像体积优化与多阶段构建
#### 镜像体积分析工具
@@ -411,6 +417,7 @@ chmod +x hadolint
# 检查 Dockerfile 最佳实践
./hadolint Dockerfile
```
#### 多阶段构建最佳实践
**Go 应用的最小化镜像构建**
@@ -528,6 +535,7 @@ EXPOSE 5000
CMD ["python", "app.py"]
```
#### 镜像体积优化检查清单
```bash
@@ -558,6 +566,7 @@ RUN apt-get update && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
```
### 19.3.7 常见性能问题及解决方案
**问题 1: 容器频繁被 OOM 杀死**
+1
View File
@@ -30,6 +30,7 @@ $ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest e72ac664f4f0 6 weeks ago 2.433 MB
```
### 20.1.3 运行 busybox
启动一个 `busybox` 容器并在容器中执行 `grep` 命令
+3
View File
@@ -25,6 +25,7 @@ debian latest 4d6ce913b130 84.98 MB
ubuntu latest b39b81afc8ca 188.3 MB
centos latest 8efe422e6104 210 MB
```
### 20.2.2 获取并使用官方镜像
由于镜像很小下载时间往往很短读者可以直接使用 `docker run` 指令直接运行一个 `Alpine` 容器并指定运行的 Linux 指令例如
@@ -33,6 +34,7 @@ centos latest 8efe422e6104 210 MB
$ docker run alpine echo '123'
123
```
### 20.2.3 迁移至 Alpine 基础镜像
目前大部分 Docker 官方镜像都已经支持 `Alpine` 作为基础镜像可以很容易进行迁移
@@ -60,6 +62,7 @@ $ apk --update add --no-cache <package>
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \
&& apk add --no-cache <package>
```
### 20.2.4 相关资源
* `Alpine` 官网https://www.alpinelinux.org/
+1
View File
@@ -28,6 +28,7 @@ Status: Downloaded newer image for centos:7
[root@43eb3b194d48 /]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
```
### 20.4.2 Fedora 系统简介
下图直观地展示了本节内容
+2
View File
@@ -35,6 +35,7 @@ WORKDIR /app
COPY --from=builder /app/main .
CMD ["./main"]
```
#### 2. GitLab CI 配置
GitLab CI`.gitlab-ci.yml`配置如下
@@ -74,6 +75,7 @@ deploy_staging:
only:
- develop
```
### 21.1.3 最佳实践
1. **不可变基础设施**一旦镜像构建完成在各个环境DevStagingProd中都应该使用同一个镜像 tag通常是 commit hash而不是重新构建
+1
View File
@@ -46,6 +46,7 @@ jobs:
with:
args: go version
```
## 21.2.3 参考资料
* [Actions Docs](https://docs.github.com/en/actions)
+2
View File
@@ -70,6 +70,7 @@ trigger:
.drone.yml
app.go
```
## 21.3.3 推送项目源代码到 GitHub
```bash
@@ -79,6 +80,7 @@ git commit -m "test drone ci"
git push origin master
```
## 21.3.4 查看项目构建过程及结果
打开我们部署好的 `Drone` 网站或者 Drone Cloud即可看到构建结果
+1
View File
@@ -39,6 +39,7 @@ VS Code 会拉取镜像并启动容器,随后你就可以在容器内运行:
```bash
go test ./...
```
## 21.6.3 结合 Docker Compose可选
如果项目同时依赖数据库/缓存例如 Postgres/Redis可以使用 `dockerComposeFile`
@@ -120,6 +120,7 @@ require (
// 如果需要依赖
)
```
#### 带依赖的 Go 应用
**应用代码使用 Gin 框架**
@@ -182,6 +183,7 @@ EXPOSE 8080
CMD ["./app"]
```
### 21.7.2 Rust 应用的最小化镜像构建
Rust 因其性能和安全性在系统级应用中备受青睐
@@ -273,6 +275,7 @@ curl http://localhost:8080/health | jq .
# Rust 应用通常比 Go 更小5-20MB取决于依赖
docker images rust-app
```
### 21.7.3 数据库容器化最佳实践
#### PostgreSQL 生产部署
@@ -455,6 +458,7 @@ services:
volumes:
postgres_data:
```
#### MySQL/MariaDB 部署
```dockerfile
@@ -495,6 +499,7 @@ server_id = 1
log_bin = mysql-bin
binlog_format = ROW
```
#### Redis 缓存部署
```dockerfile
@@ -545,6 +550,7 @@ client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
```
### 21.7.4 微服务架构的 Docker Compose 编排
**三层微服务架构示例**
@@ -736,6 +742,7 @@ server {
}
}
```
### 21.7.5 使用 VS Code Dev Containers
Dev Containers 让整个开发环境容器化提升团队一致性
+1
View File
@@ -33,6 +33,7 @@ $ git rebase upstream/master
$ git push -f origin master
```
## 排版规范
本开源书籍遵循[中文排版指南](https://github.com/mzlogin/chinese-copywriting-guidelines)规范。

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