我创建了一个相当大的Docker容器。当我将该容器提交以创建镜像时,镜像大约有7.8GB。但当我将容器导出(不是保存镜像!)到tar包并重新导入时,镜像只有3GB大小。当然历史记录会丢失,但这对我来说没问题,因为我认为镜像已经"完成"并准备好部署。
如何在不将其导出到磁盘并重新导入的情况下压缩图像/容器?此外:这样做明智吗,还是我错过了一些重要的点?
我创建了一个相当大的Docker容器。当我将该容器提交以创建镜像时,镜像大约有7.8GB。但当我将容器导出(不是保存镜像!)到tar包并重新导入时,镜像只有3GB大小。当然历史记录会丢失,但这对我来说没问题,因为我认为镜像已经"完成"并准备好部署。
如何在不将其导出到磁盘并重新导入的情况下压缩图像/容器?此外:这样做明智吗,还是我错过了一些重要的点?
FROM buildimage as build
# your existing build steps here
FROM scratch
COPY --from=build / /
CMD ["/your/start/script"]
$ 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"]
go文件是一个简单的“hello world”示例:
$ cat hello.go
package main
import "fmt"
func main() {
fmt.Printf("Hello, world.\n")
}
$ 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
看这些图片,我们可以发现,只有一个二进制文件被发布在镜像中,而构建环境却超过了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
是的,它可以运行:
$ docker run --rm test-multi-hello
Hello, world.
COPY
命令会将所有文件系统的所有权重写为 root(或运行该命令的用户),这可能不是理想的情况。 - ti7从 Docker 1.13 开始,您可以使用 --squash
标志。
在版本 1.13 之前:
据我所知,您无法使用 Docker API。对于这种情况,docker export
和 docker import
是专为此设计的,正如您自己已经提到的那样。
如果您不想保存到磁盘,您可能可以将导出流的输出流导入到导入流的输入流中。我没有测试过这个方法,但可以尝试。
docker export red_panda | docker import - exampleimagelocal:new
--squash
标志在哪些情况下可以使用? - anon安装命令如下:
pip install docker-squash
如果您有一个图片,可以使用以下方法将所有图层压缩到一个图层中:
docker-squash -f <nr_layers_to_squash> -t new_image:tag existing_image:tag
一个对我很有用的快速压缩所有图层的一行代码:
docker-squash -f $(($(docker history $IMAGE_NAME | wc -l | xargs)-1)) -t ${IMAGE_NAME}:squashed $IMAGE_NAME
--squash
标志构建镜像:
https://docs.docker.com/engine/reference/commandline/build/#squash-an-images-layers---squash-experimental
此外,还要考虑清理不需要的文件,例如apt缓存:apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
--rm
选项构建?这将删除中间镜像。或者我误解了问题? - shabbychefRUN
中调用一堆安装命令,删除不需要的Ubuntu软件包等。请参考https://github.com/dckc/ipython-docker/blob/master/Dockerfile获取一个好的例子。 - shabbychef