2022年8月25日早上
最近在学习prometheus 那一套 监控系统。
在docker安装了一个redis-exporter,竟然怎么都进不去 容器。
开始百度,测试了 sh bash csh 都不行,都是这种错误
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
连 docker exec -it redis-exporter echo $PATH
都是
OCI runtime exec failed: exec failed: unable to start container process: exec: "echo": executable file not found in $PATH: unknown
在gitub上发了issue,刚发完2分钟,我仔细一看README。还有个alpine版本,可以进入shell,正常版本进不了shell 。 github上是这样说的
当时压根没仔细看。
---------------------------分割线----------------------------------------
这就带来一个问题,我一直以为docker只是轻量级的虚拟机,应用装在一个base image 上面 。base image 肯定是一个操作系统,不管是mac 还是win 还是类linux,但是一个镜像还能只包含一个binary文件吗,那这个binary运行在什么上面?
这值得研究一下,从Dockerfile入手先
把redis-exporter 的Dockerfile 链接放在这里:
https://github.com/oliver006/redis_exporter/blob/master/docker/Dockerfile
等有时间回来
--------------------------------------------------------------分割线-------------------------------------------------------------
我回来了(2022年8月25日16点23分)
分析了一下Dockfile
ARG GOARCH
#
# build container
#
FROM --platform=linux/amd64 golang:1.19-alpine as builder
WORKDIR /go/src/github.com/oliver006/redis_exporter/
ADD . /go/src/github.com/oliver006/redis_exporter/
ARG SHA1="[no-sha]"
ARG TAG="[no-tag]"
ARG GOARCH
RUN apk --no-cache add ca-certificates git
RUN BUILD_DATE=$(date +%F-%T) CGO_ENABLED=0 GOOS=linux GOARCH=$GOARCH go build -o /redis_exporter \
-ldflags "-s -w -extldflags \"-static\" -X main.BuildVersion=$TAG -X main.BuildCommitSha=$SHA1 -X main.BuildDate=$BUILD_DATE" .
RUN [ "$GOARCH" = "amd64" ] && /redis_exporter -version || ls -la /redis_exporter
#
# scratch release container
#
FROM --platform=linux/$GOARCH scratch as scratch
COPY --from=builder /redis_exporter /redis_exporter
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
COPY --from=builder /etc/nsswitch.conf /etc/nsswitch.conf
# Run as non-root user for secure environments
USER 59000:59000
EXPOSE 9121
ENTRYPOINT [ "/redis_exporter" ]
#
# Alpine release container
#
FROM --platform=linux/$GOARCH alpine as alpine
COPY --from=builder /redis_exporter /redis_exporter
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
# Run as non-root user for secure environments
USER 59000:59000
EXPOSE 9121
ENTRYPOINT [ "/redis_exporter" ]
可以看到里面有三次From。 这里涉及到一个概念:多阶段构建。
这里引用
https://blog.csdn.net/cheng_fu/article/details/122207305
如下:
所以可以看到redis-exporter 也是先用golang编译了程序。
第一个From:FROM --platform=linux/amd64 golang:1.19-alpine as builder
而golang的镜像很大有300多M
顺便一提,–platform是为了跨平台的配置,
https://docs.docker.com/engine/reference/builder/#from
as builder 的用法见官方文档,这样下面就可以直接COPY --from builder 了
https://docs.docker.com/develop/develop-images/multistage-build/
第二个From 是 FROM --platform=linux/$GOARCH scratch as scratch
scratch 是docker提供的基础镜像,可以用来构建超小的镜像。具体解释如下:
go语言 编译后直接是可执行文件,所以From scratch 就可以,但是里面没有shell/ls/echo等一些基础的东西。
那么第三个From:FROM --platform=linux/$GOARCH alpine as alpine
Alpine Linux是一个面向安全的轻量级Linux发行版,基于musl libc和Busybox。
讲真,linux的东西我也不懂,就不冒充了。各位自行百度哈。这里说一下我知道的。
Alpine Linux 只有5M多,你敢信··
对比一下alpine 和普通版本,发现alpine14.8M,普通的9.28M,多的5M多就是Alpine Linux。
还可以看到nginx142M。对比很明显。 再看一下docker history
再把镜像导出对比一下