Dockerfile 详解

一、Dockerfile 基础概念

1.1 什么是 Dockerfile?

Dockerfile 是一个文本文件,包含了一系列用于构建 Docker 镜像的指令。它遵循特定的格式和语法,Docker 引擎通过读取这些指令来自动化构建镜像。以下是其基础示例:

FROM ubuntu:20.04 RUN apt-get update && apt-get install -y nginx COPY index.html /var/www/html/ EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]

1.2 Dockerfile 工作原理

Dockerfile 构建镜像的过程是基于分层存储(layer)的概念。每个指令都会创建一个新的镜像层,这些层是只读的,并且会被缓存以加速后续构建。构建过程大致如下:

  1. 读取Dockerfile:Docker引擎从Dockerfile中读取指令。
  2. 构建上下文:Docker客户端会将构建上下文(通常是Dockerfile所在目录)的所有文件发送给Docker守护进程。因此,为避免构建缓慢,通常使用.dockerignore文件来排除不必要的文件。
  3. 逐行执行指令:Docker引擎按照顺序执行Dockerfile中的指令,每一条指令都会生成一个新的中间镜像层。
  4. 缓存机制:如果指令与之前构建的中间层相同(通过校验和判断),则使用缓存,否则重新执行该指令并生成新的层。
  5. 最终镜像:所有指令执行完毕后,生成最终的镜像。

二、Dockerfile 指令详解

2.1 Dockerfile 常用指令

指令说明
FROM设置构建镜像时使用的基础镜像
MAINTAINER镜像的创建者
RUN构建镜像时用于执行后面跟着的命令行命令(在 docker build 时执行)
CMD类似于 RUN 指令,启动容器时用于执行后面跟着的命令行命令(在 docker run 时执行)
ENTRYPOINT启动容器时会将其后面的命令当作参数,结合CMD 指令的命令一起执行
COPY构建镜像时复制文件或者目录到容器里指定路径
ADD功能与COPY指令类似,不同点在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,ADD 指令会自动复制并解压到 <目标路径>,在不解压的前提下,无法复制 tar 压缩文件(推荐使用 COPY指令)
ENV设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量
ARG构建参数,与 ENV 作用一至。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量
VOLUME定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷
EXPOSE声明端口
WORKDIR指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
USER用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
LABEL用来给镜像添加一些元数据(metadata),以键值对的形式
ONBUILD用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这是执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令

2.2 FROM:指定基础镜像

# 语法FROM<image>[:<tag>][AS<name>]# 示例FROM ubuntu:22.04 FROM python:3.9-slim AS builder FROM --platform=linux/amd64 node:18-alpine

说明:

  • 必须是 Dockerfile 的第一个有效指令(除了 ARG)
  • 可以多次使用,用于多阶段构建
  • AS 为构建阶段命名

2.3 LABEL:添加元数据

# 语法LABEL<key>=<value><key>=<value>...# 示例LABELversion="1.0"LABELmaintainer="john@example.com"LABELdescription="这是一个示例应用"\author="John Doe"\release-date="2024-01-01"

2.4 RUN:执行命令

# 两种格式# 1. shell格式(默认使用 /bin/sh -c)RUNapt-getupdate&&apt-getinstall-y\python3\python3-pip\&&rm-rf /var/lib/apt/lists/*# 2. exec格式(推荐,避免shell解析问题)RUN["apt-get","update"]RUN["apt-get","install","-y","python3"]# 最佳实践:合并多个RUN指令减少镜像层RUNapt-getupdate\&&apt-getinstall-y\curl\wget\git\&&apt-getclean\&&rm-rf /var/lib/apt/lists/*\&&mkdir-p /app

2.5 CMD:容器启动命令

# 三种格式# 1. exec格式(推荐)CMD["executable","param1","param2"]# 2. shell格式CMDcommandparam1 param2# 3. 作为ENTRYPOINT的默认参数CMD["param1","param2"]# 示例CMD["nginx","-g","daemon off;"]CMD["python","app.py"]

重要:

  • 一个 Dockerfile 只能有一个 CMD
  • 会被 docker run 后面的命令覆盖
  • 主要提供容器默认的执行命令

2.6 ENTRYPOINT:入口点

# 两种格式# 1. exec格式(推荐)ENTRYPOINT["executable","param1","param2"]# 2. shell格式ENTRYPOINTcommandparam1 param2# 示例ENTRYPOINT["java","-jar","/app/app.jar"]ENTRYPOINT["/docker-entrypoint.sh"]

ENTRYPOINT vs CMD:

# 组合使用示例ENTRYPOINT["java","-jar","/app/app.jar"]CMD["--spring.profiles.active=prod"]# docker run myapp --debug 将执行:# java -jar /app/app.jar --debug

2.7 COPY:复制文件

# 语法COPY[--chown=<user>:<group>]<src>...<dest># 示例COPY package.json /app/ COPY requirements.txt /app/ COPY --chown=appuser:appgroup app.py /app/ COPY --from=builder /build/app /app/ COPY src/ /app/src/ COPY *.txt /app/# 模式匹配COPY hom* /mydir/# 复制所有以hom开头的文件COPY hom?.txt /mydir/# ? 匹配单个字符

2.8 ADD:增强的复制

# ADD 支持更多功能ADD https://example.com/file.tar.gz /tmp/ ADD file.tar.gz /tmp/# 自动解压tar.gzADD --chown=user:group src dest# 注意事项# 1. 会自动解压tar文件(.tar, .tar.gz, .tar.bz2等)# 2. 支持URL下载# 3. 尽量使用COPY,除非需要ADD的特殊功能

2.9 WORKDIR:设置工作目录

# 语法WORKDIR /path/to/workdir# 示例WORKDIR /app RUNpwd# 输出:/appWORKDIR src RUNpwd# 输出:/app/src# 相对于之前的WORKDIRWORKDIR /opt WORKDIR app RUNpwd# 输出:/opt/app

2.10 ENV:设置环境变量

# 语法ENV<key><value>ENV<key>=<value>...# 示例ENV NODE_ENV production ENV APP_HOME /app ENVPATH/app/bin:$PATH# 多行定义ENVJAVA_HOME=/usr/lib/jvm/java-11-openjdk\PATH=$PATH:$JAVA_HOME/bin

2.11 ARG:构建参数

# 语法ARG<name>[=<default value>]# 示例ARGVERSION=latest ARG USERNAME ARG PASSWORD# 使用ARGFROM ubuntu:${VERSION:-22.04}RUNecho"Building version:$VERSION"# 构建时传递参数# docker build --build-arg VERSION=1.0 --build-arg USERNAME=admin .

2.12 EXPOSE:声明端口

# 语法EXPOSE<port>[<port>/<protocol>...]# 示例EXPOSE80EXPOSE443/tcp EXPOSE8080/udp EXPOSE300050008000# EXPOSE 只是声明,不会实际打开端口。实际端口映射在 docker run 时指定。

2.13 VOLUME:定义数据卷

# 语法VOLUME["/path/to/dir"]VOLUME /var/log /var/db# 示例VOLUME /data VOLUME["/var/log","/var/db"]VOLUME /var/lib/mysql

2.14 USER:指定运行用户

# 语法USER<user>[:<group>]USER<UID>[:<GID>]# 示例USERnobodyUSER1000:1000USERappuser:appgroup# 创建用户示例RUNgroupadd-r appgroup&&useradd-r -g appgroup appuserUSERappuser

2.15 HEALTHCHECK:健康检查

# 语法HEALTHCHECK[OPTIONS]CMDcommandHEALTHCHECK NONE# 禁用从基础镜像继承的健康检查# 选项--interval=DURATION# 检查间隔(默认30s)--timeout=DURATION# 超时时间(默认30s)--start-period=DURATION# 启动宽限期(默认0s)--retries=N# 重试次数(默认3次)# 示例HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3\CMDcurl-f http://localhost:8080/health||exit1HEALTHCHECK CMD pg_isready -U postgres||exit1HEALTHCHECK CMDnc-z localhost80||exit1

2.16 SHELL:指定默认shell

# 语法SHELL["executable","parameters"]# 示例# Windows容器使用PowerShellSHELL["powershell","-Command"]# Linux容器使用bashSHELL["/bin/bash","-c"]

2.17 ONBUILD:延迟执行指令

# 语法ONBUILD<INSTRUCTION># 示例ONBUILD COPY./app/src ONBUILD RUNmake/app/src ONBUILD ADD./app# 使用场景:构建基础镜像FROM node:18 AS base ONBUILD COPY package*.json ./ ONBUILD RUNnpmci ONBUILD COPY..

三、多阶段构建(Multi-stage Builds)

3.1 基本概念

# 第一阶段:构建阶段FROM golang:1.20 AS builder WORKDIR /app COPY..RUN go build -o myapp.# 第二阶段:运行阶段FROM alpine:latest RUN apk --no-cacheaddca-certificates WORKDIR /root/ COPY --from=builder /app/myapp.CMD["./myapp"]

3.2 复杂多阶段示例

# 第一阶段:构建前端FROM node:18 AS frontend-builder WORKDIR /app/frontend COPY frontend/package*.json ./ RUNnpmci COPY frontend/ ./ RUNnpmrun build# 第二阶段:构建后端FROM golang:1.20 AS backend-builder WORKDIR /app/backend COPY backend/ ./ RUNCGO_ENABLED=0GOOS=linux go build -o app.# 第三阶段:生成最终镜像FROM alpine:latest RUN apk --no-cacheaddca-certificates WORKDIR /app# 从前端构建阶段复制构建结果COPY --from=frontend-builder /app/frontend/dist ./public# 从后端构建阶段复制可执行文件COPY --from=backend-builder /app/backend/app.# 从另一个镜像复制文件COPY --from=nginx:alpine /etc/nginx/nginx.conf /etc/nginx/nginx.conf EXPOSE8080CMD["./app"]

四、Dockerfile 最佳实践

4.1 优化镜像大小

# 不推荐:创建多个层RUNapt-getupdate RUNapt-getinstall-y python RUNrm-rf /var/lib/apt/lists/*# 推荐:合并指令RUNapt-getupdate\&&apt-getinstall-y\python3\python3-pip\&&apt-getclean\&&rm-rf /var/lib/apt/lists/*

4.2 使用 .dockerignore 文件

# 忽略文件示例.git .gitignore node_modules *.log *.tmp Dockerfile README.md .env .vscode *.md *.txt

4.3 安全最佳实践

# 1. 使用非root用户RUNgroupadd-r appuser&&useradd-r -g appuser appuserUSERappuser# 2. 使用官方基础镜像FROM alpine:3.18# 3. 定期更新基础镜像# 使用特定版本,而不是latestFROM ubuntu:22.04# 4. 扫描安全漏洞# 构建后运行:docker scan <image-name>

4.4 构建缓存优化

# 将不经常变化的部分放在前面# 1. 安装依赖COPY package.json package-lock.json ./ RUNnpmci# 2. 复制源代码(经常变化)COPY..# 3. 构建应用RUNnpmrun build

五、完整示例

5.1 项目结构

myapp/ ├── Dockerfile ├── .dockerignore ├── requirements.txt ├── app.py └── config/ └── settings.py

5.2 Dockerfile

# 第一阶段:构建阶段FROM python:3.11-slim AS builder WORKDIR /app# 设置环境变量ENVPYTHONDONTWRITEBYTECODE=1\PYTHONUNBUFFERED=1\PIP_NO_CACHE_DIR=1# 安装系统依赖RUNapt-getupdate\&&apt-getinstall-y --no-install-recommends\gcc\g++\libpq-dev\&&apt-getclean\&&rm-rf /var/lib/apt/lists/*# 创建虚拟环境RUN python -m venv /opt/venv ENVPATH="/opt/venv/bin:$PATH"# 安装Python依赖COPY requirements.txt.RUN pipinstall--upgrade pip\&&pipinstall--no-cache-dir -r requirements.txt# 第二阶段:运行阶段FROM python:3.11-slim WORKDIR /app# 创建非root用户RUNgroupadd-r appuser&&useradd-r -g appuser -m -d /app appuser# 从构建阶段复制虚拟环境COPY --from=builder /opt/venv /opt/venv ENVPATH="/opt/venv/bin:$PATH"# 复制应用代码COPY --chown=appuser:appuser..# 切换用户USERappuser# 健康检查HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3\CMD python -c"import requests; requests.get('http://localhost:5000/health', timeout=2)"||exit1# 暴露端口EXPOSE5000# 启动命令ENTRYPOINT["python"]CMD["app.py"]

5.3 .dockerignore 文件

# 依赖缓存__pycache__/ *.py[cod]*$py.class# 虚拟环境venv/ env/ .env# IDE.vscode/ .idea/ *.swp *.swo# 日志*.log# 测试tests/ .coverage htmlcov/# 其他.DS_Store .git/ .gitignore README.md docker-compose.yml

六、构建和测试

6.1 构建镜像

# 基本构建docker build -t myapp:1.0.# 使用构建参数docker build\--build-argVERSION=2.0\--build-argENVIRONMENT=prod\-t myapp:2.0.# 多阶段构建指定阶段docker build --target builder -t myapp:builder.# 使用不同的Dockerfiledocker build -f Dockerfile.prod -t myapp:prod.

6.2 测试镜像

# 运行容器docker run -d -p5000:5000 --name myapp myapp:1.0# 检查容器状态dockerpsdocker logs myapp# 执行健康检查docker inspect --format='{{.State.Health.Status}}'myapp# 进入容器dockerexec-it myappsh# 测试应用curlhttp://localhost:5000/health

七、高级技巧

7.1 使用 ARG 和 ENV

# 构建时可以覆盖的变量ARGNODE_ENV=production# 构建时设置的变量,运行时也可用ENVNODE_ENV=${NODE_ENV}# 构建时传递密码(不推荐,会被记录在镜像历史中)ARG DB_PASSWORD RUNecho"Password is:$DB_PASSWORD"

7.2 构建缓存控制

# 使用 --no-cache 构建:docker build --no-cache -t myapp .# 或使用特定指令禁用缓存ADD http://example.com/file.tar.gz /tmp/# 上面的ADD会禁用这一层及之后的所有缓存# 使用特定的缓存键RUN --mount=type=cache,target=/var/cache/apt\apt-getupdate&&apt-getinstall-y package

7.3 构建上下文优化

# 创建小构建上下文# 1. 使用 .dockerignore 排除不必要文件# 2. 将 Dockerfile 放在项目根目录# 3. 将构建上下文限制在必需文件

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

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

相关文章

探索非线性电液伺服系统:从PID到反步控制的奇妙之旅

非线性电液伺服系统精确模型反步控制。 pdf教程matlab/simulink源码。 与pid控制对比。嘿&#xff0c;各位技术宅们&#xff01;今天咱们要一起钻进非线性电液伺服系统的神秘世界&#xff0c;好好聊聊精确模型反步控制这一厉害的技术&#xff0c;顺便还会把它和经典的PID控制来…

【大模型预训练】18-分布式并行技术:梯度同步、参数服务器架构实现方法

引言分布式并行技术在深度学习领域的重要性不言而喻&#xff0c;尤其是在处理大规模数据和复杂模型时&#xff0c;其作用尤为显著。随着深度学习模型的不断发展和数据量的爆炸式增长&#xff0c;传统的单机训练方式已难以满足高效计算的需求。分布式并行技术通过将计算任务分配…

探索Comsol双温模型在半导体飞秒激光研究中的应用

comsol双温模型半导体 飞秒激光在现代光学和半导体物理领域&#xff0c;飞秒激光与半导体材料的相互作用一直是研究热点。而Comsol Multiphysics这款强大的多物理场仿真软件&#xff0c;为我们深入理解这一复杂过程提供了有力工具&#xff0c;其中双温模型更是关键所在。 飞秒激…

线性回归和回归决策树(CART)对比

3. CART树&#xff1a;既可做分类也可做回归&#xff0c;分类时用基尼值作为划分依据&#xff0c;回归时用平方损失&#xff08;类似最小二乘法&#xff09;衡量误差。 ​4. 回归决策树的深度影响&#xff1a;树的深度越小&#xff0c;模型越简单&#xff0c;易欠拟合&#xff…

【硕士生必看】硕士论文被退稿?可能是AI惹的祸!Paperzz智能降重+降AIGC,守护你的学术尊严!

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿 https://www.paperzz.cc/weighthttps://www.paperzz.cc/weight 副标题&#xff1a; 硕士论文查重率低≠安全&#xff01;AIGC检测才是盲审“生死线”&#xff01;Paperzz三步操作&#xff0c;10分钟将AI痕迹…

三相并联型有源电力滤波器APF仿真探索

三相并联型有源电力滤波器APF仿真&#xff08;电压外环电流内环均为PI控制&#xff09;&#xff0c;id-iq谐波检测方法&#xff0c;SVPWM调制方法。在电力系统领域&#xff0c;谐波问题一直是影响电能质量的关键因素。三相并联型有源电力滤波器&#xff08;APF&#xff09;作为…

六自由度机械臂抓取动作仿真:两套易懂代码解析

六自由度机械臂抓取动作仿真-8 两套关于抓取动作的代码&#xff0c;包括抓取动画、关节角、角速度、角加速度的变化仿真、以及抓取轨迹图 简单易懂好上手&#xff5e;在六自由度机械臂抓取动作仿真的领域中&#xff0c;为大家分享两套超实用的代码&#xff0c;助力快速上手相关…

Day32 类的定义和方法

题目 1&#xff1a;定义圆&#xff08;Circle&#xff09;类 # 示例运行 circle Circle(5) print(f"半径: {circle.radius}") print(f"面积: {circle.calculate_area()}") print(f"周长: {circle.calculate_circumference()}") 题…

货运 app 运输管理系统框架搭建

一、货运搬家系统&#xff1a;让货运搬家更高效、更便捷在当今快节奏的生活和商业环境中&#xff0c;货运搬家是人们和企业经常面临的需求。无论是个人搬家、企业搬迁&#xff0c;还是货物运输&#xff0c;都需要一个高效、便捷的解决方案。而货运搬家系统的出现&#xff0c;正…

匠魂的熔炼注册

匠魂的熔炼系统 代码概述 这是熔炼系统的主要注册类,负责注册: 所有熔炉相关的方块(加热块、焦黑块、各种功能方块) 熔炼相关的物品(模具、铸件等) 方块实体类型 配方序列化器 GUI容器 创造模式标签页 关键部分分析 1. 合金相关定义位置 合金相关的注册在以下位置: …

Simulink导弹制导系统仿真:从模型到实战模拟

Simulink导弹制导系统仿真 模型文件 使用指南 视频讲解在现代军事科技与航空航天领域&#xff0c;Simulink凭借其强大的建模仿真能力&#xff0c;成为了导弹制导系统开发与研究的得力助手。今天咱就来唠唠Simulink导弹制导系统仿真那些事儿&#xff0c;涵盖模型文件、使用指南&…

Socket编程与编码转换实战指南

一、引言昨天讲了网络编程里it和tcp的一些相关概念,今天讲一下编码转换和socket网络编程二、编码转换1.为什么要学习编码转换在计算机网络中&#xff0c;数据都是以二进制的形式进行传输的。所以在网络传输数据的时候&#xff0c;数据需要先编码转化为二进制&#xff08;bytes&…

【博士生必看】博士论文被退稿?可能是AI惹的祸!Paperzz智能降重+降AIGC,守护你的学术尊严!

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿 https://www.paperzz.cc/weighthttps://www.paperzz.cc/weight 副标题&#xff1a; 博士论文查重率5%≠安全&#xff01;AIGC检测才是学位“终极审判”&#xff01;Paperzz三步操作&#xff0c;10分钟将AI痕…

粒子群算法在风光储微电网优化调度中的应用:经济目标下的电源侧与负荷侧运行策略优化

基于粒子群算法的考虑需求侧响应的风光储微电网优化调度 考虑电源侧与负荷侧运行成本&#xff0c;以经济运行为目标函数&#xff0c;风电、光伏、储能出力、上级电网购电记忆可削减负荷为优化变量&#xff0c;并采用粒子群算法进行求解。1. 系统概述 本项目实现了一个基于多目标…

PRML为何是机器学习的经典书籍中的经典?

PRML&#xff08;Pattern Recognition and Machine Learning&#xff0c;中文名《模式识别与机器学习》&#xff09;被誉为机器学习领域的“圣经”&#xff0c;其经典性体现在内容深度与广度、理论框架的统一性、数学严谨性、结构合理性、实践资源丰富性等多个方面&#xff0c;…

【paperzz免费文献】5分钟搞定百篇文献?Paperzz一键生成文献综述,导师都说“这孩子真会用工具”!

Paperzz-AI官网免费论文查重复率AIGC检测/开题报告/文献综述/论文初稿 https://www.paperzz.cc/journalsReviewedhttps://www.paperzz.cc/journalsReviewed 副标题&#xff1a; 专科论文不用熬通宵&#xff01;只需输入标题→粘贴文献→等5分钟&#xff0c;一份逻辑清晰、内容充…

晶体塑性有限元多晶Voronoi模型生成:Neper软件在Linux系统下的神奇之旅

晶体塑性有限元多晶voronoi模型生成&#xff0c;Linux系统下的Neper软件&#xff0c;无需复杂安装&#xff0c;下载即可使用&#xff01; 在材料科学与工程领域&#xff0c;晶体塑性有限元多晶Voronoi模型的生成是一项关键任务&#xff0c;它对于理解材料在微观结构层面的力学行…

核技巧

好的,我们来深入解释核技巧(Kernel Trick)。这是机器学习和函数分析中一个极其优雅且强大的数学工具。 核技巧的核心思想 核技巧允许我们在不显式计算(甚至不知道)高维特征映射的情况下,直接计算高维特征空间中的…

Redis缓存三大问题详解:击穿、穿透与雪崩的解决方案

在使用 Redis 作为缓存层时&#xff0c;我们经常会遇到三个经典问题&#xff1a;缓存击穿、缓存穿透和缓存雪崩。这些问题可能导致系统性能下降甚至崩溃&#xff0c;本文将详细介绍这三个问题的原因和解决方案。一、&#x1f3af; 缓存击穿问题描述&#xff1a;某个热点 key 在…

“蟒蛇书”作者力荐,全球热销的Python入门经典书第3版出版

全新第3版&#xff0c;基于Python 3.13&#xff0c;全球热销75万&#xff0b;&#xff0c;中文版累计销量35万&#xff0c;全书案例素材源代码。零门槛学Python&#xff0c;轻松摆平海量烦琐事务&#xff0c;百万级爆款“蟒蛇书”作者埃里克马瑟斯作序推荐的《Python编程快速上…