Dockerfile 构建镜像
Dockerfile 构建镜像
什么是 Dockerfile
Docker 通过读取 Dockerfile 中的指令来构建镜像,类似 C 语言开发时使用 Make 通过 Makefile 构建项目
- 其中包含 Docker 控制指令,这些指令遵循将应用程序组装成容器映像所需的特定格式,官方标准 https://docs.docker.com/engine/reference/builder/
- 其中命令不区分大小写,注释使用
#
行注释 - Dockerfile 的默认文件名是
Dockerfile
,没有文件扩展名,如果名称不是或多个类似使用--file
指导,也可以使用-f
- Docker 镜像由只读层组成,每个层都来自 Dockerfile 中的一条指令
主要命令
FROM <image>
类似各自语言的导入功能,使用此命令可以导入其他镜像,在基于此镜像基础上进行构建,目的节约时间RUN <command>
基于当前状态上构建新图层,还有用于运行命令的 shell 形式WORKDIR <directory>
设置后面命令的工作目录COPY <src> <dest>
Copy 懂得都懂 😋CMD <command>
定义基于此镜像启动容器后运行的默认程序【每个 Dockerfile 只有一个 CMD,如果多个会因为自上而下使用最后一个 CMD】
示例
一个基于 ubuntu:22.04 镜像构建 flask 服务的 Dockerfile,特殊说明一下 # syntax=docker/dockerfile:1
是类似声明的操作,像 shell 的 #! /bin/bash
那种感觉。但作用别误解,作用是声明使用 dockerfile 版本 1 的语法。
# syntax=docker/dockerfile:1 # FROM 基于 ubuntu:22.04 上进行构建镜像 FROM ubuntu:22.04 # RUN 在 ubuntu:22.04 基础上执行命令 RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list RUN apt-get update && apt-get install -y python3 python3-pip RUN pip install -i https://mirrors.ustc.edu.cn/pypi/web/simple pip -U && pip install flask==2.1.* -i https://mirrors.ustc.edu.cn/pypi/web/simple # COPY 复制本地文件到镜像中 COPY hello.py / # ENV 设置虚拟环境变量,不过 FLASK_APP 只是针对于 flask 使用需要 ENV FLASK_APP=hello # EXPOSE 标志着我们的最终图像有一个监听 8000 端口的服务 EXPOSE 8000 # CMD 通常最后一步基于此图像启动容器时运行会执行的命令 CMD flask run --host 0.0.0.0 --port 8000
关于 hello.py 内容,如果学习过 flask 可以自己编写自己喜欢的内容,下面内容仅供参考
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!"
完成上面内容,执行 docker build -t test:latest .
即可开始构建镜像,如果你 Dockerfile 文件名随心时需要使用 -f
指定,构建过程可能会比较慢。
- 其中
latest
是标签,可以根据自身编写 - 想要测试构建镜像,可以使用它创建容器
docker run -p 8000:8000 test:latest
learn@debian10:~/work/dockerfile-01$ docker run -p 8000:8000 test:latest * Serving Flask app 'hello' (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:8000 * Running on http://172.17.0.2:8000 Press CTRL+C to quit 172.17.0.1 - - [16/Apr/2023 01:37:25] "GET / HTTP/1.1" 200 - 172.17.0.1 - - [16/Apr/2023 01:37:25] "GET /favicon.ico HTTP/1.1" 404 -
如果你想要创建一个基础镜像使用 FROM scratch
就可以构建。打包的 Linux 发行版的方法:https://github.com/docker/docker/blob/master/contrib
优化构建镜像
构建图像最具比较难的是构建镜像的大小,Dockerfile 中的每个 RUN、COPY、ADD 指令都会为图像添加一个层。
- 记住在进入下一层之前清理不需要内容
- 使用 shell 技巧和其他方法来使层尽可能小
想要引入一个概念,优化这个过程是对于生成过程,开发过程一般不重视
使用多阶段构建优化
# syntax=docker/dockerfile:1 FROM golang:1.16 AS builder WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go ./ RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=0 /go/src/github.com/alexellis/href-counter/app ./ CMD ["./app"]
- 使用多阶段构建,可以避免创建任何中间图像。假设上面内容用两个 dockerfile 就会存在一个中间镜像
- 其中的
AS
是给阶段的别名,不是给golang:1.16
的别名 - 在特定的构建阶段构建,通过别名
docker build --target builder -t alexellis2/href-counter:latest .
使用缓存管理优化
在构建镜像的层上,如果某个层存在变动会影响后面的层
- 要加快图像构建,最好的事情之一就是在构建中放入更少的东西,COPY 中经常修改内容不用放一起
- 不要包含不必要的文件,通过
.dockerignore
文件可以排除文件或目录 - 包管理器缓存,能不安装就别安装,如果要可以使用
RUN
的专用缓存,关于具体操作鉴 https://docs.docker.com/build/cache/backends/ - 选合适的基础镜像,尽可能减少层数减少 RUN、COPY、ADD 指令使用,比如多个 RUN 内容可以合并,创建具有良好可读性的多行脚本
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了