Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Docker ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°ΠΌΠΈ Π² Go

ДокумСнтация!

Когда Π²Ρ‹ Ρ€Π΅ΡˆΠΈΡ‚Π΅ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ, свой вСлосипСд ΠΏΠΎ Π»ΠΎΠ²Π»Π΅ Ρ…ΡƒΠΊΠΎΠ² ΠΈΠ· docker hub ΠΈΠ»ΠΈ ΠΈΠ· registry для автоматичСского обновлСния/запуска ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ² Π½Π° сСрвСрС, Π²Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Docker Cli, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ Π΄Π΅ΠΌΠΎΠ½ΠΎΠΌ Docker Π² вашСй систСмС.
Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Docker ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°ΠΌΠΈ Π² Go

Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ понадобится Go вСрсии Π½Π΅ Π½ΠΈΠΆΠ΅ 1.9.4

Если Π²Ρ‹ всС Π΅Ρ‰Π΅ Π½Π΅ ΠΏΠ΅Ρ€Π΅ΡˆΠ»ΠΈ Π½Π° ΠΌΠΎΠ΄ΡƒΠ»ΠΈ установитС Cli ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ:

go get github.com/docker/docker/client

Запуск ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠ°ΠΊ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Docker API. Π’ ΠΊΠΎΠΌΠΌΠ°Π½Π΄Π½ΠΎΠΉ строкС Π²Ρ‹ Π±Ρ‹ использовали ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ docker run, Π½ΠΎ ΠΌΡ‹ Π±Π΅Π· Ρ‚Ρ€ΡƒΠ΄Π° справимся с этой Π·Π°Π΄Π°Ρ‡Π΅ΠΉ Π² нашСм сСрвисС.
Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ эквивалСнтСн запуску ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker run alpine echo hello world

package main {
    ctx := context.Background()
    cli, err := client.NewEnvClient()
    if err != nil {
        panic(err)
    }

    // Π”Π΅Π»Π°Π΅ΠΌ docker pull
    reader, err := cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, reader)

    hostBinding := nat.PortBinding{
        HostIP:   "0.0.0.0",
        HostPort: "8000",
    }
    containerPort, err := nat.NewPort("tcp", "80")
    if err != nil {
        panic("Unable to get the port")
    }
    portBinding := nat.PortMap{containerPort: []nat.PortBinding{hostBinding}}

    // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ с Π·Π°Π΄Π°Π½Π½ΠΎΠΉ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠ΅ΠΉ
    resp, err := cli.ContainerCreate(ctx, &container.Config{
        Image: "alpine",
        Cmd:   []string{"echo", "hello world"},
        Tty:   true,
    }, &container.HostConfig{
        PortBindings: portBinding,
    }, nil, "")
    if err != nil {
        panic(err)
    }

    // ЗапускаСм ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€
    if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
        panic(err)
    }

    // ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π»ΠΎΠ³ΠΈ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°
    out, err := cli.ContainerLogs(ctx, resp.ID, types.ContainerLogsOptions{ShowStdout: true})
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, out)
}

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²

Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ эквивалСнтСн запуску ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker ps

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func main() {
    cli, err := client.NewEnvClient()
    if err != nil {
        panic(err)
    }

    // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка Π·Π°ΠΏΡƒΡ†Ρ‰Π΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²(docker ps)
    containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
    if err != nil {
        panic(err)
    }

    // Π’Ρ‹Π²ΠΎΠ΄ всСх ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠ² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²
    for _, container := range containers {
        fmt.Println(container.ID)
    }
}

ΠžΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° всСх Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²

ПослС Ρ‚ΠΎΠ³ΠΎ ΠΊΠ°ΠΊ Π²Ρ‹ Π½Π°ΡƒΡ‡ΠΈΠ»ΠΈΡΡŒ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹, ΠΏΡ€ΠΈΡˆΠ»ΠΎ врСмя Π½Π°ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ ΡƒΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΈΠΌΠΈ. Π‘Π»ΡƒΠ΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ остановит всС Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½Ρ‹Π΅ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹.

НС запускайтС этот ΠΊΠΎΠ΄ Π½Π° ΠΏΡ€ΠΎΠ΄Π°ΠΊΡˆΠ½ сСрвСрС!

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func main() {
    ctx := context.Background()
    cli, err := client.NewEnvClient()
    if err != nil {
        panic(err)
    }

    // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка Π·Π°ΠΏΡƒΡ†Ρ‰Π΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²(docker ps)
    containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
    if err != nil {
        panic(err)
    }

    for _, c := range containers {
        fmt.Print("Stopping container ", c.ID[:10], "... ")
        if err := cli.ContainerStop(ctx, c.ID, nil); err != nil {
            panic(err)
        }
        fmt.Println("Success")
    }
}

Π’Ρ‹Π²ΠΎΠ΄ Π»ΠΎΠ³ΠΎΠ² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ взятого ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ взятыми ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°ΠΌΠΈ. Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ выводятся Π»ΠΎΠ³ΠΈ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° с ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΌ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΎΠΌ. ΠŸΠ΅Ρ€Π΅Π΄ запуском Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π°, Ρ‡ΡŒΠΈ Π»ΠΎΠ³ΠΈ Π²Ρ‹ Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ.

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.NewEnvClient()
    if err != nil {
        panic(err)
    }

    options := types.ContainerLogsOptions{ShowStdout: true}
    // Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚Π΅ id ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Π° здСсь
    out, err := cli.ContainerLogs(ctx, "f1064a8a4c82", options)
    if err != nil {
        panic(err)
    }
    io.Copy(os.Stdout, out)
}

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка images

Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ эквивалСнтСн запуску ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker image ls

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func main() {
    cli, err := client.NewEnvClient()
    if err != nil {
        panic(err)
    }

    // ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ списка ΠΎΠ±Ρ€Π°Π·ΠΎΠ²
    images, err := cli.ImageList(context.Background(), types.ImageListOptions{})
    if err != nil {
        panic(err)
    }

    for _, image := range images {
        fmt.Println(image.ID)
    }
}

Pull

Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ эквивалСнтСн запуску ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker pull

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.NewEnvClient()
    if err != nil {
        panic(err)
    }

    // docker pull alpine
    out, err := cli.ImagePull(ctx, "docker.io/library/alpine", types.ImagePullOptions{})
    if err != nil {
        panic(err)
    }
    defer out.Close()
    io.Copy(os.Stdout, out)
}

Π‘ΠΊΠ°Ρ‡ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΎΠ±Ρ€Π°Π·Π° с Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ

Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ эквивалСнтСн запуску ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ docker pull, с Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠ΅ΠΉ.

Π”Π°Π½Π½Ρ‹Π΅ Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ Π² ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠΌ Π²ΠΈΠ΄Π΅. ΠžΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ docker registry ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ HTTPS,
частныС registry Ρ‚Π°ΠΊ ΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ настроСны Π½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… с использованиСм 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.NewEnvClient()
    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, "docker.io/library/alpine", types.ImagePullOptions{RegistryAuth: authStr})
    if err != nil {
        panic(err)
    }

    defer out.Close()
    io.Copy(os.Stdout, out)
}

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com