fix(examples): 修正若干无法按原样执行的命令

* appendix/repo/nodejs.md:`docker build -t my-nodejs-app` 缺上下文参数,实际会
  报 "docker buildx build" requires exactly 1 argument;补 `.`。同文件 docker run
  示例里 `# -v "$ ":/usr/src/myapp \` 这一行的注释把自己的续行反斜杠也注掉了,加上
  紧跟的空行,命令在 `--name my-running-script` 处就结束、没有镜像名,后面几行变成
  独立的无效命令。该行内容与下一行的 --mount 重复,且 `"$ "` 已是残缺文本,删去。

* 06_repository/6.4:`openssl s_client -connect YourDomainName OR HostIP:443` 里的
  占位符带空格,shell 会切成三个参数,-connect 只收到 YourDomainName,openssl 直接
  报错;`docker login YourDomainName OR HostIP` 同理。改为一个变量。

* 08_data/8.2:`docker run -v $(pwd):/app -p 3000:3000 node npm run dev` 跑不起来
  ——官方 node 镜像没有设置 WORKDIR(docker-node 的 Dockerfile 里只有 ENTRYPOINT
  与 CMD),工作目录是 /,npm 找不到 /package.json。补 -w /app,顺手引号包住 $(pwd)
  并给出确定的标签(本书 4.1、7.10 都要求避免 latest)。

* 12_implementation/12.6:整段用的是 iproute2(ip link add / ip netns exec),中间
  却夹了一句 `brctl addif`。bridge-utils 在当前 Debian/Ubuntu/RHEL 默认不再安装,
  照抄会在这一行断掉;改成等价的 `ip link set A master docker0`。

* 14.1/14.2 的 `sysctl --system`、14.1 join 节点的 `systemctl enable/start
  containerd`、6.4 的 `systemctl restart docker` 都缺 sudo,而紧邻的行(sudo tee、
  14.1 第 47 行的 sudo systemctl restart containerd)都带。补齐。

* 15_etcd/demo/cluster/docker-compose.yml 仍留着顶层 `version: "3.6"`,Compose 会
  警告 obsolete;11.1 明写「新文件建议直接省略该字段」,15.3 正文内联的同一份文件
  也早已省略,只有磁盘上的 demo 落下了。删除后 YAML 仍可正常解析。

* 11.4:「对于 web 项目中的一个 db 容器,可能是 web_db」是 Compose V1 的下划线拼接,
  V2 起统一改用连字符,只有 --compatibility 才回到下划线。

* 附录四 CMD 一节四处写成 `CMD ['executable', 'param1']` 单引号,还说「我们建议任何
  服务镜像都使用这种形式」。exec 形式是 JSON,单引号解析不出来会退回 shell 形式,本书
  7.4 就把 `CMD ['node', 'server.js']` 明确标为「 错误:单引号(JSON 不支持)」。
  一并把 `CMD ['PHP', '-a']` 的二进制名改回小写 php。
This commit is contained in:
yeasy
2026-08-07 23:26:36 -07:00
parent 08e981018e
commit 141fdc80bc
9 changed files with 22 additions and 20 deletions
+6 -3
View File
@@ -119,8 +119,11 @@ server {
使用 SSL 加密以后程序需要访问就不能采用修改配置的方式了具体方法如下
```bash
$ openssl s_client -showcerts -connect YourDomainName OR HostIP:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >ca.crt
## REGISTRY_HOST 填你的域名或主机 IP,二者选其一
$ REGISTRY_HOST=your-domain-or-host-ip
$ openssl s_client -showcerts -connect "$REGISTRY_HOST":443 </dev/null 2>/dev/null|openssl x509 -outform PEM >ca.crt
$ cat ca.crt | sudo tee -a /etc/ssl/certs/ca-certificates.crt
$ systemctl restart docker
$ sudo systemctl restart docker
```
使用 `docker login YourDomainName OR HostIP` 进行测试用户名密码填写上面 Nexus 中设置的
使用 `docker login $REGISTRY_HOST` 进行测试用户名密码填写上面 Nexus 中设置的
+1 -1
View File
@@ -261,7 +261,7 @@ $ docker run -v /host/path:/container/path:cached myapp
```bash
## 代码热更新
$ docker run -v $(pwd):/app -p 3000:3000 node npm run dev
$ docker run -v "$(pwd)":/app -w /app -p 3000:3000 node:22 npm run dev
```
#### 2. 生产环境使用 Volume
+1 -1
View File
@@ -58,7 +58,7 @@ docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
构建 (重新构建) 项目中的服务容器
服务容器一旦构建后将会带上一个标记名例如对于 web 项目中的一个 db 容器可能是 web_db
服务容器一旦构建后将会带上一个标记名例如对于 web 项目中的一个 db 服务构建出的镜像是 `web-db`Compose V1 用下划线拼接为 `web_db`V2 起统一改为连字符只有加 `--compatibility` 才会回到下划线
可以随时在项目目录下运行 `docker compose build` 来重新构建服务
+1 -1
View File
@@ -56,7 +56,7 @@ inet 172.17.0.1/16 scope global docker0
创建一对 veth pair 接口 A B绑定 A 到网桥 `docker0`并启用它
```bash
$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A master docker0
$ sudo ip link set A up
```
B 放到容器的网络命名空间命名为 eth0启动它并配置一个可用 IP (桥接网段) 和默认网关
+3 -3
View File
@@ -131,7 +131,7 @@ EOF
# 应用配置
$ sysctl --system
$ sudo sysctl --system
```
### 14.1.5 配置 kubelet
@@ -213,9 +213,9 @@ kubeadm join <CONTROL_PLANE_HOST>:6443 --token <TOKEN> \
**另一主机** 重复 **部署** 小节以前的步骤安装配置好 kubelet根据提示加入到集群
```bash
$ systemctl enable containerd
$ sudo systemctl enable containerd
$ systemctl start containerd
$ sudo systemctl start containerd
$ kubeadm join <CONTROL_PLANE_HOST>:6443 \
--token <TOKEN> \
+1 -1
View File
@@ -162,7 +162,7 @@ EOF
# 应用配置
$ sysctl --system
$ sudo sysctl --system
```
### 14.2.5 配置 kubelet
-1
View File
@@ -1,4 +1,3 @@
version: "3.6"
services:
node1:
+8 -6
View File
@@ -167,9 +167,11 @@ RUN apt-get update && apt-get install -y \
#### CMD
`CMD` 指令用于执行目标镜像中包含的软件可以包含参数`CMD` 大多数情况下都应该以 `CMD ['executable', 'param1', 'param2'...]` 的形式使用因此如果创建镜像的目的是为了部署某个服务 (比如 `Apache`)你可能会执行类似于 `CMD ['apache2', '-DFOREGROUND']` 形式的命令我们建议任何服务镜像都使用这种形式的命令
`CMD` 指令用于执行目标镜像中包含的软件可以包含参数`CMD` 大多数情况下都应该以 `CMD ["executable", "param1", "param2"...]` 的形式使用因此如果创建镜像的目的是为了部署某个服务 (比如 `Apache`)你可能会执行类似于 `CMD ["apache2", "-DFOREGROUND"]` 形式的命令我们建议任何服务镜像都使用这种形式的命令
多数情况下`CMD` 都需要一个交互式的 `shell` (bashPythonperl )例如 `CMD ['perl', '-de0']`或者 `CMD ['PHP', '-a']`使用这种形式意味着当你执行类似 `docker run -it python` 你会进入一个准备好的 `shell` `CMD` 应该在极少的情况下才能以 `CMD ['param', 'param']` 形式 `ENTRYPOINT` 协同使用除非你和你的镜像使用者都对 `ENTRYPOINT` 的工作方式十分熟悉
> 注意exec 形式是 JSON 数组**必须用双引号**写成 `CMD ['apache2', '-DFOREGROUND']` 并不会报错 Docker 解析不出 JSON会退回 shell 形式执行整串字符导致启动失败参见 [7.4 CMD](../07_dockerfile/7.4_cmd.md)
多数情况下`CMD` 都需要一个交互式的 `shell` (bashPythonperl )例如 `CMD ["perl", "-de0"]`或者 `CMD ["php", "-a"]`使用这种形式意味着当你执行类似 `docker run -it python` 你会进入一个准备好的 `shell` `CMD` 应该在极少的情况下才能以 `CMD ["param", "param"]` 的形式与 `ENTRYPOINT` 协同使用除非你和你的镜像使用者都对 `ENTRYPOINT` 的工作方式十分熟悉
#### EXPOSE
@@ -179,20 +181,20 @@ RUN apt-get update && apt-get install -y \
#### ENV
为了方便新程序运行你可以使用 `ENV` 来为容器中安装的程序更新 `PATH` 环境变量例如使用 `ENV PATH /usr/local/nginx/bin:$PATH` 来确保 `CMD ["nginx"]` 能正确运行
为了方便新程序运行你可以使用 `ENV` 来为容器中安装的程序更新 `PATH` 环境变量例如使用 `ENV PATH=/usr/local/nginx/bin:$PATH` 来确保 `CMD ["nginx"]` 能正确运行
`ENV` 指令也可用于为你想要容器化的服务提供必要的环境变量比如 Postgres 需要的 `PGDATA`
最后`ENV` 也能用于设置常见的版本号比如下面的示例
```docker
ENV PG_MAJOR 9.3
ENV PG_MAJOR=9.3
ENV PG_VERSION 9.3.4
ENV PG_VERSION=9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgres && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH
```
类似于程序中的常量这种方法可以让你只需改变 `ENV` 指令来自动的改变容器中的软件版本
+1 -3
View File
@@ -20,7 +20,7 @@ EXPOSE 8888
然后创建镜像并启动容器
```bash
$ docker build -t my-nodejs-app
$ docker build -t my-nodejs-app .
$ docker run -it --rm --name my-running-app my-nodejs-app
```
也可以直接运行一个简单容器
@@ -28,8 +28,6 @@ $ docker run -it --rm --name my-running-app my-nodejs-app
```bash
$ docker run -it --rm \
--name my-running-script \
# -v "$ ":/usr/src/myapp \
--mount type=bind,src="$(pwd)",target=/usr/src/myapp \
-w /usr/src/myapp \
node:22-alpine \