feat: complete daemon operations and recovery tooling

This commit is contained in:
2026-08-22 15:34:09 +08:00
parent a0a4a7556a
commit 1abe8df6ee
19 changed files with 1421 additions and 171 deletions
+13 -12
View File
@@ -1,7 +1,6 @@
package containerengine
import (
"bytes"
"context"
"encoding/json"
"errors"
@@ -164,24 +163,26 @@ func (e *MobyEngine) StartContainer(ctx context.Context, idOrName string) error
return nil
}
// ContainerLogs 读取指定容器的 stdout 与 stderr 日志,
// 将引擎的多路复用流解码后合并为一个只读流返回。
// ContainerLogs 跟随读取指定容器的 stdout 与 stderr 日志,将引擎的多路复用流
// 解码后合并为一个持续流返回,直到 ctx 取消或容器停止
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"})
stream, err := e.client.ContainerLogs(ctx, idOrName, client.ContainerLogsOptions{ShowStdout: true, ShowStderr: true, Follow: true, Tail: "all"})
if err != nil {
return nil, engineError("read container logs", err)
}
defer stream.Close()
var output bytes.Buffer
if _, err := stdcopy.StdCopy(&output, &output, stream); err != nil {
return nil, fmt.Errorf("decode container logs: %w", err)
}
return io.NopCloser(bytes.NewReader(output.Bytes())), nil
reader, writer := io.Pipe()
go func() {
_, copyErr := stdcopy.StdCopy(writer, writer, stream)
_ = stream.Close()
_ = writer.CloseWithError(copyErr)
}()
return reader, nil
}
// StopContainer 停止指定容器,参数可为容器 ID 或名称。
func (e *MobyEngine) StopContainer(ctx context.Context, idOrName string) error {
if _, err := e.client.ContainerStop(ctx, idOrName, client.ContainerStopOptions{}); err != nil {
// timeoutSeconds 是发送停止信号后到强制终止前的等待秒数,传给引擎以在超时后强制终止。
func (e *MobyEngine) StopContainer(ctx context.Context, idOrName string, timeoutSeconds int) error {
if _, err := e.client.ContainerStop(ctx, idOrName, client.ContainerStopOptions{Timeout: &timeoutSeconds}); err != nil {
return engineError("stop container", err)
}
return nil