Dockerfile 深入浅出:从基础到进阶全解析

news2025/3/13 10:11:23

Dockerfile 深入浅出:从基础到进阶全解析

各位同学,大家好!欢迎来到今天的 Dockerfile 课程。Docker 技术在当今的软件开发和部署领域可以说是非常热门,而 Dockerfile 作为构建 Docker 镜像的关键文件,掌握它对于我们进行容器化开发和部署至关重要。今天,我将用最通俗易懂的语言,从基础到进阶,结合常见例子,带大家全面深入地学习 Dockerfile 的编写。这份教程非常实用,建议大家收藏,跟着我一起实操,会更容易理解。

一、Dockerfile基础入门

1. 什么是 Dockerfile?

Dockerfile 是一个文本文件,它包含了构建 Docker 镜像的所有指令。怎么理解呢?我们可以把它类比成菜谱。想象一下,厨师(Docker 引擎)就像是按照菜谱上的步骤来制作菜品(镜像)。Dockerfile 中的每一条指令就像是菜谱中的一个步骤,告诉 Docker 引擎该怎么做。

2. 第一个 Dockerfile 示例:静态网站(Nginx)
需求理解

我们的目标是使用 Docker 和 Nginx 来部署一个静态网站。静态网站通常由 HTML、CSS、JavaScript 文件以及一些图片等资源组成。我们要通过 Dockerfile 构建一个包含 Nginx 服务器和静态网站文件的镜像,然后运行容器来对外提供服务。

所需文件及目录结构

首先,我们需要创建一个项目目录,例如 nginx-static,并在该目录下创建必要的文件和文件夹。来看一下详细的目录结构:

nginx-static/
├── dist
│   ├── index.html
│   ├── script.js
│   └── style.css
└── Dockerfile

1 directory, 4 files
具体文件内容
  • dist/index.html:这是静态网站的主页文件,使用简单的 HTML 代码展示一个基本的页面。其中包含了对 CSS 和 JavaScript 文件的引用。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>My Static Website</title>
</head>

<body>
    <h1>Welcome to My Static Website</h1>
    <p>This is a simple static website deployed with Docker and Nginx.</p>
    <script src="script.js"></script>
</body>

</html>
  • dist/style.css:这是一个简单的 CSS 文件,用于为页面添加一些基本的样式,比如设置字体、背景颜色、文本对齐方式等。
body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    text-align: center;
    padding-top: 50px;
}

h1 {
    color: #333;
}

p {
    color: #666;
}
  • dist/script.js:这是一个简单的 JavaScript 文件,在页面加载完成后会弹出一个提示框,让用户知道页面已经加载成功。
window.onload = function () {
    alert('Welcome to my static website!');
};
  • Dockerfile:这个 Dockerfile 用于构建包含 Nginx 服务器和静态网站文件的镜像。让我们来逐行分析一下:
# 使用官方的 Nginx 基础镜像,基于 Alpine 版本,体积较小
FROM nginx:alpine

# 将本地的 dist 目录下的所有文件复制到 Nginx 容器内的 HTML 目录中
COPY dist/ /usr/share/nginx/html

# 暴露容器的 80 端口,这是 Nginx 默认的 HTTP 服务端口
EXPOSE 80

FROM 指令指定了基础镜像,这里我们使用的是官方的 Nginx 基础镜像,基于 Alpine 版本,它的体积比较小,这样构建出来的镜像也会比较小。COPY 指令将本地的 dist 目录下的所有文件复制到 Nginx 容器内的 HTML 目录中,这样 Nginx 就可以找到我们的静态网站文件了。EXPOSE 指令声明了容器使用的端口,这里是 80 端口,这是 Nginx 默认的 HTTP 服务端口。

构建镜像

在项目根目录(nginx-static)下,打开终端并执行以下命令来构建 Docker 镜像:

docker build -t nginx-static-image .
  • -t 选项用于给镜像指定一个标签,这里我们将镜像命名为 nginx-static-image
  • . 表示使用当前目录作为构建上下文。
运行容器

构建完成后,我们可以使用以下命令来运行容器:

docker run -d -p 8080:80 nginx-static-image
  • -d 选项表示在后台运行容器。
  • -p 选项用于将宿主机的端口(这里是 8080)映射到容器的端口(这里是 80)。
  • nginx-static-image 是我们之前构建的镜像名称。
验证网站

打开浏览器,访问 http://localhost:8080,如果一切正常,你应该能够看到静态网站的页面,并且在页面加载完成后会弹出一个提示框。我们也可以使用 curl 命令来验证

[root@C9 Docker]# curl http://localhost:8080
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>My Static Website</title>
</head>

<body>
    <h1>Welcome to My Static Website</h1>
    <p>This is a simple static website deployed with Docker and Nginx.</p>
    <script src="script.js"></script>
</body>

</html>

在这里插入图片描述

二、核心指令详解(打好基础)

1. 镜像构建指令
指令用途示例
FROM指定基础镜像(必须是第一条指令)FROM ubuntu:22.04
COPY复制文件到容器(推荐使用)COPY src/ /app/src
ADD比COPY多支持URL和自动解压tar包(不推荐)ADD https://example.com/file
RUN执行命令(会生成新镜像层)RUN apt-get update && …

FROM 指令用于指定基础镜像,它是 Dockerfile 中必须的第一条指令,因为所有的镜像构建都是基于一个已有的基础镜像。COPY 指令用于将本地文件或目录复制到容器中,它的语法比较简单,只需要指定源路径和目标路径就可以了。ADD 指令虽然比 COPY 多了一些功能,比如支持 URL 和自动解压 tar 包,但是由于它的功能比较复杂,容易引入一些安全问题,所以一般不推荐使用。RUN 指令用于在容器中执行命令,它会生成一个新的镜像层,所以在使用 RUN 指令时要注意尽量合并多个命令,减少镜像层的数量。

2. 容器运行指令
指令用途示例
CMD容器启动时执行的默认命令(可被docker run覆盖)CMD [“python”, “app.py”]
ENTRYPOINT容器启动时执行的固定命令(参数可追加)ENTRYPOINT [“/app/start.sh”]
EXPOSE声明容器使用的端口(需配合docker run -p映射)EXPOSE 80 443
VOLUME创建数据卷(容器外存储数据)VOLUME [“/var/lib/mysql”]

CMD 指令用于指定容器启动时执行的默认命令,它可以被 docker run 命令中的参数覆盖。ENTRYPOINT 指令用于指定容器启动时执行的固定命令,它的参数可以追加。EXPOSE 指令用于声明容器使用的端口,但是它只是一个声明,并不会实际进行端口映射,需要配合 docker run -p 选项来进行端口映射。VOLUME 指令用于创建数据卷,数据卷可以将容器内的数据存储到容器外,这样即使容器被删除,数据也不会丢失。

3. 环境配置指令
指令用途示例
WORKDIR设置当前工作目录(相当于连续执行cd命令)WORKDIR /app && WORKDIR src
ENV设置环境变量ENV FLASK_ENV=production
USER指定运行命令的用户(提高安全性)USER appuser

WORKDIR 指令用于设置当前工作目录,它相当于在容器中连续执行 cd 命令。ENV 指令用于设置环境变量,环境变量可以在容器中被应用程序使用。USER 指令用于指定运行命令的用户,这样可以提高容器的安全性。

三、实战进阶技巧(大厂常用)

1. 构建缓存优化
# 先复制依赖文件,利用Docker缓存
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 再复制代码(代码修改时不会触发依赖重新安装)
COPY . .

在构建镜像时,Docker 会使用缓存来加速构建过程。如果我们把依赖文件和代码一起复制到容器中,那么只要代码有任何修改,就会导致依赖文件也被重新复制,从而触发依赖重新安装,这样会浪费很多时间。所以我们可以先复制依赖文件,安装依赖,然后再复制代码,这样当代码修改时,依赖安装的步骤就可以利用缓存,不会被重新执行。

2. 多阶段构建(减小镜像体积)
# 第一阶段:编译应用
FROM python:3.10-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python setup.py build

# 第二阶段:最终镜像(仅包含运行时文件)
FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /app/dist /app/dist
CMD ["python", "/app/dist/main.py"]

在构建镜像时,Docker 会使用缓存来加速构建过程。如果我们把依赖文件和代码一起复制到容器中,那么只要代码有任何修改,就会导致依赖文件也被重新复制,从而触发依赖重新安装,这样会浪费很多时间。所以我们可以先复制依赖文件,安装依赖,然后再复制代码,这样当代码修改时,依赖安装的步骤就可以利用缓存,不会被重新执行。

3. 健康检查
HEALTHCHECK --interval=5s --timeout=3s \
  CMD curl -f http://localhost:8000/health || exit 1

健康检查可以帮助我们监控容器的运行状态。HEALTHCHECK 指令用于定义一个健康检查命令,--interval 选项指定检查的间隔时间,--timeout 选项指定检查的超时时间。如果健康检查命令返回非零退出码,Docker 会认为容器不健康。

4. 动态参数(ARG)
ARG APP_VERSION=1.0.0
ENV APP_VERSION=$APP_VERSION

# 构建时指定参数
docker build --build-arg APP_VERSION=2.0.0 -t myapp .

ARG 指令用于定义一个构建时参数,这个参数可以在构建镜像时通过 --build-arg 选项来指定。我们可以使用 ENV 指令将 ARG 定义的参数设置为环境变量,这样应用程序就可以使用这个环境变量了。

四、进阶案例:Python Flask 应用详细部署

1. 需求理解

我们要使用 Docker 来部署一个基于 Python Flask 框架开发的 Web 应用。Flask 是一个轻量级的 Web 框架,非常适合快速开发小型 Web 应用。通过 Dockerfile 构建一个包含 Python 环境和 Flask 应用的镜像,然后运行容器来对外提供服务。

2. 所需文件及目录结构

首先,创建一个项目目录,例如 flask-app,并在该目录下创建必要的文件和文件夹。以下是详细的目录结构:

flask-app/
├── app.py
├── Dockerfile
└── requirements.txt

0 directories, 3 files
4. 具体文件内容
  • app.py:这是 Flask 应用的主文件,定义了一个简单的路由,当访问根路径时返回 “Hello, World!”。
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
  • requirements.txt:这个文件记录了项目所需的 Python 依赖包,这里只需要 Flask。
flask
  • Dockerfile:这个 Dockerfile 用于构建包含 Python 环境和 Flask 应用的镜像。
# 使用官方的 Python 3.10 轻量级基础镜像
FROM python:3.10-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件到工作目录
COPY requirements.txt .

# 安装依赖包,使用 --no-cache-dir 选项避免缓存占用过多空间
RUN pip install --no-cache-dir -r requirements.txt

# 复制项目代码到工作目录
COPY . .

# 暴露容器的 5000 端口,这是 Flask 应用默认的服务端口
EXPOSE 5000

# 定义容器启动时执行的命令
CMD ["python", "app.py"]
5. 构建镜像

在项目根目录(flask-app)下,打开终端并执行以下命令来构建 Docker 镜像:

docker build -t flask-app-image .
  • -t 选项用于给镜像指定一个标签,这里我们将镜像命名为 flask-app-image
  • . 表示使用当前目录作为构建上下文。
6. 运行容器

构建完成后,我们就可以运行容器了。使用以下命令:

docker run -d -p 8081:5000 flask-app-image
  • -d 选项表示在后台运行容器。
  • -p 选项用于将宿主机的端口(这里是 8081)映射到容器的端口(这里是 5000)。
  • flask-app-image 是我们之前构建的镜像名称。
7. 验证应用

打开浏览器,访问 http://localhost:8081,如果一切正常,你应该能够看到页面显示 “Hello, World!”。

进阶优化

多阶段构建

为了减小镜像体积,我们可以使用多阶段构建。来看一下优化后的 Dockerfile:

# 第一阶段:构建环境,安装依赖
FROM python:3.10-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 第二阶段:最终镜像,只包含运行所需的文件
FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

这里我们分为两个阶段。第一阶段使用 AS builder 命名为构建环境,安装所需的依赖。第二阶段是最终镜像,只复制第一阶段安装好的依赖和项目代码,这样可以大大减小镜像体积。

健康检查

我们还可以在 Dockerfile 中添加健康检查,确保应用正常运行。

# 第一阶段:构建环境,安装依赖
FROM python:3.10-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 第二阶段:最终镜像,只包含运行所需的文件
FROM python:3.10-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
COPY . .
EXPOSE 5000

# 添加健康检查,每 10 秒检查一次,超时时间为 3 秒,最多重试 3 次
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
    CMD curl -f http://localhost:5000/ || exit 1

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

通过 HEALTHCHECK 指令,我们可以设置每 10 秒检查一次应用的健康状态,超时时间为 3 秒,最多重试 3 次。如果检查失败,容器会被标记为不健康。

五、避坑指南

在使用 Docker 构建镜像和运行容器的过程中,有一些常见的坑需要我们注意。

  1. 避免安装不必要的包:尽量使用 slimalpine 基础镜像,这样可以减少镜像体积。

  2. 不要使用 root 用户:为了安全起见,我们可以添加普通用户来运行容器。

    RUN useradd -m appuser && chown -R appuser /app
    USER appuser
    
  3. 清理缓存:安装完成后,记得删除包管理器的缓存。

    RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*
    
  4. 区分 CMD 和 ENTRYPOINT:

    • CMD:容器启动时执行的默认命令,这个命令是可以被覆盖的。
    • ENTRYPOINT:是固定执行的命令,参数可以追加。

总结

最后,我们来总结一下。Dockerfile 的核心原则是分层构建缓存利用。通过合理的指令顺序和镜像优化,我们能显著提升构建效率和镜像安全性。建议大家在实际项目中多尝试不同的配置,观察构建日志中的缓存命中情况,逐步积累经验。

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

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

相关文章

Mybatis中的分页操作,如何使用PageHelper进行分页,以及Spring Boot整合Mybatis Plus分页

目的&#xff1a; 学会分页功能&#xff0c;学会分页方法 场景&#xff1a; 将下面的数据进行分页&#xff1a; 文章目录 Mybatis 单独使用分页&#xff08;没有整合&#xff09;1. PageHelper 插件 Spring Boot 整合 Mybatis Plus 使用分页1. selectPage 方法实现分页2. selec…

【网络安全】API安全防护完整指南

文章目录 API安全为什么 API 安全性重要?API 安全性与通用应用程序安全性的区别传统 Web 安全的主要特征API 安全的关键特征OWASP API 前 10 大安全威胁API1:2019 - 破坏对象级授权(Broken Object-Level Authorization)API2:2019 - 破坏用户身份验证(Broken User Authentic…

Docker 学习(四)——Dockerfile 创建镜像

Dockerfile是一个文本格式的配置文件&#xff0c;其内包含了一条条的指令(Instruction)&#xff0c;每一条指令构建一层&#xff0c;因此每一条指令的内容&#xff0c;就是描述该层应当如何构建。有了Dockerfile&#xff0c;当我们需要定制自己额外的需求时&#xff0c;只需在D…

本地部署 DeepSeek:从 Ollama 配置到 Spring Boot 集成

前言 随着人工智能技术的迅猛发展&#xff0c;越来越多的开发者希望在本地环境中部署和调用 AI 模型&#xff0c;以满足特定的业务需求。本文将详细介绍如何在本地环境中使用 Ollama 配置 DeepSeek 模型&#xff0c;并在 IntelliJ IDEA 中创建一个 Spring Boot 项目来调用该模型…

算法之 前缀和

文章目录 前缀和基础3427.变长子数组求和 前缀和与哈希表1524.和为奇数的子数组数目 距离和1685.有序数组中绝对值之和 前缀异或和1177.构建回文串检测 其他一维前缀和1310.子数组异或查询 二维前缀和1314.矩阵区域和 前缀和&#xff0c;就是定义pre[i] 为nums的前i个元素的和值…

机器视觉运动控制一体机在天地盖同步跟随贴合解决方案

市场应用背景 纸盒天地盖是一种包装形式&#xff0c;广泛应用于消费电子、食品礼盒、奢侈品及化妆品等领域。其采用高强度纸板&#xff0c;经过预组装处理&#xff0c;结构坚固稳定&#xff0c;能有效保护产品并提升品牌形象。随着包装行业快速发展&#xff0c;市场对天地盖的…

B站文生视频模型工程实践

1.前言 近年来&#xff0c;AI 内容生成&#xff08;AIGC&#xff09;领域的快速发展令人雀跃&#xff0c;OpenAI 在 2023 年初推出大型语言模型&#xff08;LLM&#xff09;GPT-4 受到了学术界和工业界的极大关注。OpenAI 随后在 2024 年初推出文生视频&#xff08;T2V&#xf…

嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库

目录 步骤 1&#xff1a;准备工作 步骤 2&#xff1a;创建 Keil 项目&#xff0c;并配置工程 步骤 3&#xff1a;在MDK工程上添加 CMSIS-DSP 库 步骤 5&#xff1a;编写代码 步骤 6&#xff1a;配置时钟和优化 步骤 7&#xff1a;调试与验证 步骤 8&#xff1a;优化和调…

【人工智能】GPT-4 vs DeepSeek-R1:谁主导了2025年的AI技术竞争?

前言 2025年&#xff0c;人工智能技术将迎来更加激烈的竞争。随着OpenAI的GPT-4和中国初创公司DeepSeek的DeepSeek-R1在全球范围内崭露头角&#xff0c;AI技术的竞争格局开始发生变化。这篇文章将详细对比这两款AI模型&#xff0c;从技术背景、应用领域、性能、成本效益等多个方…

【Python项目】基于深度学习的车辆特征分析系统

【Python项目】基于深度学习的车辆特征分析系统 技术简介&#xff1a;采用Python技术、MySQL数据库、卷积神经网络&#xff08;CNN&#xff09;等实现。 系统简介&#xff1a;该系统基于深度学习技术&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;用…

【江科大STM32】TIM输入捕获模式PWMI模式测频率

一、输入捕获测频率 接线图&#xff1a; 测信号的输入引脚为PA6&#xff0c;信号从PA6进来&#xff0c;待测的PWM信号也是STM32自己生成的&#xff0c;输出引脚是PA0&#xff0c;所以接线这里直接用一根线将PA0引到PA6就可以了。 如果有信号发生器的话&#xff0c;也可以设置成…

K8S学习之基础十六:k8s中Deployment更新策略

滚动更新 滚动更新是一种自动化程度较高的发布方式、用户体验比较平滑、是目前成熟型技术组织采用的主流发布方式&#xff0c;一次滚动发布一般有若干发布批次组成&#xff0c;每批的数量一般都是可配置的&#xff0c;可通过发布模板定义&#xff0c;例如第一批10%&#xff0c…

EtherNet/IP转Modbus解析基于网关模块的罗克韦尔PLC与Modbus上位机协议转换通讯案例

在工业自动化控制系统中&#xff0c;常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中&#xff0c;客户现场采用了 AB PLC&#xff0c;但需要控制的变频器仅支持 Modbus 协议。为了实现 AB PLC 对变频器的有效控制与监控&#xff0c;引入了捷米特 JM-EIP-RTU 网…

Devart dbForge Studio for MySQL Enterprise 9.0.338高效数据库管理工具

Devart dbForge Studio for MySQL Enterprise 9.0.338 是一款功能强大的 MySQL 数据库管理工具&#xff0c;专为数据库开发人员和管理员设计。它提供了丰富的功能&#xff0c;帮助用户更高效地管理、开发和维护 MySQL 数据库 Devart dbForge Studio for MySQL Enterprise 9.0.…

STM32-USART串口数据包

一&#xff1a;HEX数据包发送 1.为了收发数据包&#xff0c;先定义两个缓存区的数组 &#xff0c;这4个数据只存储发送或者接收的载荷数据&#xff0c;包头和包尾不存 uint8_t Serial_TxPacket[4]; uint8_t Serial_RxPacket[4]; uint8_t Serial_RxFlag;//接收一个数据包就置F…

轻闪PDF(Windows傲软PDF编辑软件)2.15.2中文安装版

前言 轻闪pdf是个很好用的文件编辑软件&#xff0c;它能让大家编辑文档变得更简单、更快。这个软件特别厉害&#xff0c;能从照片里直接“抓”出文字来&#xff0c;让你打字变得更轻松。而且&#xff0c;它还能把PDF文件变成其他格式的文件&#xff0c;反过来也行。还有啊&…

Python-07PDF转Word

2025-03-04-PDF转Word DeepSeek等大模型从来都不是简单的写一个静态博客这么肤浅&#xff08;太多博主都只讲这个内容了&#xff09;借助全网大神的奇思妙想&#xff0c;拓展我狭隘的思维边界。 文章目录 2025-03-04-PDF转Word [toc]1-参考网址2-学习要点3-核心逻辑4-核心代码 …

Arcgis中添加脚本工具箱

文章目录 准备资料1、打开arcmap2、找到目录窗口3、复制粘贴工具箱的路径4、添加或者确认python脚本路径准备资料 (1)工具箱 (2)python脚本 1、打开arcmap 2、找到目录窗口 3、复制粘贴工具箱的路径 4、添加或者确认python脚本路径 脚本上右键属性(注意:脚本内容和路径…

拥抱健康养生,开启活力生活

在快节奏的现代生活中&#xff0c;健康养生已成为人们关注的焦点&#xff0c;它不仅是对身体的呵护&#xff0c;更是一种积极的生活态度。 合理饮食是健康养生的基石。我们应秉持均衡膳食的理念&#xff0c;谷物、蔬菜、水果、蛋白质类食物一个都不能少。每天保证足够的蔬菜摄入…

字节跳动AI原生编程工具Trae和百度“三大开发神器”AgentBuilder、AppBuilder、ModelBuilder的区别是?

字节跳动AI编程工具Trae与百度"三大开发神器"&#xff08;AgentBuilder、AppBuilder、ModelBuilder&#xff09;在定位、功能架构和技术路线上存在显著差异&#xff0c;具体区别如下&#xff1a; 一、核心定位差异 Trae&#xff1a;AI原生集成开发环境&#xff08;AI…