diff --git a/01_introduction/1.1_quickstart.md b/01_introduction/1.1_quickstart.md index c2ca2a9..e3aa5fa 100644 --- a/01_introduction/1.1_quickstart.md +++ b/01_introduction/1.1_quickstart.md @@ -52,6 +52,7 @@ $ docker run -d -p 8080:80 my-hello-world 停止并删除容器: ```bash + ## 查看正在运行的容器 ID $ docker ps diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index 915aefb..e04b9c6 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -71,10 +71,12 @@ Docker 镜像包含了应用运行所需的 **一切**:代码、运行时、 - ✅ 新人入职,一条命令就能启动开发环境 ```bash + ## 新同事入职第一天 $ git clone https://github.com/company/project.git $ docker compose up + ## 完整的开发环境就准备好了 ... diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md index f8dbdfc..7388aa1 100644 --- a/02_basic_concept/2.1_image.md +++ b/02_basic_concept/2.1_image.md @@ -115,6 +115,7 @@ flowchart TD > ⚠️ **笔者特别提醒**:理解这一点可以帮你避免构建出臃肿的镜像。**关键原理**:每一层的文件变化会被记录,但 **删除操作只是标记,不会真正减小镜像体积**。 ```docker + ## 错误示范 ❌ FROM ubuntu:24.04 @@ -122,10 +123,12 @@ RUN apt-get update RUN apt-get install -y build-essential # 安装编译工具(约 200MB) RUN make && make install # 编译应用 RUN apt-get remove build-essential # 试图删除编译工具 + ## 结果:镜像仍然包含 200MB 的编译工具! ``` ```docker + ## 正确做法 ✅ FROM ubuntu:24.04 @@ -135,6 +138,7 @@ RUN apt-get update && \ apt-get remove -y build-essential && \ apt-get autoremove -y && \ rm -rf /var/lib/apt/lists/* + ## 在同一层完成安装、使用、清理 ``` @@ -142,6 +146,7 @@ RUN apt-get update && \ #### 查看镜像的分层 ```bash + ## 查看镜像的历史(每层的构建记录) $ docker history nginx:latest @@ -164,6 +169,7 @@ Docker 镜像有多种标识方式: 格式:`[仓库地址/]仓库名[:标签]` ```bash + ## 完整格式 registry.example.com/myproject/myapp:v1.2.3 diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md index 3fc68fe..644418f 100644 --- a/02_basic_concept/2.2_container.md +++ b/02_basic_concept/2.2_container.md @@ -113,6 +113,7 @@ flowchart TD > **笔者特别强调**:这是新手最容易踩的坑!**容器存储层与容器生命周期绑定。容器删除,数据就没了!** ```bash + ## 创建容器,写入数据 $ docker run -it ubuntu bash @@ -137,6 +138,7 @@ $ docker rm abc123 | **[绑定挂载 (Bind Mount) ](../08_data/8.2_bind-mounts.md)** | 挂载宿主机目录 | 开发时共享代码 | ```bash + ## 使用数据卷(推荐) $ docker run -v mydata:/var/lib/mysql mysql @@ -173,6 +175,7 @@ stateDiagram-v2 #### 常用生命周期命令 ```bash + ## 创建并启动容器(最常用) $ docker run nginx @@ -203,6 +206,7 @@ $ docker rm -f abc123 # 强制删除运行中的容器 > **核心概念**:容器的生命周期 = 主进程 (PID 1) 的生命周期 ```bash + ## 主进程运行,容器运行 ## 主进程退出,容器停止 @@ -212,6 +216,7 @@ $ docker rm -f abc123 # 强制删除运行中的容器 这就是为什么: ```bash + ## 这个容器会立即退出(bash 没有输入就退出了) $ docker run ubuntu diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md index b4774c5..07e1362 100644 --- a/02_basic_concept/2.3_repository.md +++ b/02_basic_concept/2.3_repository.md @@ -62,6 +62,7 @@ flowchart TB 示例: ```bash + ## 完整格式 registry.example.com/mycompany/myapp:v1.2.3 @@ -103,6 +104,7 @@ gcr.io/google-containers/pause:3.6 - 付费账户支持私有仓库 ```bash + ## 从 Docker Hub 拉取镜像 $ docker pull nginx # 官方镜像 @@ -152,6 +154,7 @@ $ docker push username/myapp:v1.0 Docker 官方提供了 [registry](https://hub.docker.com/_/registry/) 镜像,可以快速搭建私有 Registry: ```bash + ## 启动一个本地 Registry $ docker run -d -p 5000:5000 --name registry registry:2 @@ -211,6 +214,7 @@ $ docker pull localhost:5000/myapp:v1.0 #### 常用命令 ```bash + ## 登录 Registry $ docker login # 登录 Docker Hub @@ -242,6 +246,7 @@ $ docker logout Docker Hub 的[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official) (标有 “Official Image” 标识) 经过 Docker 团队审核,相对更安全。示例如下: ```bash + ## 官方镜像示例 nginx # ✅ 官方 @@ -261,6 +266,7 @@ someuser/myapp # ⚠️ 需要评估 > 注意:Cosign 默认会把签名写回镜像所在仓库,请使用你有推送权限的镜像地址。 ```bash + ## 准备一个你有写权限的镜像地址 $ export IMAGE=<你的仓库名>/nginx:1.27 $ docker pull nginx:1.27 @@ -278,6 +284,7 @@ $ cosign verify --key cosign.pub $IMAGE #### 漏洞扫描 ```bash + ## 使用 Docker Scout 扫描镜像漏洞 $ docker scout cves nginx:latest diff --git a/03_install/3.1_ubuntu.md b/03_install/3.1_ubuntu.md index b7cc921..560ecaa 100644 --- a/03_install/3.1_ubuntu.md +++ b/03_install/3.1_ubuntu.md @@ -95,10 +95,12 @@ $ sudo apt install docker-ce docker-ce-cli containerd.io > 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash + # $ curl -fsSL test.docker.com -o get-docker.sh $ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun + # $ sudo sh get-docker.sh --mirror AzureChinaCloud ``` diff --git a/03_install/3.2_debian.md b/03_install/3.2_debian.md index 1e6f9d0..0bb944e 100644 --- a/03_install/3.2_debian.md +++ b/03_install/3.2_debian.md @@ -86,10 +86,12 @@ $ sudo apt-get install docker-ce docker-ce-cli containerd.io > 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash + # $ curl -fsSL test.docker.com -o get-docker.sh $ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun + # $ sudo sh get-docker.sh --mirror AzureChinaCloud ``` diff --git a/03_install/3.3_fedora.md b/03_install/3.3_fedora.md index c26898e..06bcb18 100644 --- a/03_install/3.3_fedora.md +++ b/03_install/3.3_fedora.md @@ -98,10 +98,12 @@ $ sudo dnf -y install docker-ce-18.06.1.ce > 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash + # $ curl -fsSL test.docker.com -o get-docker.sh $ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun + # $ sudo sh get-docker.sh --mirror AzureChinaCloud ``` diff --git a/03_install/3.4_centos.md b/03_install/3.4_centos.md index 04a4471..e913d43 100644 --- a/03_install/3.4_centos.md +++ b/03_install/3.4_centos.md @@ -83,6 +83,7 @@ CentOS 8/Stream 默认使用 `nftables`。Docker 在新版本中已提供 `nftab 更改 `/etc/firewalld/firewalld.conf` ```bash + ## FirewallBackend=nftables FirewallBackend=iptables @@ -103,10 +104,12 @@ $ firewall-cmd --reload > 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash + # $ curl -fsSL test.docker.com -o get-docker.sh $ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun + # $ sudo sh get-docker.sh --mirror AzureChinaCloud ``` diff --git a/03_install/3.5_raspberry-pi.md b/03_install/3.5_raspberry-pi.md index 9d08a71..3fc49b2 100644 --- a/03_install/3.5_raspberry-pi.md +++ b/03_install/3.5_raspberry-pi.md @@ -111,10 +111,12 @@ $ sudo apt-get install docker-ce > 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash + # $ curl -fsSL test.docker.com -o get-docker.sh $ curl -fsSL get.docker.com -o get-docker.sh $ sudo sh get-docker.sh --mirror Aliyun + # $ sudo sh get-docker.sh --mirror AzureChinaCloud ``` diff --git a/03_install/3.6_offline.md b/03_install/3.6_offline.md index 624ef95..5398602 100644 --- a/03_install/3.6_offline.md +++ b/03_install/3.6_offline.md @@ -148,15 +148,18 @@ sudo yum versionlock delete all ##### 挂载 ISO 镜像搭建本地 File 源 ```bash + ## 删除其他网络源 rm -f /etc/yum.repos.d/* + ## 挂载光盘或者iso镜像 mount /dev/cdrom /mnt ``` ```bash + ## 添加本地源 cat >/etc/yum.repos.d/local_files.repo<< EOF @@ -170,6 +173,7 @@ EOF ``` ```bash + ## 测试刚才的本地源,安装createrepo软件 yum clean all @@ -179,15 +183,19 @@ yum install createrepo -y ##### 根据本地文件搭建 BASE 网络源 ```bash + ## 安装apache 服务器 yum install httpd -y + ## 挂载光盘 mount /dev/cdrom /mnt + ## 新建centos目录 mkdir /var/www/html/base + ## 复制光盘内的文件到刚才新建的目录 cp -R /mnt/Packages/* /var/www/html/base/ @@ -201,6 +209,7 @@ systemctl start httpd 在有网络的服务器上下载 Docker-ce 镜像 ```bash + ## 下载清华的镜像源文件 wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo @@ -208,9 +217,11 @@ sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc ``` ```bash + ## 新建 docker-ce目录 mkdir /tmp/docker-ce/ + ## 把镜像源同步到镜像文件中 reposync -r docker-ce-stable -p /tmp/docker-ce/ @@ -221,6 +232,7 @@ reposync -r docker-ce-stable -p /tmp/docker-ce/ 把下载的 docker-ce 文件夹复制到离线的服务器 ```bash + ## 把docker-ce 文件夹复制到/var/www/html/docker-ce ## 重建索引 @@ -235,6 +247,7 @@ rm -f /etc/yum.repos.d/* cat >/etc/yum.repos.d/local_files.repo<< EOF [local_base] name=local_base + ## 改成B服务器地址 baseurl=http://x.x.x.x/base @@ -243,6 +256,7 @@ gpgcheck=0 proxy=_none_ [docker_ce] name=docker_ce + ## 改成B服务器地址 baseurl=http://x.x.x.x/docker-ce diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md index d51d5a4..6de43f0 100644 --- a/04_image/4.1_pull.md +++ b/04_image/4.1_pull.md @@ -32,6 +32,7 @@ Registry地址 用户名 仓库名 标签 #### 示例 ```bash + ## 完整格式 $ docker pull docker.io/library/ubuntu:24.04 @@ -127,6 +128,7 @@ $ docker pull --platform linux/amd64 nginx 拉取镜像后,可以基于它启动容器: ```bash + ## 拉取镜像 $ docker pull ubuntu:24.04 @@ -170,6 +172,7 @@ root@e7009c6ce357:/# exit ```bash $ sudo systemctl restart docker # Linux + ## 或在 Docker Desktop 中重启 ``` @@ -226,6 +229,7 @@ Error: pull access denied, repository does not exist #### Q:磁盘空间不足 ```bash + ## 清理未使用的镜像 $ docker image prune diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md index 45c9a92..5ad9feb 100644 --- a/04_image/4.2_list.md +++ b/04_image/4.2_list.md @@ -82,6 +82,7 @@ Build Cache 0 0 0B 0B #### 按仓库名过滤 ```bash + ## 列出所有 ubuntu 镜像 $ docker images ubuntu @@ -110,6 +111,7 @@ ubuntu 24.04 329ed837d508 78MB | `reference=pattern` | 按名称模式 | `-f reference='*:latest'` | ```bash + ## 列出 nginx 之后创建的镜像 $ docker images -f since=nginx:latest @@ -147,6 +149,7 @@ REPOSITORY TAG IMAGE ID SIZE #### 处理虚悬镜像 ```bash + ## 列出虚悬镜像 $ docker images -f dangling=true @@ -190,6 +193,7 @@ $ docker images -q 常用于配合其他命令: ```bash + ## 删除所有镜像 $ docker rmi $(docker images -q) @@ -218,6 +222,7 @@ nginx latest sha256:b4f0e0bdeb5... e43d811ce2f4 使用 Go 模板语法自定义输出: ```bash + ## 只显示 ID 和仓库名 $ docker images --format "{{.ID}}: {{.Repository}}" @@ -251,6 +256,7 @@ ubuntu 24.04 78MB ### 4.2.8 常用命令组合 ```bash + ## 列出所有镜像及其大小,按大小排序(需要系统 sort 命令) $ docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | sort -h diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index cfa6d8d..3048511 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -53,6 +53,7 @@ Deleted: sha256:501ad78535f0... 摘要删除最精确,适用于 CI/CD 场景: ```bash + ## 查看镜像摘要 $ docker images --digests @@ -125,6 +126,7 @@ flowchart TD 虚悬镜像 (dangling):没有标签的镜像,通常是旧版本被新版本覆盖后产生的 ```bash + ## 查看虚悬镜像 $ docker images -f dangling=true @@ -141,6 +143,7 @@ $ docker image prune -f #### 删除所有未使用的镜像 ```bash + ## 删除所有没有被容器使用的镜像 $ docker image prune -a @@ -153,6 +156,7 @@ $ docker image prune -a --filter "until=24h" #### 按条件删除 ```bash + ## 删除所有 redis 镜像 $ docker rmi $(docker images -q redis) @@ -183,6 +187,7 @@ Error: conflict: unable to remove repository reference "nginx" **解决方案**: ```bash + ## 方案1:先删除依赖的容器 $ docker rm abc123 @@ -203,6 +208,7 @@ ubuntu latest ca2b0f26964c # 同一个镜像 $ docker rmi ubuntu:24.04 Untagged: ubuntu:24.04 + ## 只是移除标签,镜像仍存在(因为还有 ubuntu:latest 指向它) ``` @@ -238,6 +244,7 @@ Error: image has dependent child images #### 开发环境 ```bash + ## 定期清理虚悬镜像 $ docker image prune -f @@ -250,6 +257,7 @@ $ docker system prune -a #### CI/CD 环境 ```bash + ## 只保留最近使用的镜像 $ docker image prune -a --filter "until=72h" -f diff --git a/04_image/4.5_build.md b/04_image/4.5_build.md index 7194f0d..76e88dd 100644 --- a/04_image/4.5_build.md +++ b/04_image/4.5_build.md @@ -151,6 +151,7 @@ Sending build context to Docker daemon 2.048 kB 或许你已经注意到了,`docker build` 还支持从 URL 构建,比如可以直接从 Git repo 中构建: ```bash + ## $env:DOCKER_BUILDKIT=0 ## export DOCKER_BUILDKIT=0 diff --git a/05_container/5.1_run.md b/05_container/5.1_run.md index 69c2c68..ae9bb0a 100644 --- a/05_container/5.1_run.md +++ b/05_container/5.1_run.md @@ -92,6 +92,7 @@ flowchart TD #### 端口映射 ```bash + ## 将容器的 80 端口映射到宿主机的 8080 端口 $ docker run -d -p 8080:80 nginx @@ -108,6 +109,7 @@ $ docker run -d -p 127.0.0.1:8080:80 nginx #### 数据卷挂载 ```bash + ## 挂载命名卷 $ docker run -v mydata:/data nginx @@ -124,6 +126,7 @@ $ docker run -v /host/path:/container/path:ro nginx #### 环境变量 ```bash + ## 设置单个环境变量 $ docker run -e MYSQL_ROOT_PASSWORD=secret mysql @@ -136,6 +139,7 @@ $ docker run --env-file .env myapp #### 资源限制 ```bash + ## 限制内存 $ docker run -m 512m nginx @@ -150,6 +154,7 @@ $ docker run --cpus=1.5 nginx 使用 `docker start` 重新启动已停止的容器: ```bash + ## 查看所有容器(包括已停止的) $ docker ps -a @@ -187,6 +192,7 @@ root@ba267838cc1b:/# ps **原因**:主进程执行完毕或无法保持运行 ```bash + ## 这个容器会立即退出(echo 执行完就结束了) $ docker run ubuntu echo "hello" @@ -203,6 +209,7 @@ $ docker run -d nginx # nginx 是持续运行的服务 **原因**:未正确映射端口 ```bash + ## 错误:没有 -p 参数,外部无法访问 $ docker run -d nginx @@ -217,6 +224,7 @@ $ docker run -d -p 80:80 nginx **原因**:未使用数据卷,数据保存在容器存储层 ```bash + ## 使用数据卷持久化 $ docker run -v mydata:/app/data myapp diff --git a/05_container/5.2_daemon.md b/05_container/5.2_daemon.md index 9032ab3..538a2f9 100644 --- a/05_container/5.2_daemon.md +++ b/05_container/5.2_daemon.md @@ -126,6 +126,7 @@ $ docker container ls -a #### 1. 长期运行的服务使用 -d ```bash + ## Web 服务器 $ docker run -d -p 80:80 nginx @@ -144,6 +145,7 @@ $ docker run -d -p 6379:6379 redis 当容器启动有问题时,**去掉 `-d` 参数** 可以直接看到输出和错误: ```bash + ## 有问题的容器,先前台运行看看发生了什么 $ docker run myimage:latest @@ -156,6 +158,7 @@ $ docker run myimage:latest ```bash $ docker run --rm ubuntu:24.04 echo "Hello, World!" Hello, World! + ## 容器执行完后自动删除 ... @@ -164,6 +167,7 @@ Hello, World! #### 4. 配合日志查看 ```bash + ## 后台启动 $ docker run -d --name myapp myimage:latest diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md index d09928f..6057555 100644 --- a/05_container/5.3_stop.md +++ b/05_container/5.3_stop.md @@ -34,6 +34,7 @@ flowchart TD #### 自定义超时时间 ```bash + ## 等待 30 秒后强制终止 $ docker stop -t 30 mycontainer @@ -46,6 +47,7 @@ $ docker stop -t 0 mycontainer #### 停止多个容器 ```bash + ## 停止多个指定容器 $ docker stop container1 container2 container3 @@ -75,6 +77,7 @@ $ docker kill 容器名或ID #### 发送自定义信号 ```bash + ## 发送 SIGHUP(让进程重新加载配置) $ docker kill -s HUP mycontainer @@ -91,6 +94,7 @@ $ docker kill -s TERM mycontainer 容器的生命周期与主进程绑定。主进程退出时,容器自动停止: ```bash + ## 主进程是交互式 bash $ docker run -it ubuntu bash @@ -139,6 +143,7 @@ $ docker start -ai 容器名 #### 重启运行中的容器 ```bash + ## 先停止再启动 $ docker restart 容器名 @@ -209,10 +214,12 @@ $ docker stop $(docker ps -q) && docker container prune -f 确保容器主进程正确处理信号: ```dockerfile + ## Dockerfile 示例 FROM node:22 ... + ## 使用 exec 形式确保信号能传递给 node 进程 CMD ["node", "server.js"] @@ -221,6 +228,7 @@ CMD ["node", "server.js"] #### Q:容器无法停止 ```bash + ## 强制终止 $ docker kill 容器名 diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md index 5c72889..4e57fe6 100644 --- a/05_container/5.4_attach_exec.md +++ b/05_container/5.4_attach_exec.md @@ -27,6 +27,7 @@ Docker 提供两种进入容器的命令: #### docker exec 基本用法 ```bash + ## 进入容器并启动交互式 shell $ docker exec -it 容器名 /bin/bash @@ -50,6 +51,7 @@ $ docker exec -it 容器名 /bin/sh #### docker exec 示例 ```bash + ## 启动一个后台容器 $ docker run -dit --name myubuntu ubuntu @@ -74,6 +76,7 @@ CONTAINER ID IMAGE STATUS NAMES 不进入交互模式,直接执行命令: ```bash + ## 查看容器内进程 $ docker exec myubuntu ps aux @@ -90,6 +93,7 @@ $ docker exec -u root myubuntu apt update #### 只用 -i 不用 -t 的区别 ```bash + ## 只用 -i:可以执行命令,但没有提示符 $ docker exec -i myubuntu bash @@ -135,6 +139,7 @@ flowchart LR #### docker attach 示例 ```bash + ## 启动容器 $ docker run -dit --name myubuntu ubuntu @@ -168,6 +173,7 @@ CONTAINER ID IMAGE STATUS NAMES ```bash $ docker attach myubuntu root@243c32535da7:/# + ## 按 Ctrl+P 然后 Ctrl+Q read escape sequence @@ -221,6 +227,7 @@ flowchart LR #### 1. 首选 docker exec ```bash + ## 进入容器调试 $ docker exec -it myapp bash @@ -247,6 +254,7 @@ $ docker exec myapp python manage.py migrate 某些精简镜像 (如基于 `scratch` 或 `distroless`) 没有 shell: ```bash + ## 这会失败 $ docker exec -it myapp bash diff --git a/05_container/5.6_rm.md b/05_container/5.6_rm.md index dabc6f8..576c02d 100644 --- a/05_container/5.6_rm.md +++ b/05_container/5.6_rm.md @@ -32,6 +32,7 @@ mycontainer #### 强制删除运行中的容器 ```bash + ## 不加 -f 会报错 $ docker rm running_container @@ -48,6 +49,7 @@ running_container #### 删除容器及其数据卷 ```bash + ## 删除容器时同时删除其匿名卷 $ docker rm -v mycontainer @@ -62,6 +64,7 @@ $ docker rm -v mycontainer #### 删除所有已停止的容器 ```bash + ## 方式一:使用 prune 命令(推荐) $ docker container prune @@ -81,6 +84,7 @@ $ docker container prune -f #### 删除所有容器:包括运行中的 ```bash + ## 先停止所有容器,再删除 $ docker stop $(docker ps -q) @@ -94,6 +98,7 @@ $ docker rm -f $(docker ps -aq) #### 按条件删除 ```bash + ## 删除所有已退出的容器 $ docker rm $(docker ps -aq -f status=exited) @@ -125,6 +130,7 @@ $ docker container prune --filter "until=24h" #### 示例 ```bash + ## 删除所有基于 nginx 镜像的容器 $ docker rm $(docker ps -aq -f ancestor=nginx) @@ -141,6 +147,7 @@ $ docker rm $(docker ps -aq -f status=created) > 有容器依赖的镜像无法删除。 ```bash + ## 尝试删除有容器依赖的镜像 $ docker image rm nginx @@ -159,6 +166,7 @@ $ docker image rm nginx #### 开发环境 ```bash + ## 定期清理已停止的容器 $ docker container prune -f @@ -171,9 +179,11 @@ $ docker system prune -f #### 生产环境 ```bash + ## 使用 --rm 参数运行临时容器 $ docker run --rm ubuntu echo "Hello" + ## 容器退出后自动删除 ## 定期清理(设置保留时间) @@ -185,6 +195,7 @@ $ docker container prune --filter "until=168h" # 保留 7 天内的 ```bash #!/bin/bash + ## cleanup.sh - Docker 资源清理脚本 echo "清理已停止的容器..." @@ -218,6 +229,7 @@ Error: container is running ```bash $ docker stop mycontainer $ docker rm mycontainer + ## 或 $ docker rm -f mycontainer @@ -234,6 +246,7 @@ $ docker rm -f mycontainer 解决: ```bash + ## 查看空间占用 $ docker system df diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md index 60fa88e..245a923 100644 --- a/06_repository/6.1_dockerhub.md +++ b/06_repository/6.1_dockerhub.md @@ -45,6 +45,7 @@ $ docker pull nginx:alpine ```bash $ docker login + ## 默认情况下,不带其它参数进行 docker login 会自动走 Device Code Web Flow (浏览器认证) ## 若在非交互 CI 环境中,推荐结合 --username 与 --password-stdin 参数使用 @@ -54,6 +55,7 @@ $ docker login 打标签并推送: ```bash + ## 1. 标记镜像 $ docker tag myapp:v1 username/myapp:v1 diff --git a/07_dockerfile/7.10_workdir.md b/07_dockerfile/7.10_workdir.md index ac2fdc4..49d8466 100644 --- a/07_dockerfile/7.10_workdir.md +++ b/07_dockerfile/7.10_workdir.md @@ -27,6 +27,7 @@ COPY . . # 复制到 /app/ #### 常见错误 ```docker + ## ❌ 错误:cd 在下一个 RUN 中无效 RUN cd /app @@ -51,6 +52,7 @@ RUN echo "hello" > world.txt #### 正确做法 ```docker + ## ✅ 正确:使用 WORKDIR WORKDIR /app @@ -87,6 +89,7 @@ RUN pwd # 输出 /app ### 7.10.6 多阶段构建中的 WORKDIR ```docker + ## 构建阶段 FROM node:20 AS builder @@ -122,6 +125,7 @@ CMD ["node", "server.js"] #### 2. 使用绝对路径 ```docker + ## ✅ 推荐:绝对路径,意图明确 WORKDIR /app @@ -134,6 +138,7 @@ WORKDIR app #### 3. 不要用 RUN cd ```docker + ## ❌ 避免 RUN cd /app && echo "hello" > world.txt @@ -148,9 +153,11 @@ RUN echo "hello" > world.txt ```docker WORKDIR /app + ## ... 应用相关操作 ... WORKDIR /data + ## ... 数据相关操作 ... ... diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md index a5c415a..4959bf8 100644 --- a/07_dockerfile/7.11_user.md +++ b/07_dockerfile/7.11_user.md @@ -61,6 +61,7 @@ CMD ["node", "server.js"] #### 使用 UID/GID ```docker + ## 也可以使用数字 USER 1001:1001 @@ -73,9 +74,11 @@ USER 1001:1001 `USER` 指令只能切换到 **已存在** 的用户: ```docker + ## ❌ 错误:用户不存在 USER nonexistent + ## Error: unable to find user nonexistent ## ✅ 正确:先创建用户 @@ -163,6 +166,7 @@ exec gosu redis "$@" 使用 `-u` 或 `--user` 参数: ```bash + ## 以指定用户运行 $ docker run -u 1001:1001 myimage @@ -208,6 +212,7 @@ CMD ["node", "server.js"] #### 1. 始终使用非 root 用户 ```docker + ## ✅ 推荐 RUN adduser -D appuser @@ -224,6 +229,7 @@ CMD ["myapp"] # 以 root 运行 便于在宿主机和容器间共享文件: ```docker + ## 使用常见的非 root UID RUN addgroup -g 1000 -S appgroup && \ @@ -234,6 +240,7 @@ USER 1000:1000 #### 3. 多阶段构建中的 USER ```docker + ## 构建阶段可以用 root FROM node:20 AS builder diff --git a/07_dockerfile/7.12_healthcheck.md b/07_dockerfile/7.12_healthcheck.md index c79ff30..de27255 100644 --- a/07_dockerfile/7.12_healthcheck.md +++ b/07_dockerfile/7.12_healthcheck.md @@ -78,6 +78,7 @@ HEALTHCHECK NONE 使用 `curl` 或 `wget`: ```docker + ## 使用 curl HEALTHCHECK CMD curl -f http://localhost/ || exit 1 @@ -90,6 +91,7 @@ HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1 #### 数据库 ```docker + ## MySQL HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1 @@ -143,6 +145,7 @@ services: ### 7.12.7 查看健康状态 ```bash + ## 查看容器状态(包含健康信息) $ docker ps @@ -184,6 +187,7 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq 应用启动可能需要时间 (如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。 ```docker + ## 给应用 1 分钟启动时间 HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1 diff --git a/07_dockerfile/7.13_onbuild.md b/07_dockerfile/7.13_onbuild.md index 0752e35..698fcfd 100644 --- a/07_dockerfile/7.13_onbuild.md +++ b/07_dockerfile/7.13_onbuild.md @@ -47,6 +47,7 @@ CMD ["npm", "start"] ```docker FROM my-node-base + ## 只需要一行! ## 构建时会自动执行 COPY 和 RUN @@ -74,6 +75,7 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行 #### 1. 自动处理依赖安装 ```docker + ## Python 基础镜像 ONBUILD COPY requirements.txt ./ @@ -83,6 +85,7 @@ ONBUILD RUN pip install -r requirements.txt #### 2. 自动编译代码 ```docker + ## Go 基础镜像 ONBUILD COPY . . @@ -92,6 +95,7 @@ ONBUILD RUN go build -o app main.go #### 3. 处理静态资源 ```docker + ## Nginx 静态网站基础镜像 ONBUILD COPY dist/ /usr/share/nginx/html/ diff --git a/07_dockerfile/7.14_label.md b/07_dockerfile/7.14_label.md index 3be6587..b14bd26 100644 --- a/07_dockerfile/7.14_label.md +++ b/07_dockerfile/7.14_label.md @@ -73,6 +73,7 @@ LABEL org.opencontainers.image.authors="yeasy" \ 旧版本的 Dockerfile 中常看到 `MAINTAINER` 指令: ```docker + ## ❌ 已弃用 MAINTAINER user@example.com @@ -81,9 +82,11 @@ MAINTAINER user@example.com 现在推荐使用 `LABEL`: ```docker + ## ✅ 推荐 LABEL maintainer="user@example.com" + ## 或 LABEL org.opencontainers.image.authors="user@example.com" @@ -132,6 +135,7 @@ $ docker inspect nginx --format '{{json .Config.Labels}}' | jq 可以使用标签过滤镜像: ```bash + ## 列出作者是 yeasy 的所有镜像 $ docker images --filter "label=org.opencontainers.image.authors=yeasy" diff --git a/07_dockerfile/7.15_shell.md b/07_dockerfile/7.15_shell.md index 1dd42c5..529f423 100644 --- a/07_dockerfile/7.15_shell.md +++ b/07_dockerfile/7.15_shell.md @@ -38,6 +38,7 @@ RUN echo {a..z} 默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个指令就视为成功。这可能掩盖构建错误。 ```docker + ## ❌ 这里的 wget 失败了,但构建继续(因为 tar 成功了) RUN wget -O - https://invalid-url | tar xz @@ -46,6 +47,7 @@ RUN wget -O - https://invalid-url | tar xz 使用 `SHELL` 启用 `pipefail`: ```docker + ## ✅ 启用 pipefail SHELL ["/bin/bash", "-o", "pipefail", "-c"] @@ -90,11 +92,13 @@ FROM ubuntu:24.04 RUN echo "Using sh" SHELL ["/bin/bash", "-c"] + ## 使用 bash RUN echo "Using bash" SHELL ["/bin/sh", "-c"] + ## 回到 sh RUN echo "Using sh again" diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md index 3e49768..578e43d 100644 --- a/07_dockerfile/7.1_run.md +++ b/07_dockerfile/7.1_run.md @@ -82,6 +82,7 @@ RUN apt-get update && \ **❌ 隐蔽的错误**: ```docker + ## 如果下载失败,gzip 可能会报错,但如果不影响后续,构建可能继续 RUN wget http://error-url | gzip -d > file @@ -135,6 +136,7 @@ RUN echo $MY_VAR BuildKit 支持在 `RUN` 指令中使用 `--mount` 挂载缓存,加速构建。 ```docker + ## 缓存 apt 包 RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ @@ -143,6 +145,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ ``` ```docker + ## 缓存 Go 模块 RUN --mount=type=cache,target=/go/pkg/mod \ diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md index 2af16ff..5691c29 100644 --- a/07_dockerfile/7.2_copy.md +++ b/07_dockerfile/7.2_copy.md @@ -16,6 +16,7 @@ COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"] #### 复制单个文件 ```docker + ## 复制文件到指定目录 COPY package.json /app/ @@ -28,6 +29,7 @@ COPY config.json /app/settings.json #### 复制多个文件 ```docker + ## 复制多个指定文件 COPY package.json package-lock.json /app/ @@ -41,6 +43,7 @@ COPY src/*.js /app/src/ #### 复制目录 ```docker + ## 复制整个目录的内容(不是目录本身) COPY src/ /app/src/ @@ -97,6 +100,7 @@ COPY src/ ./src/ # 复制到 /app/src/ 如果目标目录不存在,Docker 会自动创建: ```docker + ## /app/config/ 不存在也会自动创建 COPY settings.json /app/config/ @@ -109,6 +113,7 @@ COPY settings.json /app/config/ 使用 `--chown` 选项设置文件的用户和组: ```docker + ## 使用用户名和组名 COPY --chown=node:node package.json /app/ @@ -136,6 +141,7 @@ COPY 会保留源文件的元数据: 这对于脚本文件特别重要: ```docker + ## start.sh 的可执行权限会被保留 COPY start.sh /app/ @@ -153,6 +159,7 @@ COPY start.sh /app/ | 推荐程度 | ✅ **推荐** | ⚠️ 特殊场景使用 | ```docker + ## 推荐:使用 COPY COPY app.tar.gz /app/ @@ -172,6 +179,7 @@ ADD app.tar.gz /app/ #### 从其他构建阶段复制 ```docker + ## 构建阶段 FROM node:20 AS builder @@ -190,6 +198,7 @@ COPY --from=builder /app/dist /usr/share/nginx/html #### 使用 --link 优化缓存 ```docker + ## 使用 --link 后,文件以独立层添加,不依赖前序指令 COPY --link --from=builder /app/dist /usr/share/nginx/html @@ -208,6 +217,7 @@ COPY --link --from=builder /app/dist /usr/share/nginx/html 使用 `.dockerignore` 排除不需要复制的文件: ```text + ## .dockerignore node_modules @@ -231,6 +241,7 @@ Dockerfile #### 1. 利用缓存,先复制依赖文件 ```docker + ## ✅ 好:先复制依赖定义,再安装,最后复制代码 COPY package.json package-lock.json ./ @@ -246,9 +257,11 @@ RUN npm install #### 2. 使用 .dockerignore ```docker + ## 确保 node_modules 不被复制 COPY . . + ## .dockerignore 中应包含 node_modules ... @@ -257,6 +270,7 @@ COPY . . #### 3. 明确复制路径 ```docker + ## ✅ 好:明确的路径 COPY src/ /app/src/ diff --git a/07_dockerfile/7.3_add.md b/07_dockerfile/7.3_add.md index 11dde46..7ec065e 100644 --- a/07_dockerfile/7.3_add.md +++ b/07_dockerfile/7.3_add.md @@ -33,6 +33,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] #### 基本用法:自动解压本地 tar ```docker + ## 自动解压 tar.gz 到目标目录 ADD app.tar.gz /app/ @@ -76,6 +77,7 @@ app.tar.gz 包含: /app/ 目录结果: #### 基本用法 ```docker + ## 从 URL 下载文件 ADD https://example.com/app.zip /app/app.zip @@ -93,6 +95,7 @@ ADD https://example.com/app.zip /app/app.zip #### 推荐替代方案 ```docker + ## ❌ 不推荐:使用 ADD 下载 ADD https://example.com/app.tar.gz /tmp/ @@ -125,6 +128,7 @@ ADD --chown=1000:1000 files/ /app/ #### ✅ 适合使用 ADD ```docker + ## 解压本地 tar 文件 FROM scratch @@ -138,6 +142,7 @@ ADD dist.tar.gz /app/ #### ❌ 不适合使用 ADD ```docker + ## 复制普通文件(用 COPY) ADD package.json /app/ # ❌ @@ -161,6 +166,7 @@ COPY archive.tar.gz /archives/ # ✅ 保持原样 ADD 可能导致构建缓存失效: ```docker + ## 如果 app.tar.gz 内容变化,此层及后续层都需重建 ADD app.tar.gz /app/ @@ -170,6 +176,7 @@ RUN npm install **优化建议**: ```docker + ## 先复制依赖文件 COPY package*.json /app/ @@ -187,6 +194,7 @@ ADD app.tar.gz /app/ #### 1. 默认使用 COPY ```docker + ## ✅ 大多数场景使用 COPY COPY . /app/ @@ -195,6 +203,7 @@ COPY . /app/ #### 2. 仅在需要解压时使用 ADD ```docker + ## ✅ 自动解压场景 ADD app.tar.gz /app/ @@ -203,6 +212,7 @@ ADD app.tar.gz /app/ #### 3. 不要用 ADD 下载文件 ```docker + ## ❌ 避免 ADD https://example.com/file.tar.gz /tmp/ @@ -215,6 +225,7 @@ RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app #### 4. 解压后清理 ```docker + ## 如果需要控制解压过程 COPY app.tar.gz /tmp/ diff --git a/07_dockerfile/7.4_cmd.md b/07_dockerfile/7.4_cmd.md index beba2bc..cf290fa 100644 --- a/07_dockerfile/7.4_cmd.md +++ b/07_dockerfile/7.4_cmd.md @@ -42,6 +42,7 @@ CMD nginx -g "daemon off;" **实际执行**:会被包装为 `sh -c` ```docker + ## 你写的 CMD echo $HOME @@ -67,9 +68,11 @@ CMD ["sh", "-c", "echo $HOME"] #### 信号传递问题示例 ```docker + ## ❌ shell 格式:docker stop 会超时 CMD node server.js + ## 实际是 sh -c "node server.js" ## SIGTERM 发给 sh,不会传递给 node @@ -77,6 +80,7 @@ CMD node server.js ## ✅ exec 格式:docker stop 正常工作 CMD ["node", "server.js"] + ## SIGTERM 直接发给 node ... @@ -89,6 +93,7 @@ CMD ["node", "server.js"] `docker run` 后的命令会覆盖 Dockerfile 中的 CMD: ```bash + ## ubuntu 默认 CMD 是 /bin/bash $ docker run -it ubuntu # 进入 bash @@ -111,6 +116,7 @@ CMD ["/bin/bash"] + cat /etc/os-release #### 错误示例 ```docker + ## ❌ 容器启动后立即退出 CMD service nginx start @@ -135,6 +141,7 @@ CMD service nginx start #### 正确做法 ```docker + ## ✅ 让 nginx 在前台运行 CMD ["nginx", "-g", "daemon off;"] @@ -152,6 +159,7 @@ CMD ["nginx", "-g", "daemon off;"] #### 单独使用 CMD ```docker + ## Dockerfile CMD ["curl", "-s", "http://example.com"] @@ -165,6 +173,7 @@ $ docker run myimage curl -v ... # 完全覆盖 #### 搭配 ENTRYPOINT ```docker + ## Dockerfile ENTRYPOINT ["curl", "-s"] @@ -185,6 +194,7 @@ $ docker run myimage http://other.com # curl -s http://other.com(参数覆盖 #### 1. 优先使用 exec 格式 ```docker + ## ✅ 推荐 CMD ["python", "app.py"] @@ -197,6 +207,7 @@ CMD ["sh", "-c", "echo $PATH && python app.py"] #### 2. 确保应用在前台运行 ```docker + ## ✅ 前台运行 CMD ["nginx", "-g", "daemon off;"] @@ -212,6 +223,7 @@ CMD systemctl start nginx #### 3. 使用双引号 ```docker + ## ✅ 正确:双引号 CMD ["node", "server.js"] @@ -224,6 +236,7 @@ CMD ['node', 'server.js'] #### 4. 配合 ENTRYPOINT 使用 ```docker + ## 用于可配置参数的场景 ENTRYPOINT ["python", "app.py"] @@ -252,6 +265,7 @@ CMD ["echo", "second"] # 只有这个生效 #### Q:如何在 CMD 中使用环境变量? ```docker + ## 方法1:使用 shell 格式 CMD echo "Port is $PORT" @@ -266,6 +280,7 @@ CMD ["sh", "-c", "echo Port is $PORT"] 可能是使用了 shell 格式,信号被 sh 吃掉了: ```docker + ## ❌ 信号无法传递 CMD python app.py diff --git a/07_dockerfile/7.5_entrypoint.md b/07_dockerfile/7.5_entrypoint.md index 1ca07ac..70276a8 100644 --- a/07_dockerfile/7.5_entrypoint.md +++ b/07_dockerfile/7.5_entrypoint.md @@ -16,6 +16,7 @@ | **shell 格式** | `ENTRYPOINT 命令 参数` | ⚠️ 不推荐 | ```docker + ## exec 格式(推荐) ENTRYPOINT ["nginx", "-g", "daemon off;"] @@ -41,6 +42,7 @@ ENTRYPOINT nginx -g "daemon off;" #### 行为对比 ```docker + ## 只用 CMD CMD ["curl", "-s", "http://example.com"] @@ -53,6 +55,7 @@ $ docker run myimage curl -v ... # curl -v ...(完全替换) ``` ```docker + ## 只用 ENTRYPOINT ENTRYPOINT ["curl", "-s"] @@ -64,6 +67,7 @@ $ docker run myimage http://example.com # curl -s http://example.com ✓ ``` ```docker + ## ENTRYPOINT + CMD 组合(推荐) ENTRYPOINT ["curl", "-s"] @@ -98,6 +102,7 @@ $ docker run myip # ✓ 正常工作 $ docker run myip -i # ✗ 错误! exec: "-i": executable file not found + ## -i 替换了整个 CMD,被当作可执行文件 ... @@ -208,19 +213,23 @@ CMD ["--host", "0.0.0.0", "--port", "8080"] ``` ```bash + ## 使用默认参数 $ docker run myapp + ## 执行: python app.py --host 0.0.0.0 --port 8080 ## 覆盖参数 $ docker run myapp --host 0.0.0.0 --port 9000 + ## 执行: python app.py --host 0.0.0.0 --port 9000 ## 完全不同的参数 $ docker run myapp --help + ## 执行: python app.py --help ... @@ -233,6 +242,7 @@ $ docker run myapp --help 使用 `--entrypoint` 参数覆盖: ```bash + ## 正常运行 $ docker run myimage @@ -267,6 +277,7 @@ $ docker run --entrypoint /bin/cat myimage /etc/os-release #### 1. 使用 exec 格式 ```docker + ## ✅ 推荐 ENTRYPOINT ["python", "app.py"] @@ -287,6 +298,7 @@ CMD ["-g", "daemon off;"] ```bash #!/bin/sh + ## 准备工作... ## 使用 exec 替换当前进程 diff --git a/07_dockerfile/7.6_env.md b/07_dockerfile/7.6_env.md index 006e9e7..9621eb0 100644 --- a/07_dockerfile/7.6_env.md +++ b/07_dockerfile/7.6_env.md @@ -3,6 +3,7 @@ ### 7.6.1 基本语法 ```docker + ## 格式一:单个变量 ENV @@ -101,6 +102,7 @@ const dbUrl = process.env.DATABASE_URL; 使用 `-e` 或 `--env` 覆盖 Dockerfile 中定义的环境变量: ```bash + ## 覆盖单个变量 $ docker run -e APP_ENV=development myimage @@ -117,6 +119,7 @@ $ docker run --env-file .env myimage #### .env 文件格式 ```bash + ## .env APP_ENV=development @@ -138,6 +141,7 @@ DATABASE_URL=postgres://localhost/mydb #### 组合使用 ```docker + ## ARG 接收构建时参数 ARG NODE_VERSION=20 @@ -152,6 +156,7 @@ RUN curl -fsSL https://nodejs.org/dist/v${NODE_VERSION}/... ``` ```bash + ## 构建时指定版本 $ docker build --build-arg NODE_VERSION=18 -t myapp . @@ -164,6 +169,7 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp . #### 1. 统一管理版本号 ```docker + ## ✅ 好:版本集中管理 ENV NGINX_VERSION=1.25.0 \ @@ -180,6 +186,7 @@ RUN apt-get install nginx=1.25.0 #### 2. 不要存储敏感信息 ```docker + ## ❌ 错误:密码写入镜像 ENV DB_PASSWORD=secret123 @@ -202,6 +209,7 @@ ENV APP_ENV=production \ #### 4. 使用有意义的变量名 ```docker + ## ✅ 好:清晰的命名 ENV REDIS_HOST=localhost \ @@ -222,6 +230,7 @@ ENV HOST=localhost \ exec 格式不会自动展开环境变量: ```docker + ## ❌ 不会展开 $PORT CMD ["python", "app.py", "--port", "$PORT"] @@ -241,6 +250,7 @@ $ docker exec mycontainer env #### Q:多行 ENV 还是多个 ENV ```docker + ## ✅ 推荐:减少层数 ENV VAR1=value1 \ diff --git a/07_dockerfile/7.7_arg.md b/07_dockerfile/7.7_arg.md index c7ddf8b..ca145f6 100644 --- a/07_dockerfile/7.7_arg.md +++ b/07_dockerfile/7.7_arg.md @@ -36,6 +36,7 @@ ARG <参数名>[=<默认值>] #### 定义和使用 ```docker + ## 定义有默认值的 ARG ARG NODE_VERSION=20 @@ -49,6 +50,7 @@ RUN echo "Using Node.js $NODE_VERSION" #### 构建时覆盖 ```bash + ## 使用默认值 $ docker build -t myapp . @@ -65,6 +67,7 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp . #### FROM 之前的 ARG ```docker + ## FROM 之前的 ARG 只能用于 FROM 指令 ARG REGISTRY=docker.io @@ -96,12 +99,14 @@ RUN echo "Node version: $NODE_VERSION" ARG BASE_VERSION=alpine FROM node:20-${BASE_VERSION} AS builder + ## 需要重新声明 ARG NODE_VERSION=20 RUN echo "Building with Node $NODE_VERSION" FROM node:20-${BASE_VERSION} + ## 每个阶段都需要重新声明 ARG NODE_VERSION=20 @@ -155,6 +160,7 @@ RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc && \ ``` ```bash + ## 构建时传入 token $ docker build --build-arg NPM_TOKEN=xxx . @@ -192,6 +198,7 @@ Docker 提供了一些预定义的 ARG,无需声明即可使用: | `FTP_PROXY` | FTP 代理 | ```bash + ## 构建时使用代理 $ docker build --build-arg HTTP_PROXY=http://proxy:8080 . @@ -204,6 +211,7 @@ $ docker build --build-arg HTTP_PROXY=http://proxy:8080 . #### 1. 为 ARG 提供合理默认值 ```docker + ## ✅ 好:有默认值 ARG NODE_VERSION=20 @@ -216,6 +224,7 @@ ARG NODE_VERSION #### 2. 不要用 ARG 存储敏感信息 ```docker + ## ❌ 错误:密码会被记录在镜像历史中 ARG DB_PASSWORD diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md index 43c18c1..75b8c74 100644 --- a/07_dockerfile/7.8_volume.md +++ b/07_dockerfile/7.8_volume.md @@ -75,6 +75,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷 #### 2. 可被命名卷覆盖 ```bash + ## 使用命名卷替代匿名卷 $ docker run -v mysql_data:/var/lib/mysql mysql:8.0 @@ -83,6 +84,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0 #### 3. 可被 Bind Mount 覆盖 ```bash + ## 使用宿主机目录替代 $ docker run -v /my/data:/var/lib/mysql mysql:8.0 @@ -149,6 +151,7 @@ VOLUME /app/uploads ### 7.8.7 查看 VOLUME 定义 ```bash + ## 查看镜像定义的 VOLUME $ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq @@ -201,9 +204,11 @@ volumes: #### 匿名卷可能导致数据丢失 ```bash + ## 使用 --rm 运行的容器,匿名卷会在容器删除时一起删除 $ docker run --rm mysql:8.0 + ## 容器停止后,数据丢失! ... @@ -222,6 +227,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0 #### 1. 定义必须持久化的路径 ```docker + ## 数据库必须使用卷 FROM postgres:16 @@ -231,6 +237,7 @@ VOLUME /var/lib/postgresql/data #### 2. 不要在 VOLUME 后修改目录 ```docker + ## ❌ 避免 VOLUME /app/data @@ -245,6 +252,7 @@ VOLUME /app/data #### 3. 文档中说明 VOLUME 用途 ```docker + ## 持久化用户上传的文件 VOLUME /app/uploads diff --git a/07_dockerfile/7.9_expose.md b/07_dockerfile/7.9_expose.md index babe9de..40d5c17 100644 --- a/07_dockerfile/7.9_expose.md +++ b/07_dockerfile/7.9_expose.md @@ -13,6 +13,7 @@ EXPOSE <端口> [<端口>/<协议>...] ### 7.9.2 基本用法 ```docker + ## 声明单个端口 EXPOSE 80 @@ -36,12 +37,14 @@ EXPOSE 53/udp 告诉镜像使用者,容器将在哪些端口提供服务: ```docker + ## 使用者一看就知道这是 web 应用 EXPOSE 80 443 ``` ```bash + ## 查看镜像暴露的端口 $ docker inspect nginx --format '{{.Config.ExposedPorts}}' @@ -53,6 +56,7 @@ map[80/tcp:{}] 使用 `docker run -P` 时,Docker 会自动映射 EXPOSE 的端口到宿主机随机端口: ```docker + ## Dockerfile EXPOSE 80 @@ -85,15 +89,18 @@ flowchart TD #### 没有 EXPOSE 也能 -p ```docker + ## 即使没有 EXPOSE,也可以使用 -p FROM nginx + ## 没有 EXPOSE ... ``` ```bash + ## 仍然可以映射端口 $ docker run -p 8080:80 mynginx @@ -106,6 +113,7 @@ $ docker run -p 8080:80 mynginx #### 误解:EXPOSE 会打开端口 ```docker + ## ❌ 错误理解:这不会让容器可从外部访问 EXPOSE 80 @@ -122,6 +130,7 @@ EXPOSE 只是元数据声明。容器是否实际监听该端口,取决于容 #### 正确理解 ```docker + ## Dockerfile FROM nginx @@ -129,6 +138,7 @@ EXPOSE 80 # 1. 声明:这个容器会在 80 端口提供服务 ``` ```bash + ## 运行:需要 -p 才能从外部访问 $ docker run -p 8080:80 nginx # 2. 映射:宿主机 8080 → 容器 80 @@ -141,6 +151,7 @@ $ docker run -p 8080:80 nginx # 2. 映射:宿主机 8080 → 容器 80 #### 1. 总是声明应用使用的端口 ```docker + ## Web 服务 FROM nginx @@ -160,6 +171,7 @@ EXPOSE 6379 #### 2. 使用明确的协议 ```docker + ## 默认是 TCP EXPOSE 80 @@ -176,6 +188,7 @@ EXPOSE 53/tcp 53/udp #### 3. 与应用实际端口保持一致 ```docker + ## ✅ 好:EXPOSE 与应用端口一致 ENV PORT=3000 diff --git a/08_data/8.1_volume.md b/08_data/8.1_volume.md index 85c94a5..7608789 100644 --- a/08_data/8.1_volume.md +++ b/08_data/8.1_volume.md @@ -147,6 +147,7 @@ $ docker run -d \ #### 只读挂载 ```bash + ## --mount 方式 $ docker run -d \ @@ -167,6 +168,7 @@ $ docker run -d \ #### 场景一:数据库持久化 ```bash + ## 创建数据卷 $ docker volume create postgres_data @@ -195,6 +197,7 @@ $ docker run -d \ #### 场景二:多容器共享数据 ```bash + ## 创建共享数据卷 $ docker volume create shared-data @@ -215,6 +218,7 @@ $ docker run --rm \ #### 场景三:配置文件持久化 ```bash + ## 将 nginx 配置存储在数据卷中 $ docker run -d \ @@ -231,6 +235,7 @@ $ docker run -d \ #### 删除数据卷 ```bash + ## 删除指定数据卷 $ docker volume rm my-vol @@ -243,6 +248,7 @@ $ docker rm -v container_name #### 清理未使用的数据卷 ```bash + ## 查看未被任何容器使用的数据卷 $ docker volume ls -f dangling=true @@ -265,6 +271,7 @@ $ docker volume prune -f #### 备份数据卷 ```bash + ## 使用临时容器挂载数据卷,打包备份 $ docker run --rm \ @@ -283,6 +290,7 @@ $ docker run --rm \ #### 恢复数据卷 ```bash + ## 创建新数据卷 $ docker volume create my-vol-restored @@ -299,6 +307,7 @@ $ docker run --rm \ ```bash #!/bin/bash + ## backup-volume.sh VOLUME_NAME=$1 @@ -328,6 +337,7 @@ Docker 有两种主要的数据持久化方式: | **备份** | 需要工具 | 直接访问文件 | ```bash + ## 数据卷 $ docker run -v mydata:/app/data nginx @@ -352,6 +362,7 @@ $ docker inspect container_name --format '{{json .Mounts}}' | jq #### Q:数据卷的数据在哪里? ```bash + ## 查看数据卷详情 $ docker volume inspect my-vol diff --git a/08_data/8.2_bind-mounts.md b/08_data/8.2_bind-mounts.md index 9d129e5..4561042 100644 --- a/08_data/8.2_bind-mounts.md +++ b/08_data/8.2_bind-mounts.md @@ -86,6 +86,7 @@ $ docker run -d \ #### 场景一:开发环境代码同步 ```bash + ## 将本地代码目录挂载到容器 $ docker run -d \ @@ -96,6 +97,7 @@ $ docker run -d \ ## 修改本地文件,容器内立即生效(热更新) $ echo "Hello" > src/index.html + ## 浏览器刷新即可看到变化 ... @@ -104,6 +106,7 @@ $ echo "Hello" > src/index.html #### 场景二:配置文件挂载 ```bash + ## 挂载自定义 nginx 配置 $ docker run -d \ @@ -114,6 +117,7 @@ $ docker run -d \ #### 场景三:日志收集 ```bash + ## 将容器日志输出到宿主机目录 $ docker run -d \ @@ -124,6 +128,7 @@ $ docker run -d \ #### 场景四:共享 SSH 密钥 ```bash + ## 挂载 SSH 密钥(只读) $ docker run --rm -it \ @@ -138,6 +143,7 @@ $ docker run --rm -it \ 防止容器修改宿主机文件: ```bash + ## --mount 语法 $ docker run -d \ @@ -163,6 +169,7 @@ touch: /app/config/new.txt: Read-only file system ### 8.2.6 挂载单个文件 ```bash + ## 挂载 bash 历史记录 $ docker run --rm -it \ @@ -228,6 +235,7 @@ bind source path does not exist: /not/exist 容器内用户可能无权访问挂载的文件: ```bash + ## 方法1:确保宿主机文件权限允许容器用户访问 $ chmod -R 755 /path/to/data @@ -246,6 +254,7 @@ $ docker run -u $(id -u):$(id -g) ... 在 Docker Desktop 上,Bind Mount 性能较差 (需要跨文件系统同步): ```bash + ## 使用 :cached 或 :delegated 提高性能(macOS) $ docker run -v /host/path:/container/path:cached myapp @@ -264,6 +273,7 @@ $ docker run -v /host/path:/container/path:cached myapp #### 1. 开发环境使用 Bind Mount ```bash + ## 代码热更新 $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev @@ -272,6 +282,7 @@ $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev #### 2. 生产环境使用 Volume ```bash + ## 数据持久化 $ docker run -v mysql_data:/var/lib/mysql mysql @@ -286,6 +297,7 @@ $ docker run -v /config/nginx.conf:/etc/nginx/nginx.conf:ro nginx #### 4. 注意路径安全 ```bash + ## ❌ 危险:挂载根目录或敏感目录 $ docker run -v /:/host ... diff --git a/09_network/9.1_dns.md b/09_network/9.1_dns.md index 835a8cf..41d3dfb 100644 --- a/09_network/9.1_dns.md +++ b/09_network/9.1_dns.md @@ -18,6 +18,7 @@ Docker 容器的 DNS 配置有两种情况: 这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过 “名字” 找到彼此,而不需要知道对方的 IP (因为 IP 可能会变)。 ```bash + ## 1. 创建自定义网络 $ docker network create mynet diff --git a/09_network/9.3_custom_network.md b/09_network/9.3_custom_network.md index 33a0f4b..febf45d 100644 --- a/09_network/9.3_custom_network.md +++ b/09_network/9.3_custom_network.md @@ -17,6 +17,7 @@ 使用 `docker network create` 命令可以创建自定义网络: ```bash + ## 创建网络 $ docker network create mynet @@ -31,6 +32,7 @@ $ docker network inspect mynet 启动容器时通过 `--network` 参数指定连接的网络: ```bash + ## 启动容器并连接到自定义网络 $ docker run -d --name web --network mynet nginx @@ -63,6 +65,7 @@ flowchart LR 以下是 Docker 网络管理中常用的命令: ```bash + ## 列出网络 $ docker network ls diff --git a/09_network/9.4_container_linking.md b/09_network/9.4_container_linking.md index 20cfe91..cc8d5bf 100644 --- a/09_network/9.4_container_linking.md +++ b/09_network/9.4_container_linking.md @@ -7,6 +7,7 @@ 同一自定义网络内的容器可以直接通过容器名通信,这是推荐的容器互联方式: ```bash + ## 创建网络 $ docker network create app-net @@ -26,6 +27,7 @@ $ docker run -d --name app --network app-net myapp 一个容器可以同时连接到多个网络,这对于需要跨网络通信的中间件容器特别有用: ```bash + ## 启动容器 $ docker run -d --name multi-net-container --network frontend nginx @@ -44,6 +46,7 @@ $ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks} `--link` 是 Docker 早期用于容器互联的方式,**已经被废弃**,不建议在新项目中使用。请使用自定义网络替代: ```bash + ## 旧方式(不推荐) $ docker run --link db:database myapp diff --git a/09_network/9.5_port_mapping.md b/09_network/9.5_port_mapping.md index 5f7727d..a0a2be4 100644 --- a/09_network/9.5_port_mapping.md +++ b/09_network/9.5_port_mapping.md @@ -30,6 +30,7 @@ Docker 提供了多种方式来指定端口映射。 使用 `-p <宿主机端口>:<容器端口>` 格式: ```bash + ## 将宿主机的 8080 端口映射到容器的 80 端口 $ docker run -d -p 8080:80 nginx @@ -103,6 +104,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web 如果不希望对外暴露 (例如数据库服务),应绑定到 `127.0.0.1`: ```bash + ## 仅允许本机访问 $ docker run -d -p 127.0.0.1:3306:3306 mysql @@ -134,6 +136,7 @@ Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内 当流量到达宿主机端口时,iptables 规则将其目标地址修改为容器 IP 并转发: ```bash + ## 简化的 iptables 逻辑 iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80 diff --git a/09_network/9.6_network_isolation.md b/09_network/9.6_network_isolation.md index 305118d..2eed861 100644 --- a/09_network/9.6_network_isolation.md +++ b/09_network/9.6_network_isolation.md @@ -7,6 +7,7 @@ Docker 网络提供了天然的隔离能力,不同网络之间的容器默认 不同网络之间默认隔离,容器只能与同一网络中的容器直接通信: ```bash + ## 创建两个网络 $ docker network create frontend @@ -42,6 +43,7 @@ ping: db: Name or service not known 如果确实需要某个容器跨网络通信,可以将其同时连接到多个网络: ```bash + ## 创建一个中间件容器,连接到两个网络 $ docker run -d --name api --network frontend myapi diff --git a/09_network/9.7_advanced_networking.md b/09_network/9.7_advanced_networking.md index 96e76b6..c04b67d 100644 --- a/09_network/9.7_advanced_networking.md +++ b/09_network/9.7_advanced_networking.md @@ -35,6 +35,7 @@ veth 对 **Docker Swarm 模式下的 Overlay 网络:** ```bash + # 初始化 Swarm(创建集群) docker swarm init @@ -61,6 +62,7 @@ docker service ps web **单机 Overlay 网络模拟(Linux 容器):** ```bash + # 创建自定义 overlay 网络 docker network create --driver overlay custom-overlay @@ -79,6 +81,7 @@ docker network inspect custom-overlay #### Overlay 网络性能优化 ```bash + # 调整 MTU(Maximum Transmission Unit)避免分片 # VXLAN 开销 50 字节,物理 MTU 1500,建议设置为 1450 docker network create --driver overlay \ @@ -122,6 +125,7 @@ networks: Calico 使用 BGP 协议进行路由,支持网络策略和 eBPF 加速。 ```yaml + # Kubernetes 中安装 Calico apiVersion: v1 kind: ConfigMap @@ -156,6 +160,7 @@ data: Flannel 提供简单的 overlay 网络实现,适合小到中等规模的集群。 ```bash + # 安装 Flannel kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml @@ -202,6 +207,7 @@ EOF Cilium 使用 eBPF 在内核级别实现网络策略和可观测性,性能优异。 ```bash + # 安装 Cilium helm repo add cilium https://helm.cilium.io helm install cilium cilium/cilium \ @@ -222,6 +228,7 @@ helm upgrade cilium cilium/cilium \ Weave 提供简单的跨主机通信,支持加密和多播。 ```bash + # Docker 中使用 Weave 网络 docker run -d --name weave \ --net=host \ @@ -269,6 +276,7 @@ DNS 响应 → 容器缓存 → 应用 **在运行时指定 DNS:** ```bash + # 单个容器 docker run -d \ --dns 8.8.8.8 \ @@ -334,6 +342,7 @@ networks: **使用 Docker 内建 DNS 的服务发现:** ```bash + # 创建自定义网络 docker network create mynet @@ -343,6 +352,7 @@ docker run -d --name db --network mynet postgres:latest # 在其他容器中通过服务名访问 docker run -it --network mynet busybox sh + # ping web # 自动解析到 web 容器 IP # ping db # 自动解析到 db 容器 IP ``` @@ -377,6 +387,7 @@ services: #### DNS 性能优化 ```bash + # 检查 DNS 延迟 time docker exec nslookup www.example.com @@ -494,6 +505,7 @@ spec: ```yaml --- + # 拒绝所有默认 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -506,6 +518,7 @@ spec: - Egress --- + # Frontend 容器策略 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -550,6 +563,7 @@ spec: port: 53 --- + # API 容器策略 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -590,6 +604,7 @@ spec: port: 53 --- + # 数据库容器策略 apiVersion: networking.k8s.io/v1 kind: NetworkPolicy @@ -660,6 +675,7 @@ spec: #### 选择建议 ```bash + # 1. 开发环境:使用 Bridge 网络 docker network create my-app docker compose up # 默认使用 bridge @@ -682,6 +698,7 @@ helm install cilium cilium/cilium --namespace kube-system **常见网络问题诊断:** ```bash + # 1. 容器无法访问外部网络 docker exec ping 8.8.8.8 docker exec cat /etc/resolv.conf diff --git a/10_buildx/10.1_buildkit.md b/10_buildx/10.1_buildkit.md index e619e4d..913a43d 100644 --- a/10_buildx/10.1_buildkit.md +++ b/10_buildx/10.1_buildkit.md @@ -15,6 +15,7 @@ BuildKit 引入了多项新指令,旨在优化构建缓存和安全性。以 要使用最新的 Dockerfile 语法特性,建议在 Dockerfile 开头添加语法指令: ```docker + ## syntax=docker/dockerfile:1 ``` @@ -53,6 +54,7 @@ COPY --from=builder /app/dist /app/dist `BuildKit` 提供了 `RUN --mount=type=cache` 指令,可以实现上边的设想。 ```docker + ## syntax=docker/dockerfile:1 FROM node:alpine as builder @@ -68,6 +70,7 @@ RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=loc COPY src /app/src RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \ + ## --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \ npm run build @@ -107,6 +110,7 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \ 该指令可以将一个镜像 (或上一构建阶段) 的文件挂载到指定位置。 ```docker + ## syntax=docker/dockerfile:1 RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \ @@ -118,6 +122,7 @@ RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoin 该指令可以将一个 `tmpfs` 文件系统挂载到指定位置。 ```docker + ## syntax=docker/dockerfile:1 RUN --mount=type=tmpfs,target=/temp \ @@ -129,6 +134,7 @@ RUN --mount=type=tmpfs,target=/temp \ 该指令可以将一个文件 (例如密钥) 挂载到指定位置。 ```docker + ## syntax=docker/dockerfile:1 RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \ @@ -144,6 +150,7 @@ $ docker build -t test --secret id=aws,src=$HOME/.aws/credentials . 该指令可以挂载 `ssh` 密钥。 ```docker + ## syntax=docker/dockerfile:1 FROM alpine diff --git a/10_buildx/10.2_buildx.md b/10_buildx/10.2_buildx.md index c9faede..118b2bd 100644 --- a/10_buildx/10.2_buildx.md +++ b/10_buildx/10.2_buildx.md @@ -19,6 +19,7 @@ Buildx 使用 [BuildKit 引擎](10.1_buildkit.md)进行构建,支持许多新 `docker buildx bake` 是一个高级构建命令,支持从 HCL、JSON 或 Compose 文件中定义构建目标,实现复杂的流水线构建。 ```bash + ## 从 Compose 文件构建所有服务 $ docker buildx bake diff --git a/10_buildx/10.3_multi-arch-images.md b/10_buildx/10.3_multi-arch-images.md index b3f7ec8..790b78e 100644 --- a/10_buildx/10.3_multi-arch-images.md +++ b/10_buildx/10.3_multi-arch-images.md @@ -60,6 +60,7 @@ $ docker buildx inspect --bootstrap 使用 `docker buildx build` 命令并指定 `--platform` 参数,可以同时构建支持多种架构的镜像。`--push` 参数会将构建好的镜像和 manifest list 推送到 Docker 仓库。 ```dockerfile + ## Dockerfile FROM --platform=$TARGETPLATFORM alpine @@ -110,6 +111,7 @@ ENTRYPOINT ["/dist"] #### 创建 manifest list ```bash + ## 首先,为每个架构构建并推送镜像 $ docker buildx build --platform linux/amd64 -t your-username/my-app:amd64 . --push diff --git a/11_compose/11.5_compose_file.md b/11_compose/11.5_compose_file.md index d27b6ca..a24f42f 100644 --- a/11_compose/11.5_compose_file.md +++ b/11_compose/11.5_compose_file.md @@ -195,6 +195,7 @@ env_file: 环境变量文件中每一行必须符合格式,支持 `#` 开头的注释行。 ```bash + ## common.env: Set development environment PROG_ENV=development @@ -558,6 +559,7 @@ db: 在当前目录新建 `.env` 文件并写入以下内容。 ```bash + ## 支持 # 号注释 MONGO_VERSION=3.6 diff --git a/11_compose/11.6_django.md b/11_compose/11.6_django.md index 54b45e0..a868e05 100644 --- a/11_compose/11.6_django.md +++ b/11_compose/11.6_django.md @@ -274,6 +274,7 @@ web-1 | Starting development server at http://0.0.0.0:8000/ 在另一个终端窗口执行: ```bash + ## 执行数据库迁移 $ docker compose exec web python manage.py migrate @@ -306,6 +307,7 @@ $ docker compose exec db psql -U django_user -d django_db | 网络未创建 | 运行 `docker compose down` 后重新 `up` | ```bash + ## 调试:检查数据库是否正常运行 $ docker compose ps @@ -323,6 +325,7 @@ $ docker compose logs db #### Q3:权限问题 ```bash + ## 如果容器内创建的文件 root 用户所有 $ sudo chown -R $USER:$USER . @@ -341,6 +344,7 @@ $ sudo chown -R $USER:$USER . | **ALLOWED_HOSTS**| `['*']` | 具体域名 |**生产环境 Compose 文件示例**: ```yaml + ## compose.prod.yaml services: diff --git a/11_compose/11.7_rails.md b/11_compose/11.7_rails.md index 27a6d4d..478e483 100644 --- a/11_compose/11.7_rails.md +++ b/11_compose/11.7_rails.md @@ -223,6 +223,7 @@ Created database 'myapp_test' ### 11.7.11 常用开发命令 ```bash + ## 数据库迁移 $ docker compose exec web rails db:migrate diff --git a/11_compose/11.8_wordpress.md b/11_compose/11.8_wordpress.md index 600bda8..c933fe1 100644 --- a/11_compose/11.8_wordpress.md +++ b/11_compose/11.8_wordpress.md @@ -137,6 +137,7 @@ $ docker compose logs -f 不要只依赖 Volume。建议定期备份数据库: ```bash + ## 导出 SQL $ docker exec wordpress_db mysqldump -u wordpress -pwordpress wordpress > backup.sql diff --git a/12_implementation/12.2_namespace.md b/12_implementation/12.2_namespace.md index 6e91548..2c10e69 100644 --- a/12_implementation/12.2_namespace.md +++ b/12_implementation/12.2_namespace.md @@ -53,6 +53,7 @@ PID Namespace 负责进程 ID 的隔离,使得容器内的进程彼此不可 #### PID 隔离效果 ```bash + ## 宿主机上查看进程 $ ps aux | grep nginx @@ -154,6 +155,7 @@ UTS Namespace 主要用于隔离主机名和域名。 #### UTS 隔离效果 ```bash + ## 宿主机 $ hostname @@ -233,6 +235,7 @@ flowchart LR #### 实验 1:UTS Namespace ```bash + ## 创建新的 UTS namespace 并启动 shell $ sudo unshare --uts /bin/bash @@ -253,6 +256,7 @@ my-server #### 实验 2:PID Namespace ```bash + ## 创建新的 PID 和 MNT namespace $ sudo unshare --pid --mount --fork /bin/bash @@ -272,6 +276,7 @@ root 8 0.0 0.0 10072 3200 pts/0 R+ 10:00 0:00 ps aux #### 实验 3:NET Namespace ```bash + ## 创建新的网络 namespace $ sudo unshare --net /bin/bash diff --git a/12_implementation/12.3_cgroups.md b/12_implementation/12.3_cgroups.md index 716192d..8617c3c 100644 --- a/12_implementation/12.3_cgroups.md +++ b/12_implementation/12.3_cgroups.md @@ -62,6 +62,7 @@ Docker 提供了丰富的参数来配置容器的资源限制,主要包括内 #### 内存限制 ```bash + ## 限制容器最多使用 512MB 内存 $ docker run -m 512m myapp @@ -85,6 +86,7 @@ $ docker run --memory-reservation 256m myapp #### CPU 限制 ```bash + ## 限制使用 1.5 个 CPU 核心 $ docker run --cpus=1.5 myapp @@ -108,6 +110,7 @@ $ docker run --cpu-shares=512 myapp #### 磁盘 I/O 限制 ```bash + ## 限制设备写入速度为 10MB/s $ docker run --device-write-bps /dev/sda:10mb myapp @@ -124,6 +127,7 @@ $ docker run --device-write-iops /dev/sda:100 myapp #### 进程数限制 ```bash + ## 限制最多 100 个进程 $ docker run --pids-limit=100 myapp @@ -134,6 +138,7 @@ $ docker run --pids-limit=100 myapp ### 12.3.5 查看容器资源使用 ```bash + ## 实时监控所有容器的资源使用 $ docker stats @@ -157,6 +162,7 @@ $ docker inspect mycontainer --format '{{json .HostConfig}}' | jq #### 内存超限 ```bash + ## 启动限制 100MB 内存的容器 $ docker run -m 100m stress --vm 1 --vm-bytes 200M @@ -175,14 +181,17 @@ abc123 Exited (137) 5 seconds ago hopeful_darwin #### CPU 限制验证 ```bash + ## 不限制 CPU $ docker run --rm stress --cpu 4 + ## 占满所有 CPU ## 限制为 1 个核心 $ docker run --rm --cpus=1 stress --cpu 4 + ## 只能使用约 100% CPU(1 个核心) ... @@ -215,10 +224,12 @@ Docker 19.03+ 默认优先使用 cgroups v2(如果系统支持),提供更 #### 检查系统使用的版本 ```bash + ## 查看 cgroup 版本 $ mount | grep cgroup cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime) + ## 如果显示 cgroup2 表示 v2 ## 或者 @@ -257,6 +268,7 @@ services: #### 1. 始终设置内存限制 ```bash + ## 防止 OOM 影响宿主机 $ docker run -m 1g myapp @@ -271,6 +283,7 @@ $ docker run --cpus=2 --cpu-shares=2048 critical-app #### 3. 监控资源使用 ```bash + ## 配合 Prometheus + cAdvisor 监控 $ docker run -d --name cadvisor \ diff --git a/12_implementation/12.4_ufs.md b/12_implementation/12.4_ufs.md index aa93632..77daa04 100644 --- a/12_implementation/12.4_ufs.md +++ b/12_implementation/12.4_ufs.md @@ -112,6 +112,7 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device #### 查看当前存储驱动与后端 ```bash + ## 查看默认存储驱动 (Storage Driver) $ docker info | grep "Storage Driver" Storage Driver: overlay2 @@ -161,6 +162,7 @@ flowchart TD ### 12.4.6 查看镜像层 ```bash + ## 查看镜像的层信息 $ docker history nginx:alpine @@ -192,6 +194,7 @@ $ docker inspect nginx:alpine --format '{{json .GraphDriver.Data}}' | jq #### 1. 减少镜像层数 ```docker + ## ❌ 每条命令创建一层 RUN apt-get update diff --git a/13_kubernetes_concepts/13.2_concepts.md b/13_kubernetes_concepts/13.2_concepts.md index 11ce542..b7fb4c1 100644 --- a/13_kubernetes_concepts/13.2_concepts.md +++ b/13_kubernetes_concepts/13.2_concepts.md @@ -77,6 +77,7 @@ status: 节点控制器会持续监控节点的健康状态。当节点变为不可达时,控制器会等待一个超时期限,然后将该节点上的 Pod 标记为失败,并触发重新调度。可以使用 `kubectl` 来管理节点,例如标记节点为不可调度或排空节点上的工作负载: ```bash + ## 标记节点为不可调度 $ kubectl cordon worker-1 @@ -224,6 +225,7 @@ spec: 标签 (Label) 是附加到 Kubernetes 对象上的键值对,用于组织和选择对象子集。标签是 Kubernetes 中实现松耦合的关键机制。 ```bash + ## 为 Pod 添加标签 $ kubectl label pod my-pod env=production @@ -250,6 +252,7 @@ Kubernetes Dashboard 是一个基于 Web 的用户界面,用于部署容器化 `kubectl` 是 Kubernetes 的命令行工具,用于与集群进行交互。常用命令如下: ```bash + ## 查看集群中的资源 $ kubectl get pods,deployments,services,nodes diff --git a/14_kubernetes_setup/14.1_kubeadm.md b/14_kubernetes_setup/14.1_kubeadm.md index 5af0c0a..96f0472 100644 --- a/14_kubernetes_setup/14.1_kubeadm.md +++ b/14_kubernetes_setup/14.1_kubeadm.md @@ -9,6 +9,7 @@ 参考[安装 Docker](../03_install/README.md) 一节添加 apt/yum 源,之后执行如下命令。 ```bash + ## debian 系 $ sudo apt install containerd.io @@ -37,6 +38,7 @@ Delegate=yes KillMode=process Restart=always RestartSec=5 + ## Having non-zero Limit*s causes performance problems due to accounting overhead ## in the kernel. We recommend using cgroups to do container-local accounting. @@ -44,6 +46,7 @@ RestartSec=5 LimitNPROC=infinity LimitCORE=infinity LimitNOFILE=infinity + ## Comment TasksMax if your systemd version does not supports it. ## Only systemd 226 and above support this version. @@ -59,15 +62,18 @@ WantedBy=multi-user.target ```toml version = 2 + ## persistent data location root = "/var/lib/cri-containerd" + ## runtime state information state = "/run/cri-containerd" plugin_dir = "" disabled_plugins = [] required_plugins = [] + ## set containerd's OOM score oom_score = 0 @@ -315,6 +321,7 @@ $ sysctl --system `/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容 ```bash + ## 启用 ipvs 相关内核模块 [Service] diff --git a/14_kubernetes_setup/14.2_kubeadm-docker.md b/14_kubernetes_setup/14.2_kubeadm-docker.md index b5fcbc2..26bfc9e 100644 --- a/14_kubernetes_setup/14.2_kubeadm-docker.md +++ b/14_kubernetes_setup/14.2_kubeadm-docker.md @@ -21,6 +21,7 @@ #### Ubuntu/Debian ```bash + ## 安装 cri-dockerd $ cd /tmp @@ -48,6 +49,7 @@ $ sudo /usr/local/bin/cri-dockerd --version #### CentOS/Fedora ```bash + ## 安装 cri-dockerd $ cd /tmp @@ -155,6 +157,7 @@ $ sysctl --system `/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容 ```bash + ## 启用 ipvs 相关内核模块 [Service] diff --git a/14_kubernetes_setup/14.4_kind.md b/14_kubernetes_setup/14.4_kind.md index c196083..f2e8383 100644 --- a/14_kubernetes_setup/14.4_kind.md +++ b/14_kubernetes_setup/14.4_kind.md @@ -26,6 +26,7 @@ brew install kind 可以下载二进制文件: ```bash + ## Linux AMD64 curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64 diff --git a/14_kubernetes_setup/14.5_k3s.md b/14_kubernetes_setup/14.5_k3s.md index 9958bb1..8a36e70 100644 --- a/14_kubernetes_setup/14.5_k3s.md +++ b/14_kubernetes_setup/14.5_k3s.md @@ -40,6 +40,7 @@ k3s-master Ready control-plane,master 1m v1.35.1+k3s1 K3s 内置了 `kubectl` 命令 (通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。 ```bash + ## 读取 K3s 的配置文件 export KUBECONFIG=/etc/rancher/k3s/k3s.yaml diff --git a/14_kubernetes_setup/14.6_systemd.md b/14_kubernetes_setup/14.6_systemd.md index 413a5b1..2e0c61a 100644 --- a/14_kubernetes_setup/14.6_systemd.md +++ b/14_kubernetes_setup/14.6_systemd.md @@ -34,6 +34,7 @@ #### 常用命令 ```bash + # 启动服务 sudo systemctl start kubelet diff --git a/16_cloud/16.2_tencentCloud.md b/16_cloud/16.2_tencentCloud.md index fb0b93d..3575325 100644 --- a/16_cloud/16.2_tencentCloud.md +++ b/16_cloud/16.2_tencentCloud.md @@ -31,6 +31,7 @@ - 完成创建后获得集群 kubeconfig 文件 ```bash + # 下载 kubeconfig 文件后,配置本地环境 export KUBECONFIG=/path/to/kubeconfig.yaml kubectl cluster-info @@ -75,6 +76,7 @@ kubectl get svc 通过腾讯云容器镜像服务 (TCR) 存储和管理私有镜像: ```bash + # 登录腾讯云镜像仓库 docker login ccr.ccs.tencentyun.com -u @@ -94,6 +96,7 @@ docker push ccr.ccs.tencentyun.com/namespace/my-app:latest 编辑 `/etc/docker/daemon.json` 文件(如果不存在则创建): ```bash + # 创建或编辑配置文件 sudo mkdir -p /etc/docker sudo nano /etc/docker/daemon.json @@ -120,6 +123,7 @@ sudo systemctl restart docker 验证配置: ```bash + # 查看镜像源是否生效 docker info | grep -A 5 "Registry Mirrors" ``` @@ -153,6 +157,7 @@ docker info | grep -A 5 "Registry Mirrors" #### 完整推送/拉取示例 ```bash + # 登录到腾讯云 TCR(使用 API 密钥) docker login ccr.ccs.tencentyun.com \ --username <腾讯云账号ID> \ diff --git a/16_cloud/16.3_alicloud.md b/16_cloud/16.3_alicloud.md index 8b8be66..e926572 100644 --- a/16_cloud/16.3_alicloud.md +++ b/16_cloud/16.3_alicloud.md @@ -33,6 +33,7 @@ - 完成创建,下载 kubeconfig 文件 ```bash + # 配置本地 kubectl export KUBECONFIG=/path/to/kubeconfig.yaml kubectl get nodes @@ -151,6 +152,7 @@ docker info | grep -A 5 "Registry Mirrors" #### 测试加速效果 ```bash + # 从加速器拉取镜像(速度应该明显提升) docker pull nginx:latest time docker pull alpine:latest @@ -170,6 +172,7 @@ time docker pull alpine:latest #### 完整推送/拉取示例 ```bash + # 登录阿里云镜像仓库(使用 Docker 登录) # 使用阿里云账户 ID 和 RAM 访问密钥或密码 docker login registry.cn-hangzhou.aliyuncs.com \ @@ -250,6 +253,7 @@ spec: 在 ACK 集群中创建 Secret,用于拉取私有镜像: ```bash + # 创建镜像拉取 Secret kubectl create secret docker-registry acr-secret \ --docker-server=registry.cn-hangzhou.aliyuncs.com \ diff --git a/17_ecosystem/17.2_coreos_install.md b/17_ecosystem/17.2_coreos_install.md index 6051717..e361cf1 100644 --- a/17_ecosystem/17.2_coreos_install.md +++ b/17_ecosystem/17.2_coreos_install.md @@ -9,6 +9,7 @@ FCC 是 Fedora CoreOS Configuration (Fedora CoreOS 配置) 的简称。 ```yaml + ## example.fcc variant: fcos diff --git a/17_ecosystem/17.3_podman.md b/17_ecosystem/17.3_podman.md index 8c5aa41..bc2c815 100644 --- a/17_ecosystem/17.3_podman.md +++ b/17_ecosystem/17.3_podman.md @@ -40,6 +40,7 @@ $ podman machine start #### 运行容器 ```bash + ## $ docker run -d -p 80:80 nginx:alpine $ podman run -d -p 80:80 nginx:alpine @@ -62,6 +63,7 @@ $ podman build -t myimage . 与 Docker 不同,Podman 支持“Pod”的概念 (类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。 ```bash + ## 创建一个 Pod $ podman pod create --name mypod -p 8080:80 @@ -84,6 +86,7 @@ $ alias docker=podman Podman 可以生成 systemd 单元文件,让容器像普通系统服务一样管理。 ```bash + ## 创建容器 $ podman run -d --name myweb -p 8080:80 nginx diff --git a/17_ecosystem/17.4_buildah.md b/17_ecosystem/17.4_buildah.md index 2c798c6..93f047d 100644 --- a/17_ecosystem/17.4_buildah.md +++ b/17_ecosystem/17.4_buildah.md @@ -49,6 +49,7 @@ $ buildah bud -t my-app:latest . 除了使用 Dockerfile,Buildah 最强大的功能来自于它的交互式和脚本化构建机制。我们可以从一个极简的镜像(或基础镜像)开始构建: ```bash + # 获取一个基础镜像 $ container=$(buildah from alpine:latest) @@ -78,6 +79,7 @@ $ buildah rm $container 通过 `buildah images` 可以查看当前环境中的镜像。推送镜像到外部 Registry 也十分安全方便: ```bash + # 查看本地构建的镜像 $ buildah images diff --git a/17_ecosystem/17.6_containerd.md b/17_ecosystem/17.6_containerd.md index d365516..c5f406a 100644 --- a/17_ecosystem/17.6_containerd.md +++ b/17_ecosystem/17.6_containerd.md @@ -56,6 +56,7 @@ Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行 安装完 containerd 和 nerdctl 后,你可以体验到几乎与 Docker 完全一致的命令行: ```bash + # 启动一个 nginx 容器 $ nerdctl run -d -p 8080:80 --name my-nginx nginx:alpine diff --git a/18_security/18.1_kernel_ns.md b/18_security/18.1_kernel_ns.md index e6e6ccd..4efd910 100644 --- a/18_security/18.1_kernel_ns.md +++ b/18_security/18.1_kernel_ns.md @@ -67,6 +67,7 @@ $ sudo systemctl restart docker 我们可以运行一个简单的容器并执行 `sleep` 命令,同时在宿主机上观察进程的所有者: ```bash + ## 在容器内以 root 身份运行 $ docker run -d --name userns_test alpine sleep 3600 diff --git a/18_security/18.5_other_feature.md b/18_security/18.5_other_feature.md index fe78cd6..03d7b02 100644 --- a/18_security/18.5_other_feature.md +++ b/18_security/18.5_other_feature.md @@ -64,6 +64,7 @@ $ docker run --rm -it \ [Trivy](https://github.com/aquasecurity/trivy) 是由 Aqua Security 发行的一款针对容器技术的快速镜像漏洞扫描利器。在分发应用前通过它的扫描可以规避绝大多数风险。 ```bash + ## 如果使用本地命令行扫描容器镜像 $ trivy image alpine:3.10 diff --git a/18_security/18.6_image_security.md b/18_security/18.6_image_security.md index 7f1afb7..2e58d5b 100644 --- a/18_security/18.6_image_security.md +++ b/18_security/18.6_image_security.md @@ -18,6 +18,7 @@ Trivy 是由 Aqua Security 开发的开源漏洞扫描器,以其轻量级、 **安装与基本使用:** ```bash + # 安装 Trivy curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin @@ -37,6 +38,7 @@ trivy repo https://github.com/aquasecurity/trivy **在 CI/CD 中集成:** ```bash + # 设置严重程度过滤 trivy image --severity HIGH,CRITICAL \ --exit-code 1 \ @@ -56,6 +58,7 @@ Grype 由 Anchore 开发,支持更广泛的软件包管理器和语言。 **安装与使用:** ```bash + # 安装 Grype curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin @@ -83,6 +86,7 @@ Snyk 提供了商业级的安全扫描服务,特别适合企业环境。 **基本使用:** ```bash + # 安装 Snyk CLI npm install -g snyk @@ -124,6 +128,7 @@ curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh - **生成 SBOM:** ```bash + # 从镜像生成 SBOM(多种格式) syft docker:nginx:latest -o json > sbom.json syft docker:nginx:latest -o spdx > sbom.spdx @@ -188,6 +193,7 @@ syft oci-archive:image.tar -o json > sbom.json 当新的 CVE 被发现时,可快速查询受影响的应用: ```bash + # 使用 Grype 针对 SBOM 进行漏洞扫描 grype sbom:sbom.json --add-cpes-if-none ``` @@ -220,12 +226,14 @@ sudo mv cosign-linux-amd64 /usr/local/bin/cosign ```bash cosign generate-key-pair + # 生成 cosign.key 和 cosign.pub ``` **签名镜像:** ```bash + # 使用私钥签名(推送到仓库前) cosign sign --key cosign.key myregistry.com/myapp:v1.0.0 @@ -235,6 +243,7 @@ cosign sign --key cosign.key myregistry.com/myapp:v1.0.0 **验证签名:** ```bash + # 使用公钥验证 cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0 @@ -253,6 +262,7 @@ cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0 **Keyless 签名(推荐用于 CI/CD):** ```bash + # 在 GitHub Actions 等 CI 中无需存储密钥 cosign sign --yes myregistry.com/myapp:v1.0.0 @@ -269,11 +279,13 @@ Docker Content Trust 使用 Notary 实现镜像签名,是 Docker 官方的签 **启用 DCT:** ```bash + # 在环境中启用 DCT export DOCKER_CONTENT_TRUST=1 # 此后所有 docker push/pull 都需要签名 docker push myregistry.com/myapp:v1.0.0 + # 如果镜像未签名,操作会被拒绝 # 禁用 DCT(仅用于特定操作) @@ -283,6 +295,7 @@ docker push --disable-content-trust myregistry.com/myapp:v1.0.0 **签名密钥管理:** ```bash + # 首次推送时会提示创建 Delegation Key # 密钥存储在 ~/.docker/trust/private/root_keys/ 和 ~/.docker/trust/private/tuf_keys/ @@ -295,6 +308,7 @@ docker inspect --format='{{.RepoDigests}}' myregistry.com/myapp:v1.0.0 #### 1. 基础镜像安全 ```dockerfile + # ❌ 不推荐:使用 latest 标签 FROM ubuntu:latest RUN apt-get update && apt-get install -y curl @@ -327,6 +341,7 @@ COPY --from=builder /app/app /app #### 3. 运行时镜像扫描策略 ```bash + # 镜像构建完成后立即扫描 trivy image --severity HIGH,CRITICAL \ --exit-code 1 \ @@ -342,6 +357,7 @@ trivy image --scanners vuln,misconfig registry:5000/myapp:latest **Harbor(私有镜像仓库)的安全扫描:** ```yaml + # harbor.yml 配置示例 trivy: enabled: true diff --git a/19_observability/19.3_performance_optimization.md b/19_observability/19.3_performance_optimization.md index 51cf8c8..e8657a2 100644 --- a/19_observability/19.3_performance_optimization.md +++ b/19_observability/19.3_performance_optimization.md @@ -48,6 +48,7 @@ **基本使用:** ```bash + # 实时监控所有运行中的容器 docker stats @@ -89,6 +90,7 @@ done **性能指标解读:** ```bash + # CPU % 超过 80%:需要增加 CPU 限制或优化应用 # MEM % 接近 100%:容器即将 OOM,需要增加内存或排查内存泄漏 # 如果 NET I/O 中 dropped 为非零:网络拥塞或丢包 @@ -132,6 +134,7 @@ networks: **从 cAdvisor 提取指标:** ```bash + # 获取所有容器的 JSON 格式性能数据 curl http://localhost:8080/api/v1.3/machine | jq . @@ -145,6 +148,7 @@ curl http://localhost:8080/api/v1.3/docker/abc123/ | jq '.stats[-1]' **与 Prometheus 集成:** ```yaml + # prometheus.yml 配置 global: scrape_interval: 15s @@ -259,6 +263,7 @@ scrape_configs: **常用的 Prometheus 查询(PromQL):** ```text + # 容器 CPU 使用百分比 rate(container_cpu_usage_seconds_total[5m]) * 100 @@ -289,6 +294,7 @@ count(container_memory_usage_bytes) by (image) #### OOM 问题诊断 ```bash + # 检查容器是否因 OOM 被杀死 docker inspect | grep OOMKilled @@ -310,6 +316,7 @@ journalctl -u docker -n 100 | grep -i "oom" **Python 应用内存泄漏检测:** ```python + # Dockerfile FROM python:3.11-slim WORKDIR /app @@ -321,6 +328,7 @@ CMD ["python", "-m", "memory_profiler", "app.py"] ``` ```python + # app.py - 内存泄漏示例 from memory_profiler import profile import tracemalloc @@ -347,6 +355,7 @@ print(f"Peak: {peak / 1024 / 1024:.2f} MB") **Java 应用内存分析:** ```bash + # 在容器中启用 JVM 远程调试 docker run -e JAVA_OPTS="-Xmx512m -Xms256m -XX:+UseG1GC" \ -p 5005:5005 \ @@ -363,6 +372,7 @@ jstat -gc 1000 # 每秒采样一次 #### 内存限制最佳实践 ```bash + # 为容器设置内存限制 docker run -m 512m --memory-swap 1g myapp:latest @@ -386,6 +396,7 @@ services: **内存超额提交(Memory Overcommit):** ```bash + # 在 Docker Compose 中区分限制和预留 # limits:绝不能超过的最大值 # reservations:Compose 排期时的参考值 @@ -407,6 +418,7 @@ services: **使用 dive 分析镜像层:** ```bash + # 安装 dive wget https://github.com/wagoodman/dive/releases/download/v0.11.0/dive_0.11.0_linux_amd64.deb sudo apt install ./dive_0.11.0_linux_amd64.deb @@ -420,6 +432,7 @@ dive myapp:latest **使用 Dockerfile 分析工具:** ```bash + # 安装 hadolint curl https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 -L -o hadolint chmod +x hadolint @@ -433,6 +446,7 @@ chmod +x hadolint **Go 应用的最小化镜像构建:** ```dockerfile + # Stage 1: 构建阶段 FROM golang:1.20-alpine AS builder @@ -469,6 +483,7 @@ ENTRYPOINT ["/app"] **Node.js 应用的多阶段构建:** ```dockerfile + # Stage 1: 依赖安装 FROM node:18-alpine AS dependencies @@ -494,6 +509,7 @@ WORKDIR /app # 从依赖阶段复制 node_modules COPY --from=dependencies /app/node_modules ./node_modules + # 从构建阶段复制构建产物 COPY --from=builder /app/dist ./dist COPY --from=builder /app/package*.json ./ @@ -514,6 +530,7 @@ CMD ["node", "dist/index.js"] **Python 应用的多阶段构建:** ```dockerfile + # Stage 1: 构建阶段 FROM python:3.11-slim AS builder @@ -550,6 +567,7 @@ CMD ["python", "app.py"] #### 镜像体积优化检查清单 ```bash + # 检查清单 □ 使用精简基础镜像(Alpine、Distroless) □ 清理包管理器缓存(apt-get clean、rm -rf /var/cache/*) @@ -585,6 +603,7 @@ RUN apt-get update && \ 症状:容器进程被无故杀死,exit code 137 解决方案: ```bash + # 增加内存限制 docker update -m 1g @@ -603,6 +622,7 @@ docker run -m 512m --memory-swap 1g myapp:latest 症状:应用性能突然下降,但 CPU 使用率不高 诊断: ```bash + # 查看 CPU 限流统计 docker exec cat /sys/fs/cgroup/cpu/cpu.stat @@ -615,6 +635,7 @@ docker update --cpus 2 诊断: ```bash + # 进入容器检查网络状态 docker exec ip -s link show diff --git a/21_case_devops/21.1_devops_workflow.md b/21_case_devops/21.1_devops_workflow.md index e167044..843d115 100644 --- a/21_case_devops/21.1_devops_workflow.md +++ b/21_case_devops/21.1_devops_workflow.md @@ -21,6 +21,7 @@ 使用 Docker 多阶段构建可以有效减小镜像体积。 ```dockerfile + ## Build stage FROM golang:1.23 AS builder diff --git a/21_case_devops/21.7_practical_examples.md b/21_case_devops/21.7_practical_examples.md index a302c39..376408b 100644 --- a/21_case_devops/21.7_practical_examples.md +++ b/21_case_devops/21.7_practical_examples.md @@ -48,6 +48,7 @@ func main() { **多阶段 Dockerfile:** ```dockerfile + # Stage 1: 构建阶段 FROM golang:1.20-alpine AS builder @@ -91,6 +92,7 @@ ENTRYPOINT ["/app"] **构建和测试:** ```bash + # 构建镜像 docker build -t go-app:latest . @@ -105,6 +107,7 @@ curl http://localhost:8080/health | jq . # 进入容器验证 docker exec go-demo ls -la / + # 只包含 /app 和系统必要文件 # 镜像大小通常 < 10MB(相比 golang:1.20-alpine 的 ~1GB) @@ -246,6 +249,7 @@ serde_json = "1.0" **多阶段构建 Dockerfile:** ```dockerfile + # Stage 1: 编译 FROM rust:1.75-alpine AS builder @@ -490,6 +494,7 @@ HEALTHCHECK --interval=30s --timeout=10s --retries=3 \ ```ini [mysqld] + # 性能优化 max_connections = 200 default_storage_engine = InnoDB @@ -530,6 +535,7 @@ HEALTHCHECK --interval=5s --timeout=3s --retries=5 \ **redis.conf 配置:** ```text + # 绑定地址 bind 0.0.0.0 @@ -841,6 +847,7 @@ WORKDIR /workspace **Docker Compose 用于 Dev Containers:** ```yaml + # .devcontainer/docker-compose.yml version: '3.9' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5462a5..87c1f9d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,6 +13,7 @@ $ cd docker_practice 修改代码后提交,并推送到自己的仓库,注意修改提交消息为对应 Issue 号和描述。 ```bash + # Update the content $ git commit -a -s diff --git a/appendix/best_practices.md b/appendix/best_practices.md index 9ef08e6..11eddc9 100644 --- a/appendix/best_practices.md +++ b/appendix/best_practices.md @@ -73,6 +73,7 @@ RUN apt-get update && apt-get install -y \ > 注意:如果你的字符串中包含空格,必须将字符串放入引号中或者对空格使用转义。如果字符串内容本身就包含引号,必须对引号使用转义。 ```docker + ## Set one or more individual labels LABEL com.example.version="0.0.1-beta" @@ -87,6 +88,7 @@ LABEL com.example.version.is-production="" 一个镜像可以包含多个标签,但建议将多个标签放入到一个 `LABEL` 指令中。 ```docker + ## Set multiple labels at once, using line-continuation characters to break long lines LABEL vendor=ACME\ Incorporated \ diff --git a/appendix/learning_roadmap.md b/appendix/learning_roadmap.md index 5dff672..ffbdf17 100644 --- a/appendix/learning_roadmap.md +++ b/appendix/learning_roadmap.md @@ -48,6 +48,7 @@ Docker 安装配置 **验证学习成果:** ```bash + # 完成以下任务说明基础入门完成 1. 运行官方 nginx 镜像,访问 http://localhost 2. 使用 docker exec 进入容器修改首页 @@ -468,6 +469,7 @@ Kubernetes 进阶 (Week 24-36) 准备建议: ```bash + # 1. 学习本书第 1-11 章(基础到中级) # 2. 完成 20+ 个实战项目 # 3. 参考官方学习指南 @@ -781,6 +783,7 @@ A(要点): ### 学习进度跟踪模板 ```markdown + # Docker 学习进度跟踪 ## 第一阶段:基础入门(目标:2 周) @@ -831,6 +834,7 @@ A(要点): **常用命令速查:** ```bash + # 镜像管理 docker build -t image:tag . # 构建镜像 docker images # 列出镜像 diff --git a/appendix/repo/nodejs.md b/appendix/repo/nodejs.md index 4b325ef..0b43a3e 100644 --- a/appendix/repo/nodejs.md +++ b/appendix/repo/nodejs.md @@ -12,6 +12,7 @@ ```docker FROM node:20 + ## replace this with your application's default port EXPOSE 8888