Drone CI в Docker: лёгкий self-hosted пайплайн для небольшой команды
Я Семёнов Евгений Сергеевич, директор АйТи Фреш. Когда клиент из 5–10 разработчиков просит свой CI/CD, и при этом не хочет тащить Jenkins с его джунглями плагинов — я ставлю Drone. У нас на практике он крутится у десятка заказчиков рядом с Gitea. Один сервер, один раннер, YAML в репозитории — и всё. Расскажу, как поднять с нуля на Ubuntu и связать с Git-хостингом.
Почему Drone
Drone — это Go-шный бинарник, собранный как два контейнера: сервер и раннер. Сервер принимает вебхуки от Git-а, раннер исполняет шаги пайплайна в Docker. Никаких агентов на Java, никаких Groovy-скриптов. Всё описывается в файле .drone.yml в корне репозитория.
- Потребление: сервер ~100 МБ ОЗУ, раннер ~150 МБ.
- Поднимается за 10 минут на любом Docker-хосте.
- Обновление — просто замена тегов образов.
- Веб-интерфейс чистый, без легаси.
Минусы: комьюнити меньше чем у GitLab CI или GitHub Actions, часть плагинов устарели, корпоративные фичи (SSO, аудит) — в платной Harness-версии.
Что понадобится
- Сервер с Docker + docker compose (Ubuntu 22.04/24.04, Debian 12 — всё едино).
- Домен, например
ci.company.ru, с wildcard DNS или отдельной A-записью. - Git-хостинг: Gitea/GitHub/GitLab — регистрируем OAuth-приложение.
- Let's Encrypt сертификат или свой внутренний PKI (мы обычно берём корпоративный AD CS).
Регистрация OAuth в Gitea
Для примера берём Gitea. Идём в Site Administration → Applications → Create OAuth2 Application.
Application Name: Drone
Redirect URI: https://ci.company.ru/login
# Сохраняем Client ID и Client Secret
Docker Compose для Drone
Файл /opt/drone/docker-compose.yml:
services:
drone-server:
image: drone/drone:2.24
restart: unless-stopped
ports:
- "8080:80"
volumes:
- drone-data:/data
environment:
DRONE_GITEA_SERVER: https://git.company.ru
DRONE_GITEA_CLIENT_ID: ${GITEA_CLIENT_ID}
DRONE_GITEA_CLIENT_SECRET: ${GITEA_CLIENT_SECRET}
DRONE_RPC_SECRET: ${RPC_SECRET}
DRONE_SERVER_HOST: ci.company.ru
DRONE_SERVER_PROTO: https
DRONE_USER_CREATE: username:admin,admin:true
DRONE_LOGS_TEXT: "true"
drone-runner:
image: drone/drone-runner-docker:1.8
restart: unless-stopped
depends_on: [drone-server]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
DRONE_RPC_HOST: drone-server
DRONE_RPC_PROTO: http
DRONE_RPC_SECRET: ${RPC_SECRET}
DRONE_RUNNER_CAPACITY: 4
DRONE_RUNNER_NAME: runner-1
volumes:
drone-data:
В .env:
GITEA_CLIENT_ID=xxxxx
GITEA_CLIENT_SECRET=yyyyy
RPC_SECRET=$(openssl rand -hex 16)
docker compose up -d
docker compose logs -f drone-server
Перед Drone-сервером ставлю nginx/traefik с Let's Encrypt, порт 8080 внутрь, 443 наружу. Для Traefik — пару меток на сервис, готово.
Пример .drone.yml для Python-приложения
kind: pipeline
type: docker
name: default
steps:
- name: tests
image: python:3.12-slim
commands:
- pip install -r requirements.txt
- pytest --cov=app tests/
- name: build-image
image: plugins/docker
settings:
registry: registry.company.ru
repo: registry.company.ru/myapp
tags:
- ${DRONE_COMMIT_SHA:0:8}
- latest
username:
from_secret: registry_user
password:
from_secret: registry_pass
when:
branch: [main]
- name: deploy
image: appleboy/drone-ssh
settings:
host: prod.company.ru
username: deploy
key:
from_secret: ssh_key
script:
- cd /opt/myapp
- docker compose pull
- docker compose up -d
when:
branch: [main]
Секреты и переменные
| Где | Что | Когда применять |
|---|---|---|
| Репозиторий → Settings → Secrets | Индивидуальные секреты | Креды реестра, SSH-ключи, API-токены |
| Organization secrets | Общие для всех репо организации | Общий Sentry DSN, Slack webhook |
| Переменные окружения в YAML | Несекретные значения | Имя окружения, версии |
Я всегда ставлю у секретов флаг «Allow Pull Requests» выключенным, иначе форк-PR может слить секреты через echo $SECRET.
Кэширование зависимостей
На каждом запуске качать пакеты заново — долго. Решения:
- Volume-кэш: монтируем директорию pip/npm/go в volume, который живёт между запусками.
- S3-кэш через плагин
drone-s3-cache. - Prebuilt-образ с зависимостями — на регулярной основе пересобираем «базовый» образ и используем его в шагах.
steps:
- name: restore-cache
image: meltwater/drone-cache
settings:
backend: filesystem
mount:
- .venv
- node_modules
restore: true
- name: build
image: python:3.12
commands:
- pip install --target .venv -r requirements.txt
Реальный кейс: Drone для студии веб-разработки
В июне 2025 года к нам пришли ребята из веб-студии — 7 разработчиков, 14 активных проектов на Laravel + Vue. До нас — всё деплоили вручную по SSH. Задача: поднять CI/CD для автотестов и авто-деплоя на стейджинг и прод. Gitea у них уже была, Jenkins пугал.
За 2 рабочих дня мы развернули Drone на виртуалке 4 vCPU / 8 ГБ ОЗУ (наш сервер Dell Xeon Platinum 8280, дата-центр МТС Москва), настроили общий .drone.yml-шаблон и подключили 14 репозиториев. Стоимость работ — 34 000 руб. Через месяц время деплоя на стейджинг сократилось с 20 минут ручных действий до 90 секунд автоматом.
Типичные грабли
- Неправильный RPC_SECRET. Раннер не подключается к серверу. Проверяйте, что один и тот же в обеих переменных.
- OAuth redirect mismatch. В настройках Gitea ровно тот же URL, что в DRONE_SERVER_HOST (с протоколом).
- Нет места на /var/lib/docker. Образы для сборок копятся. Настройте
docker system pruneпо cron в раннере. - Медленные сборки. Включите кэш зависимостей, используйте слим-образы, параллельные шаги.
- Отвалы в середине пайплайна. Чаще всего сеть в docker-in-docker. Добавляйте retries, увеличивайте таймауты в плагинах.
Настроим CI/CD под ваш стек
Мы ставим Drone, GitLab CI, Gitea Actions, Jenkins — в зависимости от того, что действительно подходит вашей команде. 15+ лет админского опыта, 8 серверов Dell Xeon Platinum 8280 с 40G Mellanox в дата-центре МТС Москва для отказоустойчивого хостинга ваших CI.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — Drone CI
- Чем Drone лучше Jenkins?
- Drone легче в настройке, пайплайны описаны в YAML и хранятся в репозитории. Сервер — один контейнер, раннеры — отдельные. Занимает 200 МБ ОЗУ против 1,5 ГБ у Jenkins. Но экосистема плагинов у Jenkins шире.
- С чем интегрируется Drone?
- Gitea, GitHub, GitLab, Bitbucket, Gogs. Использует OAuth для авторизации. Webhooks настраиваются автоматически при активации репозитория в веб-интерфейсе Drone.
- Сколько раннеров нужно?
- Для одной команды из 5–10 разработчиков — один docker-runner на сервере. Для параллельных сборок можно ставить несколько с увеличенным DRONE_RUNNER_CAPACITY. На нашей инфраструктуре — по 2 раннера на клиентский проект.
- Как хранить секреты в Drone?
- Через веб-интерфейс репозитория, вкладка Secrets. Секреты прокидываются как переменные окружения только в шаги, которые их явно запрашивают. Для репозиториев с публичным pull request — обязательно ставьте pull_request_read_only=true.
- Можно ли развернуть Drone без Docker?
- Сервер — да, это один бинарь Go. Но раннер с docker-пайплайнами всё равно требует доступа к Docker-демону. Есть alternative раннеры: exec, ssh, kubernetes, digitalocean. Для большинства задач docker-runner — оптимум.
