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 多阶段构建。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭