Dockerfile
Dockerfile
指令集
按官方 v1.4 语法,全部大写,大小写不敏感,但行业习惯全大写;
1. 定义基础 & 元数据
| 指令 | 作用 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM python:3.11-alpine |
| LABEL | 为镜像打键值对标签 | LABEL maintainer="ops@corp.com" |
| ARG | 声明构建期变量 | ARG VERSION=latest |
2. 文件系统操作
| 指令 | 作用 | 示例 |
|---|---|---|
| COPY | 复制本地文件/目录 | COPY app.py /opt/app/ |
| ADD | 类似 COPY,但可解压 tar/远程 URL(不推荐用 URL) | ADD app.tar.gz /opt/app/ |
| WORKDIR | 设置后续指令的工作目录 | WORKDIR /opt/app |
| VOLUME | 声明挂载点(匿名卷) | VOLUME ["/data"] |
3. 软件安装 & 配置
| 指令 | 作用 | 示例 |
|---|---|---|
| RUN | 构建阶段执行命令,结果提交为新层 | RUN apt-get update && apt-get install -y curl |
| ENV | 设置环境变量(运行期也生效) | ENV PATH=/usr/local/bin:$PATH |
4. 运行阶段
| 指令 | 作用 | 示例 |
|---|---|---|
| CMD | 容器启动默认命令(可被 docker run 覆盖) | CMD ["python","app.py"] |
| ENTRYPOINT | 容器入口(通常配 CMD 做默认参数) | ENTRYPOINT ["java","-jar","/app.jar"] |
| EXPOSE | 声明监听端口(文档/随机映射用) | EXPOSE 8080/tcp |
5. 构建阶段控制
| 指令 | 作用 | 示例 |
|---|---|---|
| ONBUILD | 触发器:被别人 FROM 时自动执行 |
ONBUILD COPY . /app/src |
| STOPSIGNAL | 指定停止容器时发送的信号 | STOPSIGNAL SIGTERM |
| HEALTHCHECK | 声明健康检查 | `HEALTHCHECK --interval=30s CMD curl -f http://localhost/ |
| SHELL | Windows 镜像里替换默认 shell | SHELL ["powershell","-Command"] |
6. 多阶段构建(Docker 17.05+)
| 指令 | 作用 | 示例 |
|---|---|---|
| FROM … AS |
定义多阶段构建 | FROM golang:1.21 AS builder |
7. 语法版本声明(放在第一行)
| 指令 | 作用 | 示例 |
|---|---|---|
| # syntax=docker/dockerfile:1 | 指定解析器版本 | # syntax=docker/dockerfile:1 |
速记口诀
- FROM → RUN/COPY → ENV → EXPOSE → CMD/ENTRYPOINT → HEALTHCHECK
掌握以上指令即可覆盖 99% 的构建场景。
样例
# 使用更小的基础镜像
FROM python:3.9-alpine3.16
# 安装依赖
RUN apk add --no-cache \
tzdata \
shadow \
&& rm -rf /var/cache/apk/*
# 设置工作目录
WORKDIR /opt/autumn/ssh_monitor
# 复制脚本文件
COPY ssh_monitor.py /opt/autumn/ssh_monitor/ssh_monitor.py
# 安装 Python 依赖
RUN pip install --no-cache-dir dingtalkchatbot==1.5.0
# 创建日志目录
RUN mkdir -p /opt/autumn/ssh_monitor && touch /opt/autumn/ssh_monitor/ssh_monitor.log && chmod 644 /opt/autumn/ssh_monitor/ssh_monitor.log
# 添加健康检查
HEALTHCHECK --interval=5m --timeout=3s \
CMD pgrep -f 'python /opt/autumn/ssh_monitor/ssh_monitor.py' || exit 1
# 设置容器启动命令
CMD ["python", "/opt/autumn/ssh_monitor/ssh_monitor.py"]
# 暴露必要的文件系统
VOLUME ["/var/log"]
1. 基础镜像
FROM python:3.9-alpine3.16
- 使用
python:3.9-alpine3.16作为基础镜像。 - Alpine 镜像体积极小(≈5 MB),再叠加 Python 运行时,整体镜像可以控制在 50 MB 左右。
- 注意:Alpine 采用 musl libc,如果依赖的 Python 包需要编译 C 扩展,有可能因为缺少
musl-dev、gcc等工具而失败。
2. 安装系统依赖
RUN apk add --no-cache \
tzdata \
shadow \
&& rm -rf /var/cache/apk/*
-
tzdata:设置时区用;脚本里如果要按北京时间写日志就需要它。 -
shadow:提供useradd/groupadd等管理用户/组的工具;如果你后面想切非 root 用户会用到。 -
--no-cache与rm -rf /var/cache/apk/*作用相同:避免把 apk 缓存留在镜像层里,减小体积。 - 这两包加起来不到 3 MB,对体积影响很小。
3. 创建工作目录
WORKDIR /opt/autumn/ssh_monitor
- 设置容器内工作目录,如果目录不存在 Docker 会自动创建。
- 后续所有相对路径命令都会以该目录为基准。
4. 复制脚本
COPY ssh_monitor.py /opt/autumn/ssh_monitor/ssh_monitor.py
- 把本地同目录下的
ssh_monitor.py拷贝到镜像的指定位置。 - 建议:如果脚本需要配置文件、模板等,可以改成
COPY . .一次性复制整个目录,再写.dockerignore排除不需要的文件。
5. 安装 Python 依赖
RUN pip install --no-cache-dir dingtalkchatbot==1.5.0
- 安装钉钉机器人 SDK。
-
--no-cache-dir同样是为了避免 pip 缓存留在镜像层里。 - 如果后面依赖增多,建议把
requirements.txt先 COPY 进来,再pip install -r requirements.txt,这样依赖变化时可以利用 Docker 缓存,减少构建时间。
6. 创建日志文件并赋权
RUN mkdir -p /opt/autumn/ssh_monitor && \
touch /opt/autumn/ssh_monitor/ssh_monitor.log && \
chmod 644 /opt/autumn/ssh_monitor/ssh_monitor.log
- 这三步其实可以合并成一句:
RUN touch ssh_monitor.log && chmod 644 ssh_monitor.log
因为上一步WORKDIR已经把目录创建好了。 - 文件权限 644:所有者可读写,组/其他只读;如果容器里用非 root 用户运行,记得改成该用户可写。
7. 健康检查
HEALTHCHECK --interval=5m --timeout=3s \
CMD pgrep -f 'python /opt/autumn/ssh_monitor/ssh_monitor.py' || exit 1
-
每 5 分钟执行一次健康检查,超时 3 秒。
-
检查逻辑:用
pgrep查找包含指定命令行的进程;找不到说明进程挂了,就返回非 0,Docker 会把容器标成unhealthy。 -
注意:
- Alpine 里
pgrep属于procps包,需要提前apk add procps,否则健康检查命令会失败。 - 如果脚本本身会 fork 子进程或改名,则
pgrep可能误判。
- Alpine 里
8. 容器启动命令
CMD ["python", "/opt/autumn/ssh_monitor/ssh_monitor.py"]
-
容器启动后执行的唯一进程就是这句 Python 脚本。
-
如果脚本里有死循环或守护逻辑,这里没问题;否则容器会立刻退出。
-
建议:
- 用
exec形式(数组)而非 shell 形式,确保 PID 1 是 Python 进程,可以正确接收 SIGTERM。 - 如果脚本需要前台持续运行,确保里面有
while True或阻塞式监听。
- 用
9. 声明卷
VOLUME ["/var/log"]
- 只是“声明”了一个挂载点
/var/log,告诉使用者“你可以在这里挂卷”。 - 实际上镜像里并没有往
/var/log写东西,这个声明对镜像构建没影响,也不会自动挂载宿主机目录。 - 如果脚本把日志写到
/opt/autumn/ssh_monitor/ssh_monitor.log,而你想持久化,应该
VOLUME ["/opt/autumn/ssh_monitor"]或启动容器时-v /host/path:/opt/autumn/ssh_monitor。
天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。

浙公网安备 33010602011771号