自学内容网 自学内容网

Docker:Dockerfile 构建 Docker image

在本章的学习之前最好先对docker image具有分层理解

Docker:Docker image & Docker Container-CSDN博客

Dockerfile简介

Dockerfile 是一个文本文件,包含了一系列指令和参数,用于自动化地创建Docker镜像。它就像是一个制作蛋糕的食谱,每一步都详细说明了需要做什么。

使用Dockerfile的好处:

  1. 自动化:自动化构建过程,减少人为错误。
  2. 版本控制:可以像管理代码一样管理Docker镜像的构建过程。
  3. 可重复性:确保每次构建都产生相同的结果。
  4. 文档化:Dockerfile本身就是一份关于如何构建和运行应用的文档。

主要的Dockerfile指令

  1. FROM:指定基础镜像,就像选择蛋糕的底座。
  2. RUN:执行命令,相当于在蛋糕上添加各种配料。
  3. COPY/ADD:复制文件到镜像中,就像把准备好的装饰品放到蛋糕上。
  4. WORKDIR:设置工作目录,相当于确定在蛋糕的哪一层进行操作。
  5. ENV:设置环境变量,就像调整烤箱的温度和湿度。
  6. EXPOSE:声明容器要监听的端口,类似于为蛋糕预留放蜡烛的位置。
  7. CMD/ENTRYPOINT:指定容器启动时运行的命令,就像决定如何切和吃这个蛋糕。

dockerfile官方指令


Dockerfile优化

根据这个demo,你可以对dockerfile的结构有大致的了解,但是我们还是需要构建更高效的dockerfile

# 1. FROM:指定基础镜像
FROM ubuntu:20.04

# 2. ENV:设置环境变量
ENV PYTHONUNBUFFERED=1 \
    PATH=/app/bin:$PATH

# 3. WORKDIR:设置工作目录
WORKDIR /app

# 4. COPY:复制文件到镜像中
COPY . /app

# 5. RUN:执行命令
RUN apt-get update && apt-get install -y python3 python3-pip && \
    pip3 install -r requirements.txt && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# 6. EXPOSE:声明端口
EXPOSE 80

# 7. CMD:指定启动命令(可被覆盖)
CMD ["python3", "app.py"]

# 或者使用 ENTRYPOINT(不可被覆盖)
# ENTRYPOINT ["python3", "app.py"]

顺序很重要

将变化最少的层放在Dockerfile的顶部,以利用Docker的缓存机制。

  • FROM 总是第一条指令
  • ENV 和 WORKDIR 通常在前面设置
  • COPY/ADD 和 RUN 指令通常交替使用
  • EXPOSE 在应用设置完成后声明
  • CMD 或 ENTRYPOINT 通常是最后一条指令

最佳实践

  • 使用 && 连接多个 RUN 命令,减少层数
  • 清理不必要的文件,减小镜像大小
  • 使用 COPY 而不是 ADD,除非需要自动解压缩功能
  • 为 ENV 设置合理的默认值
  • 使用 EXPOSE 声明应用使用的端口,提高可读性

CMD vs ENTRYPOINT:

  • CMD: 提供默认命令和参数,可被 docker run 命令行参数覆盖
  • ENTRYPOINT: 配置容器启动时运行的可执行文件,不易被覆盖

构建上下文

  • COPY 和 ADD 使用的路径是相对于构建上下文的
  • 使用 .dockerignore 文件排除不需要的文件

多阶段构建

  • 可以使用多个 FROM 指令来创建更小、更安全的最终镜像

优化效果

优化Dockerfile可以带来更高效、更安全、更易维护的容器化应用,同时提升开发和部署的整体效率。


如何创建和使用Dockerfile

我们将创建一个简单的Python Web应用,并将其打包成Docker镜像。

首先,让我们创建一个简单的Flask应用,然后为它编写Dockerfile。

创建项目结构:

my_flask_app/
├── app.py
├── requirements.txt
└── Dockerfile

创建 app.py

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello, Docker!"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

创建 requirements.txt

Flask==2.0.1

创建并编辑 Dockerfile

# 使用官方Python运行时作为父镜像
FROM python:3.9-slim

# 设置工作目录为/app
WORKDIR /app

# 将当前目录内容复制到容器中的/app
COPY . .

# 安装requirements.txt中指定的任何所需包
RUN pip install --no-cache-dir -r requirements.txt

# 使端口5000可供此容器外的环境使用
EXPOSE 5000

# 定义环境变量
ENV NAME World

# 在容器启动时运行app.py
CMD ["python", "app.py"]

解释:

  1. FROM python:3.9-slim: 使用官方Python 3.9镜像作为基础,slim版本较小。
  2. WORKDIR /app: 在容器内部创建一个/app目录,后续操作都在这个目录进行。
  3. COPY . .: 将当前目录的所有文件复制到容器的/app目录。
  4. RUN pip install --no-cache-dir -r requirements.txt: 安装Flask及其依赖。
  5. EXPOSE 5000: 声明应用使用5000端口(注意这只是声明,实际上还需要在运行时映射端口)。
  6. ENV NAME World: 设置一个环境变量(这里只是示例,我们的app.py没有使用它)。
  7. CMD ["python", "app.py"]: 指定容器启动时运行的命令。

构建Docker镜像: 在包含Dockerfile的目录中运行以下命令:

docker build -t my-flask-app .

到这,我们就可以看见,我们自己创建的镜像了

这里就不演示运行Docker容器了


参考

https://medium.com/@smihahawan/multistage-docker-deployment-483ecbf1cb1d

https://medium.com/@navneetskahlon/layers-in-docker-images-optimizing-dockerfile-instructions-for-efficient-builds-5edb3af012ad


原文地址:https://blog.csdn.net/unravel_tom/article/details/140212141

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!