🚀

自宅サーバーにKamalでデプロイしてみた

に公開

やりたいこと

ローカルネットワーク内にLinuxサーバーを配置して、そこに公開用アプリと非公開用アプリを動かしたい

図にするとこんな感じです。

※Unboundはただのネームサーバーなので、この図はちょっとおかしいですが、ご容赦ください 🙏

つかうもの

  • Docker Hub
  • Unbound
  • Cloudflare Tunnel
  • Kamal

実行環境

  • デプロイを実行する環境
    • Ubuntu on WSL2
  • 自宅サーバー
    • EndeavourOS

つかうものの説明

Docker Hub

(2025/07時点で)KamalはPublicなDocker imageを使ったアプリケーションを動かすことが標準ではサポートされていないように見えます。
理由は、Kamalを実行するディレクトリのgitのコミットハッシュを基準としたDocker imageのタグを利用してデプロイするのが基本的な挙動なので、このあたりに追従することが難しいです。

自宅サーバーであれば、Docker Registryを自前運用すればいいだろうと考えたのですが、Kamalで利用しているDocker buildxにInsecureのパラメータをうまく渡すことができず(?)、めんどくさかったのでDocker Hubを利用するようにしました。

💭 フリーランスのお仕事でDockerを使っているので、無料の範囲内で使えますが、ありがたく使わせてもらっているので、このタイミングで課金しました(Private Repositoryが使いたかった)。

Unbound

Kamal Proxyでサブドメインに応じたDispatchをさせたいので、ネームサーバーを自宅サーバー上に構築しました。
外部に公開したくないアプリのドメインは、別になんでもいいわけですし。

↓のように、内部用のドメインを自宅サーバーのIPに流すだけですね。

local-data: "aa.example.internal. 300 IN A 192.168.1.xxx"
local-data: "bb.example.internal. 300 IN A 192.168.1.xxx"

💭 サブドメインごとに指定しているけど、いらないのでは・・・。

Cloudflare Tunnel

Cloudflareが無料で提供しているサービスで、自宅サーバーとCloudflareの間にトンネルを張って、外部からアクセスできるようにする便利なサービスです。
80ポートなどを開放する必要もなく、Dockerでサクッと起動することもでき、大変便利です。
https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/

設定

*.example.comを*.example.internalに流すだけです

起動

docker run -d --restart unless-stopped --network=host cloudflare/cloudflared:latest tunnel --no-autoupdate run --token xxx

Kamal

本題のKamalです。
Kamalがv2になったときProxyがTraefikから自前のKamal Proxyになってだいぶ設定がしやすくなったっぽい(?)です。
というのも、今回のように、アプリごとにサブドメインの設定があると思うのですが、各アプリのKamal configに自分のサブドメインの設定だけを行えば、あとはよしなにやってくれます。
もちろん、サブドメイン名の衝突が起こると問題があるでしょうが、そんなことをする人はいないはず。

設定

とあるPublicなRailsアプリを例にとります。

# config/deploy.yml

service: example

image: kehra/example

servers:
  web:
    - 192.168.1.xxx

proxy:
  app_port: 3000
  host: cc.example.com

registry:
  username: test

  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  secret:
    - RAILS_MASTER_KEY

volumes:
  - "storage:/rails/storage"

asset_path: /rails/public/assets

builder:
  arch: amd64

ssh:
  user: kehra
  keys: [ ~/.ssh/id_rsa ]
# .env

RAILS_MASTER_KEY=your_rails_master_key_here
KAMAL_REGISTRY_PASSWORD=your_registry_password_here

あとは、.envを何かしらの方法で読み込んで、kamal setupをするだけです。

締め

Claude Codeなど多様なAIツールのおかげで、ちょっとしたアプリを作るハードルが大きく下がったと思います。
しかし、それらを定常的に動かす場をサクッと用意したいなと思い、Dockerで動かすことを前提とした自宅サーバーを用意してみました。

お仕事ではRailsをメインで使っているので、Kamalがどういうものかを使って確かめるというところからも、こんな構成を取ってみました。

もし、どなたかのご参考になれば嬉しいです。

Discussion