Files

3.4 KiB
Raw Permalink Blame History

title, published, updated, image, description, tags, draft, series, seriesOrder, difficulty
title published updated image description tags draft series seriesOrder difficulty
Docker 编译 musl 可执行文件 2025-03-27 2025-03-27 /posts/docker-musl-build/img/cover.svg 解决 Go 语言跨平台编译问题,使用 Docker + musl 编译静态链接的可执行文件。
Docker
Go
运维
false Docker 实践笔记 1 进阶

解决问题

用 Go 进行跨平台编译时往往步骤复杂,用 Docker 可以轻松解决。但 Docker 的当前最小镜像 Alpine 其动态链接库采用 musl,与主流的 glibc 不同,往往不能方便执行。

查阅资料

# 启动容器并挂载当前目录到 `/app`
docker run -it --rm -v "$PWD":/app -w /app ubuntu:20.04 bash

# 在容器内执行以下操作:
apt-get update && apt-get install -y musl-tools golang-go  # 安装 musl 和 Go
export CC=musl-gcc  # 指定 musl 编译器
export CGO_ENABLED=1  # 启用 CGO
# 设置代理
go env -w GOPROXY=https://goproxy.cn,direct
go build -ldflags '-linkmode external -extldflags "-static"' -o myapp  # 静态编译
exit  # 退出容器

# 验证结果(在宿主机执行)
file myapp  # 应显示 "statically linked"
ldd myapp   # 应显示 "not a dynamic executable"

wget https://go.dev/dl/go1.21.linux-amd64.tar.gz

ENV PATH="/data/go/bin:$PATH"

遇到问题

  1. go mod tidy 时报错 tls: failed to verify certificate: x509: certificate

    解决:RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*

    基础镜像的证书未更新,导致 https 的请求出现类似错误。

    image-20250327100813512

  2. 直接安装 golang-go 其版本过低

    解决: PATH="/data/go/bin:$PATH" 手动指定环境

最终方案

  1. 下载 go1.24.1.linux-amd64.tar.gz 解压
  2. 编写 Dockerfile
  3. 执行 docker build -t go-build:v1 .

Dockerfile 内容:

FROM ubuntu:20.04

LABEL org.opencontainers.image.authors="sutong"

COPY go/ /go/

ENV PATH="/go/bin:$PATH"

RUN apt-get update && apt-get install -y musl-tools

## go mod tidy 时报错 tls: failed to verify certificate: x509: certificate
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
# 指定 musl 编译器
ENV CC=musl-gcc
# 启用 CGO
ENV CGO_ENABLED=1

VOLUME /data

WORKDIR /data

CMD ["/bin/bash"]

构建

# docker build -t go-build:v1 .

# 直接执行编译 编译后删除
docker run --rm -v .:/data go-build:v1 go build -o app_musl

# 构建编译环境
docker run -it -d -v .:/data --name <容器名称> go-build:v1 /bin/bash
# egdocker run -it -d -v .:/data --name logbus-build go-build:v1 /bin/bash

docker exec -it <容器名称> go build -o <myapp>
# egdocker exec -it logbus-build go build -o logbus_musl_1

额外注意

若没科学上网需要设置代理:

docker exec -it <容器名称> /bin/bash
go env -w GOPROXY=https://goproxy.cn,direct
go build -ldflags '-linkmode external -extldflags "-static"' -o myapp  # 静态编译
go build # musl 库编译

运行环境示例

FROM alpine:latest

LABEL org.opencontainers.image.authors="sutong"

COPY glog_musl /app/

COPY conf.ini /data/
COPY ipname.ini /data/

WORKDIR /app

RUN chmod 777 /app/glog_musl

CMD ["./glog_musl", "logsweb", "/data/conf.ini"]

# docker build -t glog:v1 .
# docker run -p 6801:6801 glog:v1