В этой статье мы рассмотрим пример простого HTTP-сервера, написанного на языке программирования Golang, который предоставляет информацию о контейнерах Docker.

Ссылка на Github

Импорты

Мы начинаем с импорта нескольких пакетов которые нам понадобятся, чтобы работать с Docker и HTTP. Это подобно тому, как вы берете инструменты для ремонта, прежде чем начать работу.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/docker/docker/api/types"
	"github.com/docker/docker/client"
	"net/http"
)

Структура 'DContainer'

Мы определяем специальную структуру (как шаблон), которая будет хранить информацию о контейнерах. В данном случае, эта структура содержит ID контейнера и имя образа.

type DContainer struct {
	ID    string `json:"id"`
	Image string `json:"image"`
}

Функция 'getContainers'

Эта функция ответственна за обработку запросов, которые мы получаем от пользователей. Она использует специальные инструменты, чтобы связаться с Docker, получить список контейнеров и вернуть этот список в формате JSON.

func getContainers(w http.ResponseWriter, r *http.Request) {
    // Создание клиента Docker через переменную 'cli'.
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // Получение списка контейнеров с использованием Docker API.
    containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // Создание среза 'containersList' для хранения информации о контейнерах.
    containersList := make([]DContainer, len(containers))

    // Проход по списку контейнеров и заполнение 'containersList'.
    for i, container := range containers {
        containersList[i] = DContainer{
            ID:    container.ID[:10], // Обрезаем ID контейнера до 10 символов.
            Image: container.Image,
        }
    }

    // Установка заголовка HTTP-ответа для указания формата JSON.
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)

    // Кодирование 'containersList' в формат JSON и отправка его в HTTP-ответе.
    if err := json.NewEncoder(w).Encode(containersList); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
}

Функция main

Это место, где начинается выполнение программы. Мы говорим программе, что делать при запуске. В данном случае, мы говорим ей создать сервер, который будет слушать запросы на порту 3600, и мы также указываем, какой код должен выполняться при получении запросов.

func main() {
	http.HandleFunc("/containers", getContainers)

	port := ":3600"
	fmt.Printf("Server listening on %s\n", port)
	if err := http.ListenAndServe(port, nil); err != nil {
		panic(err)
	}
}

Запуск сервера

  • Убедитесть, что у вас установлены Docker и Go

  • Скопировать код в файл с расширением .go

  • Запустить сервер выполнив go run main.go

После запуска сервер будет доступен по адресу http://localhost:3600/containers и предоставит информацию о контейнерах в формате JSON.

Этот сервер - простой пример исключительно для обучения. Вы можете его расширить и добавить больше функций, чтобы сделать его более полезным для мониторинга контейнеров Docker.

Комментарии (7)


  1. diyor28
    02.10.2023 16:20
    +2

    Хотелось бы увидеть продолжение в виде полноценного проекта


  1. mthbtqeytjhzdv
    02.10.2023 16:20
    +1

    Не знаю на сколько ценно, то что написано в статье, но мне как фронту, было интересно почитать.


  1. maledog
    02.10.2023 16:20
    +2

    Вот так легко и непринужденно любой пользователей в вашей сети сможет получить список контейнеров на вашем сервере. Я бы добавил хотя бы basic auth, он в стандартной библиотеке.


    1. sardor-wd Автор
      02.10.2023 16:20

      да, basic auth будет подключен во второй части статьи


  1. capcom6
    02.10.2023 16:20

    В статье нет планов по дальнейшему развитию сего проекта (хотя теги намекают), но вот лично у меня давно руки не дойдут сделать минималистичный аналог cadvisor, хотя там ничего сложного.

    Что касается аутентификации, то не сторонник, чтобы этим занимался сам сервис, если он простой как две копейки. Для простых случаев есть reverse-прокси/api gateway. Что nginx, что Traefik прекрасно справятся с организацией Basic-аутентификации. Для Docker Swarm я себе свой простенький reverse-прокси с auto-discovery и возможность аутентификации для отдельных сервисов написал ради интереса (не для прода).

    В общем, есть куда стремиться, главное не перестараться.

    PS Если хочется прокачаться, то стоит сервис мониторинга и сервис бота делать отдельными. А связь между ними организовать по GRPC. Подозреваю, к этому все и придет)


  1. diyor28
    02.10.2023 16:20
    +2

    Хотелось бы увидеть продолжение в виде полноценного проекта


  1. SiGGthror
    02.10.2023 16:20
    +1

    Я не уверен что на каждый реквест нам нужно создавать заново клиент.


  1. mrobespierre
    02.10.2023 16:20
    +2

    Это так странно видеть приличный go-код от негофера. Бросайте фронт, переходите в бэк, у вас неплохо получается)