物联网软件

This commit is contained in:
BBIT-Kai
2026-02-04 14:02:57 +08:00
parent 646e312a4c
commit 1c11f3f06c
28 changed files with 4526 additions and 271 deletions
+165
View File
@@ -0,0 +1,165 @@
package docker
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"io"
"sentinel/pkg/config"
"time"
"sentinel/pkg/log"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/registry"
"github.com/docker/docker/client"
)
type DockerManager struct {
registry string
username string
password string
cli *client.Client
timeout time.Duration
}
func NewDockerManager() (*DockerManager, error) {
cli, err := client.NewClientWithOpts(
client.FromEnv,
client.WithAPIVersionNegotiation(),
)
if err != nil {
return nil, err
}
return &DockerManager{
cli: cli,
registry: config.DOCKER_REGISTRY,
username: config.DOCKER_USERNAME,
password: config.DOCKER_PASSWORD,
timeout: config.DOCKER_TIME_OUT,
}, nil
}
func (d *DockerManager) PullImage(ctx context.Context, refStr string) error {
auth := registry.AuthConfig{
ServerAddress: d.registry,
Username: d.username,
Password: d.password,
}
authBytes, _ := json.Marshal(auth)
authStr := base64.StdEncoding.EncodeToString(authBytes)
reader, err := d.cli.ImagePull(ctx, refStr, image.PullOptions{
RegistryAuth: authStr,
})
if err != nil {
return err
}
defer reader.Close()
// 消费输出,避免挂起
_, _ = io.Copy(io.Discard, reader)
return nil
}
func (d *DockerManager) RunContainer(ctx context.Context) error {
// 停止并删除已有容器
if err := d.StopAndRemoveContainer(ctx); err != nil {
return err
}
// 创建容器
log.Println("正在启动名为<", config.DOCKER_CONTAINER_NAME, ">的容器")
resp, err := d.cli.ContainerCreate(
ctx,
&container.Config{
Image: config.DOCKER_IMAGE,
Healthcheck: &container.HealthConfig{
Test: []string{"CMD-SHELL", "echo ok"},
Interval: 5 * time.Second,
Timeout: 2 * time.Second,
Retries: 3,
},
},
&container.HostConfig{
Binds: config.DOCKER_CONTAINER_BINDS,
NetworkMode: "host", // <-- 使用宿主机网络
},
nil, // NetworkConfig
nil, // Platform
config.DOCKER_CONTAINER_NAME,
)
if err != nil {
return err
}
// 启动容器
if err := d.cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
return err
}
log.Println("容器已成功运行")
return nil
}
// StopAndRemoveContainer 停止并删除指定容器
func (d *DockerManager) StopAndRemoveContainer(ctx context.Context) error {
containers, err := d.cli.ContainerList(ctx, container.ListOptions{
All: true,
Filters: filters.NewArgs(
filters.KeyValuePair{Key: "name", Value: config.DOCKER_CONTAINER_NAME},
),
})
if err != nil {
return err
}
for _, c := range containers {
log.Println("正在停止名为<", config.DOCKER_CONTAINER_NAME, ">的容器:", c.ID)
timeout := 10 * time.Second
seconds := int(timeout.Seconds())
if err := d.cli.ContainerStop(ctx, c.ID, container.StopOptions{
Timeout: &seconds,
}); err != nil {
log.Println("Failed to stop container %s: %v", c.ID, err)
return err
}
if err := d.cli.ContainerRemove(ctx, c.ID, container.RemoveOptions{}); err != nil {
log.Println("Failed to remove container %s: %v", c.ID, err)
return err
}
}
return nil
}
func (d *DockerManager) CheckContainerHealth(ctx context.Context, containerName string) (string, error) {
if containerName == "" {
return "", errors.New("containerName must not be empty")
}
containers, err := d.cli.ContainerList(ctx, container.ListOptions{
All: true,
Filters: filters.NewArgs(
filters.KeyValuePair{Key: "name", Value: containerName},
),
})
if err != nil {
return "", err
}
if len(containers) == 0 {
return "", errors.New("container not found")
}
inspect, err := d.cli.ContainerInspect(ctx, containers[0].ID)
if err != nil {
return "", err
}
if inspect.State.Health != nil {
return inspect.State.Health.Status, nil
}
return "unknown", nil
}