Сегодня большинство производственных систем работают на контейнерах. И большая часть контейнеризации выполняется через докер. Docker решает одну из самых больших проблем, с которыми мы сталкиваемся при разработке программного обеспечения:

¯ \ _ (ツ) _ / ¯
Работает на моем компьютере

Мы используем команду docker, чтобы поговорить с демоном докеров, запущенным на нашем хост-компьютере.

$ docker run nginx
$ docker ps
$ docker stop <container_id>

Код за командой docker - это docker cli. Он использует библиотеку docker client для связи с демоном docker через REST API docker engine.

Да, команда docker, которую мы используем изо дня в день, управляется API, а это означает, что мы можем подключать быстрые решения для масштабирования приложений докеров. Давайте посмотрим, как мы можем выполнить основные действия докера, такие как запуск, список и удаление, с помощью Golang.

Вы можете установить docker SDK for go, используя go get.

go get github.com/docker/docker

Вот что мы собираемся сделать: возьмем nginx:latest изображение и выполним некоторые основные действия. В следующих разделах будут представлены команды, соответствующий фрагмент кода и объяснение кода.

Создать докер-контейнер

Команда

$ docker run nginx:latest

Код

Все API-интерфейсы Docker Engine доступны через объект cli, возвращаемый client.NewEnvClient().

cli, err := client.NewEnvClient() 
if err != nil {      
    fmt.Println("Unable to create docker client")  
    panic(err) 
}

NewEnvClient возвращает клиента, принимая необходимые параметры из переменных среды вместо параметров функции.

На данный момент не нужно беспокоиться о переменных среды, если вам не нужно передавать некоторые параметры. По умолчанию он позаботится об этом. Мы используем client.NewEnvClient(), потому что это самый простой способ создать докер-клиент без передачи каких-либо аргументов.

cli.ContainerCreate создает для нас контейнер. Он принимает несколько аргументов и возвращает структуруContainerCreateCreatedBody с идентификатором контейнера в ней. Сигнатура типа функции выглядит так:

ContainerCreate func(ctx context.Context, 
config *container.Config, 
hostConfig *container.HostConfig, 
networkingConfig *network.NetworkingConfig, 
containerName string) (container.ContainerCreateCreatedBody, error)

Параметры config, hostConfig и networkingConfig - это типы, которые необходимо импортировать из модуля докера.

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"

Узнав параметры функции, мы вызываем функцию cli.ContainerCreate()

cont, err := cli.ContainerCreate( 
    context.Background(), 
    &container.Config{ 
        Image: image, }, 
    &container.HostConfig { 
    PortBindings: portBinding, }, nil, "") 
   
    if err != nil { 
        panic(err)
    }

Поскольку мы запускаем контейнер nginx, мы должны открыть порт 80 контейнера для порта 8000 хост-машины. Отображение передается как атрибут: PortBindings в структуру параметров hostConfig. Обратите внимание, что мы уже построили отображение, импортировав его типы из пакета nat.

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") 
}

После создания контейнера мы получаем идентификатор контейнера из возвращенного объекта и запускаем контейнер.

cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})

Если вы заключите этот код в пакет и вызовете функцию, адрес localhost:8000 в вашем браузере должен напечатать приветственное сообщение от nginx, запущенного внутри контейнера.

Список контейнеров докеров

Командование

$ docker container ps

Код

Код здесь довольно прост: вы создаете NewEnvClient(), вызываете ContainerList и затем перебираете возвращенный список контейнеров. ContainerList принимает несколько параметров, таких как ограничение, фильтр и т. Д. Типа types.ContainerListOptions, но мы просто передаем пустые параметры.

Остановить контейнер докеров

Командование

$ docker container stop <container-id>

Код

ContainerStop() также принимает тайм-аут как последний аргумент. Здесь мы не указываем таймауты для остановки контейнера.

err = cli.ContainerStop(context.Background(), containerID, nil) 
if err != nil {  
  panic(err) 
} 

Принимаем в производство

Код, который вы видели, почти готов к работе :)
Вы можете запустить этот код в рабочую среду, просто обернув эти фрагменты в собственные пакеты. Замените все panic операторами return и замените операторы Print некоторой записью в журнал.

Вот, я уже сделал это для вас.

Клонируйте репозиторий и cd в папку docker-sdk. Структура кода там должна выглядеть так:

docker-sdk
|
|_ main.go
|
|_ glide.lock
|
|_ glide.yaml
|
|_ container/
   |
   |_ container.go
   |
   |_ container_test.go

Я использовал Glide как пакетный менеджер. Итак, установите glide, выполнив brew install glide. Если вы не используете macOS, сделайте go get github.com/Masterminds/glide.

Установите зависимости, запустив glide install из папки docker-sdk.

Теперь вы можете поиграть с кодом, вызывая различные функции пакета container внутри main.go.

Считаете этот пост интересным?
Для меня было бы очень много значить, если бы вы могли удерживать значок хлопать и кричать мне в twitter. Это действительно сделало бы мой день лучше.

Также вы можете подписаться на нашу рассылку, чтобы получать больше сообщений в блогах и курсов по серверной инженерии.
- спасибо!