微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

禁用 cgo 以使 golang:alpine 工作有什么风险吗?

如何解决禁用 cgo 以使 golang:alpine 工作有什么风险吗?

我的目标是为我的 golang 应用程序比较两个 docker 解决方案:

  1. 使用 ubuntu 作为基础镜像
  2. 使用 golang:alpine 作为基础镜像

我的 Dockerfile 非常简单,类似于:

FROM ubuntu:20.04
# FROM golang:alpine for alpine based images

# myApp binary is pre-built before running docker build
copY bin/myApp app/myApp
copY myApp-config.json app/myApp-config.json

CMD MYAPP_CONfig=app/myApp-config.json ./app/myApp

对于基于 alpine 的图像,我点击了 same issue here,其中 /app/myApp 无法启动,因为我生成的图像中缺少 CGO 动态链接。我通过在 go build 期间禁用 CGO 来解决这个问题:

CGO_ENABLED=0

由于我对 docker 很陌生,所以我的问题是:

  1. 禁用 CGO 是否有任何风险?我的理解是go build会回退到CGO的原生go实现,但是不知道有没有什么隐藏的陷阱。我的应用确实严重依赖 net/http,这似乎需要在运行时存在 CGO。
  2. 似乎 alpine 图像是用于 golang 的事实上的基础图像,处理这个 CGO 问题的标准方法是什么?

谢谢!

解决方法

如果您的应用基于 net/http - 那么您可能需要担心的唯一考虑因素就是 DNS 解析。

TL;DR

您可能会看到的唯一问题是在具有主机名的 kubernetes 环境中 以 .local

结尾

使用 CGO_ENABLED=1(go build 默认),它将使用本机操作系统的 DNS 解析器。

CGO_ENABLED=0scratch Docker 构建一起使用 - 然后使用 Go 的 DNS 解析器。

有什么区别?查看官方Go docs

解析域名的方法,是否间接用 Dial 等函数或直接使用 LookupHost 和 LookupAddr,因操作系统而异。

在 Unix 系统上,解析器有两种解析名称的选项。它 可以使用纯 Go 解析器直接将 DNS 请求发送到 /etc/resolv.conf 中列出的服务器,或者它可以使用基于 cgo 的解析器 调用 C 库例程,例如 getaddrinfo 和 getnameinfo。

默认使用纯 Go 解析器,因为一个被阻止的 DNS 请求 只消耗一个 goroutine,而阻塞的 C 调用消耗一个 操作系统线程。当 cgo 可用时,基于 cgo 的解析器 在各种条件下使用:在不 让程序直接发出 DNS 请求 (OS X),当 LOCALDOMAIN 环境变量存在(即使为空),当 RES_OPTIONS 或 HOSTALIASES 环境变量非空,当 ASR_CONFIG 环境变量非空(仅限 OpenBSD),当 /etc/resolv.conf 或 /etc/nsswitch.conf 指定使用功能 Go 解析器未实现,以及当名称为 查找以 .local 结尾或 mDNS 名称。


就我个人而言,我已经在 net/http Docker 容器中的 scratch Docker 容器中构建了数十个基于 CGO_ENABLED=0 的微服务,没有任何问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。