Go Hello World:Docker 打包与运行
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| CA | Certificate Authority | 证书颁发机构 |
| CPU | Central Processing Unit | 中央处理器 |
| HTTP | Hypertext Transfer Protocol | 超文本传输协议 |
| SIGTERM | Termination Signal | 请求进程正常终止的信号 |
目标:创建 HTTP 服务,编译成二进制,再放入非 root 容器。只需 Docker 和 curl,无需本机安装 Go。以下命令在 Bash 中执行。
1. 创建项目#
mkdir go-hello
cd go-hello保存 go.mod:
module example.com/go-hello
go 1.26.0保存 main.go:
package main
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
fmt.Fprintln(w, "Hello World from Go!")
})
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "ok")
})
server := &http.Server{
Addr: ":8080", Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
IdleTimeout: 60 * time.Second,
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go func() {
log.Println("listening on :8080")
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}()
<-ctx.Done()
shutdown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.Shutdown(shutdown); err != nil {
log.Fatal(err)
}
}2. Dockerfile#
保存 Dockerfile:
# syntax=docker/dockerfile:1
FROM golang:1.26-bookworm AS build
WORKDIR /src
COPY go.mod ./
COPY main.go ./
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/server .
FROM scratch
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /out/server /server
USER 65532:65532
EXPOSE 8080
ENTRYPOINT ["/server"]构建阶段包含编译器;运行阶段只有程序和 CA 证书。CGO_ENABLED=0 适用于本例纯 Go 服务;依赖 C 库的项目需另选运行镜像。scratch 没有 shell,不能使用 docker exec ... sh。
保存 .dockerignore:
.git
.env
.env.*
server
*.log本例只用标准库,不需要 go.sum。添加第三方依赖后提交 go.sum,在构建阶段先复制 go.mod go.sum 并执行 go mod download,再复制源码。
3. 构建、运行与验证#
docker build -t go-hello:local .
docker run -d --name go-hello --read-only --cap-drop=ALL --security-opt=no-new-privileges:true -p 127.0.0.1:8080:8080 go-hello:local
curl --fail --retry 10 --retry-connrefused --retry-delay 1 http://127.0.0.1:8080/
curl --fail http://127.0.0.1:8080/healthz
docker logs go-hello预期分别返回 Hello World from Go! 和 ok。EXPOSE 仅声明端口,-p 才建立映射;服务必须监听容器所有接口,不能只绑定容器内的 localhost。
4. 停止与清理#
docker stop --timeout 10 go-hello
docker inspect go-hello --format '{{.State.ExitCode}}'
docker rm go-hello
docker image rm go-hello:local正常退出码为 0;程序收到 SIGTERM 后最多等待 5 秒处理在途请求。部署到不同 CPU 架构时需构建匹配目标架构的镜像;正式交付固定基础镜像 digest 并做漏洞扫描。
参考:Docker 多阶段构建。