# 缩减docker镜像体积

以一个C语言的hello word为例:

#include <stdio.h>
#include <unistd.h>
int main () {
  printf("Hello, world!");
  sleep(100000); 
  return 0;
} 

dockerfile 如下:

FROM gcc
COPY hello.c .
RUN gcc -o hello hello.c
CMD ["./hello"]

打包一下:

docker build -f gcc -t hello:gcc .  
Sending build context to Docker daemon  9.826MB
Step 1/4 : FROM gcc
 ---> 828cd42f8a79
Step 2/4 : COPY hello.c .
 ---> Using cache
 ---> 8b885dff2f96
Step 3/4 : RUN gcc -o hello hello.c
 ---> Using cache
 ---> a67d4b9e5d34
Step 4/4 : CMD ["./hello"]
 ---> Running in 4149076b6bdc
Removing intermediate container 4149076b6bdc
 ---> 72502b8ed5aa
Successfully built 72502b8ed5aa
Successfully tagged hello:gcc

后发现镜像体积接近1G多:

docker images | grep gcc
hello               gcc                 72502b8ed5aa        7 seconds ago       1.19GB

改成多层构建

FROM gcc AS mybuildstage
COPY hello.c .
RUN gcc -o hello hello.c
FROM ubuntu
COPY --from=mybuildstage hello .
CMD ["./hello"]

打包后发现体积变成73.9MB了

docker images | grep gcc1
hello               gcc1                c7b00d5f6293        55 seconds ago      73.9MB

就一个hello world,能不能更小一点呢?用scratch吧

FROM gcc
COPY hello.c .
RUN gcc -o hello hello.c
FROM scratch
COPY --from=0 hello .
CMD ["./hello"]

打包后的镜像只有16.4kB了:

docker images | grep gcc2           
hello               gcc2                e582940e0091        50 seconds ago          16.4kB

但运行不起来:

docker run -itd hello:gcc2
4e9269f8daa2d57a60d5999058aa0b70cc6e921c0839dcc9fd05c6c8f4275fd5

docker ps --all | grep gcc2
4e9269f8daa2        hello:gcc2          "./hello"           3 minutes ago       Exited (1) 3 minutes ago                       sharp_hellman

docker logs 4e9269f8daa2
standard_init_linux.go:211: exec user process caused "no such file or directory"

折中一下,用 busybox:glibc 吧:

FROM gcc
COPY hello.c .
RUN gcc -o hello hello.c
FROM busybox:glibc
COPY --from=0 hello .
CMD ["./hello"]

打包后是5.21MB,不错。

docker images  | grep gcc3
hello               gcc3                11d69c32e379        54 seconds ago          5.21MB

正常运行:

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
eef52f039b56        hello:gcc3          "./hello"           2 seconds ago       Up 1 second                             kind_lamarr

并且可以进容器敲各种命令:

docker exec -it eef52f039b56 /bin/sh
/ # 
/ # 
/ # ls
bin    dev    etc    hello  home   lib    lib64  proc   root   sys    tmp    usr    var
/ # pwd
/

参考:https://mp.weixin.qq.com/s/6bgtD0Aer6-3u4u9jWBBhw