Мне давно нравится использовать Dokku для развертывания проектов, которые я делаю (см. первую статью про Dokku). При этом очевидно, что с помощью Dokku неудобно разворачивать сторонние сервисы, для этого удобнее использовать простой Docker Compose, а иногда и вообще хочется запустить что-то просто на “голом железе”, без контейнеров.
Вот мы подняли у себя на сервере пару приложений Dokku, пару контейнеров через Docker Compose, и в добавок небольшой сервис запустили прямо из бинарного файла. Теперь к этому всему хочется настроить маршрутизацию запросов, чтобы:
- запросы к домену
blog.example.comшли в Dokku-приложение, - запросы к домену
stats.example.comшли в обычный Docker-контейнер, который мы подняли через Docker Compose - запросы к домену
runner.example.comи вовсе шли куда-то на порт, который слушает запущенный из бинарного файла сервис
К сожалению, когда мы настраиваем Dokku по самой простой инструкции, то Dokku забирает себе порты 80 и 443, и работает так, что маршутризировать запросы может только в Dokku-же приложения.
Значит, нам нужно:
- настроить Dokku так, чтобы он слушал не 80 и не 443 порты
- перед Dokku поднять сервис, который будет маршрутизировать трафик
Самый простой способ поднять Dokku, как оказалось - поднять его в Docker:
docker container run -d \
--env DOKKU_HOST_ROOT=/var/lib/dokku/home/dokku \
--env DOKKU_LIB_HOST_ROOT=/var/lib/dokku/var/lib/dokku \
--name dokku \
--publish 3022:22 \
--publish 8080:80 \
--publish 8443:443 \
--volume /var/lib/dokku:/mnt/dokku \
--volume /var/run/docker.sock:/var/run/docker.sock \
dokku/dokku:0.37.6
обратите внимание на маппинг портов:
- 80-ый порт (HTTP) Dokku будет доступен с 8080 порта хоста
- 443-ый порт (HTTPS) Dokku доступен с 8443 порта хоста
- 22-ой порт (SSH) Dokku доступен с 3022-ой порта хоста
Настройка таким образом поднятого Dokku совпадает с обычной настройкой, только вместо команды dokku нужно писать docker exec dokku dokku. Например:
$ docker exec dokku dokku apps:create blog
Если вы используете оболочку fish, то можно создать соответсвующий alias:
~> alias dokku="docker exec dokku dokku" --save
это позволит пользоваться привычной командой dokku, fish под капотом сам заменит ее на docker exec dokku dokku.
Небольшая ремарка по настройке: чтобы добавить SSH-ключ админа, нужно будет зайти в командную строку контейнера и выполнить
echo "<публичный ключ>" | dokku ssh-keys:add admin. Если выполнить команду с хостаecho "<публичный ключ>" | docker exec dokku dokku ssh-keys:add admin, то ничего не произойдет.
В качестве сервиса для маршрутизации запросов я использую Caddy. Не буду описывать как его поднять, смотрите документацию: https://caddyserver.com/docs/install
Предположим что я хочу направить трафик с домена blog.example.com на приложение blog, которое управляется Dokku. Для этого нужно:
- Присвоить домен
blog.example.comнашему приложению:docker exec dokku dokku domains:add blog blog.example.com - Добавить правило маршрутизации трафика в Caddyfile:
blog.example.com {
reverse_proxy 127.0.0.1:8080
}
Благодаря такому подходу, сохраняется и удобство + надежность развертывания приложений через Caddy, а также гибкость и простота запуска сторонних приложений через Docker Compose или вообще без контейнеров. При этом, все запросы к сервисам идут через HTTPS, а маршрутизация настраивается в единой точке.