func (w *Worker) KillDockerWorker() error {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.WithHost(w.Host))
	if err != nil {
		gaia.Cfg.Logger.Error("failed to setup docker client", "error", err)
		return err
	}
	cli.NegotiateAPIVersion(ctx)
	if err := cli.ContainerRemove(ctx, w.ContainerID, types.ContainerRemoveOptions{
		RemoveVolumes: true,
		Force:         true,
	}); err != nil {
		gaia.Cfg.Logger.Error("failed to remove docker worker", "error", err, "containerid", w.ContainerID)
		return err
	}
	return nil
}
KillDockerWorker disconnects the existing docker worker and
kills the docker container.
package docker
import (
	"context"
	"fmt"
	"io"
	"time"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/client"
	"github.com/gaia-pipeline/gaia"
	"github.com/gaia-pipeline/gaia/security"
)
type Worker struct {
	Host          string `json:"host"`
	WorkerID      string `json:"worker_id"`
	ContainerID   string `json:"container_id"`
	PipelineRunID string `json:"pipeline_run_id"`
}
func NewDockerWorker(host string, pipelineRunID string) *Worker {
	return &Worker{Host: host, PipelineRunID: pipelineRunID}
}
func (w *Worker) SetupDockerWorker(workerImage string, workerSecret string) error {
	w.WorkerID = security.GenerateRandomUUIDV5()
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()
	cli, err := client.NewClientWithOpts(client.WithHost(w.Host))
	if err != nil {
		gaia.Cfg.Logger.Error("failed to setup docker client", "error", err)
		return err
	}
	cli.NegotiateAPIVersion(ctx)
	createContainer := func() (container.ContainerCreateCreatedBody, error) {
		return cli.ContainerCreate(ctx, &container.Config{
			Image: workerImage,
			Env: []string{
				"GAIA_WORKER_HOST_URL=" + gaia.Cfg.DockerWorkerHostURL,
				"GAIA_MODE=worker",
				"GAIA_WORKER_GRPC_HOST_URL=" + gaia.Cfg.DockerWorkerGRPCHostURL,
				"GAIA_WORKER_TAGS=" + fmt.Sprintf("%s,dockerworker", w.WorkerID),
				"GAIA_WORKER_SECRET=" + workerSecret,
			},
		}, &container.HostConfig{}, nil, nil, "")
	}
	resp, err := createContainer()
	if err != nil {
		gaia.Cfg.Logger.Error("failed to create worker container", "error", err)
		gaia.Cfg.Logger.Info("try to pull docker image before trying it again...")
		out, err := cli.ImagePull(ctx, workerImage, types.ImagePullOptions{})
		if err != nil {
			gaia.Cfg.Logger.Error("failed to pull worker image", "error", err)
			return err
		}
		defer out.Close()
		gaia.Cfg.Logger.Info("pulling docker image. This may take a while...")
		buffer := make([]byte, 1024)
		for {
			_, err := out.Read(buffer)
			if err != nil {
				if err != io.EOF {
					gaia.Cfg.Logger.Error("failed to pull worker image", "error", err)
					return err
				}
				break
			}
		}
		gaia.Cfg.Logger.Info("finished pulling docker image. Continue with pipeline run...")
		resp, err = createContainer()
		if err != nil {
			gaia.Cfg.Logger.Error("failed to create worker container after pull", "error", err)
			return err
		}
	}
	if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
		gaia.Cfg.Logger.Error("failed to start worker container", "error", err)
		return err
	}
	w.ContainerID = resp.ID
	return nil
}
func (w *Worker) IsDockerWorkerRunning() bool {
	ctx := context.Background()
	cli, err := client.NewClientWithOpts(client.WithHost(w.Host))
	if err != nil {
		gaia.Cfg.Logger.Error("failed to setup docker client", "error", err)
		return false
	}
	cli.NegotiateAPIVersion(ctx)
	resp, err := cli.ContainerInspect(ctx, w.ContainerID)
	if err != nil {
		return false
	}
	if resp.State.Running {
		return true
	}
	return false
}