近期使用Docker打包镜像遇到的问题总结
总结最近使用docker遇到的问题和解决办法。
背景
在 github.com/yeqown/goreportcard 项目中我改造了 goreportcard
。
后续为了方便部署,我准备将其打包成为docker镜像并上传到 DockerHub
。期间遇到了下面的问题,并一一解决,这里做一个记录帮助以后遇到类似的问题可以快速解决。
初期的目标是:将goreportcard
和golangci-lint
编译好,尽可能较小镜像的体积。因此第一次尝试,我使用了分阶段编译,用golang:1.14.1
编译,alpine
来发布。
基本 Dockerfile 如下:
# building stage
FROM golang:1.14-alpine3.11 as build
WORKDIR /tmp/build
COPY . .
RUN export GOPROXY="https://goproxy.cn,direct" \
&& go mod download \
&& go build -o app ./cmd/goreportcard-cli/ \
&& go get github.com/golangci/golangci-lint && go install github.com/golangci/golangci-lint/cmd/golangci-lint
# release stage
FROM golang:1.14-alpine3.11 as release
WORKDIR /app/goreportcard
COPY --from=build /tmp/build/app .
COPY --from=build /tmp/build/tpl ./tpl
COPY --from=build /tmp/build/assets ./assets
# FIXED: 不能使用golangci-lint, `File not found` 错误
COPY --from=build /go/bin/golangci-lint /usr/local/bin
EXPOSE 8000
ENTRYPOINT ["./app", "start-web", "&"]
问题清单和解决方案
由于并不是所有的问题都和Docker有关,因此我会使用
[分类]
在标题上注明。
0. 如何调试Docker打包过程 [Docker]
在Docker打包过程中会有如下字样,其中---> 5d5cac8457ad
字样就是一个可以运行的镜像,因此我们可以尝试运行这个镜像来获取我们想要的信息,
而不用在 Dockerfile
中通过 echo
来Debug🐶。
docker build -t goreportcard:v1.0.0 .
Sending build context to Docker daemon 12.08MB
Step 1/13 : FROM golang:1.14-alpine3.11 as build
---> 5d5cac8457ad
Step 2/13 : WORKDIR /tmp/build
---> Using cache
---> c57b9255d5fb
Step 3/13 : COPY . .
运行打包过程中的镜像
docker run -it c57b9255d5fb
1 golangci-lint 编译好后复制到 alpine中无法运行?[Go]
遇到这个问题的时候,提示错误信息大致为File or Path not found
,但同时 goreportcard
是可以运行,这两者是在相同地环境下编译出来的。
因此肯定是编译的时候存在差异,初步判断为CGO_ENABLED,GOOS,GOARCH
三个变量,通过搜索和尝试最终统一增加这三个环境变量解决问题。
&& export CGO_ENABLED=0 \
&& export GOARCH=amd64 \
&& export GOOS=linux \
2. golangci-lint 需要Go
可执行文件? [Go]
// TODO:
3. go get
需要 git
/ ssh
客户端? [Go]
// TODO:
4. 在 alpine 中如何安装预编译好的软件,如git? [Docker]
这个是在git
的 linux安装帮助 里找到的😂,也不知道为啥,只能夸下git
可真专业
apk add git
5. 在 alpine 中安装软件特别慢,如何解决? [Docker]
sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
6. 镜像中 go get
怎么使用宿主的缓存? [Go+Docker]
把宿主机的 path/go/pkg
挂载到 /go/pkg
,这里默认使用的是go的容器镜像。