mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-11 04:14:38 +00:00
style: apply global formatting fixes (struct, spacing, zhlint)
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
## 7.10 WORKDIR 指定工作目录
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
WORKDIR <工作目录路径>
|
||||
```
|
||||
@@ -12,6 +16,8 @@ WORKDIR <工作目录路径>
|
||||
|
||||
### 基本用法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
WORKDIR /app
|
||||
|
||||
@@ -24,8 +30,12 @@ COPY . . # 复制到 /app/
|
||||
|
||||
### 为什么需要 WORKDIR
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 常见错误
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 错误:cd 在下一个 RUN 中无效
|
||||
|
||||
@@ -35,6 +45,8 @@ RUN echo "hello" > world.txt # 文件在根目录!
|
||||
|
||||
#### 原因分析
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
RUN cd /app
|
||||
↓
|
||||
@@ -46,10 +58,12 @@ RUN echo "hello" > world.txt
|
||||
启动新容器(工作目录在 /)→ 创建 /world.txt
|
||||
```
|
||||
|
||||
每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态(包括工作目录)不会保留**。
|
||||
每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态 (包括工作目录) 不会保留**。
|
||||
|
||||
#### 正确做法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 正确:使用 WORKDIR
|
||||
|
||||
@@ -75,6 +89,8 @@ RUN pwd # 输出 /a/b/c
|
||||
|
||||
### 使用环境变量
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV APP_HOME=/app
|
||||
WORKDIR $APP_HOME
|
||||
@@ -86,6 +102,8 @@ RUN pwd # 输出 /app
|
||||
|
||||
### 多阶段构建中的 WORKDIR
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 构建阶段
|
||||
|
||||
@@ -107,7 +125,11 @@ COPY --from=builder /build/dist .
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 尽早设置 WORKDIR
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。尽早设置 WORKDIR
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM node:20
|
||||
@@ -119,7 +141,9 @@ COPY . .
|
||||
CMD ["node", "server.js"]
|
||||
```
|
||||
|
||||
#### 2. 使用绝对路径
|
||||
#### 2。使用绝对路径
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 推荐:绝对路径,意图明确
|
||||
@@ -131,7 +155,9 @@ WORKDIR /app
|
||||
WORKDIR app
|
||||
```
|
||||
|
||||
#### 3. 不要用 RUN cd
|
||||
#### 3。不要用 RUN cd
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 避免
|
||||
@@ -144,7 +170,9 @@ WORKDIR /app
|
||||
RUN echo "hello" > world.txt
|
||||
```
|
||||
|
||||
#### 4. 适时重置 WORKDIR
|
||||
#### 4。适时重置 WORKDIR
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
WORKDIR /app
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
## 7.11 USER 指定当前用户
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
USER <用户名>[:<用户组>]
|
||||
USER <UID>[:<GID>]
|
||||
```
|
||||
|
||||
`USER` 指令切换后续指令(RUN、CMD、ENTRYPOINT)的执行用户。
|
||||
`USER` 指令切换后续指令 (RUN、CMD、ENTRYPOINT) 的执行用户。
|
||||
|
||||
---
|
||||
|
||||
@@ -34,8 +38,12 @@ flowchart LR
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 创建并切换用户
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM node:20-alpine
|
||||
|
||||
@@ -60,6 +68,8 @@ CMD ["node", "server.js"]
|
||||
|
||||
#### 使用 UID/GID
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 也可以使用数字
|
||||
|
||||
@@ -84,6 +94,10 @@ RUN useradd -r -s /bin/false appuser
|
||||
USER appuser
|
||||
```
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 创建用户的方式
|
||||
|
||||
**Debian/Ubuntu**:
|
||||
@@ -112,7 +126,9 @@ RUN addgroup -g 1001 -S appgroup && \
|
||||
|
||||
### 运行时切换用户
|
||||
|
||||
#### 使用 gosu(推荐)
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 使用 gosu (推荐)
|
||||
|
||||
在 ENTRYPOINT 脚本中切换用户时,不要使用 `su` 或 `sudo`,应使用 [gosu](https://github.com/tianon/gosu):
|
||||
|
||||
@@ -205,7 +221,11 @@ CMD ["node", "server.js"]
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 始终使用非 root 用户
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。始终使用非 root 用户
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 推荐
|
||||
@@ -219,7 +239,7 @@ CMD ["myapp"]
|
||||
CMD ["myapp"] # 以 root 运行
|
||||
```
|
||||
|
||||
#### 2. 使用固定 UID/GID
|
||||
#### 2。使用固定 UID/GID
|
||||
|
||||
便于在宿主机和容器间共享文件:
|
||||
|
||||
@@ -231,7 +251,9 @@ RUN addgroup -g 1000 -S appgroup && \
|
||||
USER 1000:1000
|
||||
```
|
||||
|
||||
#### 3. 多阶段构建中的 USER
|
||||
#### 3。多阶段构建中的 USER
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 构建阶段可以用 root
|
||||
@@ -255,7 +277,9 @@ CMD ["node", "server.js"]
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### Q: 权限被拒绝
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### Q:权限被拒绝
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -269,12 +293,12 @@ permission denied: '/app/data.log'
|
||||
RUN mkdir -p /app/data && chown appuser:appuser /app/data
|
||||
```
|
||||
|
||||
#### Q: 无法绑定低于 1024 的端口
|
||||
#### Q:无法绑定低于 1024 的端口
|
||||
|
||||
非 root 用户无法绑定 80、443 等端口。
|
||||
|
||||
**解决**:
|
||||
1. 使用高端口(如 8080)
|
||||
1. 使用高端口 (如 8080)
|
||||
2. 在运行时映射端口:`docker run -p 80:8080`
|
||||
|
||||
---
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.12 HEALTHCHECK 健康检查
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
HEALTHCHECK [选项] CMD <命令>
|
||||
HEALTHCHECK NONE
|
||||
@@ -19,7 +23,7 @@ HEALTHCHECK NONE
|
||||
- 应用陷入死循环,CPU 爆满但进程存活
|
||||
|
||||
**引入 HEALTHCHECK 后**:
|
||||
Docker 定期执行指定的检查命令,根据返回值判断容器是否"健康"。
|
||||
Docker 定期执行指定的检查命令,根据返回值判断容器是否 “健康”。
|
||||
|
||||
```
|
||||
容器状态转换:
|
||||
@@ -32,8 +36,12 @@ Starting ──成功──> Healthy ──失败N次──> Unhealthy
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### Web 服务检查
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM nginx
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
@@ -44,9 +52,9 @@ HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
||||
|
||||
#### 命令返回值
|
||||
|
||||
- `0`: 成功 (healthy)
|
||||
- `1`: 失败 (unhealthy)
|
||||
- `2`: 保留值 (不使用)
|
||||
- `0`:成功 (healthy)
|
||||
- `1`:失败 (unhealthy)
|
||||
- `2`:保留值 (不使用)
|
||||
|
||||
#### 常用选项
|
||||
|
||||
@@ -72,6 +80,8 @@ HEALTHCHECK NONE
|
||||
|
||||
### 常见检查脚本
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### HTTP 服务
|
||||
|
||||
使用 `curl` 或 `wget`:
|
||||
@@ -88,6 +98,8 @@ HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
|
||||
|
||||
#### 数据库
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## MySQL
|
||||
|
||||
@@ -100,6 +112,8 @@ HEALTHCHECK CMD redis-cli ping || exit 1
|
||||
|
||||
#### 自定义脚本
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
COPY healthcheck.sh /usr/local/bin/
|
||||
HEALTHCHECK CMD ["healthcheck.sh"]
|
||||
@@ -109,7 +123,7 @@ HEALTHCHECK CMD ["healthcheck.sh"]
|
||||
|
||||
### 在 Compose 中使用
|
||||
|
||||
可以在 `compose.yaml`(或 `docker-compose.yml`)中覆盖或定义健康检查:
|
||||
可以在 `compose.yaml` (或 `docker-compose.yml`) 中覆盖或定义健康检查:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -172,17 +186,19 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 避免副作用
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。避免副作用
|
||||
|
||||
健康检查会被频繁执行,不要在检查脚本中进行写操作或消耗大量资源的操作。
|
||||
|
||||
#### 2. 使用轻量级工具
|
||||
#### 2。使用轻量级工具
|
||||
|
||||
优先使用镜像中已有的工具(如 `wget`),避免为了健康检查安装庞大的依赖(如 `curl`)。
|
||||
优先使用镜像中已有的工具 (如 `wget`),避免为了健康检查安装庞大的依赖 (如 `curl`)。
|
||||
|
||||
#### 3. 设置合理的 Start Period
|
||||
#### 3。设置合理的 Start Period
|
||||
|
||||
应用启动可能需要时间(如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。
|
||||
应用启动可能需要时间 (如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。
|
||||
|
||||
```docker
|
||||
## 给应用 1 分钟启动时间
|
||||
@@ -190,8 +206,8 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq
|
||||
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
|
||||
```
|
||||
|
||||
#### 4. 只检查核心依赖
|
||||
#### 4。只检查核心依赖
|
||||
|
||||
健康检查应主要关注**当前服务**是否可用,而不是检查其下游依赖(数据库等)。下游依赖的检查应由应用逻辑处理。
|
||||
健康检查应主要关注**当前服务**是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。
|
||||
|
||||
---
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
## 7.13 ONBUILD 为他人做嫁衣裳
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ONBUILD <其它指令>
|
||||
```
|
||||
|
||||
`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令(如 `RUN`, `COPY` 等),这些指令**在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。
|
||||
`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令 (如 `RUN`,`COPY` 等),这些指令**在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。
|
||||
|
||||
---
|
||||
|
||||
@@ -57,6 +61,8 @@ FROM my-node-base
|
||||
|
||||
### 执行机制
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
基础镜像构建:
|
||||
Dockerfile (含 ONBUILD) ──build──> 基础镜像 (记录了 ONBUILD 触发器)
|
||||
@@ -70,7 +76,11 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行
|
||||
|
||||
### 常见使用场景
|
||||
|
||||
#### 1. 自动处理依赖安装
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。自动处理依赖安装
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Python 基础镜像
|
||||
@@ -79,7 +89,9 @@ ONBUILD COPY requirements.txt ./
|
||||
ONBUILD RUN pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### 2. 自动编译代码
|
||||
#### 2。自动编译代码
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Go 基础镜像
|
||||
@@ -88,7 +100,9 @@ ONBUILD COPY . .
|
||||
ONBUILD RUN go build -o app main.go
|
||||
```
|
||||
|
||||
#### 3. 处理静态资源
|
||||
#### 3。处理静态资源
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Nginx 静态网站基础镜像
|
||||
@@ -100,30 +114,34 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
|
||||
|
||||
### 注意事项
|
||||
|
||||
#### 1. 继承性限制
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。继承性限制
|
||||
|
||||
`ONBUILD` 指令**只会继承一次**。
|
||||
- 镜像 A (含 ONBUILD)
|
||||
- 镜像 B (FROM A) -> 触发 ONBUILD
|
||||
- 镜像 C (FROM B) -> **不会**再次触发 ONBUILD
|
||||
|
||||
#### 2. 构建上下文
|
||||
#### 2。构建上下文
|
||||
|
||||
子镜像构建时,`ONBUILD COPY . .` 中的 `.` 指的是**子项目**的构建上下文,而不是基础镜像的上下文。
|
||||
|
||||
#### 3. 不允许级联
|
||||
#### 3。不允许级联
|
||||
|
||||
`ONBUILD ONBUILD` 是非法的。你不能写 `ONBUILD ONBUILD COPY ...`。
|
||||
|
||||
#### 4. 可能会导致构建失败
|
||||
#### 4。可能会导致构建失败
|
||||
|
||||
由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求(例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。
|
||||
由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求 (例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。
|
||||
|
||||
---
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 命名规范
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。命名规范
|
||||
|
||||
建议在镜像标签中添加 `-onbuild` 后缀,明确告知使用者该镜像包含触发器。
|
||||
|
||||
@@ -132,11 +150,11 @@ node:20-onbuild
|
||||
python:3.12-onbuild
|
||||
```
|
||||
|
||||
#### 2. 避免执行耗时操作
|
||||
#### 2。避免执行耗时操作
|
||||
|
||||
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作(如更新系统软件),这会让子镜像构建变得缓慢且不可控。
|
||||
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件),这会让子镜像构建变得缓慢且不可控。
|
||||
|
||||
#### 3. 清理工作
|
||||
#### 3。清理工作
|
||||
|
||||
如果 `ONBUILD` 指令产生了临时文件,最好在同一个指令链中清理,或者提供机制让子镜像清理。
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.14 LABEL 为镜像添加元数据
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
LABEL <key>=<value> <key>=<value> ...
|
||||
```
|
||||
@@ -14,21 +18,27 @@ LABEL <key>=<value> <key>=<value> ...
|
||||
|
||||
1. **版本管理**:记录版本号、构建时间、Git Commit ID
|
||||
2. **联系信息**:维护者邮箱、文档地址、支持渠道
|
||||
3. **自动化工具**: CI/CD 工具可以读取标签触发操作
|
||||
3. **自动化工具**:CI/CD 工具可以读取标签触发操作
|
||||
4. **许可证信息**:声明开源协议
|
||||
|
||||
---
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 定义单个标签
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
LABEL version="1.0"
|
||||
LABEL description="这是一个 Web 应用服务器"
|
||||
```
|
||||
|
||||
#### 定义多个标签(推荐)
|
||||
#### 定义多个标签 (推荐)
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
LABEL maintainer="user@example.com" \
|
||||
@@ -41,7 +51,7 @@ LABEL maintainer="user@example.com" \
|
||||
|
||||
---
|
||||
|
||||
### 常用标签规范(OCI Annotations)
|
||||
### 常用标签规范
|
||||
|
||||
为了标准和互操作性,推荐使用 [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys) 定义的标准标签:
|
||||
|
||||
@@ -57,8 +67,14 @@ LABEL maintainer="user@example.com" \
|
||||
| `org.opencontainers.image.title` | 镜像标题 | `My App` |
|
||||
| `org.opencontainers.image.description` | 描述 | `Production ready web server` |
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 示例
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
LABEL org.opencontainers.image.authors="yeasy" \
|
||||
org.opencontainers.image.documentation="https://yeasy.gitbooks.io" \
|
||||
@@ -68,7 +84,7 @@ LABEL org.opencontainers.image.authors="yeasy" \
|
||||
|
||||
---
|
||||
|
||||
### MAINTAINER 指令(已废弃)
|
||||
### MAINTAINER 指令 (已废弃)
|
||||
|
||||
旧版本的 Dockerfile 中常看到 `MAINTAINER` 指令:
|
||||
|
||||
@@ -116,6 +132,8 @@ $ docker build \
|
||||
|
||||
### 查看标签
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### docker inspect
|
||||
|
||||
查看镜像的标签信息:
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.15 SHELL 指令
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
SHELL ["executable", "parameters"]
|
||||
```
|
||||
@@ -10,15 +14,17 @@ SHELL ["executable", "parameters"]
|
||||
- **Linux 默认**:`["/bin/sh", "-c"]`
|
||||
- **Windows 默认**:`["cmd", "/S", "/C"]`
|
||||
|
||||
该指令会影响后续的 `RUN`, `CMD`, `ENTRYPOINT` 指令(当它们使用 shell 格式时)。
|
||||
该指令会影响后续的 `RUN`,`CMD`,`ENTRYPOINT` 指令 (当它们使用 shell 格式时)。
|
||||
|
||||
---
|
||||
|
||||
### 为什么要用 SHELL 指令
|
||||
|
||||
#### 1. 使用 bash 特性
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
默认的 `/bin/sh`(通常是 dash 或 alpine 的 ash)功能有限。如果你需要使用 bash 的特有功能(如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。
|
||||
#### 1。使用 bash 特性
|
||||
|
||||
默认的 `/bin/sh` (通常是 dash 或 alpine 的 ash) 功能有限。如果你需要使用 bash 的特有功能 (如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。
|
||||
|
||||
```docker
|
||||
FROM ubuntu:24.04
|
||||
@@ -32,7 +38,7 @@ SHELL ["/bin/bash", "-c"]
|
||||
RUN echo {a..z}
|
||||
```
|
||||
|
||||
#### 2. 增强错误处理(pipefail)
|
||||
#### 2。增强错误处理
|
||||
|
||||
默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个指令就视为成功。这可能掩盖构建错误。
|
||||
|
||||
@@ -54,7 +60,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
RUN wget -O - https://invalid-url | tar xz
|
||||
```
|
||||
|
||||
#### 3. Windows 环境
|
||||
#### 3。Windows 环境
|
||||
|
||||
在 Windows 容器中,经常需要在 `cmd` 和 `powershell` 之间切换。
|
||||
|
||||
@@ -103,7 +109,7 @@ RUN echo "Using sh again"
|
||||
|
||||
### 对其他指令的影响
|
||||
|
||||
`SHELL` 影响的是所有使用 **shell 格式** 的指令:
|
||||
`SHELL` 影响的是所有使用 **shell 格式**的指令:
|
||||
|
||||
| 指令格式 | 是否受 SHELL 影响 |
|
||||
|---------|-------------------|
|
||||
@@ -118,7 +124,9 @@ RUN echo "Using sh again"
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 推荐开启 pipefail
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。推荐开启 pipefail
|
||||
|
||||
对于使用 bash 的镜像,强烈建议开启 `pipefail`,以确保构建过程中的错误能被及时捕获。
|
||||
|
||||
@@ -126,11 +134,11 @@ RUN echo "Using sh again"
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
```
|
||||
|
||||
#### 2. 明确意图
|
||||
#### 2。明确意图
|
||||
|
||||
如果由于脚本需求必须更改 shell,最好在 Dockerfile 中显式声明,而不是依赖默认行为。
|
||||
|
||||
#### 3. 尽量保持一致
|
||||
#### 3。尽量保持一致
|
||||
|
||||
避免在 Dockerfile 中频繁切换 SHELL,这会使构建过程难以理解和调试。尽量在头部定义一次即可。
|
||||
|
||||
|
||||
@@ -125,6 +125,8 @@ RUN set -x ; cd ${LARAVEL_PATH} \
|
||||
|
||||
### 最后一个阶段构建 NGINX 镜像
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM nginx:alpine as nginx
|
||||
|
||||
@@ -152,7 +154,7 @@ $ docker build -t my/nginx --target=nginx .
|
||||
$ docker network create laravel
|
||||
```
|
||||
|
||||
启动 laravel 容器, `--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致
|
||||
启动 laravel 容器,`--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致
|
||||
|
||||
```bash
|
||||
$ docker run -dit --rm --name=laravel --network=laravel my/laravel
|
||||
@@ -170,7 +172,7 @@ $ docker run -dit --rm --network=laravel -p 8080:80 my/nginx
|
||||
|
||||
### 生产环境优化
|
||||
|
||||
本小节内容为了方便测试,将配置文件直接放到了镜像中,实际在使用时 **建议** 将配置文件作为 `config` 或 `secret` 挂载到容器中,请读者自行学习 `Kubernetes` 的相关内容。
|
||||
本小节内容为了方便测试,将配置文件直接放到了镜像中,实际在使用时**建议**将配置文件作为 `config` 或 `secret` 挂载到容器中,请读者自行学习 `Kubernetes` 的相关内容。
|
||||
|
||||
由于篇幅所限本小节只是简单列出,更多内容可以参考 https://github.com/khs1994-docker/laravel-demo 项目。
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.1 RUN 执行命令
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
RUN <command>
|
||||
RUN ["executable", "param1", "param2"]
|
||||
@@ -13,7 +17,11 @@ RUN ["executable", "param1", "param2"]
|
||||
|
||||
### 两种格式对比
|
||||
|
||||
#### 1. Shell 格式
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。Shell 格式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
RUN apt-get update
|
||||
@@ -26,7 +34,9 @@ RUN apt-get update
|
||||
RUN echo "Hello" > /test.txt
|
||||
```
|
||||
|
||||
#### 2. Exec 格式
|
||||
#### 2。Exec 格式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
RUN ["apt-get", "update"]
|
||||
@@ -34,17 +44,19 @@ RUN ["apt-get", "update"]
|
||||
|
||||
- **特点**:直接调用可执行文件,不经过 Shell。
|
||||
- **优势**:避免 Shell 字符串解析问题,适用于参数中包含特殊字符的情况。
|
||||
- **注意**:无法使用 `$VAR` 环境变量替换(除非显式调用 shell)。
|
||||
- **注意**:无法使用 `$VAR` 环境变量替换 (除非显式调用 shell)。
|
||||
|
||||
---
|
||||
|
||||
### 常见最佳实践
|
||||
|
||||
#### 1. 组合命令(减少层数)
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。组合命令 (减少层数)
|
||||
|
||||
每一个 `RUN` 指令都会新建一层镜像。为了减少镜像体积和层数,应使用 `&&` 连接命令。
|
||||
|
||||
**❌ 糟糕的写法**(创建 3 层):
|
||||
**❌ 糟糕的写法** (创建 3 层):
|
||||
|
||||
```docker
|
||||
RUN apt-get update
|
||||
@@ -52,7 +64,7 @@ RUN apt-get install -y nginx
|
||||
RUN rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
**✅ 推荐写法**(创建 1 层):
|
||||
**✅ 推荐写法** (创建 1 层):
|
||||
|
||||
```docker
|
||||
RUN apt-get update && \
|
||||
@@ -60,7 +72,7 @@ RUN apt-get update && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
```
|
||||
|
||||
#### 2. 清理缓存
|
||||
#### 2。清理缓存
|
||||
|
||||
在安装完软件后,立即清除缓存,可以显著减小镜像体积。
|
||||
|
||||
@@ -74,7 +86,7 @@ RUN apt-get update && \
|
||||
RUN apk add --no-cache package-bar
|
||||
```
|
||||
|
||||
#### 3. 使用 `set -e` 和 `pipefail`
|
||||
#### 3。使用 `set -e` 和 `pipefail`
|
||||
|
||||
默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个 `RUN` 就视为成功。
|
||||
|
||||
@@ -97,21 +109,27 @@ RUN wget http://url | gzip -d > file
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### Q: 为什么 `RUN cd /app` 不生效?
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### Q:为什么 `RUN cd /app` 不生效?
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
RUN cd /app
|
||||
RUN touch hello.txt
|
||||
```
|
||||
|
||||
**结果**:`hello.txt` 会出现在根目录 `/`,而不是 `/app`。**原因**:每个 `RUN` 都在一个新的 Shell/容器 环境中执行。`cd` 只影响当前 `RUN` 的环境。**解决**:使用 `WORKDIR` 指令。
|
||||
**结果**:`hello.txt` 会出现在根目录 `/`,而不是 `/app`。**原因**:每个 `RUN` 都在一个新的 Shell/容器环境中执行。`cd` 只影响当前 `RUN` 的环境。**解决**:使用 `WORKDIR` 指令。
|
||||
|
||||
```docker
|
||||
WORKDIR /app
|
||||
RUN touch hello.txt
|
||||
```
|
||||
|
||||
#### Q: 环境变量不生效?
|
||||
#### Q:环境变量不生效?
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
RUN export MY_VAR=hello
|
||||
@@ -129,7 +147,9 @@ RUN echo $MY_VAR
|
||||
|
||||
### 高级技巧
|
||||
|
||||
#### 1. 使用 BuildKit 的挂载缓存
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。使用 BuildKit 的挂载缓存
|
||||
|
||||
BuildKit 支持在 `RUN` 指令中使用 `--mount` 挂载缓存,加速构建。
|
||||
|
||||
@@ -148,7 +168,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
go build -o app
|
||||
```
|
||||
|
||||
#### 2. 挂载密钥
|
||||
#### 2。挂载密钥
|
||||
|
||||
安全地使用 SSH 密钥或 Token,而不将其记录在镜像中。
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.2 COPY 复制文件
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
COPY [选项] <源路径>... <目标路径>
|
||||
COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"]
|
||||
@@ -13,8 +17,12 @@ COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"]
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 复制单个文件
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 复制文件到指定目录
|
||||
|
||||
@@ -27,6 +35,8 @@ COPY config.json /app/settings.json
|
||||
|
||||
#### 复制多个文件
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 复制多个指定文件
|
||||
|
||||
@@ -40,6 +50,8 @@ COPY src/*.js /app/src/
|
||||
|
||||
#### 复制目录
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 复制整个目录的内容(不是目录本身)
|
||||
|
||||
@@ -78,13 +90,19 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js
|
||||
|
||||
### 目标路径
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 绝对路径
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
COPY app.js /usr/src/app/
|
||||
```
|
||||
|
||||
#### 相对路径(基于 WORKDIR)
|
||||
#### 相对路径 (基于 WORKDIR)
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
WORKDIR /app
|
||||
@@ -168,8 +186,12 @@ ADD app.tar.gz /app/
|
||||
|
||||
### 多阶段构建中的 COPY
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 从其他构建阶段复制
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 构建阶段
|
||||
|
||||
@@ -186,7 +208,9 @@ FROM nginx:alpine
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
```
|
||||
|
||||
#### 使用 --link 优化缓存(BuildKit)
|
||||
#### 使用 --link 优化缓存
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 使用 --link 后,文件以独立层添加,不依赖前序指令
|
||||
@@ -225,7 +249,11 @@ Dockerfile
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 利用缓存,先复制依赖文件
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。利用缓存,先复制依赖文件
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:先复制依赖定义,再安装,最后复制代码
|
||||
@@ -240,7 +268,9 @@ COPY . .
|
||||
RUN npm install
|
||||
```
|
||||
|
||||
#### 2. 使用 .dockerignore
|
||||
#### 2。使用。dockerignore
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 确保 node_modules 不被复制
|
||||
@@ -251,7 +281,9 @@ COPY . .
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 明确复制路径
|
||||
#### 3。明确复制路径
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:明确的路径
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.3 ADD 更高级的复制文件
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ADD [选项] <源路径>... <目标路径>
|
||||
ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||||
@@ -9,7 +13,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||||
|
||||
`ADD` 在 `COPY` 基础上增加了两个功能:
|
||||
1. 自动解压 tar 压缩包
|
||||
2. 支持从 URL 下载文件(不推荐)
|
||||
2. 支持从 URL 下载文件 (不推荐)
|
||||
|
||||
---
|
||||
|
||||
@@ -29,7 +33,11 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
|
||||
|
||||
### 自动解压功能
|
||||
|
||||
#### 基本用法(自动解压本地 tar)
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 基本用法 (自动解压本地 tar)
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 自动解压 tar.gz 到目标目录
|
||||
@@ -54,6 +62,8 @@ ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz /
|
||||
|
||||
#### 解压过程
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
ADD app.tar.gz /app/
|
||||
│
|
||||
@@ -69,10 +79,14 @@ app.tar.gz 包含: /app/ 目录结果:
|
||||
|
||||
---
|
||||
|
||||
### URL 下载功能(不推荐)
|
||||
### URL 下载功能 (不推荐)
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 基本用法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 从 URL 下载文件
|
||||
|
||||
@@ -90,6 +104,8 @@ ADD https://example.com/app.zip /app/app.zip
|
||||
|
||||
#### 推荐替代方案
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 不推荐:使用 ADD 下载
|
||||
|
||||
@@ -110,6 +126,8 @@ RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app
|
||||
|
||||
### 修改文件所有者
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ADD --chown=node:node app.tar.gz /app/
|
||||
ADD --chown=1000:1000 files/ /app/
|
||||
@@ -119,8 +137,12 @@ ADD --chown=1000:1000 files/ /app/
|
||||
|
||||
### 何时使用 ADD
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### ✅ 适合使用 ADD
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 解压本地 tar 文件
|
||||
|
||||
@@ -134,6 +156,8 @@ ADD dist.tar.gz /app/
|
||||
|
||||
#### ❌ 不适合使用 ADD
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 复制普通文件(用 COPY)
|
||||
|
||||
@@ -181,7 +205,11 @@ ADD app.tar.gz /app/
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 默认使用 COPY
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。默认使用 COPY
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 大多数场景使用 COPY
|
||||
@@ -189,7 +217,9 @@ ADD app.tar.gz /app/
|
||||
COPY . /app/
|
||||
```
|
||||
|
||||
#### 2. 仅在需要解压时使用 ADD
|
||||
#### 2。仅在需要解压时使用 ADD
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 自动解压场景
|
||||
@@ -197,7 +227,9 @@ COPY . /app/
|
||||
ADD app.tar.gz /app/
|
||||
```
|
||||
|
||||
#### 3. 不要用 ADD 下载文件
|
||||
#### 3。不要用 ADD 下载文件
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 避免
|
||||
@@ -209,7 +241,9 @@ ADD https://example.com/file.tar.gz /tmp/
|
||||
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
|
||||
```
|
||||
|
||||
#### 4. 解压后清理
|
||||
#### 4。解压后清理
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 如果需要控制解压过程
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
## 7.4 CMD 容器启动命令
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 什么是 CMD
|
||||
|
||||
`CMD` 指令用于指定容器启动时默认执行的命令。它定义了容器的"主进程"。
|
||||
`CMD` 指令用于指定容器启动时默认执行的命令。它定义了容器的 “主进程”。
|
||||
|
||||
> **核心概念**:容器的生命周期 = 主进程的生命周期。CMD 指定的命令就是这个主进程。
|
||||
|
||||
@@ -18,7 +20,9 @@ CMD 有三种格式:
|
||||
| **shell 格式** | `CMD 命令 参数1 参数2` | ⚠️ 简单场景 |
|
||||
| **参数格式** | `CMD ["参数1", "参数2"]` | 配合 ENTRYPOINT |
|
||||
|
||||
#### exec 格式(推荐)
|
||||
#### exec 格式 (推荐)
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -28,11 +32,13 @@ CMD ["node", "server.js"]
|
||||
|
||||
**优点**:
|
||||
- 直接执行指定程序,是容器的 PID 1
|
||||
- 正确接收信号(如 SIGTERM)
|
||||
- 正确接收信号 (如 SIGTERM)
|
||||
- 无需 shell 解析
|
||||
|
||||
#### shell 格式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
CMD echo "Hello World"
|
||||
CMD nginx -g "daemon off;"
|
||||
@@ -63,8 +69,14 @@ CMD ["sh", "-c", "echo $HOME"]
|
||||
| 环境变量 | ❌ 需要 shell 包装 | ✅ 自动解析 |
|
||||
| 推荐使用 | ✅ 大多数场景 | 需要 shell 特性时 |
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 信号传递问题示例
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ shell 格式:docker stop 会超时
|
||||
|
||||
@@ -107,8 +119,12 @@ CMD ["/bin/bash"] + cat /etc/os-release
|
||||
|
||||
### 经典错误:容器立即退出
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 错误示例
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 容器启动后立即退出
|
||||
|
||||
@@ -117,6 +133,8 @@ CMD service nginx start
|
||||
|
||||
#### 原因分析
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
1. CMD service nginx start
|
||||
↓ 被转换为
|
||||
@@ -133,6 +151,8 @@ CMD service nginx start
|
||||
|
||||
#### 正确做法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 让 nginx 在前台运行
|
||||
|
||||
@@ -150,6 +170,8 @@ CMD ["nginx", "-g", "daemon off;"]
|
||||
|
||||
#### 单独使用 CMD
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Dockerfile
|
||||
|
||||
@@ -163,6 +185,8 @@ $ docker run myimage curl -v ... # 完全覆盖
|
||||
|
||||
#### 搭配 ENTRYPOINT
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Dockerfile
|
||||
|
||||
@@ -175,13 +199,17 @@ $ docker run myimage # curl -s http://example.com
|
||||
$ docker run myimage http://other.com # curl -s http://other.com(参数覆盖)
|
||||
```
|
||||
|
||||
详见 [ENTRYPOINT 入口点](7.5_entrypoint.md) 章节。
|
||||
详见 [ENTRYPOINT 入口点](7.5_entrypoint.md)章节。
|
||||
|
||||
---
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 优先使用 exec 格式
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。优先使用 exec 格式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 推荐
|
||||
@@ -193,7 +221,9 @@ CMD ["python", "app.py"]
|
||||
CMD ["sh", "-c", "echo $PATH && python app.py"]
|
||||
```
|
||||
|
||||
#### 2. 确保应用在前台运行
|
||||
#### 2。确保应用在前台运行
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 前台运行
|
||||
@@ -208,7 +238,9 @@ CMD service nginx start
|
||||
CMD systemctl start nginx
|
||||
```
|
||||
|
||||
#### 3. 使用双引号
|
||||
#### 3。使用双引号
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 正确:双引号
|
||||
@@ -220,7 +252,9 @@ CMD ["node", "server.js"]
|
||||
CMD ['node', 'server.js']
|
||||
```
|
||||
|
||||
#### 4. 配合 ENTRYPOINT 使用
|
||||
#### 4。配合 ENTRYPOINT 使用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 用于可配置参数的场景
|
||||
@@ -239,7 +273,9 @@ $ docker run myapp --port 9000
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### Q: CMD 可以写多个吗?
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### Q:CMD 可以写多个吗?
|
||||
|
||||
不可以。多个 CMD 只有最后一个生效:
|
||||
|
||||
@@ -248,7 +284,9 @@ CMD ["echo", "first"]
|
||||
CMD ["echo", "second"] # 只有这个生效
|
||||
```
|
||||
|
||||
#### Q: 如何在 CMD 中使用环境变量?
|
||||
#### Q:如何在 CMD 中使用环境变量?
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 方法1:使用 shell 格式
|
||||
@@ -260,7 +298,7 @@ CMD echo "Port is $PORT"
|
||||
CMD ["sh", "-c", "echo Port is $PORT"]
|
||||
```
|
||||
|
||||
#### Q: 为什么我的容器不响应 Ctrl+C?
|
||||
#### Q:为什么我的容器不响应 Ctrl+C?
|
||||
|
||||
可能是使用了 shell 格式,信号被 sh 吃掉了:
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
## 7.5 ENTRYPOINT 入口点
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 什么是 ENTRYPOINT
|
||||
|
||||
`ENTRYPOINT` 指定容器启动时运行的入口程序。与 CMD 不同,ENTRYPOINT 定义的命令不会被 `docker run` 的参数覆盖,而是**接收这些参数**。
|
||||
@@ -29,6 +31,8 @@ ENTRYPOINT nginx -g "daemon off;"
|
||||
|
||||
### ENTRYPOINT vs CMD
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 核心区别
|
||||
|
||||
| 特性 | ENTRYPOINT | CMD |
|
||||
@@ -40,6 +44,8 @@ ENTRYPOINT nginx -g "daemon off;"
|
||||
|
||||
#### 行为对比
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 只用 CMD
|
||||
|
||||
@@ -80,12 +86,16 @@ $ docker run myimage -v http://other.com # curl -s -v http://other.com ✓
|
||||
|
||||
### 场景一:让镜像像命令一样使用
|
||||
|
||||
#### 需求(启动前准备)
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
创建一个查询公网 IP 的"命令"镜像。
|
||||
#### 需求 (启动前准备)
|
||||
|
||||
创建一个查询公网 IP 的 “命令” 镜像。
|
||||
|
||||
#### 使用 CMD 的问题
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM ubuntu:24.04
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
@@ -105,6 +115,8 @@ exec: "-i": executable file not found
|
||||
|
||||
#### 使用 ENTRYPOINT 解决
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM ubuntu:24.04
|
||||
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
|
||||
@@ -123,6 +135,8 @@ HTTP/1.1 200 OK
|
||||
|
||||
#### 交互图示
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
ENTRYPOINT ["curl", "-s", "http://myip.ipip.net"]
|
||||
│
|
||||
@@ -138,12 +152,16 @@ curl -s http://myip.ipip.net -i
|
||||
|
||||
### 场景二:启动前的准备工作
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 需求
|
||||
|
||||
在启动主服务前执行初始化脚本(如数据库迁移、权限设置)。
|
||||
在启动主服务前执行初始化脚本 (如数据库迁移、权限设置)。
|
||||
|
||||
#### 实现方式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM redis:7-alpine
|
||||
COPY docker-entrypoint.sh /usr/local/bin/
|
||||
@@ -175,6 +193,8 @@ exec "$@"
|
||||
|
||||
#### 工作流程
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```
|
||||
docker run redis docker run redis bash
|
||||
│ │
|
||||
@@ -189,14 +209,16 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash
|
||||
|
||||
#### 关键点
|
||||
|
||||
1. **exec "$@"**:用传入的参数替换当前进程,确保信号正确传递
|
||||
1. **exec “$@”**:用传入的参数替换当前进程,确保信号正确传递
|
||||
2. **条件判断**:根据 CMD 不同执行不同逻辑
|
||||
3. **用户切换**:使用 `gosu` 切换用户(比 `su` 更适合容器)
|
||||
3. **用户切换**:使用 `gosu` 切换用户 (比 `su` 更适合容器)
|
||||
|
||||
---
|
||||
|
||||
### 场景三:带参数的应用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM python:3.12-slim
|
||||
WORKDIR /app
|
||||
@@ -264,7 +286,11 @@ $ docker run --entrypoint /bin/cat myimage /etc/os-release
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 使用 exec 格式
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。使用 exec 格式
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 推荐
|
||||
@@ -276,14 +302,16 @@ ENTRYPOINT ["python", "app.py"]
|
||||
ENTRYPOINT python app.py
|
||||
```
|
||||
|
||||
#### 2. 提供有意义的默认参数
|
||||
#### 2。提供有意义的默认参数
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENTRYPOINT ["nginx"]
|
||||
CMD ["-g", "daemon off;"]
|
||||
```
|
||||
|
||||
#### 3. 入口脚本使用 exec
|
||||
#### 3。入口脚本使用 exec
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -296,7 +324,7 @@ CMD ["-g", "daemon off;"]
|
||||
exec "$@"
|
||||
```
|
||||
|
||||
#### 4. 处理信号
|
||||
#### 4。处理信号
|
||||
|
||||
确保 ENTRYPOINT 脚本能正确传递信号:
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.6 ENV 设置环境变量
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 格式一:单个变量
|
||||
|
||||
@@ -16,8 +20,12 @@ ENV <key1>=<value1> <key2>=<value2> ...
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 设置单个变量
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV NODE_VERSION 20.10.0
|
||||
ENV APP_ENV production
|
||||
@@ -25,6 +33,8 @@ ENV APP_ENV production
|
||||
|
||||
#### 设置多个变量
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV NODE_VERSION=20.10.0 \
|
||||
APP_ENV=production \
|
||||
@@ -37,7 +47,11 @@ ENV NODE_VERSION=20.10.0 \
|
||||
|
||||
### 环境变量的作用
|
||||
|
||||
#### 1. 后续指令中使用
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。后续指令中使用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV NODE_VERSION=20.10.0
|
||||
@@ -57,7 +71,9 @@ WORKDIR $APP_HOME
|
||||
COPY . $APP_HOME
|
||||
```
|
||||
|
||||
#### 2. 容器运行时使用
|
||||
#### 2。容器运行时使用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV DATABASE_URL=postgres://localhost/mydb
|
||||
@@ -114,7 +130,11 @@ $ docker run -e APP_ENV=development -e DEBUG=true myimage
|
||||
$ docker run --env-file .env myimage
|
||||
```
|
||||
|
||||
#### .env 文件格式
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 。env 文件格式
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -137,8 +157,14 @@ DATABASE_URL=postgres://localhost/mydb
|
||||
| **覆盖方式** | `docker run -e` | `docker build --build-arg` |
|
||||
| **适用场景** | 应用配置 | 构建参数(如版本号) |
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 组合使用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ARG 接收构建时参数
|
||||
|
||||
@@ -163,7 +189,11 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp .
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 统一管理版本号
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。统一管理版本号
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:版本集中管理
|
||||
@@ -179,7 +209,9 @@ RUN apt-get install nginx=${NGINX_VERSION}
|
||||
RUN apt-get install nginx=1.25.0
|
||||
```
|
||||
|
||||
#### 2. 不要存储敏感信息
|
||||
#### 2。不要存储敏感信息
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 错误:密码写入镜像
|
||||
@@ -193,7 +225,9 @@ ENV DB_PASSWORD=secret123
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 为应用提供合理默认值
|
||||
#### 3。为应用提供合理默认值
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ENV APP_ENV=production \
|
||||
@@ -201,7 +235,9 @@ ENV APP_ENV=production \
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
#### 4. 使用有意义的变量名
|
||||
#### 4。使用有意义的变量名
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:清晰的命名
|
||||
@@ -219,7 +255,9 @@ ENV HOST=localhost \
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### Q: 环境变量在 CMD 中不展开
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### Q:环境变量在 CMD 中不展开
|
||||
|
||||
exec 格式不会自动展开环境变量:
|
||||
|
||||
@@ -233,7 +271,7 @@ CMD ["python", "app.py", "--port", "$PORT"]
|
||||
CMD ["sh", "-c", "python app.py --port $PORT"]
|
||||
```
|
||||
|
||||
#### Q: 如何查看容器的环境变量
|
||||
#### Q:如何查看容器的环境变量
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -242,7 +280,9 @@ $ docker inspect mycontainer --format '{{json .Config.Env}}'
|
||||
$ docker exec mycontainer env
|
||||
```
|
||||
|
||||
#### Q: 多行 ENV 还是多个 ENV
|
||||
#### Q:多行 ENV 还是多个 ENV
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 推荐:减少层数
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.7 ARG 构建参数
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG <参数名>[=<默认值>]
|
||||
```
|
||||
@@ -33,8 +37,12 @@ ARG <参数名>[=<默认值>]
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 定义和使用
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 定义有默认值的 ARG
|
||||
|
||||
@@ -64,8 +72,12 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp .
|
||||
|
||||
### ARG 的作用域
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### FROM 之前的 ARG
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## FROM 之前的 ARG 只能用于 FROM 指令
|
||||
|
||||
@@ -81,6 +93,8 @@ RUN echo $REGISTRY # 输出空
|
||||
|
||||
#### FROM 之后重新声明
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
@@ -94,6 +108,8 @@ RUN echo "Node version: $NODE_VERSION"
|
||||
|
||||
#### 多阶段构建中的 ARG
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG BASE_VERSION=alpine
|
||||
|
||||
@@ -114,7 +130,11 @@ RUN echo "Running with Node $NODE_VERSION"
|
||||
|
||||
### 常见使用场景
|
||||
|
||||
#### 1. 控制基础镜像版本
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。控制基础镜像版本
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG ALPINE_VERSION=3.19
|
||||
@@ -125,7 +145,9 @@ FROM alpine:${ALPINE_VERSION}
|
||||
$ docker build --build-arg ALPINE_VERSION=3.18 .
|
||||
```
|
||||
|
||||
#### 2. 设置软件版本
|
||||
#### 2。设置软件版本
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG NGINX_VERSION=1.25.0
|
||||
@@ -133,7 +155,9 @@ ARG NGINX_VERSION=1.25.0
|
||||
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
|
||||
```
|
||||
|
||||
#### 3. 配置构建环境
|
||||
#### 3。配置构建环境
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG BUILD_ENV=production
|
||||
@@ -146,7 +170,9 @@ RUN if [ "$ENABLE_DEBUG" = "true" ]; then \
|
||||
fi
|
||||
```
|
||||
|
||||
#### 4. 配置私有仓库
|
||||
#### 4。配置私有仓库
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG NPM_TOKEN
|
||||
@@ -203,7 +229,11 @@ $ docker build --build-arg HTTP_PROXY=http://proxy:8080 .
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 为 ARG 提供合理默认值
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。为 ARG 提供合理默认值
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:有默认值
|
||||
@@ -215,7 +245,9 @@ ARG NODE_VERSION=20
|
||||
ARG NODE_VERSION
|
||||
```
|
||||
|
||||
#### 2. 不要用 ARG 存储敏感信息
|
||||
#### 2。不要用 ARG 存储敏感信息
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 错误:密码会被记录在镜像历史中
|
||||
@@ -228,7 +260,9 @@ RUN echo "password=$DB_PASSWORD" > /app/.env
|
||||
...
|
||||
```
|
||||
|
||||
#### 3. 使用 ARG 提高构建灵活性
|
||||
#### 3。使用 ARG 提高构建灵活性
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG BASE_IMAGE=python:3.12-slim
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.8 VOLUME 定义匿名卷
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
VOLUME ["/路径1", "/路径2"]
|
||||
VOLUME /路径
|
||||
@@ -43,8 +47,12 @@ flowchart LR
|
||||
|
||||
### 基本用法
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 定义单个卷
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM mysql:8.0
|
||||
VOLUME /var/lib/mysql
|
||||
@@ -52,6 +60,8 @@ VOLUME /var/lib/mysql
|
||||
|
||||
#### 定义多个卷
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM myapp
|
||||
VOLUME ["/data", "/logs", "/config"]
|
||||
@@ -61,7 +71,9 @@ VOLUME ["/data", "/logs", "/config"]
|
||||
|
||||
### VOLUME 的行为
|
||||
|
||||
#### 1. 自动创建匿名卷
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。自动创建匿名卷
|
||||
|
||||
如果运行时未指定挂载,Docker 会自动创建匿名卷:
|
||||
|
||||
@@ -72,7 +84,7 @@ DRIVER VOLUME NAME
|
||||
local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
```
|
||||
|
||||
#### 2. 可被命名卷覆盖
|
||||
#### 2。可被命名卷覆盖
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -82,7 +94,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
|
||||
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
```
|
||||
|
||||
#### 3. 可被 Bind Mount 覆盖
|
||||
#### 3。可被 Bind Mount 覆盖
|
||||
|
||||
运行以下命令:
|
||||
|
||||
@@ -109,8 +121,14 @@ RUN echo "hello" > /data/test.txt
|
||||
|
||||
**原因**:VOLUME 指令之后,Docker 将该目录视为外部挂载点,不再记录对它的修改。
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 正确做法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM ubuntu
|
||||
|
||||
@@ -127,8 +145,12 @@ VOLUME /data
|
||||
|
||||
### 常见使用场景
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 数据库持久化
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM postgres:15
|
||||
VOLUME /var/lib/postgresql/data
|
||||
@@ -136,6 +158,8 @@ VOLUME /var/lib/postgresql/data
|
||||
|
||||
#### 日志目录
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM nginx
|
||||
VOLUME /var/log/nginx
|
||||
@@ -143,6 +167,8 @@ VOLUME /var/log/nginx
|
||||
|
||||
#### 上传文件目录
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
FROM myapp
|
||||
VOLUME /app/uploads
|
||||
@@ -182,7 +208,7 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq
|
||||
|
||||
### 在 Compose 中
|
||||
|
||||
在 Compose 中 配置如下:
|
||||
在 Compose 中配置如下:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
@@ -204,6 +230,12 @@ volumes:
|
||||
|
||||
### 安全注意事项
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 匿名卷可能导致数据丢失
|
||||
|
||||
运行以下命令:
|
||||
@@ -227,7 +259,11 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 定义必须持久化的路径
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。定义必须持久化的路径
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 数据库必须使用卷
|
||||
@@ -236,7 +272,9 @@ FROM postgres:15
|
||||
VOLUME /var/lib/postgresql/data
|
||||
```
|
||||
|
||||
#### 2. 不要在 VOLUME 后修改目录
|
||||
#### 2。不要在 VOLUME 后修改目录
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 避免
|
||||
@@ -250,7 +288,9 @@ RUN mkdir -p /app/data && cp init-data.json /app/data/
|
||||
VOLUME /app/data
|
||||
```
|
||||
|
||||
#### 3. 文档中说明 VOLUME 用途
|
||||
#### 3。文档中说明 VOLUME 用途
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 持久化用户上传的文件
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
## 7.9 EXPOSE 声明端口
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
### 基本语法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
EXPOSE <端口> [<端口>/<协议>...]
|
||||
```
|
||||
@@ -12,6 +16,8 @@ EXPOSE <端口> [<端口>/<协议>...]
|
||||
|
||||
### 基本用法
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 声明单个端口
|
||||
|
||||
@@ -31,7 +37,9 @@ EXPOSE 53/udp
|
||||
|
||||
### EXPOSE 的作用
|
||||
|
||||
#### 1. 文档说明
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。文档说明
|
||||
|
||||
告诉镜像使用者,容器将在哪些端口提供服务:
|
||||
|
||||
@@ -48,7 +56,7 @@ $ docker inspect nginx --format '{{.Config.ExposedPorts}}'
|
||||
map[80/tcp:{}]
|
||||
```
|
||||
|
||||
#### 2. 配合 -P 使用
|
||||
#### 2。配合 -P 使用
|
||||
|
||||
使用 `docker run -P` 时,Docker 会自动映射 EXPOSE 的端口到宿主机随机端口:
|
||||
|
||||
@@ -82,8 +90,14 @@ flowchart TD
|
||||
Expose ~~~ Run
|
||||
```
|
||||
|
||||
#### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
#### 没有 EXPOSE 也能 -p
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 即使没有 EXPOSE,也可以使用 -p
|
||||
|
||||
@@ -103,8 +117,12 @@ $ docker run -p 8080:80 mynginx
|
||||
|
||||
### 常见误解
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 误解:EXPOSE 会打开端口
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ❌ 错误理解:这不会让容器可从外部访问
|
||||
|
||||
@@ -120,6 +138,8 @@ EXPOSE 只是元数据声明。容器是否实际监听该端口,取决于容
|
||||
|
||||
#### 正确理解
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Dockerfile
|
||||
|
||||
@@ -137,7 +157,11 @@ $ docker run -p 8080:80 nginx # 2. 映射:宿主机 8080 → 容器 80
|
||||
|
||||
### 最佳实践
|
||||
|
||||
#### 1. 总是声明应用使用的端口
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
#### 1。总是声明应用使用的端口
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## Web 服务
|
||||
@@ -156,7 +180,9 @@ FROM redis
|
||||
EXPOSE 6379
|
||||
```
|
||||
|
||||
#### 2. 使用明确的协议
|
||||
#### 2。使用明确的协议
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## 默认是 TCP
|
||||
@@ -172,7 +198,9 @@ EXPOSE 53/udp
|
||||
EXPOSE 53/tcp 53/udp
|
||||
```
|
||||
|
||||
#### 3. 与应用实际端口保持一致
|
||||
#### 3。与应用实际端口保持一致
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
## ✅ 好:EXPOSE 与应用端口一致
|
||||
@@ -191,6 +219,8 @@ CMD ["node", "server.js"] # 实际监听 3000
|
||||
|
||||
### 使用环境变量
|
||||
|
||||
如下代码块所示,展示了相关示例:
|
||||
|
||||
```docker
|
||||
ARG PORT=80
|
||||
EXPOSE $PORT
|
||||
@@ -200,7 +230,7 @@ EXPOSE $PORT
|
||||
|
||||
### 在 Compose 中
|
||||
|
||||
在 Compose 中 配置如下:
|
||||
在 Compose 中配置如下:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
# 第七章 Dockerfile 指令详解
|
||||
|
||||
本节涵盖了相关内容与详细描述,主要探讨以下几个方面:
|
||||
|
||||
## 什么是 Dockerfile
|
||||
|
||||
Dockerfile 是一个文本文件,其內包含了一条条的 **指令(Instruction)**,每一条指令构建一层,therefore 每一条指令的内容,就是描述该层应当如何构建。
|
||||
Dockerfile 是一个文本文件,其內包含了一条条的**指令 (Instruction)**,每一条指令构建一层,therefore 每一条指令的内容,就是描述该层应当如何构建。
|
||||
|
||||
在 [第四章](../04_image/README.md) 中,我们通过 `docker commit` 学习了镜像的构成。但是,手动 `commit` 只能作为临时修补,并不适合作为生产环境镜像的构建方式。
|
||||
在[第四章](../04_image/README.md)中,我们通过 `docker commit` 学习了镜像的构成。但是,手动 `commit` 只能作为临时修补,并不适合作为生产环境镜像的构建方式。
|
||||
|
||||
使用 Dockerfile 构建镜像有以下优势:
|
||||
|
||||
* **自动化**:可以通过 `docker build` 命令自动构建镜像。
|
||||
* **可重复性**:由于 Dockerfile 是文本文件,可以确保每次构建的结果一致。
|
||||
* **版本控制**:Dockerfile 可以纳入版本控制系统(如 Git),便于追踪变更。
|
||||
* **版本控制**:Dockerfile 可以纳入版本控制系统 (如 Git),便于追踪变更。
|
||||
* **透明性**:任何人都可以通过阅读 Dockerfile 了解镜像的构建过程。
|
||||
|
||||
## Dockerfile 基本结构
|
||||
|
||||
Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
|
||||
|
||||
### 概述
|
||||
|
||||
总体概述了以下内容。
|
||||
|
||||
### 指令详解
|
||||
|
||||
本章将详细讲解 Dockerfile 中的各个指令:
|
||||
|
||||
Reference in New Issue
Block a user