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 内容可以合并,创建具有良好可读性的多行脚本
posted @   sha0dow  阅读(146)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示