你以为 Alpine 镜像想用就能用?

你以为 Alpine 镜像想用就能用?🌚

1 大致流程

  • alpine 镜像体积只有 5MB,作为 Docker 下最小的 Linux 镜像,很适合打造一些轻量级镜像。但 alpine 底层使用 musl-libc,兼容性与 glibc 有一定差距。
  1. 用 Golang 编写了一个简单的 hello, world 程序, Dockerfile 使用 alpine 作为基础镜像 FROM alpine:latest 能够正常运行;
  2. 基于 Gin 框架 Web 应用,相似的 Dockerfile 文件,build 完成后 run 的时候报了一些不明原因的错误,最后基础镜像改为 centos 或 alpine-glibc 后 (FROM centos:latest) 重新构建的镜像可以正常运行。

2 问题复现

2.1 使用 alpine 作为基础镜像构建 Golang “hello, world” 应用, ENTRYPOINT 使用 sh 运行程序

2.1.1 编写 “hello, world” Dockerfile,基础镜像 alpine

hello.go

package main

import (
	"fmt"
	"os"
	"flag"
)

var config = flag.String("config", "go & docker", "[-config value]")

func main() {
	flag.Parse()
	fmt.Printf("os.Args: %s\n", os.Args)
	fmt.Printf("hello, %s\n", *config)
}
FROM alpine:latest
ENV PARAMS=""
WORKDIR /
ADD hello /
ENTRYPOINT [ "sh", "-c", "./hello $PARAMS" ]
2.1.2 构建镜像

docker build -t hellogo:0.9 .

Sending build context to Docker daemon  2.152MB

Step 1/5 : FROM alpine:latest
 ---> 961769676411
Step 2/5 : ENV PARAMS=""
 ---> Using cache
 ---> 3d8a4e790bbf
Step 3/5 : WORKDIR /
 ---> Using cache
 ---> f693abea2696
Step 4/5 : ADD hello /
 ---> Using cache
 ---> 156c71a0b934
Step 5/5 : ENTRYPOINT [ "sh", "-c", "./hello $PARAMS" ]
 ---> Using cache
 ---> c5d4aa11a311
Successfully built c5d4aa11a311
Successfully tagged hellogo:0.9
2.1.3 运行

docker run --rm hellogo:0.9

输出结果

os.Args: [./hello]
hello, go & docker

由此可见,运行 hello, world 没啥问题

2.2 使用 alpine 作为基础镜像构建web应用, ENTRYPOINT 使用 sh 运行程序

2.2.1 编写 Dockerfile,基础镜像 alpine
FROM alpine:latest
WORKDIR /
ENV PARAMS=""
ADD orderserver /
ADD configs /configs
EXPOSE 60001
ENTRYPOINT ["sh", "-c", "/orderserver $PARAMS"]
2.2.2 构建镜像

执行命令docker build -t orderserver:build-with-alpine .

Sending build context to Docker daemon  23.83MB

Step 1/7 : FROM alpine:latest
 ---> 961769676411
Step 2/7 : WORKDIR /
 ---> Running in 4e77f58acc2a
Removing intermediate container 4e77f58acc2a
 ---> 576bb22ca7c6
Step 3/7 : ENV PARAMS=""
 ---> Running in 7d601c97afad
Removing intermediate container 7d601c97afad
 ---> d1bbcbd11e4f
Step 4/7 : ADD orderserver /
 ---> e804183d1957
Step 5/7 : ADD configs /configs
 ---> 5f22f0e5e099
Step 6/7 : EXPOSE 60001
 ---> Running in 849525af1bad
Removing intermediate container 849525af1bad
 ---> 354f12aa7c3d
Step 7/7 : ENTRYPOINT ["sh", "-c", "/orderserver $PARAMS"]
 ---> Running in 4119e9b8543a
Removing intermediate container 4119e9b8543a
 ---> 40c84a5e3673
Successfully built 40c84a5e3673
Successfully tagged orderserver:build-with-alpine
2.2.3 启动镜像

docker run -P --rm --name orderserver0 -v /docker/data/have-you-ordered/configs:/mounted -e PARAMS="-config /mounted/config.json" orderserver:build-with-alpine

docker : sh: /orderserver: not found

镜像因为不明原因报了找不到 orderserver 文件

2.3 使用 alpine 作为基础镜像构建, ENTRYPOINT 直接执行目标二进制文件,有更详细的报错信息,但仍然难以排查原因

2.3.1 编写 Dockerfile,ENTRYPOINT 直接执行目标程序
FROM alpine:latest
WORKDIR /
ENV PARAMS=""
ADD orderserver /
ADD configs /configs
EXPOSE 60001
#ENTRYPOINT ["sh", "-c", "/orderserver $PARAMS"]
ENTRYPOINT ["/orderserver"]
2.3.2 build

docker build -t orderserver:for-test .

Sending build context to Docker daemon  23.83MB

Step 1/7 : FROM alpine:latest
 ---> 961769676411
Step 2/7 : WORKDIR /
 ---> Running in 94a464e58a2a
Removing intermediate container 94a464e58a2a
 ---> a2bd2111ff1a
Step 3/7 : ENV PARAMS=""
 ---> Running in d836703cad25
Removing intermediate container d836703cad25
 ---> 1beadaa8423a
Step 4/7 : ADD orderserver /
 ---> a10094c7eebb
Step 5/7 : ADD configs /configs
 ---> 6e80ce8fb8cd
Step 6/7 : EXPOSE 60001
 ---> Running in c70a05d12a5f
Removing intermediate container c70a05d12a5f
 ---> c9d7ea756259
Step 7/7 : ENTRYPOINT ["/orderserver"]
 ---> Running in 430fd5268cf0
Removing intermediate container 430fd5268cf0
 ---> 9bb02c756cd0
Successfully built 9bb02c756cd0
Successfully tagged orderserver:for-test
2.3.3 运行镜像

报错信息:
docker : standard_init_linux.go:211: exec user process caused "no such file or directory"

与使用 sh 执行相比,报错信息更详细,不过貌似对问题排查仍然没什么帮助

2.4 使用 frolvlad/alpine-glibc 作为基础镜像构建并运行

2.4.1 编写 Dockerfile ,基础镜像 alpine-glibc
FROM frolvlad/alpine-glibc:latest
WORKDIR /
ENV PARAMS=""
ADD orderserver /
ADD configs /configs
EXPOSE 60001
ENTRYPOINT ["sh", "-c", "/orderserver $PARAMS"]
2.4.2 构建镜像

docker build -t orderserver:using-glibc .

Sending build context to Docker daemon  23.83MB

Step 1/7 : FROM frolvlad/alpine-glibc:latest
 ---> e8076a77c225
Step 2/7 : WORKDIR /
 ---> Running in fc67e5d9e5fa
Removing intermediate container fc67e5d9e5fa
 ---> 2ced8d6cdaf2
Step 3/7 : ENV PARAMS=""
 ---> Running in fbb048b38832
Removing intermediate container fbb048b38832
 ---> bec33277d8a1
Step 4/7 : ADD orderserver /
 ---> 7df727ecfc51
Step 5/7 : ADD configs /configs
 ---> 5dc592e179c3
Step 6/7 : EXPOSE 60001
 ---> Running in 001fa109df4e
Removing intermediate container 001fa109df4e
 ---> e1a8e1f7a580
Step 7/7 : ENTRYPOINT ["sh", "-c", "/orderserver $PARAMS"]
 ---> Running in 06fc223499e5
Removing intermediate container 06fc223499e5
 ---> 0c819ac833c6
Successfully built 0c819ac833c6
Successfully tagged orderserver:using-glibc
2.4.3 启动镜像

docker run -P --rm --name orderserver0 -v /docker/data/have-you-ordered/configs:/mounted -e PARAMS="-config /mounted/config.json" orderserver:using-glibc

看到一下信息代表Web应用能够正常启动了,底下报错只是因为没有配置Elasticsearch

2019/10/11 09:27:48 {{[http://es.0:49204]  } :60001 having-meal 1h}
os.Args: [/orderserver -config /mounted/config.json]
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET    /api                      --> have-you-ordered/internal/app/orderserver.ApiHelloGo (3 handlers)
[GIN-debug] GET    /api/ordered/:date        --> have-you-ordered/internal/app/orderserver.ApiOrdered (3 handlers)
[GIN-debug] POST   /api/order                --> have-you-ordered/internal/app/orderserver.PostOrder (3 handlers)
[GIN-debug] POST   /api/fake-order           --> have-you-ordered/cmd/orderserver/app.Run.func1 (3 handlers)
[GIN-debug] GET    /api/dashboard/agg-by-day --> have-you-ordered/internal/app/orderserver.AggHistogram (3 handlers)
[GIN-debug] POST   /api/control/fetch        --> have-you-ordered/internal/app/orderserver.ManuallyFetch (3 handlers)
[GIN-debug] Listening and serving HTTP on :60001
2019/10/11 09:27:48 Start Fetch Interval: 3600 sec
2019/10/11 09:27:48 Error getting response: dial tcp 127.0.0.1:49204: connect: connection refused
2019/10/11 09:27:48 Fetch interval error: runtime error: invalid memory address or nil pointer dereference

3 总结

  1. 选择基础镜像需要充分考虑运行环境要求,当遇到未知错误时,需要考虑运行环境兼容性问题。

其实说了这么多,本人水平有限,还是没有找到特别明确的原因,望指点🙏

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wuweijie@apache.org

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值