Docker предоставляет API для взаимодействия с демоном Docker (называемый Docker Engine API), и мы можем создавать и расширять приложения и решения Docker, используя официальный Go SDK.
Установить SDK
SDK можно установить с помощью следующей команды:
go get github.com/docker/docker/client
Управление локальным докером
В этом разделе будет рассказано, как использовать API Golang + Docker для управления локальным Docker.
запустить контейнер
Первый пример покажет, как запустить контейнер, эквивалентный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)
}
Запуск контейнеров в фоновом режиме
Вы также можете запускать контейнеры в фоновом режиме, что эквивалентно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)
}
Посмотреть список контейнеров
Список запущенных контейнеров, таких как использование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)
}
}
еслиdocker ps -a
, мы можем изменитьtypes.ContainerListOptions
серединаAll
Для этой цели служат атрибуты:
// 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)
}
Остановить все запущенные контейнеры
В приведенном выше примере мы можем получить список контейнеров, поэтому в этом случае мы можем пойти и остановить все запущенные контейнеры.
Примечание. Не запускайте приведенный ниже код на рабочем сервере.
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")
}
}
Получить журналы указанного контейнера
Указав ID контейнера, мы можем получить логи контейнера с соответствующим 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)
}
Посмотреть список зеркал
Получить все локальные зеркала, эквивалентныеdocker image ls
или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)
}
}
вытащить изображение
Вытяните указанное изображение, что эквивалентно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)
}
Вытащить частное изображение
В дополнение к общедоступным образам мы обычно используем некоторые частные образы, которые могут быть частными образами на DockerHub или самостоятельными репозиториями образов, такими какharbor. В настоящее время нам нужно предоставить соответствующие учетные данные, чтобы иметь возможность получить изображение.
Стоит отметить, что при использовании Go SDK API Docker учетные данные передаются открытым текстом, поэтому, если это самодельный репозиторий образов, обязательно используйте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)
}
Сохраните контейнер как изображение
Мы можем передать существующий контейнер черезcommit
Сохранить как изображение:
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)
}
Управление удаленным докером
Конечно, помимо управления локальным Docker, мы также можем управлять удаленным Docker с помощью API Golang + Docker.
Удаленное подключение
По умолчанию Docker запускается через несетевой сокет Unix и может взаимодействовать только локально (/var/run/docker.sock
), вы не можете напрямую подключиться к Docker удаленно.
Нам нужно отредактировать файл конфигурации/etc/docker/daemon.json
, и измените следующее (поместите192.168.59.3
на свой IP-адрес), затем перезапустите Docker:
# vi /etc/docker/daemon.json
{
"hosts": [
"tcp://192.168.59.3:2375",
"unix:///var/run/docker.sock"
]
}
systemctl restart docker
изменить клиент
Создайтеclient
Когда вам нужно указать адрес удаленного Docker, вы можете управлять удаленным Docker как локальным Docker:
cli, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(),
client.WithHost("tcp://192.168.59.3:2375"))
Суммировать
Уже есть много продуктов, которые могут управлять Docker, и они делают это таким образом, например:portainer.
Оригинальная ссылка:Доступно на 8scat.com/posts/play-…