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

云原生--核心组件-容器篇-4-认识Dockerfile文件(镜像创建的基础文件和指令介绍)

1、Dockerfile的定义与作用

  • 定义:
    Dockerfile是一个文本文件,包含一系列Docker指令,用于自动化构建Docker镜像。Docker 在构建镜像时会按照Dockerfile中的指令逐步执行,每一行指令都会生成一个新的镜像层(layer)。这些层是只读的,并且可以通过缓存机制提高构建效率,最终生成一个可运行的容器镜像。

  • 核心作用:

    • 标准化镜像构建流程。
    • 确保环境一致性(开发、测试、生产)。
    • 通过分层存储技术提升构建效率。

2、Dockerfile的基本结构

一个典型的Dockerfile包含以下部分:
(1)、基础镜像(Base Image):指定构建镜像的起点。
(2)、元数据定义(Labels):添加镜像的元数据(如作者、版本)。
(3)、构建过程指令:安装依赖、复制文件、设置环境变量,端口暴露等。
(4)、启动指令:定义容器启动时的默认命令。

3、Dockerfile常用指令详解

在这里插入图片描述

(1)、FROM

  • 作用:指定基础镜像,是Dockerfile的第一个指令,后续的构建操作都基于这个基础镜像进行。
  • 语法:
FROM <image>[:<tag>] [AS <name>]

dockerfile示例:

FROM python:3.9-slim     # 使用轻量级的 Python 3.9 基础镜像
FROM ubuntu:20.04 AS build-env     # 为多阶段构建命名阶段
FROM openjdk:17-jdk-slim

(2)、LABEL

  • 作用:为镜像添加元数据标签。
  • 语法:
LABEL <key>=<value> [<key>=<value>...]

dockerfile示例:

LABEL maintainer="john.doe@example.com" \version="1.0" \description="A Python web application"

(3)、RUN

  • 作用:构建过程,在容器中执行命令,常用于安装软件包、配置环境等操作。
  • 语法:
RUN <command>            # Shell格式(默认)
RUN ["executable", "param1", "param2"]     # Exec格式
  • 最佳实践:
    合并多个命令,减少镜像层数。
    dockerfile示例:
RUN apt-get update && apt-get install -y build-essential && rm -rf /var/lib/apt/lists/*

(4)、COPY/ADD

  • COPY:将本地文件/目录复制到镜像中。
  • ADD:功能与COPY类似,但还支持从远程URL复制文件以及自动解压压缩包。
  • 语法:
COPY <src> <dest>
ADD <src> <dest>

dockerfile示例:

COPY requirements.txt /app/requirements.txt     # 复制依赖文件
ADD https://example.com/app.tar.gz /app/      # 下载并解压文件

(5)、WORKDIR

  • 作用:设置工作目录,后续指令(如RUN, COPY,ADD等)都在此目录下执行。
  • 语法:
WORKDIR /path/to/directory

dockerfile示例:

WORKDIR /app

(6)、ENV

  • 作用:设置环境变量。这些环境变量在容器运行时可以被应用程序使用。
  • 语法:
ENV <key>=<value> [ <key>=<value>... ]

dockerfile示例:

ENV PYTHONUNBUFFERED=1 \DATABASE_URL="postgres://user:pass@localhost:5432/mydb"

(7)、EXPOSE

  • 作用:声明容器运行时会监听的端口,但并不实际进行端口映射。
  • 语法:
EXPOSE <port> [<port>...]

dockerfile示例:

EXPOSE 8000

(8)、CMD/ENTRYPOINT

  • CMD:定义容器启动时默认执行的命令(如果有多个,仅最后一个生效)。
  • ENTRYPOINT:与CMD类似,优先级高于CMD,也是用于指定容器启动时执行的命令,但ENTRYPOINT不会被docker run后面的命令覆盖,而CMD则可能会被覆盖。
  • 语法:
CMD ["executable", "param1", "param2"]    # 推荐exec格式
ENTRYPOINT ["executable", "param1"]

dockerfile示例:

CMD ["python", "app.py"]                 # 默认启动命令
ENTRYPOINT ["nginx", "-g", "daemon off;"]      # 固定启动命令

(9)、ARG

  • 作用:定义构建时变量(仅在构建过程中有效)。在构建镜像时可以通过–build-arg参数传递值。
  • 语法:
ARG <name>[=<default value>]

dockerfile示例:

ARG BUILD_VERSION=1.0
RUN echo "Build Version: $BUILD_VERSION" > version.txt

4、Dockerfile示例

(1)、Python Web应用

Dockerfile示例:

# 1. 指定基础镜像
FROM python:3.9-slim# 2. 设置工作目录
WORKDIR /app# 3. 复制 requirements.txt 文件到镜像中
COPY requirements.txt .# 4. 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt# 5. 复制当前目录下的所有文件到镜像的工作目录中
COPY . .# 6. 暴露应用程序运行的端口
EXPOSE 5000# 7. 设置环境变量
ENV FLASK_APP=app.py
ENV FLASK_ENV=development# 8. 指定容器启动时运行的命令
CMD ["flask", "run", "--host=0.0.0.0"]

解释:

  1. FROM python:3.9-slim
  • 作用:指定基础镜像。
  • 解释:这里使用的是官方的Python 3.9精简版镜像(slim表示精简版,体积较小)。它是构建其他镜像的基础。
  1. WORKDIR /app
  • 作用:设置工作目录。
  • 解释:在镜像中创建一个/app目录,并将其设置为后续指令的工作目录。如果目录不存在,Docker会自动创建它。
  1. COPY requirements.txt .
  • 作用:将本地文件复制到镜像中。
  • 解释:将主机上的requirements.txt文件复制到镜像的/app目录下。
  1. RUN pip install --no-cache-dir -r requirements.txt
  • 作用:运行命令安装依赖。
  • 解释:使用pip安装requirements.txt中列出的所有Python依赖项。–no-cache-dir参数避免缓存以减小镜像体积。
  1. COPY . .
  • 作用:复制文件。
  • 解释:将主机当前目录下的所有文件(包括子目录)复制到镜像的/app目录中。
  1. EXPOSE 5000
  • 作用:声明容器对外暴露的端口。
  • 解释:告诉Docker容器运行时会监听5000端口。注意,这只是声明,不会自动发布端口,实际运行时需要通过-p参数映射端口。
  1. ENV FLASK_APP=app.py和ENV FLASK_ENV=development
  • 作用:设置环境变量。
  • 解释:
    • FLASK_APP指定Flask应用程序的入口文件。
    • FLASK_ENV设置Flask的运行模式为开发模式(启用调试功能)。
  1. CMD [“flask”, “run”, “–host=0.0.0.0”]
  • 作用:指定容器启动时运行的默认命令。
  • 解释:当容器启动时,会运行flask run --host=0.0.0.0命令,启动Flask开发服务器并监听所有网络接口。

(2)、Java Web示例

Spring Boot的Java应用程序镜像构建示例。
Dockerfile示例:

# 1. 使用Maven基础镜像构建阶段
FROM maven:3.8.6-openjdk-17 AS build# 2. 设置工作目录
WORKDIR /app# 3. 复制Maven配置文件(如果需要)
COPY pom.xml .# 4. 下载依赖项
RUN mvn dependency:go-offline# 5. 复制项目源代码
COPY src ./src# 6. 构建应用程序
RUN mvn clean package -DskipTests# 7. 使用运行时基础镜像
FROM openjdk:17-jdk-slim# 8. 设置工作目录
WORKDIR /app# 9. 从构建阶段复制 JAR 文件
COPY --from=build /app/target/my-springboot-app.jar /app/my-springboot-app.jar# 10. 暴露应用程序端口
EXPOSE 8080# 11. 启动应用程序
ENTRYPOINT ["java", "-jar", "my-springboot-app.jar"]

解释:

  1. FROM maven:3.8.6-openjdk-17 AS build
  • 作用:指定基础镜像,并为构建阶段命名。
  • 解释:
    • 使用官方的Maven 3.8.6镜像,内置OpenJDK 17。
    • AS build定义了一个构建阶段,后续可以通过COPY --from引用。
  1. WORKDIR /app
  • 作用:设置工作目录。
  • 解释:在镜像中创建/app目录,并将其作为后续指令的工作目录。
  1. COPY pom.xml .
  • 作用:将主机上的pom.xml文件复制到镜像中。
  • 解释:Maven项目的核心配置文件,定义了项目的依赖项和构建步骤。
  1. RUN mvn dependency:go-offline
  • 作用:下载依赖项并使构建过程离线化。
  • 解释:
    • mvn dependency:go-offline下载所有依赖项到本地缓存。
    • 这样可以减少后续构建时间,并避免网络波动对构建的影响。
  1. COPY src ./src
  • 作用:复制项目源代码。
  • 解释:将主机上的src目录复制到镜像的/app/src中。
  1. RUN mvn clean package -DskipTests
  • 作用:编译、打包项目。
  • 解释:
    • mvn clean清理旧的构建文件。
    • mvn package 打包项目,生成可运行的 JAR 文件。
    • -DskipTests 跳过测试以加速构建(生产环境中建议单独运行测试)。
  1. FROM openjdk:17-jdk-slim
  • 作用:指定运行时基础镜像。
  • 解释:
    • 使用更轻量级的OpenJDK 17镜像作为运行时环境。
    • 这是最终镜像的基础,只包含运行应用程序所需的组件。
      说明:
      使用maven:3.8.6-openjdk-17作为构建阶段,使用openjdk:17-jdk-slim作为运行时阶段。这种方式可以显著减小最终镜像的体积,因为它只包含运行应用程序所需的组件。
  1. WORKDIR /app
  • 作用:设置工作目录。
  • 解释:在运行时镜像中创建/app目录,并将其作为工作目录。
  1. COPY --from=build /app/target/my-springboot-app.jar /app/my-springboot-app.jar
  • 作用:从构建阶段复制生成的JAR文件。
  • 解释:
    • –from=build引用前面定义的构建阶段。
    • 将构建阶段生成的my-springboot-app.jar文件复制到运行时镜像的/app目录。
  1. EXPOSE 8080
  • 作用:声明容器对外暴露的端口。
  • 解释:告诉Docker容器运行时会监听8080端口。实际运行时需要通过-p参数映射端口。
  1. ENTRYPOINT [“java”, “-jar”, “my-springboot-app.jar”]
  • 作用:指定容器启动时运行的命令。
  • 解释:
    • 使用java -jar命令运行JAR文件。
    • ENTRYPOINT不会被覆盖,适合定义不可变的启动命令。

5、构建与运行镜像

构建命令示例:

docker build -t my-flask-app:1.0 .     # 构建并标记镜像
docker build --no-cache .             # 忽略缓存,强制重新构建
docker build --build-arg VERSION=2.0 .   # 传递构建参数

解释:
最后的.表示Dockerfile所在的路径

运行容器示例:

docker run -d -p 5000:5000 --name my-app my-flask-app:1.0

6、Dockerfile最佳实践

(1)、轻量级基础镜像

优先选择*-slim或*-alpine版本(如python:3.9-slim)。

(2)、合并RUN命令:

减少镜像层数,提高构建速度。

bash示例:

RUN apt-get update && apt-get install -y <package> && rm -rf /var/lib/apt/lists/*

(3)、多阶段构建

分离构建环境和运行环境,减少最终镜像体积。

(4)、缓存优化

将不常变化的指令放在前面(如依赖安装),常变化的放在后面(如代码复制)。

(5)、使用.dockerignore

排除不必要的文件(如.git, node_modules)。

(6)、安全加固

使用非root用户运行容器(通过USER 指令)。

7、常见问题与解决方案

(1)、镜像体积过大?

  • 解决方案:
    • 使用多阶段构建。
    • 选择轻量级基础镜像(如alpine)。
    • 清理构建过程中的临时文件(如apt-get clean)。

(2)、构建缓存失效?

  • 原因:Docker会缓存每一层的构建结果,如果某层指令变化,则后续层会重新构建。
  • 解决:
    • 保持依赖文件(如requirements.txt)在代码的前面。
    • 使用–no-cache强制重新构建。

(3)、容器启动失败?

  • 常见原因:
    • 工作目录未正确设置。
    • 启动命令未指定(缺少CMD或ENTRYPOINT)。
  • 解决:

dockerfile示例:

WORKDIR /app
CMD ["python", "app.py"]

8、总结

  • Dockerfile 是容器化应用的核心,通过标准化构建流程确保环境一致性。
  • 关键指令:FROM, RUN, COPY, CMD, ENTRYPOINT 是构建镜像的基础。
  • 最佳实践:轻量基础镜像、多阶段构建、缓存优化是提升效率的关键。

逆风前行,Dare To Be!!!

相关文章:

  • 企业数据赋能 | 应用模板分享:汽车销售仪表板
  • 《一键式江湖:Docker Compose中间件部署108式》开篇:告别“配置地狱”,从此笑傲云原生武林!》
  • 以科技之力,启智慧出行 —— 阅读《NVIDIA 自动驾驶安全报告》及观看实验室视频有感
  • 【计算机视觉】CV实战项目- Four-Flower:基于TensorFlow的花朵分类实战指南
  • 大数据学习栈记——Hive4.0.1安装
  • 运算符分为哪几类?哪些运算符常用作判断?简述运算符的优先级
  • MCP+A2A协议终极指南:AI系统构建技术全解析(医疗/金融实战+Streamable HTTP代码详解)
  • Vue Router 核心指南:构建高效单页应用的导航艺术
  • Spring MVC 拦截器教程
  • 08-STM32外部中断
  • 【题解-Acwing】861. 二分图的最大匹配
  • 云原生 | K8S中数据存储之StorageClass
  • MAGI-1: Autoregressive Video Generation at Scale
  • 【MySQL】数据类型和表的操作
  • 在 UniApp 中实现 App 与 H5 页面的跳转及通信
  • prometheus手动添加k8s集群外的node-exporter监控
  • 【Linux网络】Http服务优化 - 增加请求后缀、状态码描述、重定向、自动跳转及注册多功能服务
  • 基于RuoYi的WMS仓库管理系统源码级解决方案
  • spring框架学习(下)
  • Excel如何安装使用EPM插件并且汉化?
  • 最高法知产庭年度报告:民事案件二审发回重审率持续下降
  • 一图读懂|上海海关公布一季度数据:钢材出口增长超143%
  • 商务部:汽车流通消费改革试点正在加快推进
  • 在黄岩朵云书院,邂逅陈丹燕与月季花的故事
  • “今日海上”对话“今日维也纳”,东西方艺术在上海碰撞
  • 影子调查丨掉落的喷淋头:太原一7天酒店加盟店消防设施造假迷局