docker镜像构建

基本的构建命令为: docker build -t name:tag -f Dockerfile .
-t: 表示构建出来的镜像名称
-f: 表示构建使用的dockerfile文件名称
.: 表示构建使用当前路径作为上下文(context),如果你是在根目录/下面构建,不建议使用.(不建议使用根路径作为上下文),因为根路径下面有虚拟文件系统,如/proc之类的,构建的时候会报找不到文件的错误。

contextpath和dockerfile

镜像构建流程为首先将指定的上下文(contextpath)路径下的文件打包,发送到服务端。服务端再将收到的文件解压,然后以解压后的路径作为上下文,进行镜像构建。

docker构建命令中如果没有以-f指定Dockerfile,则以上下文中的Dockerfile文件作为构建文件;如果通过-f指定了Dockerfile文件路径及名称,则在构建上下文中寻找指定的文件。

Dockerfile中常见指令

  • FROM:用于指定基础镜像。
  • COPY: 从构建上下文中复制指定文件/目录到构建镜像的指定位置。如果源路径为文件夹,则复制文件夹内的所有文件到目标路径。
  • RUN:执行命令。
  • ENV:指定容器启动后容器内的环境变量。
  • ARG:指定镜像构建时的环境变量。ARG key[=value],默认值可以在构建命令中用--build-arg key=value来覆盖。可以实现同一份Dockerfile构建出不同的镜像。
  • ENTRYPOINT:指定容器启动时执行的命令。指定该参数后,CMD中的内容会作为参数,也可以在run的时候指定参数。通过--entrypoint来覆盖。
  • CMD:未指定ENTRYPOINT时,CMD作为容器启动命令,可以在docker run时被覆盖。指定ENTRYPOINT时,会作为ENTRYPOINT的参数。
  • WORKDIR:改变之后构建命令执行容器的默认工作目录,目录不存在时会自动创建。(构建镜像时,每一层都会在上一层的基础上创建一个新容器)
  • USER:使用指定用户执行后面的构建命令,用户需提前创建好。

构建缓存

docker build的时候,如果某一层无法使用上一次的构建缓存,则后续层均无法使用,故若大多数层均未改变,建议将未改动的层放在前面。如RUN apt get install -y tmux命令,如果tmux版本有变化,则无法继续使用构建缓存,建议将该语句放到后面。
参考:https://blog.orenoid.com/2019/12/17/docker-build-optimize/
--no-cache=true可以不使用缓存,不知道能否解决构建时提示缓存不足的问题。

多阶段构建

FROM golang:alpine as builder  // 使用该镜像作为编译镜像并编译
...
go build -o /go/src/github.com/go/helloworld/app

FROM alpine:latest as prod    // 使用该镜像作为最终镜像的base镜像
...
COPY --from=builder /go/src/github.com/go/helloworld/app .   // 拷贝上一步编译得到的二进制。
...
CMD [""./app"]

可以直接编译得到最终镜像:docker build -t go/helloworld:3 .

也可以只构建builder阶段的镜像: docker build --target builder -t username/imagename:tag .

构建时,可以复制上一阶段的镜像中的文件,也可以复制任意镜像中的文件。

COPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf

as后面的名字可以任意填写,主要作用是作为一个标识,方便单独构建其中一个镜像,或者是其他镜像从中获取部分文件。

参考: https://yeasy.gitbook.io/docker_practice/image/multistage-builds/laravel

构建多架构支持的镜像

  • 原理:当用户获取一个镜像时,Docker 引擎会首先查找该镜像是否有 manifest 列表,如果有的话 Docker 引擎会按照 Docker 运行环境(系统及架构)查找出对应镜像。如果没有的话会直接获取镜像。

  • 查看:docker manifest inspect golang:alpine查看镜像的manifest。需要开启实验特性才能查看manifest,开启方法为:

    export DOCKER_CLI_EXPERIMENTAL=enabled

  • 构建方法

    1. 分别构建不同架构的镜像,如<registry>/<namespace>/<repo>:<tag>-arm64, <registry>/<namespace>/<repo>:<tag>-amd64,并推送到镜像仓库。

    2. 然后创建manifest列表,docker manifest create <registry>/<namespace>/<repo>:<tag> <registry>/<namespace>/<repo>:<tag>-arm64 <registry>/<namespace>/<repo>:<tag>-amd64
      如果要修改可以使用-a--amend。也可以通过annotate指令修改manifest。

    3. 推送manifest到镜像仓库。docker manifest push <registry>/<namespace>/<repo>:<tag>

    4. 使用: docker pull <registry>/<namespace>/<repo>:<tag>在不同架构的操作系统下执行会拉取到各自架构的镜像。当然,也可以手动指定架构来拉取,如在x86机器下拉取arm镜像,可以通过docker pull --platform=arm64 nginx:latest拉取。

其他构建工具

buildah

没有守护进程,不需要 root 特权,而且生成的是符合 OCI 的镜像,因此你的镜像的运行方式与使用 Docker 构建的镜像完全相同。它还能使用 Dockerfile 或 Containerfile 构建镜像, Dockerfile 与 Containerfile 实际上是同一个东西,只是叫法不同罢了。除此之外,Buildah 还提供了对镜像层更精细的控制,支持提交大量的变更到单个层。我认为,它与 Docker 之间有一个出乎意料的区别(但这个区别是好事),那就是使用 Buildah 构建的镜像特定于用户,因此你可以只列出自己构建的镜像。

Kaniko

Google 发布了“ Kaniko ”,一种用于在未授权容器或 Kubernetes 集群中构建容器镜像的开源工具。虽然 Kaniko 也是根据用户给定的 Dockerfile 构建镜像,但是并不依赖于 Docker 守护进程,而是在用户空间中完全执行每个命令,并对所导致的文件系统更改做快照。一般多用于在流水线中执行的编译构建。它与 Buildah 的主要区别在于,Kaniko 更加侧重于 Kubernetes 中的镜像构建。

另外需要指定镜像仓库名字,从而自动推送到目标仓库。

--context:指定构建上下文(可以挂载本地目录,也可以指定git地址,如git://github.com/mycorp/my-app.git),

--destination:指定要推送的仓库地址,

--dockerfile:指定dockerfile文件。存在一个问题是,tag是写死的,每次得到的镜像会覆盖。

docker容器使用:
docker run -d -v ${hostpath}/Dockerfile:/workspace/Dockerfile -v ${hostpath}:/kaniko/.docker ${image} --dockerfile=/workspace/Dockerfile --context=/workspace --destination=${dst-registry} 注:{hostpath}中需要存在推送到目标仓库所需的.dockerconfig,即用户名密码文件。
k8s中使用:https://segmentfault.com/a/1190000039713484

buildkit

并行构建、跳过未使用的阶段、更好的增量构建以及不需要 root 权限等构建。但是,它仍然需要运行守护进程 (buildkitd)。因此,如果你不想摆脱 Docker,同时又想要一些新的功能和改进,那么可以考虑一下 buildkit。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容