在Docker中,commit和dockerfile有什么区别?

13

当我制作Docker镜像时,

使用commit命令和使用Dockerfile来构建命令会有什么区别吗?我是从镜像大小和算法方面来说的。

2个回答

9
是的,大小会有所不同。 docker commit 基本上是将 "运行" 容器的当前状态 "快照" 并保存为图像。这基本上意味着如果您的 "运行" 容器正在生成日志文件、更新软件包或进行文件更改,它们将被保存到图像中。每次运行 docker commit,都会创建一个新的图像。
另一方面,docker build 通过引用脚本(Dockerfile)创建图像。通常情况下,只有在检测到更改时,docker build 才会创建一个新的图像。
两种方法的图像大小取决于您在两种情况下做了什么,docker build 将给出一致的图像大小,因为它是基于 Dockerfile 中指定的内容构建的。而 docker commit 的图像大小取决于容器的当前状态。如果您在容器运行后删除了很多东西,您可能会得到较小的图像,反之亦然。
简而言之,它们类似但服务于不同的目的。然后,docker build 的最终产品本质上是提交。
用不同的类比来说,docker build 就像 git clone,而 docker commit 就像 git commit

6
我不确定我完全同意这个观点。就 OP 的问题而言,“算法”并没有什么区别,如果您在构建和 Dockerfile 中完全相同,那么大小也应该完全相同(因为构建只是自动执行了相同操作的版本)。我的看法。 - johnharris85
如果我像 Dockerfile 一样做同样的事情,那么两个镜像的大小是相同的吗? 这意味着,在容器中,我执行与 Dockerfile 相同的命令,并进行提交。 - Haksung Kim
@HaksungKim,理论上来说,它们可能具有相同的大小。此外,请注意,Dockerfile中的每个RUN命令都会创建一个层。如果要使用docker commit完成此操作,则可能需要在容器内部跳进和跳出以在运行下一个命令之前进行提交。 - Andy
@Andy 哦,这些信息对我很有用。所以说,使用 Dockerfile 的 docker build 命令由于层次结构的原因具有更大的大小。但是使用 Dockerfile 的优点在于文档化。 - Haksung Kim

3

最好的方法是尝试一下(或比较github上的代码,但那时已经过了我的睡觉时间)。生成的图像中有一些细微的差别。主要是有一些引用不在那里,这些引用用于缓存以前的构建。而且,在我的例子中,与容器相关联的命令是不同的。老实说,我无法确定为什么docker commit版本更小,但两个图像都基于相同的父级层,并且非常相似。对于可维护性来说,Dockerfile将更易于管理。

Dockerfile 版本

$ cat df.apt-get-git
FROM debian:latest

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y \
      git \
      vim \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

$ docker build -t test-git:dockerfile -f df.apt-get-git .
Sending build context to Docker daemon 248.3 kB
Step 1 : FROM debian:latest
 ---> 7b0a06c805e8
Step 2 : RUN apt-get update  && DEBIAN_FRONTEND=noninteractive apt-get install -y       git       vim  && apt-get clean  && rm -rf /var/lib/apt/lists/*
 ---> Running in 44588d9cdef4
Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB]
Ign http://deb.debian.org jessie InRelease
....
Updating certificates in /etc/ssl/certs... 174 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
Processing triggers for systemd (215-17+deb8u5) ...
 ---> 01cb5ddcddd1
Removing intermediate container 44588d9cdef4
Successfully built 01cb5ddcddd1

$ docker inspect test-git:dockerfile
[
    {
        "Id": "sha256:01cb5ddcddd101e498ff9e09e4cb4efad85f49a3b87c5792c807ebccedc83977",
        "RepoTags": [
            "test-git:dockerfile"
        ],
        "RepoDigests": [],
        "Parent": "sha256:7b0a06c805e8f23807fb8856621c60851727e85c7bcb751012c813f122734c8d",
        "Comment": "",
        "Created": "2016-12-28T02:55:23.950610688Z",
        "Container": "44588d9cdef49728a012a5a19657ac2b97b6de191ece375607a22043ae993043",
        "ContainerConfig": {
            "Hostname": "397f80c505a4",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "apt-get update  \u0026\u0026 DEBIAN_FRONTEND=noninteractive apt-get install -y       git       vim  \u0026\u0026 apt-get clean  \u0026\u0026 rm -rf /var/lib/apt/lists/*"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:7b0a06c805e8f23807fb8856621c60851727e85c7bcb751012c813f122734c8d",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {}
        },
        "DockerVersion": "1.12.3",
        "Author": "",
        "Config": {
            "Hostname": "397f80c505a4",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "ArgsEscaped": true,
            "Image": "sha256:7b0a06c805e8f23807fb8856621c60851727e85c7bcb751012c813f122734c8d",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": [],
            "Labels": {}
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 245152070,
        "VirtualSize": 245152070,
        "GraphDriver": {
            "Name": "aufs",
            "Data": null
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:f96222d75c5563900bc4dd852179b720a0885de8f7a0619ba0ac76e92542bbc8",
                "sha256:e839e7442c5bbd0a3843822997bcd6830f88fc03417ad6dfd4cc9cb9c6ce0dfa"
            ]
        }
    }
]

代码提交版本

$ docker run --name test-git-commit debian:latest /bin/sh -c 'apt-get update \
>   &&  DEBIAN_FRONTEND=noninteractive apt-get install -y \
>         git \
>         vim \
>   &&  apt-get clean \
>   && rm -rf /var/lib/apt/lists/*'
Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB]
...
Updating certificates in /etc/ssl/certs... 174 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....done.
Processing triggers for systemd (215-17+deb8u5) ...

$ docker commit test-git-commit test-git:commit
sha256:141c140e3bb0b8a865e58cfd1674f9dac70623c6537f362b15a0ec0a8edbfd0c

$ docker inspect test-git:commit
[
    {
        "Id": "sha256:141c140e3bb0b8a865e58cfd1674f9dac70623c6537f362b15a0ec0a8edbfd0c",
        "RepoTags": [
            "test-git:commit"
        ],
        "RepoDigests": [],
        "Parent": "sha256:7b0a06c805e8f23807fb8856621c60851727e85c7bcb751012c813f122734c8d",
        "Comment": "",
        "Created": "2016-12-28T02:57:50.962700517Z",
        "Container": "5160a31123f3594255a03c42ab72a41ec1fbe72a394923608c8e5654e5d3027b",
        "ContainerConfig": {
            "Hostname": "5160a31123f3",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "apt-get update \\\n  \u0026\u0026  DEBIAN_FRONTEND=noninteractive apt-get install -y \\\n        git \\\n        vim \\\n  \u0026\u0026  apt-get clean \\\n  \u0026\u0026 rm -rf /var/lib/apt/lists/*"
            ],
            "Image": "debian:latest",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "1.12.3",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "apt-get update \\\n  \u0026\u0026  DEBIAN_FRONTEND=noninteractive apt-get install -y \\\n        git \\\n        vim \\\n  \u0026\u0026  apt-get clean \\\n  \u0026\u0026 rm -rf /var/lib/apt/lists/*"
            ],
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 236898630,
        "VirtualSize": 236898630,
        "GraphDriver": {
            "Name": "aufs",
            "Data": null
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:f96222d75c5563900bc4dd852179b720a0885de8f7a0619ba0ac76e92542bbc8",
                "sha256:c1fd858a68b921981cd15793cbf673a7794d950bb5cc70769ba250df7b7439f9"
            ]
        }
    }
]

1
这是非常有趣的结果。我认为@Andy的评论对于分析这个结果很有帮助。我认为Docker构建命令比Docker提交命令具有更多的层。 - Haksung Kim
从上面的检查输出中,您可以看到我只为每个版本生成一个额外的层。docker build将为Dockerfile中的每个指令生成一个层,这就是为什么将具有类似缓存要求的指令合并成一个最佳实践的原因。 - BMitch
好的,看起来你只添加了一个层。但是docker build命令的大小仍然比docker commit大。为了分析这个问题,也许我们可以在git上查看代码。我在谷歌或stackoverflow上找不到。不过,非常感谢你的解释。 - Haksung Kim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接