サーバーをセットアップする
cornus のコマンドはすべてサーバーと通信します。このページには、サーバーが取りうる構成ごとに短い手順書をまとめています。必要なもの、起動するコマンド、うまくいったかを確認する方法です。cornus setup は、選んだ構成のセクションへ直接リンクします。
ここにあるのはリファレンスではなく手順書です。各セクションの末尾には、その主題を網羅的に扱うページへのリンクがあります。フラグ、値、機能の一覧が必要になったらそちらをたどってください。
どの構成にするか
サーバーは一つのプロセスです。構成ごとに変わるのは どこで動くか と どのランタイムを駆動するか (デプロイバックエンド) です。
| やりたいこと | 構成 | cornus setup のシナリオ |
|---|---|---|
| 最小の準備で Cornus を試す | ローカル、Docker | local |
| Docker デーモンなしで動かす | ローカル、containerd または bare | local |
| デーモンを一切使わない | ローカル、bare | local |
| Incus のインスタンスを使う | ローカル、Incus | local |
| 手元のマシンからクラスターへデプロイする | ローカル、Kubernetes | local |
| もっと強力なビルド / デプロイ用ホストを使う | SSH 経由のリモートホスト | ssh-* |
| デプロイ先のクラスター内で Cornus を動かす | クラスター内 | kube-port-forward、kube-url |
| ホストを汚さない | コンテナとして | docker-container、containerd-container、incus-container |
| 他の人が運用するサーバーを使う | セットアップ不要 | url |
どの構成にも共通する原則が二つあります。
- ビルドエンジンには権限が必要です。 runc、overlayfs、user 名前空間を使うため、サーバーを root / 特権付きで実行するか、
cornus serve --rootlessを使ってください。権限のありかた を参照してください。 - 決める前に確認してください。
cornus daemon preflightはcornus serveが起動時に実行するのと同じホストチェックを行い、cornus serveが起動を拒否する構成では終了ステータスが 0 以外になります。以下の手順書はすべてこれを使います。
ローカルサーバー
Cornus を手元のマシンで動かします。データディレクトリにはレジストリの CAS とビルドキャッシュが入ります。再起動をまたいで保持するには --data-dir (または CORNUS_DATA) を指定してください。
まずバイナリを入手します。インストール を参照してください。
Docker
既定であり、準備が最も少ない構成です。
必要なもの: Docker ソケット /var/run/docker.sock。
cornus daemon preflight # 先にホストを検証する
cornus serve --data-dir ~/.local/share/cornus確認: サーバーが起動していれば cornus health は何も出力せず終了ステータス 0 になります。
詳細: dockerhost バックエンド。
Podman
cornus は Podman を、Docker 互換エンドポイントではなくネイティブの libpod API 経由で駆動します。
必要なもの: podman の API ソケット。そしてどのソケットを使うかを cornus に伝える必要があります。推測は一切しません。どちらの変数も設定されていない場合、どのデーモンを指しているのか当てにいくのではなく、サーバーは起動を拒否します。
# ルートレス (デスクトップや CI で一般的な構成)
systemctl --user enable --now podman.socket
export CORNUS_PODMAN_SOCKET="$XDG_RUNTIME_DIR/podman/podman.sock"
# ...またはルートフル
sudo systemctl enable --now podman.socket
export CORNUS_PODMAN_SOCKET=/run/podman/podman.sock
CORNUS_DEPLOY_BACKEND=podman cornus daemon preflight
CORNUS_DEPLOY_BACKEND=podman cornus serve --data-dir ~/.local/share/cornuspodman.socket を有効にしても Podman がデーモンになるわけではありません。このユニットは socket activation なので、サービスは必要になったときに起動し、アイドルになれば終了します。
socket ユニットをまったく有効化したくない場合は、cornus 自身にサービスを実行させることもできます。必要なのは PATH 上の podman バイナリだけです。
CORNUS_DEPLOY_BACKEND=podman CORNUS_PODMAN_SERVICE=1 cornus serveリモートの podman には SSH 経由で到達できます。podman system connection が保存している接続先をそのまま使えます。
export CORNUS_PODMAN_SOCKET="ssh://core@host/run/user/1000/podman/podman.sock"ルートレスでの注意点: ルートレスなワークロードのネットワーク名前空間はホストから経路がないため、cornus port-forward と cornus tunnel はダイヤルによって到達できません。ワークロードへは per-instance companion 経由で到達するため CORNUS_PODMAN_REMOTE=1 を設定してください。このモードには CORNUS_AGENT_IMAGE と CORNUS_ADVERTISE_URL も必要です。デプロイ、ログ、exec はどちらでも動作し、ルートフルな podman にはこの制約はありません。
確認: cornus health。
詳細: podman バックエンド。
containerd
dockerd は不要ですが、デーモンは使います。
必要なもの: root、containerd ソケット、そして /opt/cni/bin の CNI プラグイン (bridge、portmap、host-local、loopback)。
sudo CORNUS_DEPLOY_BACKEND=containerd cornus daemon preflight
sudo CORNUS_DEPLOY_BACKEND=containerd cornus serve --data-dir /var/lib/cornus確認: cornus health。
詳細: containerd バックエンド。
bare (デーモンなし)
Cornus が自分で OCI ランタイムを駆動し、自分で監督します。dockerd も containerd も使いません。
必要なもの: root、PATH 上の OCI ランタイム、そして同じ CNI プラグイン。既定は runc で、CORNUS_BARE_RUNTIME により crun、youki、runsc (gVisor) を選べます。
sudo CORNUS_DEPLOY_BACKEND=bare cornus daemon preflight
sudo CORNUS_DEPLOY_BACKEND=bare cornus serve --data-dir /var/lib/cornusランタイムが見つからない場合は、最初のデプロイ時ではなく起動時に、対処のわかるエラーで直ちに失敗します。
この構成は systemd で動かしてください
bare では cornus 自身がワークロードの監督者 です。各コンテナの PID 1 を待ち受け、再起動ポリシーを自分で適用します (CORNUS_BARE_SHIM を使えばコンテナごとの shim に切り離せますが、既定では無効です)。そのため端末から起動したサーバーは、終了するときにワークロードの監督ごと道連れにします。生き残ったコンテナに再接続し、ホスト再起動後に再構築する起動時の reconcile も、cornus が動いていなければ実行されません。クラッシュと再起動の両方をワークロードが越えられるようにするのが Restart=on-failure と WantedBy=multi-user.target です。
他のバックエンドは監督をデーモンやクラスターに任せているため、cornus を失っても失われるのは API であってワークロードではありません。そちらではフォアグラウンドの cornus serve も妥当な開発ループのままです。
cornus setup はこの構成向けの cornus.service を提案します。自分で組み立てるより、それを使ってください。
確認: cornus health。
詳細: bare バックエンド。
Incus
ワークロードは Incus のアプリケーションコンテナになります。
必要なもの: incusd 6.3+ (それ以前のリリースには OCI 対応がありません)、そのソケットへのアクセス権、そして デーモンホスト側の skopeo と umoci。incusd がイメージを平坦化するためにこれらを呼び出すので、incusd が動くホストに必要です。
CORNUS_DEPLOY_BACKEND=incus cornus daemon preflight
CORNUS_DEPLOY_BACKEND=incus cornus serve --data-dir ~/.local/share/cornusCORNUS_INCUS_SOCKET (既定 /var/lib/incus/unix.socket) と CORNUS_INCUS_PROJECT (既定 default) で接続先を変更できます。
確認: cornus health。
詳細: incus バックエンド。
手元のマシンから Kubernetes へ
サーバーはローカルで動き、kubeconfig で到達できるクラスター (k3s、kind、minikube、リモートのもの) へデプロイします。ローカルのコンテナランタイムは一切使いません。
必要なもの: 到達できるクラスター (KUBECONFIG、なければ ~/.kube/config) と、CORNUS_K8S_NAMESPACE (既定 default) で Deployment と Service を管理できる RBAC。
CORNUS_DEPLOY_BACKEND=kubernetes cornus daemon preflight
CORNUS_ADVERTISE_REGISTRY=192.0.2.10:5000 \
CORNUS_DEPLOY_BACKEND=kubernetes cornus serve --data-dir ~/.local/share/cornusイメージをプルするのはノードであって、あなたではありません
ここでは CORNUS_ADVERTISE_REGISTRY は任意ではありません。ビルドしたイメージをこのサーバーのレジストリからプルするのはクラスターのノード自身です。そのため 127.0.0.1:5000 のようなアドレスは ノード上では ノード自身を指してしまい、手元のマシンに置かれたイメージをプルできずにすべてのデプロイが失敗します。ノードが到達できるアドレスを設定してください。
Cornus は本来クラスター 内部 で動かすことを主眼としており、その場合レジストリは構造上ノードが到達できるサービスエンドポイントになるので、この問題は起きません。サーバーを特にローカルで動かしたい理由がなければ クラスター内 を選んでください。
詳細: kubernetes バックエンド。
SSH 経由のリモートホスト
サーバーは別のマシンで動き、CLI はローカルポートをバインドしない SSH トンネルで到達します。どのランタイムを駆動するかは そちら側 で CORNUS_DEPLOY_BACKEND により決まります。トンネル自体はバックエンドに依存しません。
四つとも手順の形は同じです。
- リモートホストに cornus バイナリをインストールする (インストール)。
- そのバックエンドの前提条件を満たす (下記)。
- 検証する:
ssh HOST '<env> cornus daemon preflight'。 - ループバックにバインドして実行する。トンネルはホスト側で出るので、ホスト自身のループバックでサーバーに届きます:
ssh HOST '<env> cornus serve --addr 127.0.0.1:5000'。 - 手元側を設定する:
cornus setup --scenario ssh-<backend>。
手順 4 はシェルで済ませるより systemd ユニットにする価値があります。cornus setup は選んだバックエンド向けの正しい cornus.service を、前提条件をコメントに含めて生成します。自分で組み立てるより、それを使ってください。
Docker
ホストに必要なもの: Docker ソケット。環境変数: なし (既定)。
ssh HOST 'cornus daemon preflight'
cornus setup --scenario ssh-dockercontainerd
ホストに必要なもの: root、containerd ソケット、/opt/cni/bin の CNI プラグイン。環境変数: CORNUS_DEPLOY_BACKEND=containerd。
ssh HOST 'sudo CORNUS_DEPLOY_BACKEND=containerd cornus daemon preflight'
cornus setup --scenario ssh-containerdbare
ホストに必要なもの: root、PATH 上の OCI ランタイム、CNI プラグイン。環境変数: CORNUS_DEPLOY_BACKEND=bare。
ssh HOST 'sudo CORNUS_DEPLOY_BACKEND=bare cornus daemon preflight'
cornus setup --scenario ssh-bareIncus
ホストに必要なもの: incusd 6.3+、ソケットへのアクセス権、skopeo と umoci。環境変数: CORNUS_DEPLOY_BACKEND=incus。
ssh HOST 'CORNUS_DEPLOY_BACKEND=incus cornus daemon preflight'
cornus setup --scenario ssh-incusそのホスト上でコンテナとして
リモートホストにバイナリをインストールする必要はありません。Docker ホストであれば、サーバーは公開イメージから実行でき、同じトンネルで到達できます。cornus setup --scenario ssh-docker は「サーバーをリモートホスト上でコンテナとして実行しますか」と尋ね、この形に切り替えます。
ホストに必要なもの: Docker と、データディレクトリ用のホスト側ディレクトリ。cornus バイナリも systemd ユニットも不要です。
# 先に、そちらでバインドを確認します。
ssh HOST 'docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/cornus:/var/lib/cornus:rshared \
ghcr.io/moriyoshi/cornus:latest daemon preflight'
ssh HOST 'docker run -d --name cornus --privileged --restart unless-stopped \
-p 127.0.0.1:5000:5000 \
-e CORNUS_DATA=/var/lib/cornus \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/cornus:/var/lib/cornus:rshared \
ghcr.io/moriyoshi/cornus:latest serve --addr :5000'公開先は リモートホストのループバック です。そこはまさに SSH トンネルが出る場所であり、そのホストのネットワークには何も公開されません。この形では systemd ユニットを提案しません。起動すべきバイナリがなく、再起動後に復帰させるのは --restart unless-stopped だからです。
バインドの重要性はローカルの場合と同じです。コンテナとして と サーバーをコンテナで実行する を参照してください。
四つ共通のレジストリに関する注意: ホストのデプロイ先が導出されたレジストリアドレスからプルできない場合は、--registry-host を設定してください。
詳細: SSH 経由のリモートコンテナホスト。
クラスター内
Cornus が本来想定している構成です。サーバーはデプロイ先のクラスター内で StatefulSet として動くため、レジストリは構造上ノードが到達できるサービスエンドポイントになり、ビルドキャッシュも再起動をまたいで残ります。
必要なもの: クラスターと kubectl / helm。手元のマシンには CLI 以外は不要です。
helm install cornus oci://ghcr.io/moriyoshi/charts/cornus
kubectl rollout status statefulset/cornus --timeout=300sHelm が推奨経路です。chart にはバージョンがあり、イメージタグも chart のバージョンに追随するため、1 コマンドで互いに一致するサーバーとマニフェストが手に入ります。raw マニフェストでも構いませんが、ブランチではなく リリースタグ に固定してください。これは広範な RBAC を持つ特権付き StatefulSet をインストールします。
次に CLI をそこへ向けます。
cornus setup --scenario kube-port-forward # 自動ポート転送。公開は不要
cornus setup --scenario kube-url # または ingress URL で到達するレジストリの公開: NodePort のレジストリはノードのアドレスを自動的に通知します。ClusterIP や ingress の場合は registry.advertiseHost (またはクライアント側の --registry-host) を設定してください。cornus setup が対応する cornus-values.yaml を生成します。
詳細: インストール、Helm chart の values、リモートクラスターで作業する、そしてこの流れをシングルノードの k3s クラスターでたどる クイックスタート。
管理対象のホスト上のコンテナとして
サーバー自体を、管理対象のホストランタイム上でコンテナとして動かします。docker における難所はもっぱらバインドマウントであり、間違えても起動時には失敗しません。デプロイ時に何も言わずに失敗します。
必要なもの: Docker と、データディレクトリ用のホスト側ディレクトリ。それだけです。Compose も、配布されるファイルも必要ありません。
# 先に、実際に動かすイメージでバインドを確認します。
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/cornus:/var/lib/cornus:rshared \
ghcr.io/moriyoshi/cornus:latest daemon preflight
docker run -d --name cornus --privileged --restart unless-stopped \
-p 127.0.0.1:5000:5000 \
-e CORNUS_DATA=/var/lib/cornus \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /srv/cornus:/var/lib/cornus:rshared \
ghcr.io/moriyoshi/cornus:latest serve --addr :5000preflight は 先に 実行してください。何も動いていないうちにバインドを直すほうがはるかに安く済みます。三つのオプションはいずれも必要です。ソケットのバインドがあるからこそホストの docker を使えます。:rshared があるからこそ、コンテナ内で cornus が行ったマウントがホストへ伝わります。--privileged はインプロセスのビルドとカーネル 9P マウントに必要です。
cornus setup --scenario docker-container はホスト側のデータディレクトリとポートを尋ね、その回答を埋め込んだこのコマンドを表示します。
確認: cornus health。
containerd または Incus ホスト上で
どちらもサポートされており、設定方法は十分に異なるため、始める前に目を通しておく価値があります。
- containerd では
docker runではなくctr runを使います。これは重要な点です。cornus は自身のコンテナを、これからデプロイに使う containerd に問い合わせて特定するため、その同じ containerd がサーバーのコンテナを作成した場合にのみ自分自身を見つけられます。さらに--net-hostと/run/cornusのバインドが必要で、どちらか欠けていると事前チェックが起動を拒否します。cornus setup --scenario containerd-containerを使ってください。 - Incus ではデーモンのソケットだけが必要です (このバックエンドは incusd に cornus 自身のパスを一切渡しません) 。加えて incus のブリッジへの経路のために
--network hostが必要です。サーバーを incus のインスタンスとして実行する場合、そのどちらも不要です。cornus setup --scenario incus-containerを使ってください。
詳細: サーバーをコンテナで実行する。
他の人が運用するサーバー
セットアップは不要です。運用している人に URL と、必要なら資格情報を尋ねてから、次を実行します。
cornus setup --scenario url認証が必要な場合は、ウィザードが SSH 鍵の登録またはトークンの保存を案内します。セキュリティと認証 を参照してください。
サーバーが起動したら
cornus health # 待ち受けているか
cornus version # 設定したプロファイルで CLI が到達できるか
cornus compose up # 何かデプロイするcornus health は成功するのに cornus version が失敗する場合、サーバーは問題なく接続プロファイルのほうに問題があります。cornus setup をもう一度実行するか、接続設定 を参照してください。