在 alpine 上打包运行go服务

前言

有一位朋友看了 Docker私有仓库搭建&Go服务部署之后就在自己的项目中开发环境用上了, 然后现在项目要部署到测试及生产环境, 因为他们之前的项目没用docker且go的版本为1.12, 当前项目的环境为go 1.14, 老大要求每个项目的环境必须隔离, 打包也必须要镜像内打包(避免人工打包失误), 这位朋友在容器内打包的时候遇到了挺麻烦的问题求助了一下我, 所以就有了这篇文章
上次讲的是开发环境自己在本地打包然后把二进制放在镜像里运行, 方便快捷, 这次线上环境要在容器内用go打包二进制运行文件的话就需要对应的环境和依赖安装了, 包管理的话还是建议go mod, 个人感觉方便好用

在 alpine 上打包运行go服务

之前的Dockerfile是这样

# 设置基础镜像
FROM golang:1.14.4-alpine

# 作者描述信息
LABEL maintainer="飞啊飞"

# 使用国内源
RUN echo -e http://mirrors.aliyun.com/alpine/v3.7/main/ > /etc/apk/repositories

# copy当前目录的文件到镜像里面的工作目录目录下
COPY ./config/test.json /demo/   // 配置文件
COPY server /demo/               // 打包的linux二进制文件

#设置东八区,北京时间
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata && ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 指定路径
WORKDIR /demo/

# 执行命令  这里给文件增加执行权限
RUN ["chmod", "+x", "/demo/server"]

# 容器入口, 执行命令
CMD ["./server", "-config", "test.json"]

因为服务器版本的问题, 所以需要在docker内打包部署, 奉上一份正确的Dockerfile, 然后下面说遇到的问题

# 设置基础镜像
FROM golang:1.14.4-alpine

# 作者描述信息
LABEL maintainer="飞啊飞"

# copy整个项目
COPY ./config/test.json /demo/   // 配置文件
COPY . /demo/                    // 项目文件

# 使用阿里源&&设置东八区,北京时间
ENV TZ=Asia/Shanghai
RUN echo -e http://mirrors.aliyun.com/alpine/v3.10/main/ > /etc/apk/repositories \
    && apk update \
    && apk add --no-cache tzdata gcc g++ libffi-dev musl-dev openssl-dev make linux-headers libc-dev libc6-compat binutils \
    && ln -sf /usr/share/zoneinfo/$TZ /etc/localtime \
    && echo $TZ > /etc/timezone 

# 指定路径
WORKDIR /demo/

# 打包二进制&&增加执行权限
RUN export GOPROXY=https://mirrors.aliyun.com/goproxy/ \
    && go mod tidy \
    && export GOARCH=amd64 \
    && export GOOS=linux \
    && go build -o server ./main.go \
    && chmod +x server

# 容器入口, 执行命令
CMD ["./server", "-config", "test.json"]

说一下主要的两个坑

一 报错如下, 需要安装GCC

exec: "gcc": executable file not found in $PATH
# github.com/karalabe/usb
exec: "gcc": executable file not found in $PATH
# github.com/ethereum/go-ethereum/rpc
exec: "gcc": executable file not found in $PATH

二 GCC运行失败

# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../x86_64-alpine-linux-musl/bin/ld: /tmp/go-link-364684937/000000.o: unable to initialize decompress status for section .debug_info
/usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../x86_64-alpine-linux-musl/bin/ld: /tmp/go-link-364684937/000000.o: unable to initialize decompress status for section .debug_info
/usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../x86_64-alpine-linux-musl/bin/ld: /tmp/go-link-364684937/000000.o: unable to initialize decompress status for section .debug_info
/usr/lib/gcc/x86_64-alpine-linux-musl/6.4.0/../../../../x86_64-alpine-linux-musl/bin/ld: /tmp/go-link-364684937/000000.o: unable to initialize decompress status for section .debug_info
/tmp/go-link-364684937/000000.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status

参考一:
https://stackoverflow.com/questions/53964313/error-compiling-go-from-source-in-an-alpine-docker-container-loadinternal-can

在 alpine 上打包运行go服务_第1张图片
cgo在alpine 上运行需要依赖musl_dev 这个包, 在Dockerfile中加入后还是不行

参考二:
https://github.com/zmap/zlint/issues/316
在 alpine 上打包运行go服务_第2张图片
问题定位到了, 需要binutils 包的版本大于2.32并且 alpine 的版本大于等于 3.10, 我之前仓库用的是alpine 3.7版本的, 下载的binutils 包版本太低, 所以把阿里源的仓库版本改为3.10就好了, 问题解决

总结

找这种问题还是挺费劲的, 所以在此记录一下, 与人方便与己方便

你可能感兴趣的:(Docker,docker,alpine,gcc,go,musl-dev)