refactor: use nginx -s reload instead of systemd

- doc: add comment
This commit is contained in:
2026-08-17 10:10:14 +08:00
parent 79f18fcdea
commit f536987a7e
62 changed files with 2216 additions and 598 deletions
+28 -3
View File
@@ -17,13 +17,15 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// MobyEngine adapts the official Docker Engine Go client.
// MobyEngine 适配官方 Docker Engine Go 客户端,实现 Engine 接口。
type MobyEngine struct {
// client 底层 Docker Engine 客户端。
client *client.Client
}
// NewMobyEngine creates a client from Docker's documented environment variables.
// API negotiation remains enabled, including when DOCKER_HOST selects a non-default socket.
// NewMobyEngine 依据 Docker 官方文档定义的环境变量创建客户端。
// 即使 DOCKER_HOST 指向非默认 socket,API 版本协商仍然保持启用。
// 创建失败时返回包装后的错误。
func NewMobyEngine() (*MobyEngine, error) {
apiClient, err := client.New(client.FromEnv)
if err != nil {
@@ -32,6 +34,7 @@ func NewMobyEngine() (*MobyEngine, error) {
return &MobyEngine{client: apiClient}, nil
}
// Ping 探测 Docker Engine 是否可达,不可达时返回包装后的错误。
func (e *MobyEngine) Ping(ctx context.Context) error {
if _, err := e.client.Ping(ctx, client.PingOptions{NegotiateAPIVersion: true}); err != nil {
return fmt.Errorf("ping Docker Engine: %w", err)
@@ -39,6 +42,8 @@ func (e *MobyEngine) Ping(ctx context.Context) error {
return nil
}
// PullImage 从远端仓库拉取指定镜像引用。
// 拉取完成后逐条读取并校验引擎返回的 JSON 流,确保过程中无错误。
func (e *MobyEngine) PullImage(ctx context.Context, imageReference string) error {
response, err := e.client.ImagePull(ctx, imageReference, client.ImagePullOptions{})
if err != nil {
@@ -51,6 +56,8 @@ func (e *MobyEngine) PullImage(ctx context.Context, imageReference string) error
return nil
}
// LoadImage 从归档读取流加载镜像。
// input 为空时返回错误;加载完成后同样校验引擎返回的 JSON 流。
func (e *MobyEngine) LoadImage(ctx context.Context, input io.Reader) error {
if input == nil {
return errors.New("image archive reader is required")
@@ -66,6 +73,8 @@ func (e *MobyEngine) LoadImage(ctx context.Context, input io.Reader) error {
return nil
}
// decodeImageLoadResponse 逐条解码 Docker 引擎的 JSON 消息流。
// 读到 EOF 表示成功;遇到消息中的错误字段时立即返回该错误。
func decodeImageLoadResponse(input io.Reader) error {
decoder := json.NewDecoder(input)
for {
@@ -82,6 +91,8 @@ func decodeImageLoadResponse(input io.Reader) error {
}
}
// InspectImage 检查指定镜像引用并返回不可变镜像信息。
// 找不到镜像时返回的错误会包装 ErrNotFound。
func (e *MobyEngine) InspectImage(ctx context.Context, reference string) (Image, error) {
response, err := e.client.ImageInspect(ctx, reference)
if err != nil {
@@ -103,6 +114,8 @@ func (e *MobyEngine) InspectImage(ctx context.Context, reference string) (Image,
}, nil
}
// CreateContainer 依据给定规格创建容器。
// 成功创建后立即通过 InspectContainer 返回容器的完整运行时状态。
func (e *MobyEngine) CreateContainer(ctx context.Context, spec ContainerSpec) (Container, error) {
apiMounts := make([]mount.Mount, 0, len(spec.Mounts))
for _, item := range spec.Mounts {
@@ -143,6 +156,7 @@ func (e *MobyEngine) CreateContainer(ctx context.Context, spec ContainerSpec) (C
return e.InspectContainer(ctx, result.ID)
}
// StartContainer 启动指定容器,参数可为容器 ID 或名称。
func (e *MobyEngine) StartContainer(ctx context.Context, idOrName string) error {
if _, err := e.client.ContainerStart(ctx, idOrName, client.ContainerStartOptions{}); err != nil {
return engineError("start container", err)
@@ -150,6 +164,8 @@ func (e *MobyEngine) StartContainer(ctx context.Context, idOrName string) error
return nil
}
// ContainerLogs 读取指定容器的 stdout 与 stderr 日志,
// 将引擎的多路复用流解码后合并为一个只读流返回。
func (e *MobyEngine) ContainerLogs(ctx context.Context, idOrName string) (io.ReadCloser, error) {
stream, err := e.client.ContainerLogs(ctx, idOrName, client.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Tail: "all"})
if err != nil {
@@ -163,6 +179,7 @@ func (e *MobyEngine) ContainerLogs(ctx context.Context, idOrName string) (io.Rea
return io.NopCloser(bytes.NewReader(output.Bytes())), nil
}
// StopContainer 停止指定容器,参数可为容器 ID 或名称。
func (e *MobyEngine) StopContainer(ctx context.Context, idOrName string) error {
if _, err := e.client.ContainerStop(ctx, idOrName, client.ContainerStopOptions{}); err != nil {
return engineError("stop container", err)
@@ -170,6 +187,8 @@ func (e *MobyEngine) StopContainer(ctx context.Context, idOrName string) error {
return nil
}
// InspectContainer 检查指定容器并返回其运行时状态。
// 各字段按引擎返回的嵌套结构逐层提取,缺失的可选部分保持零值。
func (e *MobyEngine) InspectContainer(ctx context.Context, idOrName string) (Container, error) {
result, err := e.client.ContainerInspect(ctx, idOrName, client.ContainerInspectOptions{})
if err != nil {
@@ -214,6 +233,7 @@ func (e *MobyEngine) InspectContainer(ctx context.Context, idOrName string) (Con
return record, nil
}
// RemoveContainer 移除指定容器,force 决定是否强制移除正在运行的容器。
func (e *MobyEngine) RemoveContainer(ctx context.Context, idOrName string, force bool) error {
_, err := e.client.ContainerRemove(ctx, idOrName, client.ContainerRemoveOptions{Force: force})
if err != nil {
@@ -222,10 +242,13 @@ func (e *MobyEngine) RemoveContainer(ctx context.Context, idOrName string, force
return nil
}
// Close 关闭底层 Docker Engine 客户端连接。
func (e *MobyEngine) Close() error {
return e.client.Close()
}
// engineError 包装引擎操作错误。
// 当底层错误属于“未找到”类别时,额外包装 ErrNotFound,以便调用方通过 errors.Is 识别。
func engineError(action string, err error) error {
if cerrdefs.IsNotFound(err) {
return fmt.Errorf("%s: %w: %v", action, ErrNotFound, err)
@@ -233,6 +256,8 @@ func engineError(action string, err error) error {
return fmt.Errorf("%s: %w", action, err)
}
// cloneMap 浅拷贝一个字符串映射,避免调用方后续修改影响内部数据。
// 若 source 为 nil 则返回 nil。
func cloneMap(source map[string]string) map[string]string {
if source == nil {
return nil