CH 27 · 展開形態の選定
本章のゴール
これまで dsh web をローカルで動かして dsh を使ってきましたが、これが最も一般的ですが唯一の方法ではありません。dsh には主に 4 つの実行方法があり、それぞれ異なるシーンに向いています:
- ローカル Web UI:これまでのチュートリアルで実演してきたもの
- Headless CLI:インターフェース不要、1 コマンドでタスクを実行して終了、スクリプトや CI に組み込みやすい
- Python SDK:dsh を自分の Python プログラムに組み込み、Agent をコード内の関数呼び出しにする
- Docker コンテナ化:dsh をコンテナに入れてサーバーで動かす、チーム共有に向く——本章で完全な展開チュートリアルを解説
読み終えると、自分のニーズにどの方法を使うべきか(dsh web しか知らない、ではなく)が分かります。
まず確認:なぜ dsh に複数の形態があるのか
CH 08 の「すべてはプラグイン」を思い出してください。dsh のコアは @deepseek-ai/dsh-base(モデルアダプタ、ツール、永続化、サンドボックス、承認などの低層機能)で、その上に異なる bundle を重ねると異なる形態になります:
| 重ねる bundle | 形態 | 起動方法 |
|---|---|---|
@deepseek-ai/dsh-web-app | ブラウザ UI 付き Web UI | dsh web |
@deepseek-ai/dsh-headless | UI なし、実行後終了する CLI | dsh --profile headless "task" |
| Python SDK ラッパ | Python プログラムに組み込んで呼び出す | pip install deepseek-harness-sdk |
| 上記いずれかをコンテナ化 | サーバーで長期稼働 | docker compose up -d |
同じ土台に 4 つの着せ方。これも「すべてはプラグイン」の現れであり、形態そのものが bundle の組み合わせです。
形態 1:ローカル Web UI
CH 03 から CH 04 で実演してきたのがこれです。dsh web で起動し、ブラウザで http://127.0.0.1:3080 を開くと、セッション・プラグイン・キーがすべてローカルに保存されます。
日常利用、プラグインのデバッグ、初心者に適しています。制約は PC の電源が入っているときしか使えないこと——電源を切れば Agent も止まるため、24 時間オンラインが必要、または他者に常時アクセスさせる必要があるシーンには向きません。
形態 2:Headless CLI
CH 05 で既にハンズオンしました。UI なしでタスクを渡せば実行して結果を返し終了します。
dsh --profile headless "Summarize the current directory's README into three sentences"スクリプト、CI/CD、定時タスク(CH 15 で毎日 AI ホットトピックを集めるものがこれを使っています)、バッチ処理に向きます。マルチターンの対話が必要なシーンには向きません。
注意点:headless の呼び出し 1 回ごとに独立したセッションとなり、完了時に終了します。コンテキストを再利用するには Python SDK を使うか、ファイル経由の受け渡しを書く必要があります。
形態 3:Python SDK
dsh を Python コードのライブラリとして扱い、Agent を関数呼び出しにします。pip install deepseek-harness-sdk でインストールでき、SDK には Node ランタイムが同梱されるため、対象マシンに Node を別途インストールする必要はありません。
from deepseek_harness_sdk import DeepSeekHarness
dsh = DeepSeekHarness()
result = dsh.run("List the current directory's files, skip node_modules")
print(result.last_message)Agent を自分のプロダクトに組み込みたい、セッションを細かく制御したい(再利用、イベント監視、ストリーミング出力)、コンテキストを共有するバッチタスク、に向きます。単にタスクをさっと走らせたいだけ(headless で 1 コマンドで十分)には向きません。
詳細:SDK と Web UI はそれぞれ独立したインスタンスであり、起動中の Web UI を共有することはできず、それぞれが独自の DSH_HOME を持ちます。
形態 4:Docker コンテナ(展開チュートリアル完全版)
dsh を Docker コンテナにインストールしてサーバーで動かす、長期稼働とチーム共有に向きます。
サーバーに進む前にひとこと:サーバーをまだ持っていない場合、Tencent Cloud の新規ユーザー向けキャンペーン では低コストな軽量アプリケーションサーバーが用意されていることが多く、年間わずか 100 元強で dsh には十分です。また Tencent Cloud ではインスタンス作成時に DeepSeek Harness イメージを直接選択することもできるため、いじるのが好きな方はそちらも調べてみてください。以下は成熟したコミュニティのオープンソースプロジェクトを使った完全な展開手順を実演します。
deepseek-harness-web-docker は dsh + Caddy(リバースプロキシ + Basic 認証)を 1 つのコンテナにまとめ、すぐに使える状態で配布しており、データは永続化、自動ヘルスチェックも備えています。
このプロジェクトが解決する問題
サーバーで公式の dsh web を直接使うと 3 つの痛みがあります:
- 認証がない——dsh の Web UI にはログイン機構がなく、パブリックに展開すると裸で動かしているのと同じ
- ループバックでしかリッスンしない——既定は
127.0.0.1で、外部アクセスを許可するには設定変更が必要 - 環境管理が面倒——Node バージョン、依存関係、データディレクトリをすべて自前で管理する必要がある
このプロジェクトは Caddy をリバースプロキシとして使い、Basic 認証(ユーザー名/パスワードログイン)を追加します。dsh はコンテナ内のループバックだけでリッスンし、外部からのリクエストは Caddy の認証を通過しなければ入れません。データはすべてホストの ./data ディレクトリにマウントされるため、コンテナを削除してもデータは失われません。
ステップ 1:準備
Linux サーバー(2 コア 2G から)と、宝塔(BT)パネルをインストールします。宝塔 AI は使う前にまずモデルを設定する必要があります——左メニュー AI → 上部 Settings → Add Custom Model をクリックし、モデルの API Key を入力します。

モデルを設定すると、宝塔 AI がコマンド実行を助けてくれるようになります。
ステップ 2:宝塔 AI でワンクリック展開
宝塔パネルの左メニューで AI をクリックし、以下のプロンプトを送信します:
Help me deploy DeepSeek Harness Web Docker, do this in order:
1. Confirm Docker and Docker Compose are installed, install if not
2. Project address is https://github.com/Xidong-AI/deepseek-harness-web-docker
3. Enter the project directory, cp .env.example .env
4. Edit .env: DSH_AUTH_USER=admin, DSH_AUTH_PASSWORD set a strong password, DEEPSEEK_API_KEY etc. tell me the file path before starting I'll fill it in myself
5. docker compose up -d to start
6. Give me a summary after verification宝塔 AI が手順を踏んでくれます。ステップ 4 に差し掛かると、.env ファイルの API Key 以外を設定し、ファイルパスを教えてくれるので、自分で DEEPSEEK_API_KEY を入力します:

入力後「Done」と返信すれば、AI は docker compose up -d を続行して起動し、ヘルスチェックで検証し、最後に完全なサマリーを返してくれます:

コンテナの状態が healthy で、Basic 認証が有効になっている(認証なしで 401 を返す)なら、展開成功です。
ステップ 3:アクセス
ブラウザで http://server-IP:3080 を開くと、Basic 認証のダイアログがポップアップするので、.env に設定したユーザー名とパスワードを入力すれば dsh の Web UI に入れます。
ブラウザの左上に「保護されていません」と表示されますが、これは現在のプロトコルが HTTP で SSL 証明書がないためであり、dsh 自身の問題ではありません。本番展開ではドメイン + HTTPS を紐付ける必要があります(次のステップ)。

ログイン後はローカルで dsh を使うのと変わらず、ワークスペースを選んでメッセージを送信します。
ステップ 4:ドメイン + HTTPS を紐付ける
本番環境ではドメイン + HTTPS を紐付けなければ正常に動作しません。http://server-IP で直接アクセスすると、ワークスペースを選ぶ際に以下のエラーが出ます:

原因は crypto.randomUUID() がブラウザの Web API で、仕様上セキュアコンテキスト——すなわち https:// のページ、または localhost/127.0.0.1——でのみ利用可能と定められているためです。http://IP でのアクセスは非セキュアコンテキストとなり、この関数は undefined のため、セッション作成やワークスペース選択の瞬間にフロントエンドが crypto.randomUUID is not a function を投げます。
したがって、ドメイン + HTTPS の紐付けは任意の最適化ではなく必須です。
前提条件:まずドメイン管理コンソール(Tencent Cloud DNSPod、Alibaba Cloud Wanwang など)でドメインの A レコードを追加し、サーバーのパブリック IP に向けてください。数分待って反映されるのを待ちます。
先ほど続けた会話のまま(新しい会話を始める必要はありません)、宝塔 AI に以下を送信します:
Help me bind a domain to the dsh I just deployed and apply for an SSL certificate and configure it for me
1. The domain is your-domain, already resolved to this server
2. Verify that https://your-domain is accessible, tell me the result宝塔 AI が自動的に Caddy の設定を変更し、ポートを開き、コンテナを再起動し、証明書を申請します。完了後 https://your-domain にアクセスすると、ブラウザの左上に鍵アイコンが表示され、「保護されていません」は消えます。
証明書は Let's Encrypt が発行し、Caddy が自動更新するため、手動管理は不要です。
継続的な運用
展開後の日常的な質問は宝塔 AI に直接聞けばよいです。例えば:
- 「How to upgrade the dsh container to the latest version?」
- 「How to view the dsh container's running logs?」
- 「How to restart the dsh container?」
- 「How to back up dsh's data?」
- 「The dsh container is taking too much disk space, how to clean it up?」
AI が実際の環境に応じたコマンドを提示し実行してくれます。データはすべてプロジェクトディレクトリの ./data/ に保存されているため、コンテナ削除やイメージのアップグレードでデータは失われません。バックアップはこの ./data ディレクトリを丸ごとコピーするだけです。
コンテナ内にインストールできるツール
コンテナには node 22、pnpm、python3、git、curl、jq、ripgrep、make/gcc(ネイティブモジュールのコンパイル用)、Rust などの汎用ツールがプリインストールされています。Agent は x-cmd を使って自分でさらにツールをインストールすることもでき(root 不要)、インストールされたデータも ./data に入るため再起動後も残ります。
注意事項
- 現在バージョンの dsh にはマルチユーザー分離がない——全員が同じ Basic 認証でログインし、同じセッションと設定を共有します。チームで共有する際は機密情報を保存しないか、各人が独立したインスタンスを展開してください。
- compose に API Key をハードコードしない——
.envファイルを使い、プロジェクトで既に git ignore されています。 - Agent はコンテナ内で動く——見えるのはコンテナ内のファイルシステムであり、サーバーのものではありません。サーバー上のディレクトリを操作させたい場合は、docker-compose でボリュームマウントを追加し、ホストディレクトリをコンテナにマップする必要があります。
- パスワード変更:
.envのDSH_AUTH_PASSWORDを編集し、docker compose up -dを実行すると、コンテナ起動時にハッシュが自動再生成されます。
どう選ぶか:早見表
| ニーズ | 選ぶ形態 | 理由 |
|---|---|---|
| ブラウザを毎日開いて Agent と作業 | ローカル Web UI | 直感的な UI、軌跡が見え承認できる |
| スクリプト / CI / 定時タスクに組み込む | Headless CLI | 1 コマンド、実行して終了 |
| Agent を自分のプログラムに組み込む | Python SDK | 関数レベル呼び出し、セッションとイベントを制御できる |
| サーバーで長期稼働 / チーム共有 | Docker | コンテナ化展開、自動再起動、データマウント |
| バッチタスクでコンテキスト共有が必要 | Python SDK | headless は呼び出しごとに独立セッション、SDK は再利用可能 |
実用的なアドバイス:ほとんどの人はまずローカル Web UI から始めれば十分です。自動化が必要になったら headless を、プロダクトに組み込みたくなったら SDK を、サーバーで動かしたくなったら Docker を追加で。最初から 4 つとも整える必要はありません——dsh のうまみは必要なときにすぐ切り替えられることで、土台は同じ 1 セットです。
この章で学んだこと
以下の項目を自分で達成できれば合格です:
- [ ] dsh には 4 つの展開形態(ローカル Web UI、Headless CLI、Python SDK、Docker)があることを知っている
- [ ] 4 つの形態の起動方法と適用シーンを説明できる
- [ ] ニーズに応じて適切な形態を選べる(
dsh webしか知らない、ではなく) - [ ] Headless の呼び出しはそれぞれ独立したセッションであり、コンテキストを再利用するには SDK を使う必要があることを知っている
- [ ] Python SDK には Node ランタイムが同梱されており、Web UI とは独立したインスタンスであることを知っている
- [ ] deepseek-harness-web-docker プロジェクトを使って、Basic 認証付きでサーバーに dsh を展開できる
- [ ] 展開した dsh にドメイン + HTTPS を紐付けられる(Caddy 自動証明書)
- [ ] Docker 展開の注意事項を言える:マルチユーザー分離なし、.env にキー、コンテナ内のパス差異
