【Docker】Dockerfile 编写实践

news2025/4/13 20:38:48

👻创作者:丶重明
👻创作时间:2025年4月8日
👻擅长领域:运维

目录

  • 1. Dockerfile编写原则
    • 1.1.选择合适的基础镜像
    • 1.2.镜像层优化
    • 1.3.多阶段构建
    • 1.4.安全增强
  • 2. 关键指令与技巧
    • 2.1.COPY vs ADD
    • 2.2.ENTRYPOINT vs CMD
    • 2.3.健康检查
    • 2.4.环境变量管理
  • 3. 实战:构建Prometheus镜像
  • 4. 附页:Dockerfile指令

1. Dockerfile编写原则

1.1.选择合适的基础镜像

基础镜像的选择直接影响镜像的安全性、体积和可维护性。可以从这三个方面考虑:

  • 最小化原则:优先使用轻量级镜像
  • 安全扫描:定期检查基础镜像漏洞(使用 docker scan)
  • 固定版本:避免使用latest标签,明确指定版本号

示例:

# 推荐,这个镜像很小,仅有8MB左右
alpine:3.21.3

# 不推荐,基础镜像过大,版本号不明确
ubuntu:latest

1.2.镜像层优化

Docker 镜像由只读层(Layer)堆叠而成,每一层对应 Dockerfile 中的一条指令。优化层的核心逻辑是减少层数和层体积。

  • 合并指令:通过&& \合并多个RUN命令
  • 清理缓存:在同一个RUN层中删除临时文件
  • 层顺序:将高频变化的层(如代码)放在最后

示例:

# 通过&& \这种方式将多个命令合并为一层
RUN apk add --no-cache curl tar && \
    curl -LO https://example.com/pkg.tar.gz && \
    tar -xzf pkg.tar.gz && \
    rm pkg.tar.gz

1.3.多阶段构建

多阶段构建(Multi-stage Build)是减少生产镜像体积的杀手锏。其核心思想是:用“胖”镜像构建,用“瘦”镜像运行。

  • 分离构建环境与运行时环境
  • 减少最终镜像体积

1.4.安全增强

容器安全是生产环境的核心要求。以下是三个关键实践:

  • 非root用户运行
  • 限制文件系统写入权限
  • 使用 .dockerignore 排除敏感文件

示例:

RUN addgroup -S appgroup && \
    adduser -S appuser -G appgroup
USER appuser

2. 关键指令与技巧

2.1.COPY vs ADD

  • 优先使用COPY:仅用于复制本地文件
  • 谨慎使用ADD:自动解压压缩包,可能引入意外行为

2.2.ENTRYPOINT vs CMD

  • ENTRYPOINT:定义容器主进程
  • CMD:提供默认参数

示例:

ENTRYPOINT ["/bin/prometheus"]
CMD ["--config.file=/etc/prometheus/prometheus.yml"]

2.3.健康检查

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:9090/-/healthy || exit 1

这一层命令的含义是:

  • HEALTHCHECK:为容器设定健康检查机制
  • --interval=30s:健康检查的时间间隔
  • --timeout=3s:健康检查命令的超时时间
  • CMD ...:具体的健康检查命令

每隔 30 秒就向http://localhost:9090/-/healthy发送一个 HTTP 请求,并且要求在 3 秒内完成。

若请求成功(状态码为 200 - 399),则判定容器健康;若请求失败或者超时,就判定容器不健康。

2.4.环境变量管理

  • 使用 ENV 定义常量
  • 敏感数据通过 --env-file 或 Secrets 传递

3. 实战:构建Prometheus镜像

dockerfile目录结构:直接在外部目录解压

# tree /prom_docker/
/prom_docker/
├── dockerfile
└── prometheus
    ├── LICENSE
    ├── NOTICE
    ├── prometheus
    ├── prometheus.yml
    └── promtool

1 directory, 6 files

完整的Dockerfile文件:

FROM alpine:3.21.3

# 创建非特权用户
RUN addgroup -S prometheus && \
    adduser -S -D -H -s /bin/false -G prometheus prometheus && \
    mkdir -p /etc/prometheus /prometheus && \
    chown -R prometheus:prometheus /etc/prometheus /prometheus

# 复制必要文件
COPY prometheus/LICENSE prometheus/NOTICE .
COPY prometheus/prometheus \
    prometheus/promtool \
    /usr/local/bin/
COPY prometheus/prometheus.yml \
    /etc/prometheus/

# 设置运行时参数
USER prometheus
WORKDIR /prometheus
EXPOSE 9090
VOLUME ["/prometheus"]

# 健康检查(使用 promtool 无依赖)
HEALTHCHECK --interval=30s --timeout=10s \
  CMD ["/usr/local/bin/promtool", "check", "healthy", "--prometheus-url=http://localhost:9090"]

# 入口指令
ENTRYPOINT ["/usr/local/bin/prometheus"]
CMD [ \
    "--config.file=/etc/prometheus/prometheus.yml", \
    "--storage.tsdb.path=/prometheus", \
    "--web.enable-lifecycle", \
    "--web.external-url=/" \
]

构建镜像:

[root@localhost prom_docker]# docker build -t prometheus:v3.2.1 .

运行测试:

# docker run -d -p 9090:9090 --name prometheus-1 2c7c81224aa2
b91210a45af9f60c93c7e6652480da8d98a9077818cd2e75c769e3670ec1429d

在这里插入图片描述

4. 附页:Dockerfile指令

以下是 Dockerfile 中常见指令及其功能、语法和示例的表格:

指令功能语法示例
FROM指定基础镜像,是 Dockerfile 的起始指令FROM <image>[:<tag>][@<digest>]FROM python:3.9
RUN在新的镜像层中执行命令,常用于安装软件包等操作RUN <command>(shell 形式)
RUN ["executable", "param1", "param2"](exec 形式)
RUN apt-get update && apt-get install -y python3
RUN ["pip", "install", "flask"]
CMD为容器提供默认的执行命令,一个 Dockerfile 中只能有一个 CMD,若有多个则只有最后一个生效CMD ["executable","param1","param2"](exec 形式)
CMD command param1 param2(shell 形式)
CMD ["param1","param2"](为 ENTRYPOINT 提供默认参数)
CMD ["python", "app.py"]
CMD python app.py
LABEL为镜像添加元数据,如作者、版本等信息LABEL <key>=<value> <key>=<value> ...LABEL maintainer="example@example.com" version="1.0"
EXPOSE声明容器运行时监听的网络端口,但不进行端口映射EXPOSE <port> [<port>/<protocol> ...]EXPOSE 8080
EXPOSE 80/tcp 443/tcp
ENV设置环境变量,在容器运行时可使用ENV <key>=<value> ...ENV APP_NAME=myapp
ENV DB_HOST=localhost DB_PORT=5432
ADD将文件、目录或远程文件复制到镜像中,若复制的是压缩文件会自动解压ADD <src>... <dest>ADD app.tar.gz /app
ADD http://example.com/file.txt /tmp/
COPY将文件或目录从构建上下文复制到镜像中,不具备自动解压和远程文件处理功能COPY <src>... <dest>COPY requirements.txt /app/
ENTRYPOINT配置容器启动时执行的命令,可与 CMD 结合使用ENTRYPOINT ["executable", "param1", "param2"](exec 形式)
ENTRYPOINT command param1 param2(shell 形式)
ENTRYPOINT ["python", "app.py"]
VOLUME创建挂载点,用于将主机目录或数据卷挂载到容器中VOLUME ["/data"]VOLUME ["/var/lib/mysql"]
USER指定后续 RUNCMDENTRYPOINT 指令执行时的用户和用户组USER <user>[:<group>]USER myuser
WORKDIR设置工作目录,后续的 RUNCMDENTRYPOINTCOPYADD 指令都会在该目录下执行WORKDIR /path/to/workdirWORKDIR /app
ARG定义构建时的变量,在构建镜像时可通过 --build-arg 传递值ARG <name>[=<default value>]ARG VERSION=1.0
docker build --build-arg VERSION=2.0 .
ONBUILD定义一个触发器,当该镜像被用作其他镜像的基础镜像时,这些指令会在后续的 FROM 指令之后执行ONBUILD <INSTRUCTION>ONBUILD COPY . /app
STOPSIGNAL设置停止容器时发送的系统调用信号STOPSIGNAL signalSTOPSIGNAL SIGTERM
HEALTHCHECK配置容器的健康检查命令HEALTHCHECK [OPTIONS] CMD <command>
HEALTHCHECK NONE
HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
SHELL覆盖默认的 shell 命令,用于 RUNCMDENTRYPOINT 指令的 shell 形式SHELL ["executable", "parameters"]SHELL ["/bin/bash", "-c"]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331915.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW商业软件开发注意问题

在 LabVIEW 商业软件开发进程中&#xff0c;性能优化、界面设计及兼容性与扩展性&#xff0c;对软件品质、用户体验和市场适配性起着决定性作用。下面&#xff0c;借助多个LabVIEW 编程特性的实际案例&#xff0c;深入分析这些方面的开发要点。 一、性能优化&#xff1a;提升软…

Java 中 SQL 注入问题剖析​

一、引言​ 在当今数字化时代&#xff0c;数据是企业和组织的核心资产之一。许多应用程序都依赖于数据库来存储和管理数据&#xff0c;而 Java 作为一种广泛使用的编程语言&#xff0c;常被用于开发与数据库交互的应用程序。然而&#xff0c;SQL 注入这一安全漏洞却如同隐藏在…

深度学习项目--分组卷积与ResNext网络实验探究(pytorch复现)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 ResNext是分组卷积的开始之作&#xff0c;这里本文将学习ResNext网络&#xff1b;本文复现了ResNext50神经网络&#xff0c;并用其进行了猴痘病分类实验…

CSS 笔记——Flexbox(弹性盒布局)

目录 1. Flex 容器与 Flex 项目 2. 主轴与交叉轴 3. Flex 容器的属性 display flex-direction justify-content align-items align-content flex-wrap 4. Flex 项目的属性 flex-grow flex-shrink flex-basis flex align-self 5. Flexbox 的优点 6. Flexbox 的…

cpp(c++)win 10编译GDAL、PROJ、SQLite3、curl、libtiff

cpp&#xff08;c&#xff09;编译GDAL、PROJ、SQLite3 Sqlite3libtiffcurlprojGDAL Sqlite3 1、下载 Sqlite3 源码、工具、二进制预编译 exe Sqlite3 官网&#xff1a;https://www.sqlite.org/download.html 下载 sqlite-amalgamation-3430200.zipsqlite-dll-win64-x64-3430…

每日一题(小白)暴力娱乐篇23

由题意得知给我们一串数字&#xff0c;我们每次交换两位&#xff0c;最少交换多少次成功得到有顺序的数组。我们以平常的思维去思考&#xff0c;加入给你一串数字获得最少的交换次数&#xff0c;意味着你的交换后续基本不会变&#xff0c;比如说2 1 3 5 4 中1与2交换后不变&…

01-Redis-基础

1 redis诞生历程 redis的作者笔名叫做antirez&#xff0c;2008年的时候他做了一个记录网站访问情况的系统&#xff0c;比如每天有多少个用户&#xff0c;多少个页面被浏览&#xff0c;访客的IP、操作系统、浏览器、使用的搜索关键词等等(跟百度统计、CNZZ功能一样)。最开始存储…

【从零开始学习JVM | 第一篇】快速认识JVM

什么是JVM&#xff1f; JVM--Java虚拟机&#xff0c;它是Java实现平台无关性的基石。 Java程序运行的时候&#xff0c;编译器将Java代码编译为平台无关的Java字节码文件&#xff08;.class&#xff09;&#xff0c;接下来对应平台的JVM对字节码进行运行解释&#xff0c;翻译成…

使用RabbitMQ实现异步秒杀

搭建RabbitMQ 在虚拟机上用docker搭建RabbitMQ&#xff0c;首先拉取镜像 docker run --privilegedtrue -d -p 5672:5672 -p 15672:15672 --name rabbitmq rabbitmq:management mkdir -p /usr/local/docker/rabbitmq再创建rabbitmq容器&#xff0c;下面的命令已经能够创建之后…

解决华硕主板Z890m下载ubuntu20.04后没有以太网问题

问题描述&#xff1a; 华硕主板Z890m下载双系统ubuntu20.04后&#xff0c;发现ubuntu不能打开以太网。 问题原因&#xff1a; 华硕主板的网卡驱动是r8125,而ubuntu20.04的驱动版本是r8169&#xff0c;所以是网卡驱动不匹配造成 解决方案 开机界面按下F2进入BOIS模式&#…

xLua的Lua调用C#的2,3,4

使用Lua在Unity中创建游戏对象&#xff0c;组件&#xff1a; 相关代码如下&#xff1a; Lua --Lua实例化类 --C# Npc objnew Npc() --通过调用构造函数创建对象 local objCS.Npc() obj.HP100 print(obj.HP) local obj1CS.Npc("admin") print(obj1.Name)--表方法希…

Debian系统_主板作为路由器_测试局域网设备间网速

Debian系统_主板作为路由器_测试局域网设备间网速 一、360软件测网速 360测出来的网速实际上是宽带的速度&#xff0c;并不是路由器LAN口到电脑这一段的网速 二、使用iperf3 进行双向带宽测试 1、开发板端下载软件 //Debian系统或者/Ubuntu sudo apt update && sudo…

从 macos 切换到 windows 上安装的工具类软件

起因 用了很多年的macos, 已经习惯了macos上的操作, 期望能在windows上获得类似的体验, 于是花了一些时间来找windows上相对应的软件. 截图软件 snipaste​​​​​​ windows和macos都有的软件, 截图非常好用 文件同步软件 oneDrive: 尝试了不同的同步软件, 还是微软在各…

JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)

目录 JavaScript中通过array.map(&#xff09;实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等&#xff0c;array.map&#xff08;&#xff09;的使用详解&#xff08;附实际应用代码&#xff09; 一、什么时候该使用Array.map()&#xff0…

SQL优化技术分享:从 321 秒到 0.2 秒的性能飞跃 —— 基于 PawSQL 的 TPCH 查询优化实战

在数据库性能优化领域&#xff0c;TPC-H 测试集是一个经典的基准测试工具&#xff0c;常用于评估数据库系统的查询性能。本文将基于 TPCH 测试集中的第 20个查询&#xff0c;结合 PawSQL 自动化优化工具&#xff0c;详细分析如何通过 SQL 重写和索引设计&#xff0c;将查询性能…

密码学基础——DES算法

前面的密码学基础——密码学文章中介绍了密码学相关的概念&#xff0c;其中简要地对称密码体制(也叫单钥密码体制、秘密密钥体制&#xff09;进行了解释&#xff0c;我们可以知道单钥体制的加密密钥和解密密钥相同&#xff0c;单钥密码分为流密码和分组密码。 流密码&#xff0…

在 Linux 终端中轻松设置 Chromium 的 User-Agent:模拟手机模式与自定义浏览体验

在 Linux 系统中&#xff0c;通过终端灵活控制 Chromium 的行为可以大幅提升工作效率。本文将详细介绍如何通过命令行参数和环境变量自定义 Chromium 的 User-Agent&#xff0c;并结合手机模式模拟&#xff0c;实现更灵活的浏览体验。 为什么需要自定义 User-Agent&#xff1f;…

http页面的加载过程

HTTP/2 核心概念 1.1 流&#xff08;Stream&#xff09; • 定义&#xff1a;HTTP/2 连接中的逻辑通道&#xff0c;用于传输数据&#xff0c;每个流有唯一标识符&#xff08;Stream ID&#xff09;。 • 特点&#xff1a; ◦ 支持多路复用&#xff08;多个流并行传输&#…

MySQL【8.0.41版】安装详细教程--无需手动配置环境

一、MySQL 介绍 1. 概述 MySQL 是一个开源的关系型数据库管理系统&#xff0c;由瑞典公司 MySQL AB 开发&#xff0c;现属于 Oracle 旗下。它基于 SQL&#xff08;结构化查询语言&#xff09;进行数据管理&#xff0c;支持多用户、多线程操作&#xff0c;广泛应用于 Web 应用、…

鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)

还在为组件状态混乱、页面跳转丢参数而头疼&#xff1f; 这篇博客将揭秘如何用鸿蒙ArkTS打造一个漂亮美观的智能计算器&#xff1a; ✅ 输入完整表达式&#xff0c;秒出结果——字符串切割简单计算 ✅ 状态管理黑科技——Provide/Consume 实现跨组件实时响应 ✅ 路由传参实战—…