在 alpine 上打包运行go服务

简介: 在 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


20200807101331862.png


cgo在alpine 上运行需要依赖musl_dev 这个包, 在Dockerfile中加入后还是不行

参考二:

https://github.com/zmap/zlint/issues/316

20200807101629499.png


问题定位到了, 需要binutils 包的版本大于2.32并且 alpine 的版本大于等于 3.10, 我之前仓库用的是alpine 3.7版本的, 下载的binutils 包版本太低, 所以把阿里源的仓库版本改为3.10就好了, 问题解决


总结


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

目录
相关文章
|
4月前
|
缓存 弹性计算 API
用 Go 快速开发一个 RESTful API 服务
用 Go 快速开发一个 RESTful API 服务
|
1月前
|
Go UED
Go Web服务中如何优雅平滑重启?
在生产环境中,服务升级时如何确保不中断当前请求并应用新代码是一个挑战。本文介绍了如何使用 Go 语言的 `endless` 包实现服务的优雅重启,确保在不停止服务的情况下完成无缝升级。通过示例代码和测试步骤,详细展示了 `endless` 包的工作原理和实际应用。
50 3
|
1月前
|
JSON Go UED
Go Web服务中如何优雅关机?
在构建 Web 服务时,优雅关机是一个关键的技术点,它确保服务关闭时所有正在处理的请求都能顺利完成。本文通过一个简单的 Go 语言示例,展示了如何使用 Gin 框架实现优雅关机。通过捕获系统信号和使用 `http.Server` 的 `Shutdown` 方法,我们可以在服务关闭前等待所有请求处理完毕,从而提升用户体验,避免数据丢失或不一致。
26 1
|
6月前
|
Go
go创建web服务
go创建web服务
|
3月前
|
Go API 开发者
深入探讨:使用Go语言构建高性能RESTful API服务
在本文中,我们将探索Go语言在构建高效、可靠的RESTful API服务中的独特优势。通过实际案例分析,我们将展示Go如何通过其并发模型、简洁的语法和内置的http包,成为现代后端服务开发的有力工具。
|
4月前
|
安全 Go Docker
Go服务Docker Pod不断重启排查和解决
该文章分享了Go服务在Docker Pod中不断重启的问题排查过程和解决方案,识别出并发写map导致fatal error的问题,并提供了使用sync.Map或concurrent-map库作为并发安全的替代方案。
55 4
|
4月前
|
监控 Go 微服务
使用 ServiceWeaver 构建 go 服务
使用 ServiceWeaver 构建 go 服务
|
4月前
|
安全 小程序 Go
如何更干净地退出Go服务
如何更干净地退出Go服务
|
4月前
|
运维 监控 容灾
[go 面试] 实现服务高可用的策略和实践
[go 面试] 实现服务高可用的策略和实践
|
5月前
|
XML JSON Go
Swoole与Go系列教程之WebSocket服务的应用
在 WebSocket 协议出现之前,Web 应用为了能过获取到实时的数据都是通过不断轮询服务端的接口。轮询的效率、延时很低,并且很耗费资源。
1061 2
Swoole与Go系列教程之WebSocket服务的应用