Docker provides an API (called Docker Engine API) for interacting with the Docker daemon. We can use the official Go language SDK to build and extend Docker applications and solutions. Installing the SDK You can install the SDK by running the following command: go get github.com/docker/docker/client Managing local Docker This section will introduce how to use Golang + Docker API to manage local Docker. Running the container The first example will show how to run a container, equivalent to docker run docker.io/library/alpine echo "hello world": package main import ( "context" "io" "os" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" "github.com/docker/docker/pkg/stdcopy" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } reader, err := cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{}) if err != nil { panic(err) } io.Copy(os.Stdout, reader) resp, err := cli.ContainerCreate(ctx, &container.Config{ Image: "alpine", Cmd: []string{"echo", "hello world"}, }, nil, nil, "") if err != nil { panic(err) } if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { panic(err) } statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) select { case err := <-errCh: if err != nil { panic(err) } case <-statusCh: } out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true}) if err != nil { panic(err) } stdcopy.StdCopy(os.Stdout, os.Stderr, out) } Running containers in the background You can also run the container in the background, which is equivalent to docker run -d bfirsh/reticulate-splines: package main import ( "context" "fmt" "io" "os" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } imageName := "bfirsh/reticulate-splines" out, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) if err != nil { panic(err) } io.Copy(os.Stdout, out) resp, err := cli.ContainerCreate(ctx, &container.Config{ Image: imageName, }, nil, nil, "") if err != nil { panic(err) } if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { panic(err) } fmt.Println(resp.ID) } View container list List running containers, just like with docker ps: package main import ( "context" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } containers, err := cli.ContainerList(ctx, types.ContainerListOptions{}) if err != nil { panic(err) } for _, container := range containers { fmt.Println(container.ID) } } If it is docker ps -a, we can achieve this by modifying the All property in types.ContainerListOptions: // type ContainerListOptions struct { // Quiet bool // Size bool // All bool //Latest bool // Since string // Before string // Limit int // Filters filters.Args // } options := types.ContainerListOptions{ All: true, } containers, err := cli.ContainerList(ctx, options) if err != nil { panic(err) } Stop all running containersIn the above example, we can get a list of containers, so in this case, we can stop all running containers. Note: Do not run the following code on a production server. package main import ( "context" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } containers, err := cli.ContainerList(ctx, types.ContainerListOptions{}) if err != nil { panic(err) } for _, container := range containers { fmt.Print("Stopping container ", container.ID[:10], "... ") if err := cli.ContainerStop(ctx, container.ID, nil); err != nil { panic(err) } fmt.Println("Success") } } Get the logs of a specified container By specifying the container ID, we can get the logs of the container with the corresponding ID: package main import ( "context" "io" "os" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } options := types.ContainerLogsOptions{ShowStdout: true} out, err := cli.ContainerLogs(ctx, "f1064a8a4c82", options) if err != nil { panic(err) } io.Copy(os.Stdout, out) } View mirror list Get all local images, equivalent to docker image ls or docker images: package main import ( "context" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } images, err := cli.ImageList(ctx, types.ImageListOptions{}) if err != nil { panic(err) } for _, image := range images { fmt.Println(image.ID) } } Pull the image Pull the specified image, which is equivalent to docker pull alpine: package main import ( "context" "io" "os" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } out, err := cli.ImagePull(ctx, "alpine", types.ImagePullOptions{}) if err != nil { panic(err) } defer out.Close() io.Copy(os.Stdout, out) } Pull private image In addition to public images, we usually use some private images, which can be private images on DockerHub or self-hosted image repositories, such as harbor. At this time, we need to provide the corresponding credentials to pull the image. It is worth noting that when using the Go SDK of the Docker API, the credentials are transmitted in plain text, so if you build your own image repository, be sure to use HTTPS! package main import ( "context" "encoding/base64" "encoding/json" "io" "os" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } authConfig := types.AuthConfig{ Username: "username", Password: "password", } encodedJSON, err := json.Marshal(authConfig) if err != nil { panic(err) } authStr := base64.URLEncoding.EncodeToString(encodedJSON) out, err := cli.ImagePull(ctx, "alpine", types.ImagePullOptions{RegistryAuth: authStr}) if err != nil { panic(err) } defer out.Close() io.Copy(os.Stdout, out) } Save the container as an image We can save an existing container as an image by committing: package main import ( "context" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" ) func main() { ctx := context.Background() cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { panic(err) } createResp, err := cli.ContainerCreate(ctx, &container.Config{ Image: "alpine", Cmd: []string{"touch", "/helloworld"}, }, nil, nil, "") if err != nil { panic(err) } if err := cli.ContainerStart(ctx, createResp.ID, types.ContainerStartOptions{}); err != nil { panic(err) } statusCh, errCh := cli.ContainerWait(ctx, createResp.ID, container.WaitConditionNotRunning) select { case err := <-errCh: if err != nil { panic(err) } case <-statusCh: } commitResp, err := cli.ContainerCommit(ctx, createResp.ID, types.ContainerCommitOptions{Reference: "helloworld"}) if err != nil { panic(err) } fmt.Println(commitResp.ID) } Managing remote Docker Of course, in addition to managing local Docker, we can also manage remote Docker by using Golang + Docker API. remote connection By default, Docker runs through a non-network Unix socket and can only communicate locally (/var/run/docker.sock). It is not possible to connect to Docker remotely. # vi /etc/docker/daemon.json { "hosts": [ "tcp://192.168.59.3:2375", "unix:///var/run/docker.sock" ] } systemctl restart docker Modify the client When creating a client, you need to specify the address of the remote Docker, so that you can manage the remote Docker just like managing the local Docker: cli, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(), client.WithHost("tcp://192.168.59.3:2375")) Summarize There are already many products that can manage Docker, and they are implemented in this way, such as portainer. This is the end of this article about using Golang to play with Docker API. For more information about running Docker API with Golang, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: HTML elements (tags) and their usage
>>: Chinese website user experience rankings
Table of contents 1. Project Construction 2. Vue3...
The specific code is as follows: <!DOCTYPE htm...
Table of contents 1. JavaScript is single-threade...
Let's talk about some problems I have encounte...
accomplish This effect is difficult to replicate ...
MyISAM storage engine The MyISAM storage engine i...
Step 1: Confirm the architecture of your system d...
<!--[if lte IE 6]> <![endif]--> Visibl...
Tab selection cards are used very frequently on r...
Today I will introduce to you a difference betwee...
illustrate When you install the system yourself, ...
docker-compose-monitor.yml version: '2' n...
1. Set up a shared folder on the virtual machine:...
1. Cancel the blue color of the a tag when it is ...
Table of contents Background 1. Thought Analysis ...