Прежде чем перейти к основному содержанию, хочу предупредить, что текст статьи сгенерирован с помощью искусственного интеллекта. Я стремился сделать материал доступным и информативным, но если вы предпочитаете работать непосредственно с кодом, не стесняйтесь переходить к нему. Весь код снабжен комментариями для лучшего понимания.
Ссылка на GitHub
Введение
В современном мире разработки программного обеспечения, где количество и сложность проектов постоянно растут, управление инфраструктурой становится все более трудоемким. Возникает потребность в быстром и гибком доступе к конфигурационным файлам, особенно когда вы находитесь вне офиса. Именно эту проблему решает наш проект: Telegram-бот для управления Docker-контейнерами.
Проблематика
С ростом числа проектов увеличивается и сложность их управления. Каждый проект имеет свою уникальную конфигурацию, хранящуюся в env-файлах, и иногда необходимо быстро внести изменения в эти файлы. Например, во время встречи или переговоров, когда доступ к рабочему компьютеру ограничен.
Решение
Наш Telegram-бот предоставляет удобный интерфейс для управления Docker-контейнерами прямо из вашего смартфона. Благодаря этому, вы можете быстро и безопасно менять конфигурацию ваших проектов, не зависимо от вашего местоположения.
Архитектура
Сервер: На сервере хранятся все ваши проекты в директории вида
/home/user/git/<имя_проекта>/
, где расположены файлыdocker-compose.yml
и.env
.Telegram-бот: Внутри бота имеется каталог
CFG
, структурированный следующим образом:./cfg/<имя_проекта>/<вариант_env>
. Это позволяет хранить различные варианты конфигураций для каждого проекта.
Работа с ботом
Отправьте команду
/start
для начала работы.Выберите нужный проект из списка.
Выберите нужный env-файл или выполните другую команду (например, остановить или перезапустить контейнер).
Ключевые компоненты
Инициализация и настройка логгирования
# Получение значения переменной DEBUG из окружения
DEBUG = os.environ.get("DEBUG")
# Настройка логгирования в зависимости от DEBUG
if DEBUG:
logging.basicConfig(
level=logging.INFO,
# ...
)
else:
logging.basicConfig(
level=logging.ERROR,
# ...
)
Здесь мы настраиваем логгирование в зависимости от переменной окружения DEBUG
. Это позволяет контролировать уровень детализации логов.
Инициализация бота и диспетчера
# Получение токена бота и ID администратора из переменных окружения
BOT_API_TOKEN = os.environ.get("BOT_API_TOKEN")
ADMIN_ID = os.environ.get("ADMIN_ID")
# Инициализация бота и диспетчера
bot = Bot(token=BOT_API_TOKEN)
dp = Dispatcher()
Здесь мы инициализируем бота и диспетчера, используя токен и ID администратора из переменных окружения.
Обработка команд
@dp.message(CommandStart)
async def handle_start(msg: types.Message):
# Проверка прав доступа пользователя
if msg.from_user.id != int(ADMIN_ID):
await msg.answer("You are not allowed to use this bot.")
return
# ...
При получении команды /start
, бот проверяет, является ли пользователь администратором. Если да, то предлагает список доступных проектов.
Выполнение Docker-команд
def docker_command(*args):
try:
subprocess.run(["docker-compose", *args], check=True)
return True
except subprocess.CalledProcessError as e:
logger.exception(f"Exception: {e}")
return False
Эта функция выполняет команды Docker с помощью модуля subprocess
. Она возвращает True
, если команда выполнена успешно, и False
в противном случае.
Упаковка проекта с использованием Poetry в Docker
Структура Dockerfile
Использование официального образа Python
FROM python:3.11
Здесь мы используем официальный образ Python версии 3.11 как базовый образ.
Установка переменных окружения для Poetry
ENV POETRY_HOME="/opt/poetry" \
POETRY_VIRTUALENVS_IN_PROJECT=true \
POETRY_NO_INTERACTION=1
Мы устанавливаем несколько переменных окружения, которые будут использоваться Poetry.
Добавление Poetry в PATH
ENV PATH="$POETRY_HOME/bin:$HOME/.local/bin:$PATH"
Добавляем путь к исполняемому файлу Poetry в переменную окружения PATH.
Установка Poetry
RUN pip install poetry
Устанавливаем Poetry с помощью pip.
Установка рабочего каталога и копирование исходного кода
RUN mkdir /app
WORKDIR /app
COPY . /app
Здесь мы создаем рабочий каталог /app
и копируем в него исходный код проекта.
Установка зависимостей
COPY pyproject.toml poetry.lock /app/
RUN poetry install --no-dev --no-root --no-interaction --no-ansi -vvv
Копируем файлы pyproject.toml
и poetry.lock
в рабочий каталог и устанавливаем зависимости с помощью Poetry.
Запуск приложения
ENTRYPOINT ["poetry", "run", "python3", "botenv.py"]
Задаем точку входа для запуска приложения.
Интеграция Docker и Docker Compose
Структура файла docker-compose.yml
Версия и сервисы
version: '3.8'
services:
bot_env:
Здесь мы используем версию 3.8 файла Compose и определяем один сервис bot_env
.
Построение образа
build:
context: .
dockerfile: Dockerfile
Контекст сборки установлен на текущую директорию, а Dockerfile указан явно.
Имя и тег образа
image: omeh2003/bot_env:latest
Образ будет сохранен с именем omeh2003/bot_env
и тегом latest
.
Тома
volumes:
- "./data/:/app/data/"
- "./cfg/:/app/cfg/"
- "/home/omeh2003/git/:/app/git/"
- "./.env:/app/.env"
Здесь мы монтируем четыре тома для хранения данных, конфигураций, исходного кода и переменных окружения.
Проверка работоспособности
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/"]
interval: 1m30s
timeout: 10s
retries: 3
Healthcheck выполняет проверку доступности приложения каждые 1 минуту 30 секунд, с таймаутом в 10 секунд и до 3 попыток.
Перезапуск и порты
restart: always
ports:
- "5000:5000"
Сервис будет автоматически перезапускаться, и порт 5000 хоста будет проброшен на порт 5000 контейнера.
Теперь у нас есть команды
Д
docker-compose build
: Эта команда собирает образ для приложения на основе информации из файлаDockerfile
. Она учитывает все параметры, указанные в разделеbuild
вашего файлаdocker-compose.yml
.docker-compose up
: Эта команда запускает приложение, используя настройки из файлаdocker-compose.yml
. Если образ не был предварительно собран, команда сначала выполнит сборку. Флаг-d
позволяет запустить контейнеры в фоновом режиме.docker-compose down
: Эта команда останавливает все запущенные контейнеры, удаляет их и также удаляет созданные сети, объявленные вdocker-compose.yml
.
Эти команды значительно упрощают процесс развертывания и управления приложением, делая его более воспроизводимым и изолированным.
Ссылка на GitHub
Комментарии (7)
semenovs Автор
25.09.2023 04:42Странно что никто не написал что внутри докер контейнера это работать не будет. Видимо сам проект никто не посмотрел )
hrad
25.09.2023 04:42Кто захочет - тот разберётся, соберёт образ с docker client, прокинет docker.sock да перепишет аккуратно. Может быть даже применит Docker SDK for Python. ;)
avkritsky
25.09.2023 04:42День добрый. Можно отредактировать файл /lib/systemd/system/docker.service, заменив параметр ExecStart следующей строкой:
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 $DOCKER_OPTS
и перезапустить сервис докера (systemctl daemon-reload и service docker restart)
Тогда у Вас появится возможность стучать в API-шку Вашего серверного докера, а сам проект запускать в… докере. Ну, как возможный вариант.
ReDev1L
25.09.2023 04:42Чёт жесть какая то, есть много api/sdk вместо команд подпроцессом. Причём на любой докер хост.
Если цель была на встречах рулить - то лучше ноут и консоль, чем очепятки в телеге и ронять сервисы.
jlexand
25.09.2023 04:42Выглядит как способ получения интерфейса с помощью телеграм бота как раз таки что бы не использовать терминал, но это так, догадка
antirek
интересная мотивация, конечно: ни конфигурировать нормально, ни внимание встрече уделить )))
хотя аналог ctop'а в тг может быть и нужен
semenovs Автор
Конфигурации заранее написаны. Вы только выбираете какой проект и какой конфиг. И если прочитаете текст в начале статьи, то не я придумал мотивацию. Я далек от таких материй.
про с_top практически в точку
есть уже функционал, который занимается мониторингом внутри контейнера. Снаружи контейнера ,собиранием логов отчётов и получается, что его нужно копировать каждый свой новый проект, и я его со временем просто весь Перенесу в этого Бота и они он будет там. А так он есть и сейчас тоже работает и очень хорошо.