上篇讲了流量回放工具 goreplay 的二进制使用方式。想将其打包成一个镜像,在K8s部署的线上生产环境使用。
基于后向兼容性,希望构建的镜像 系统基于ubuntu 18.04,基于最新的Go版本进行编译安装。但同时不希望镜像的体积过大。
以下内容为构建容器镜像的一些方式。
在 Docker 17.05前,构建镜像通常采用两种方式:
1. 全部放入一个 Dockerfile
将所有的构建过程包含在一个 Dockerfile 中,包括项目及其依赖库的编译、测试、打包等流程,这里可能会带来的一些问题:
但这样的坏处也显而易见:镜像层次多,镜像体积较大,同时部署时间变长
代码语言:javascript复制FROM ubuntu:18.04
# Install build dependencies
RUN apt-get update && apt-get install -y
build-essential
libpcap-dev
curl
ca-certificates
wget
# Install Go
RUN curl -OLs https://go.dev/dl/go1.21.3.linux-amd64.tar.gz
&& tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz
&& rm go1.21.3.linux-amd64.tar.gz
ENV PATH /usr/local/go/bin:$PATH
# Get goreplay source code
RUN wget -c https://github.com/buger/goreplay/archive/refs/tags/1.3.3.tar.gz && tar -zxvf 1.3.3.tar.gz
RUN export GOPROXY=https://goproxy.cn
# Build goreplay
RUN cd goreplay-1.3.3 && go build -o gor
RUN mv goreplay-1.3.3/gor ./
COPY ./start.sh /app/start.sh
# 用于调试
#CMD sleep 86400
#CMD ["./start.sh"]
针对如上Dockerfile,执行ocker build -t ubuntu-with-gor/20231017 .
,
docker image ls
查看编译出的镜像大小,高达1.14G
2. 另外一种方式是分散到多个 Dockerfile,构建多个镜像,前一个镜像为后面的依赖
预先在一个 Dockerfile中 将项目及其依赖库构建好,再将其拷贝到另一个镜像的运行环境中
这种方式需编写两个 Dockerfile ,为了便利及后续可维护性,最好还要通过一个shell脚本能两个编译阶段整合起来。
这种方式构建出的镜像较小,能规避第一种方式的问题。但复杂度稍高。
使用多阶段构建
为解决以上问题,从Docker 17.05开始, 支持多阶段构建 (Multi-stage builds[1])
使用多阶段构建可以很解决前面提到的问题,且只需编写一个 Dockerfile (多个FROM,前面的是后面的基础)
在 /data/tmp/goreplay-lab3 目录下:
代码语言:javascript复制FROM ubuntu:18.04 AS build-env
# Install build dependencies
RUN apt-get update && apt-get install -y
build-essential
libpcap-dev
curl
ca-certificates
wget
# Install Go
RUN curl -OLs https://go.dev/dl/go1.21.3.linux-amd64.tar.gz
&& tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz
&& rm go1.21.3.linux-amd64.tar.gz
ENV PATH /usr/local/go/bin:$PATH
# Get goreplay source code
RUN wget -c https://github.com/buger/goreplay/archive/refs/tags/1.3.3.tar.gz && tar -zxvf 1.3.3.tar.gz
# Build goreplay
RUN cd goreplay-1.3.3 && go build -o gor
RUN mv goreplay-1.3.3/gor ./
FROM ubuntu:18.04
COPY --from=build-env ./gor ./gor
COPY ./start.sh ./start.sh
#CMD sleep 86400
#CMD ["./start.sh"]
如果是Dockerfile,则构建时 docker build -t xxx .
即可。其中 .
是指将当前目录作为构建上下文(可能需要copy什么东西之类的)
如果不叫Dockerfile,则需要 docker build -t xxx -f 文件名称如Dockerfile.new .
执行
docker build -t ubuntu-with-gor/20231017multistage .
运行
docker run -it ubuntu-with-gor/20231017multistage /gor --input-raw :8000 --output-stdout
根据报错,libpcap这个依赖,没法打包到gor二进制文件中,还是要以动态链接的形式引用
调整Dockerfile:
代码语言:javascript复制FROM ubuntu:18.04 AS build-env
RUN apt-get update && apt-get install -y
build-essential
libpcap-dev
curl
ca-certificates
wget
# Install Go
RUN curl -OLs https://go.dev/dl/go1.21.3.linux-amd64.tar.gz
&& tar -C /usr/local -xzf go1.21.3.linux-amd64.tar.gz
&& rm go1.21.3.linux-amd64.tar.gz
ENV PATH /usr/local/go/bin:$PATH
# Get goreplay source code
RUN wget -c https://github.com/buger/goreplay/archive/refs/tags/1.3.3.tar.gz && tar -zxvf 1.3.3.tar.gz
# Build goreplay
RUN cd goreplay-1.3.3 && go build -o gor
RUN mv goreplay-1.3.3/gor ./
FROM ubuntu:18.04
# Install dependencies (还是需要libpcap,不然gor无法运行...)
RUN apt-get update && apt-get install -y libpcap-dev
COPY --from=build-env ./gor ./gor
COPY ./start.sh ./start.sh
#CMD sleep 86400
#CMD ["./start.sh"]
再次构建,可以正常运行。
最后对比两种构建方式,镜像的体积差异:
可见针对于这个case,使用了多阶段构建,省了将近1G的空间..
另: 如何查看docker镜像每一层的大小?
可以使用以下命令:
代码语言:javascript复制docker history <镜像名称>
执行此命令后,将显示有关镜像每一层的详细信息,包括大小、创建时间和所用命令。
如果只想查看镜像的总大小而不需要每一层的详细信息,可以使用以下命令,将列出所有镜像及其大小。
代码语言:javascript复制docker images --format "{{.Repository}}:{{.Tag}}t{{.Size}}"
代码语言:javascript复制[root@xxxxxx goreplay-lab3]# docker history ubuntu-with-gor/20231017multistage
IMAGE CREATED CREATED BY SIZE COMMENT
ef445692c1c3 4 minutes ago /bin/sh -c #(nop) COPY file:3477a1d7e70cfddc… 124B
2a1beab897af 4 minutes ago /bin/sh -c #(nop) COPY file:e2d87186c89499c8… 17MB
684a5fa4113a 4 minutes ago /bin/sh -c apt-get update && apt-get install… 71.2MB
71eaf13299f4 11 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 11 months ago /bin/sh -c #(nop) ADD file:fc5d658c47ede5882… 63.1MB
[root@xxxxxx goreplay-lab3]# docker history ubuntu-with-gor/20231017v3
IMAGE CREATED CREATED BY SIZE COMMENT
cf6bf1961c5f 48 minutes ago /bin/sh -c #(nop) COPY file:3477a1d7e70cfddc… 124B
64e2cd095db3 48 minutes ago /bin/sh -c mv goreplay-1.3.3/gor ./ 17MB
21c9b5bdda07 48 minutes ago /bin/sh -c cd goreplay-1.3.3 && go build -o … 580MB
fb02ab4a0ca5 50 minutes ago /bin/sh -c export GOPROXY=https://goproxy.cn 0B
81848581b4b1 50 minutes ago /bin/sh -c wget -c https://github.com/buger/… 768kB
f7fe340b3104 2 hours ago /bin/sh -c #(nop) ENV PATH=/usr/local/go/bi… 0B
cae91c2acab5 2 hours ago /bin/sh -c curl -OLs https://go.dev/dl/go1.2… 214MB
1d45d6924b67 2 hours ago /bin/sh -c apt-get update && apt-get install… 267MB
71eaf13299f4 11 months ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 11 months ago /bin/sh -c #(nop) ADD file:fc5d658c47ede5882… 63.1MB
参考资料
[1]
Multi-stage builds: https://docs.docker.com/build/building/multi-stage/