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 内容可以合并,创建具有良好可读性的多行脚本

浙公网安备 33010602011771号