当前位置: 首页 > news >正文

docker学习(5)-Dockerfile

docker学习(5)-Dockerfile

2026-04-15 18:01  xiashengwang  阅读(0)  评论(0)    收藏  举报

一、Dockerfile 基础

1. Dockerfile是什么
Dockerfile 是一个文本文件,包含了一系列指令,用于自动化构建 Docker 镜像。每个指令都会在镜像中创建一个新的层。

2. 常用指令详解

指令 说明 示例
FROM 指定基础镜像,必须是第一条指令 FROM python:3.9-slim
RUN 在构建时执行命令,用于安装软件包等 RUN apt-get update && apt-get install -y curl
COPY 将本地文件复制到镜像中,推荐使用 COPY app.py /app/
ADD 类似 COPY,但支持自动解压 tar 和 URL 下载 ADD app.tar.gz /app/
WORKDIR 设置工作目录,后续指令在该目录下执行 WORKDIR /app
ENV 设置环境变量 ENV NODE_ENV=production
ARG 定义构建参数,构建时通过 --build-arg 传递 ARG VERSION=latest
EXPOSE 声明容器运行时监听的端口(仅文档作用) EXPOSE 8080
CMD 容器启动时执行的命令,可被 docker run 覆盖 CMD ["python", "app.py"]
ENTRYPOINT 容器启动时执行的命令,不可被覆盖(可追加参数) ENTRYPOINT ["python"]
VOLUME 声明数据卷,用于持久化 VOLUME /data
USER 指定运行用户(安全) USER appuser
LABEL 添加元数据 LABEL version="1.0"
HEALTHCHECK 定义健康检查命令 HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD curl -f http://localhost/ || exit 1

注意:

  • RUN 尽量合并为一条,减少层数。
  • CMDENTRYPOINT 的区别:ENTRYPOINT 定义容器的主要进程,CMD 提供默认参数。通常组合使用:ENTRYPOINT ["python"]CMD ["app.py"],这样 docker run image script.py 可覆盖 app.py

二、镜像分层与构建缓存

1. 镜像分层原理
Docker 镜像由多个只读层叠加而成。每条指令创建一个新层。当运行容器时,在最上面添加一个可写层。
优点:

  • 共享基础层,节省磁盘空间和网络带宽。
  • 构建时利用缓存,如果某层未改变,则直接利用缓存。

2. 构建缓存最佳实践

  • 将不常变化的层放在前面,如依赖安装。
  • 例如,先 COPY requirements.txt,再 RUN pip install,这样只要 requirements.txt 不变,依赖层就会使用缓存。
  • 频繁变化的代码放在后面,如 COPY .

3. 查看镜像历史
docker history <image>
可看到各层的大小和构建指令。

三、编写高效的 Dockerfile

1. 选择合适的基础镜像

  • alpine:体积小(5MB),但可能存在兼容性问题。
  • slim:官方精简版,体积适中(~150MB),推荐用于 Python/Node.js。
  • 全量版:体积大,但包含所有工具,适合开发。
    原则:在满足需求的前提下,选择尽可能小的基础镜像。

2. 减少层数

  • 合并 RUN 指令,例如 RUN apt-get update && apt-get install -y package && rm -rf /var/lib/apt/lists/*
    对于Debian/Ubuntu系(nginx,node,python),安装软件后删除缓存:rm -rf /var/lib/apt/lists/*
    对于Alpine系(node:alpine、nginx:alpine),安装软件后删除缓存:RUN apk add --no-cache 你要装的软件

3. 清理临时文件
在同一个 RUN 中安装后删除缓存,避免镜像臃肿。
比如上面的最后一条命令:rm -rf /var/lib/apt/lists/*

4. 使用 .dockerignore
在同一个 RUN 中安装后删除缓存,避免镜像臃肿。

  • 创建 .dockerignore 文件,排除不需要的文件(如 node_modules.git__pycache__),加快构建并减小上下文。

.dockerignore

# 通用
.git
.gitignore
.env
.DS_Store# Node
node_modules
npm-debug.log
dist# Python
__pycache__
.venv
*.pyc

5. 多阶段构建(Multi-stage Builds)
多阶段构建允许你在一个 Dockerfile 中使用多个 FROM 语句,最终只将需要的产物复制到最终镜像中,极大减小镜像体积。

# 构建阶段
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

上面这段,node:18只是用于编译,真正的输出镜像是基于nginx:alpine的。并且docker有缓存机制,node:18的npm安装不会每次都下载,只要package*.json不变,他就会跳过,节省编译时间。

6. 安全实践

  • 避免以 root 用户运行:创建专用用户并切换。
  • 使用 COPY 而非 ADD,除非需要自动解压。
  • 固定基础镜像版本:避免使用 latest,指定具体标签(如 python:3.9-slim)。

四、实践任务

1:为 Python Flask 应用编写优化的 Dockerfile

  • 使用 python:3.9-slim 作为基础镜像
  • 设置非 root 用户运行
  • 使用多阶段构建?不需要,但可尝试将依赖安装与代码复制分离,利用缓存
  • 最终镜像尽可能小(<200MB)

1)创建dockerfile,如下:

# 使用官方 Python slim 镜像
FROM Python:3.9-slim#环境变量
ENV PYTHONUNBUFFERED=1 \PYTHONDONTWRITEBYTECODE=1#创建非root用户
RUN addgroup --system app && adduser --system --group app# 设置工作目录
WORKDIR /app# 安装系统依赖(如有需要)
RUN apt-get update && apt-get install -y --no-install-recommends gcc && rm -rf /var/lib/apt/lists/*# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt# 复制应用代码
COPY app.py .# 切换到非root用户
USER app# 暴露应用端口
EXPOSE 5000# 启动应用
CMD ["python", "app.py"]

2)构建镜像:
切换到项目的根目录,执行以下命令:
docker build -t flask-app-optimized .
语法是这样的:

docker build    [选项]        [参数]构建      -t 标签      在哪里找Dockerfile

3)查看镜像大小
docker images
怎么感觉比之前那个还大?
image

4)运行容器测试
docker run -d --name my-flask-app-optimized -p 5001:5000 flask-app-optimized
如果出错,可以查看log,命令如下:
docker logs 容器名
image

5)分析镜像层
使用 docker history 分析任一镜像的层大小
image

6)使用 .dockerignore
在项目根目录创建 .dockerignore 文件,内容示例:

__pycache__
*.pyc
*.pyo
*.pyd
.Python
.env
.git
.gitignore
.idea
.vscode
*.log

在构建时就不会使用这些文件,加快构建时间。