
CI/CD連載 1本目の記事です。
Dokployというのを知ったので動かしてみました。よくあるクラウドサービスのPaaSマネージドサービスようなインフラをオンプレ環境やVPSなどに簡単に構築できるものです。自宅サーバーは欲しいなと思いつつ(昔たててqmailで自宅メールサーバー運用したりしたことはあったが)、K8sはあんまり興味ないな、と思っていて何かしらいいのがないかなと思っていたところ、結構自分の理想に近かったので試してみました。
- ソースコードをアップロードしてコンテナでサービス起動
- 各種OSSのサービスを簡単起動
- これらすべてウェブベースの管理画面があり、AWSとかGoogle Cloudの管理画面のようにシステムの設定や閲覧ができる
- ログ、メトリックスのビューア完備(Dozzleとかを自前で立てる必要はない)
今回試していない機能ですが、以下の機能もあります
- 通知
- Docker Swarmベースの複数のサーバーノード管理
- 管理画面のユーザー管理
- バックアップ機能付きのデータベースサポート
- GitHubやGitLabと連携した自動デプロイ
- スケジュール機能
- SSH鍵管理とか
このサービスはDockerとTraefikのリバースプロキシサーバが主要要素で、コンテナでアプリケーションを起動できます。アプリケーションをビルドしてDocker上で起動したり、Docker上で動いているデータベースのデータをバックアップしたりする便利機能群を提供しています。
なお、Dokployそのものはローカルマシンに入れずに、SaaSで動いているDokployに外部からマシン管理機構だけを任せる運用というサービスも提供されています。月当たり$3.5/台+$1ぐらい。また、さまざまなホスティング環境もサポートしています。
インストールしてみる
DokployはLinuxのみをサポートしています。macOSでは直接は動かないのでLinuxの仮想PCを入れてその上で動かします。
macOSは仮想化機能がOS内蔵なのにWSLみたいな直接使えるインタフェースがないので、UTMを入れてその上でDebianを動かします。WWDCのたびにVirtualization Frameworkの新情報を待ち望んでいるのですが・・・今年は新情報来たらいいな。
UTMはApp Storeでも入れられますし、公式サイトからダウンロードしてもいいですし、Homebrew使って brew install --cask utm
でもお好きな方法を選びます。
Linuxインストール
DokployがサポートしているOSはDebian, Ubuntu, Centosです。今回はUbuntuを選びました。手元のmacはM3なので下記のページの「小さなCDまたはUSBメモリ」のARM64のイメージをダウンロードします。Debian Downloadで出てくるサイトだとAMD64版しかないので要注意
UTMのウインドウで+ボタンを押して「仮想化」を選びます。OS選択ではLinuxを選び、Apple仮想化と、ISOイメージで先ほどダウンロードした.isoファイルを選択して、あとはすべてデフォルトでインストールしていきました。特にパッケージなども追加はしていません。SSHサーバのみが入った感じですかね。
起動してIDとパスワードを入れて起動できたら、sudo
とcurl
コマンドだけインストールしておきます。
$ su - |
内部で起動したサービスにつながるかテスト。ネットワークはデフォルトのホストネットワークを使っています。まずはゲストの中でIPアドレスを確認します。192.168.64.7というIPv4アドレスを持っているようです。
$ ip a |
引き続き、ゲストの中からPythonのウェブサーバーを起動してみます。
$ python3 -m http.server |
ホストのマシンからこのゲスト上で動いているサービスにアクセスしてみてHTMLが帰ってきたら無事にサーバーがでっきていることの確認ができます。
% curl http://192.168.64.7:8000 |
これでLinuxのインストールは完了。
Dokployのインストール
Dokployはシェルでインストールします。さまざまなビルドツールとかをダウンロードするので、そこそこの量のダウンロードが走ります。間違ってもテザリングでやらないように・・・勇気と無謀は違います。この手のシェルでインストールはちょっと怖い気持ちはあるのですが、まあ何もないLinux仮想環境なのでえいやで実行します。最後のシェル実行だけroot権限が必要なのでsudo
をつけます。
$ curl -sSL https://dokploy.com/install.sh | sudo sh |
最後に管理画面のURLが表示されますが、IP部分は先ほどip a
コマンドで出てきたものを使います。

アプリケーションのデプロイ
アプリケーションをデプロイしていきます。
設定ファイルなしの自動ビルド(Railpack)
まずはGoのアプリケーションを作ってみます。ふつうのウェブアプリケーションです。
module goapp |
package main |
すべてのアプリケーション、データベースなどは「サービス」という名前のインスタンスで、各サービスは必ず「プロジェクト」に属すという構成になっています。プロジェクト共有で環境変数を設定したり、サービスごとに環境変数を設定することもできます。まずはプロジェクトを作ります。名前を入れるだけですね。go appにしました。

プロジェクトの中にはサービスをおきます。サービスは(自作)アプリケーション、データベース、Compose、テンプレート(後述)、AIで相談して作る、というのがあります。今回はアプリケーションを作ります。こちらもほぼ名前だけです。サーバーはDokployを複数サーバー管理に使っている場合に選びます。今回は1台だけなので選ぶ必要はありません。

アプリケーションのGeneralタブでアプリケーションをデプロイします。ビルドタイプはDockerやBuildpackなどいろいろありますがデフォルトのRailpackにしました。Gitとかと接続もできますが、今回はローカルで作ったzipのソースをドラッグしてデプロイします。Railpackの場合、Goアプリケーションはトップにmain.goがあればこれをアプリとみなしてビルドするようです。Deployボタンをおせば初回は50秒、2回目は9秒ほどでビルドが終わりました。

外からアクセスできるようにするためにはドメインを作成します。DMZで動いているマシンならtraefik.meのサブドメインの無料のドメイン発行機能もあり、ボタン一発(サイコロアイコン)で外からもアクセスさせることもできます。

Deokployが動いているサーバーの80番ポートでサービスは公開されるので、そのアドレスで起動すればOKですね。

複数アプリケーション起動したくなると思うので、その場合はドメインのパスを /
から /hello
とすればそれ以外のパスは他のアプリから使えます。ただし、アプリケーションが受け取るパスはこのプリフィックス部分も含むため、プリフィックス部分は環境変数とかで変えられる機能をアプリ側につけると良さそうです。パスのプリフィックスをトリムする機能はなさげですので。
なおブラウザの管理画面からデプロイ(ビルド)時のログが見れたり、アプリケーションのログも見れるし、メトリックスも見れるし、シェルがあるならコンテナの中に入ることもできるし、コマンドを起動もできるし、ローカル開発と遜色なく利用できます。
複数のアプリケーションを起動の準備
PaaSなので複数のアプリケーションを稼働させられます。ただ、各アプリケーションはみんな自分のパスの空間を持っています。例えば、/health
でヘルスチェック用のエンドポイントを提供というのはみんなやっているので、80番ポートにフラットにマウントされてしまうと複数のアプリケーションが稼働できません。そこで、バーチャルホストの設定をして複数起動できるようにします。
先ほどのGoアプリと、このPythonアプリ、どちらも /hello
というエンドポイントを持っています。192.168のアドレスにマッピングすると使い分けられません。DokployにはTraefikというプロキシが内蔵されています。このプロキシがリクエストを受けるときに、HTTPリクエストに含まれるhostヘッダーフィールドを見て後続のサービスを判断してリクエストを投げ分けます。

そのためにはサービスごとにドメインを発行する必要があります。hostsファイルでも良かったのですがワイルドカード対応のためにdnsmasqをローカルに入れて使います。macOSの手順を書いています。他のOSの方は生成AIにでも投げて自分の環境に合わせて変更してください。
# dnsmasqをインストール |
設定ファイルは以下の通りです。Linuxだと/etc/dnsmasq.confですかね。ローカル用にprivate
というトップレベルドメインを作ってしまいましょう。次の行を足します。どんなサブドメイン向けのリクエストもこのIPアドレスが返ります。
address=/.private/192.168.64.7 |
privateドメインだけはこのDNSサーバーを見にいくようにします。/etc/resolver/
フォルダを作りprivate
というファイルを作成して以下の内容を書きます。
nameserver 127.0.0.1 |
最後にDNSサーバーとOSキャッシュをクリアします。
$ sudo brew services restart dnsmasq |
試しにping test.private
とかいろいろ叩いてみて、192.168.64.7を向いているか確認します。確認できたらアプリをインストールします。
Docker形式のアプリのビルド
以下の記事で書いたPythonアプリケーションをデプロイしてみます。
プロジェクトは先ほどの使い回しでも新規で作っても大丈夫です。その後サービスを作ります。今度のアプリケーションはDockerファイル入りなので、ビルドタイプにDockerfileを選び、ファイル名のDockerfileも入れます。あとはまたzipにしてドロップしてデプロイボタンを押せばビルド完了です。

ドメイン設定ではpyapp.private
というドメインを追加します。

先ほどのGoのアプリケーションの方のドメイン設定にはgoapp.private
というドメインを追加しておきます。ドメインは複数設定できるので前のものは消さなくても大丈夫です。

新しいドメインでアクセスすると複数のサービスが同時に利用できました。

テンプレートカタログからアプリケーションのデプロイ
自作のアプリケーション以外にも人気のアプリケーションを簡単にデプロイできるテンプレートがあります。

試しにminioを選択しました。サーバー選択だけですぐにアプリが登録できました。デプロイ(コンテナのダウンロード)はされていない状態です。ドメインはtraefikの自動生成になっていているのでminio.private
に書き換えて、デプロイボタンをおしたところ、あっという間に起動しました。パスワードなどは環境変数のところに書いてありました。楽勝ですね。

Dokployでできないこと
ドメインの管理はdnsmasqでやりました。AWSとかだとRoute 53みたいなサービスでドメインも一緒にコントロールできますが、ネットワーク周りはオンプレだったり外からアクセスできるサービスだったり、有料のドメインだったりが絡むので扱いきれないのはまあ仕方がないですね。
Dokployそのものの制限というよりも下で動いているDocker/Traefikの制約でできないのがオートスケールです。スケールそのものはDocker Composeの機能にあるのですが、明示的にコマンドを打つ必要があります。AWSやGoogle CloudのロードバランサーはサービスのメモリやCPUの計測値や接続数をみてスケーリングを行えます。モニタリングは大変でも、接続数が70超えたらインスタンス増やす、みたいなのが簡単にできる(ついでにしばらくアクセスがなかったらインスタンスがなくなる)とかがあれば、少なめリソースの自宅サーバーでたくさんサービスを起動しておいて・・・・みたいなのができるんですけどね。
まとめ
「アプリケーション」「データベース」の2つに特化したローカルPaaSのDokployで遊んでみた記録でした。今回はデータベース周りの機能はまだ触らず、またcomposeで複数のアプリの組み合わせを起動みたいなことはしていませんが、基本的なアプリケーションのデプロイを色々試したり、
クラウドのコンソールでちょいちょいアプリケーションを動かして遊んでいた人は、それがそのままオンプレやローカルで動くと考えると興味を持つ人は多いんじゃないでしょうか。「技術は螺旋で行ったり来たりする」と言われますが、コンテナや12 factors appといったクラウドで発展したものがオンプレでも便利に使えるようになるという流れは自然な発展な気がします。
もちろん、フルサービスなGoogle CloudやAWSと比べるとネットワーク周りの設定がなかったり機能が少ない点はありますが、モニタリングやログビューアとかも備えており、ローカルで動かしてテストするのと遜色なく利用できます。今回紹介したもの以外にも色々同様のものもあり、今後さらに発展していていってくれるんじゃないかと思っています。
DNSサーバーを建てるときに、最初.localでやろうとしてハマって「macOSのmDNSが別の用途で使うからダメ」というアドバイスを@takabowと@takuan_oshoにもらってなんとか書き切りました。ありがとうございます。