如何展平Docker镜像?

Tho*_*rig 28 docker

我做了一个相当大的Docker容器.当我提交容器来创建图像时,图像大约为7.8 GB.但是当我export将容器(不是save图像!)转换为tarball并重新导入它时,图像只有3 GB大.当然历史遗失了,但这对我来说没问题,因为我认为图像已经"完成"并准备好部署.

如何在不将图像/容器导出到磁盘并再次导入的情况下展平图像/容器?并且:这样做是明智的想法还是我错过了一些重要的观点?

qkr*_*ger 23

从Docker 1.13开始,您可以使用该--squash标志.


1.13版之前:

据我所知,你不能使用Docker api.docker export并且docker import是专为这种情况下,因为你自己已经不在话下.

如果您不想保存到磁盘,则可以将导出的输出流管道输入到导入的输入流中.我没有测试过这个,但试试看

docker export red_panda | docker import - exampleimagelocal:new
Run Code Online (Sandbox Code Playgroud)

  • 适用于 Docker 17.03.0-ce。从 33GB 图像大小减少到 19GB (3认同)
  • 您在哪里可以使用`--squash`标志? (3认同)
  • docker build --squash -f <directory-to-dockerfile> 。 (3认同)
  • `--squash` 需要一些守护进程的实验标志。`export` 适用于容器,不适用于图像。您对如何将图像转换为容器而不在该图像内运行任何内容有什么建议吗?我的一个想法是运行容器中不存在的入口点。这似乎仍然创建了一个新的容器。 (2认同)

BMi*_*tch 21

现在Docker已经在17.05发布了多阶段构建,你可以重新格式化你的构建,如下所示:

FROM buildimage as build
# your existing build steps here
FROM scratch
COPY --from=build / /
CMD ["/your/start/script"]
Run Code Online (Sandbox Code Playgroud)

结果将是您的构建环境图层缓存在构建服务器上,但只有一个展平的副本将存在于您标记和推送的结果图像中.


请注意,您通常会将其重新构造为具有复杂的构建环境,并且只复制几个目录.以下是Go从源代码和单个构建命令生成单个二进制映像的示例,无需在主机上安装Go并在docker之外编译:

$ cat Dockerfile 
ARG GOLANG_VER=1.8
FROM golang:${GOLANG_VER} as builder
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download 
RUN go-wrapper install

FROM scratch
COPY --from=builder /go/bin/app /app
CMD ["/app"]
Run Code Online (Sandbox Code Playgroud)

go文件是一个简单的hello世界:

$ cat hello.go 
package main

import "fmt"

func main() {
        fmt.Printf("Hello, world.\n")
}
Run Code Online (Sandbox Code Playgroud)

构建创建环境,构建环境和临时环境,然后将临时标记为:

$ docker build -t test-multi-hello .                                                                                                                              
Sending build context to Docker daemon  4.096kB
Step 1/9 : ARG GOLANG_VER=1.8
 ---> 
Step 2/9 : FROM golang:${GOLANG_VER} as builder
 ---> a0c61f0b0796
Step 3/9 : WORKDIR /go/src/app
 ---> Using cache
 ---> af5177aae437
Step 4/9 : COPY . .
 ---> Using cache
 ---> 976490d44468
Step 5/9 : RUN go-wrapper download
 ---> Using cache
 ---> e31ac3ce83c3
Step 6/9 : RUN go-wrapper install
 ---> Using cache
 ---> 2630f482fe78
Step 7/9 : FROM scratch
 ---> 
Step 8/9 : COPY --from=builder /go/bin/app /app
 ---> Using cache
 ---> 5645db256412
Step 9/9 : CMD /app
 ---> Using cache
 ---> 8d428d6f7113
Successfully built 8d428d6f7113
Successfully tagged test-multi-hello:latest
Run Code Online (Sandbox Code Playgroud)

查看图像,只有单个二进制文件出现在映像中,而构建环境超过700MB:

$ docker images | grep 2630f482fe78
<none>                <none>              2630f482fe78        6 days ago          700MB

$ docker images | grep 8d428d6f7113
test-multi-hello      latest              8d428d6f7113        6 days ago          1.56MB
Run Code Online (Sandbox Code Playgroud)

是的,它运行:

$ docker run --rm test-multi-hello 
Hello, world.
Run Code Online (Sandbox Code Playgroud)

  • 请注意,通过这种方法,工作目录,入口点,环境等将消失,您必须重复它们。除此之外,完美!:) (3认同)
  • 请注意,`COPY`会将所有文件系统所有权重写为root(或运行该命令的用户),这可能是不可取的. (3认同)