UbuntuのWorkshopでClaude Codeをサンドボックス化された開発環境で実行してみる

UbuntuのWorkshopでClaude Codeをサンドボックス化された開発環境で実行してみる

2026.06.29

はじめに

皆様こんにちは、あかいけです。

Claude Codeのようなコーディングエージェントは便利ですが、危険な操作(rmや得体の知れないcurl | sh)でホストのファイルや認証情報まで触られると怖いので、隔離した環境で動かしたいですよね。

そして先日CanonicalがUbuntuの新機能である「Workshop」を発表されたのですが、まさにこのようなユースケースに使えそうです。

https://ubuntu.com/workshop
https://ubuntu.com/workshop/docs/tutorial/part-1-get-started/

というわけで今回は、WorkshopでClaude Codeのサンドボックス環境を構築してみました。

Workshopとは

Workshopは、Canonicalが2026年5月に公開したUbuntu向けの開発環境管理ツールであり、YAMLファイルでサンドボックス化された開発環境を構築することができます。

実体はsnapアプリで、内部ではCanonical製のLXD(システムコンテナ/VMマネージャー)を使っています。

https://github.com/canonical/workshop

Canonicalの公式ブログでは、Workshopの特徴として「再現性・隔離・権限制御」が挙げられています。

  • 再現性
    • YAMLファイルに環境を宣言する形なので、テキストとしてGit管理・チーム共有でき、別マシンでも同じ環境を作れます
  • 隔離
    • Dockerの「アプリケーションコンテナ」ではなく、LXDの非特権システムコンテナで動きます
    • 1台のマシンに近い感覚で、それでいてホストとは分離されています
  • 権限制御
    • snapd由来のPlug/Slot(インターフェース)で、ホスト資源へのアクセスを明示的に許可します
    • 何も指定しなければ遮断されたままです

https://canonical.com/blog/introducing-workshop-sandboxed-development-environments

この「デフォルトは遮断、必要なものだけ明示的に許可」という考え方が、AIエージェントを安心して走らせたいニーズと相性が良さそうだなと思いました。

WorkshopはLXDを開発環境向けに使いやすくするツール

まず整理しておくと、Workshopの土台はLXDです。

DockerやDev Containerが基本的に1プロセスを動かす「アプリケーションコンテナ」なのに対し、LXDのシステムコンテナはinit(systemd)が動いて複数サービスを常駐でき、中身も通常のUbuntuとほぼ同等です。1台のマシンに近い感覚で扱えます。

では、Workshopは何をしてくれるのかと言うと、このLXDを「開発環境」として手軽に扱えるようにするレイヤーです。
具体的には以下のような特徴があります。

  • YAMLファイルで環境を定義し、workshop init/launch/refreshで構築・更新できる
  • 利用したいプログラミング言語やツールを「SDK」という再利用可能な部品としてSDK Storeから追加できる
  • ホスト資源(GPU・ssh-agent・ポートなど)へのアクセスを「インターフェース」で明示的に制御できる

LXD単体でも同じことはできますが、それを「YAMLファイル」で使いやすくしてくれているのがWorkshop、という位置づけと言えそうです。

前提条件

前述の通り、WorkshopはLXDに依存するため、動かせるのはLinux系の環境になります。
とはいえ対応範囲は意外と広く、Ubuntuに限らずsnapが使えるLinuxディストリビューションでサポートされていますし、WSL2でも利用できます。

本記事は以下の環境を前提にしています。

  • Ubuntu 24.04 LTSなど、snapが使えるLinux環境(他のsnap対応ディストリビューションやWSL2でも可)
  • LXD 6.8以降
  • Claude Codeを使える何らかのサブスクリプション契約をしていること

試してみる

セットアップ

細かいオプションは公式ドキュメントが詳しいので、あわせて参照してください。

https://ubuntu.com/workshop/docs/tutorial/part-1-get-started/

インストール

まずはLXDとWorkshop本体を入れます。

# LXD 6.8 以降をインストール (6/stable チャンネル)
sudo snap install --channel=6/stable lxd

# Workshop 本体をインストール
sudo snap install --classic workshop

インストール後、バージョン確認ができればOKです。

# バージョン確認
workshop --version
0.9.2

利用できるSDKを確認する

Workshopは「SDK」という単位で、言語ランタイムやAIツールを環境に追加します。
SDKの検索や情報表示は、workshopではなくsdkコマンドで行います

  • SDK Store から SDK を検索
sdk find claude-code
NAME          VERSION      PUBLISHER       SUMMARY
claude-code   2.1.179      Dmitry Lyfar    Claude Code CLI
hermes-agent  2026.5.29.2  Matias Piipari  Hermes Agent — self-improving AI agent from Nous Research
  • 特定 SDK のチャンネルや対応ベースを確認
sdk info claude-code
name:       claude-code
publisher:  Dmitry Lyfar (dlyfar)
license:    https://www.anthropic.com/legal/commercial-terms
website:    https://github.com/canonical/claude-code-sdk

This SDK provides the Claude Code CLI for AI-assisted coding within a
workshop. The agent is sandboxed in the workshop container. Credentials are
persisted between workshop updates.

CHANNELS
  CHANNEL           VERSION  BUILD       BASE  REV     SIZE
  latest/stable     2.1.179  2026-06-25  all    27  62.16MB
  latest/candidate  ↑                               
  latest/beta       ↑                               
  latest/edge       ↑

なお、目的のSDKが存在するか・正確な名前は、必ずsdk find <名前>で確認してください(例えばClaude Code用ならsdk find claude-code)。
本記事の設定例も、実行前に一度チェックしておくと安心です。

なおどんなSDKがあるかを一覧で眺めたいときは、GitHubのcanonical/reference-sdksにカタログがあるのでこちらを参照するのが良さそうです。

https://github.com/canonical/reference-sdks

Claude Codeのサンドボックスを立ち上げる

Claude Codeには確認なしで動く自動承認モードがあり、便利な反面、ホストでそのまま全権を渡すのは少し怖いところです。SDKにClaude Code(claude-code)が用意されているので、これを使ってみます。

まずはプロジェクトを用意します。

mkdir -p ~/claude-code-workshop && cd ~/claude-code-workshop
git init

workshop initで、claude-code SDK入りの定義を作成します。
環境の定義は、プロジェクト直下の.workshop/<名前>.yamlに置かれます。

workshop init dev --sdks claude-code/latest/stable --base ubuntu@24.04

生成される.workshop/dev.yamlはこんな形です。

.workshop/dev.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: claude-code
    channel: latest/stable

以下コマンドでWorkshopが定義を認識していることを確認できます。

workshop list
WORKSHOP  STATUS  NOTES
dev       Off     -
WARNING: There is 1 new warning. See "workshop warnings".

あとは起動するだけです。
初回はベースイメージとSDKのダウンロードが走ります。
(WARNINGが出ていますが、これは後で解説します)

  • 定義を読んで環境を構築・起動
workshop launch
"dev" launched
WARNING: There is 1 new warning. See "workshop warnings".
  • 起動後の状態を確認
workshop info
name:      dev
base:      ubuntu@24.04
project:   ~/claude-code-workshop
hostname:  dev.claude-code-workshop.wp
status:    ready
notes:     –
sdks:
  system:
    installed:  (2)
  claude-code:
    tracking:   latest/stable
    installed:  2.1.179  2026-06-25  (27)
    mounts:
      claude-config:
        host-source:      …/97c30ea5/dev/mount/claude-code/claude-config
        workshop-target:  /home/workshop/.claude
WARNING: There is 1 new warning. See "workshop warnings".
  • マシンに保存されているSDKボリュームの確認
sdk list
NAME         VERSION  REV      SIZE
claude-code  2.1.179   27  115.23MB
system       -          2   25.09kB
  • Claude Code が使えるか確認
workshop exec dev -- claude --version
2.1.179 (Claude Code)
WARNING: There is 1 new warning. See "workshop warnings".
  • .workshop.lockを.gitignoreに追加
echo ".workshop.lock" >> .gitignore

起動できたら、シェルに入って中を覗いてみます。

workshop shell
workshop@dev:/project$ pwd
/project

workshop@dev:/project$ whoami
workshop

workshop@dev:/project$ ls -la
total 18
drwxrwxr-x  4 workshop workshop 4096 Jun 28 20:03 .
drwxr-xr-x 22 root     root       26 Jun 28 20:06 ..
drwxrwxr-x  7 workshop workshop 4096 Jun 28 20:00 .git
drwxr-xr-x  2 workshop workshop 4096 Jun 28 20:01 .workshop
-rw-r--r--  1 workshop workshop    8 Jun 28 20:03 .workshop.lock

workshop@dev:/project$ ls -la /
total 25
drwxr-xr-x  22 root     root       26 Jun 28 20:06 .
drwxr-xr-x  22 root     root       26 Jun 28 20:06 ..
lrwxrwxrwx   1 root     root        7 Apr 22  2024 bin -> usr/bin
drwxr-xr-x   2 root     root        2 Feb 26  2024 bin.usr-is-merged
drwxr-xr-x   2 root     root        2 Jun 15 22:50 boot
drwxr-xr-x   9 root     root      540 Jun 28 20:06 dev
drwxr-xr-x 104 root     root      196 Jun 28 20:06 etc
drwxr-xr-x   4 root     root        4 Jun 28 20:06 home
lrwxrwxrwx   1 root     root        7 Apr 22  2024 lib -> usr/lib
drwxr-xr-x   2 root     root        2 Apr  8  2024 lib.usr-is-merged
lrwxrwxrwx   1 root     root        9 Apr 22  2024 lib64 -> usr/lib64
drwxr-xr-x   2 root     root        2 Jun 15 22:43 media
drwxr-xr-x   2 root     root        2 Jun 15 22:43 mnt
drwxr-xr-x   2 root     root        2 Jun 15 22:43 opt
dr-xr-xr-x 574 nobody   nogroup     0 Jun 28 20:06 proc
drwxrwxr-x   4 workshop workshop 4096 Jun 28 23:08 project
drwx------   3 root     root        5 Jun 15 22:46 root
drwxr-xr-x  20 root     root      640 Jun 28 20:06 run
lrwxrwxrwx   1 root     root        8 Apr 22  2024 sbin -> usr/sbin
drwxr-xr-x   2 root     root        2 Mar 31  2024 sbin.usr-is-merged
drwxr-xr-x   2 root     root        3 Jun 28 20:06 snap
drwxr-xr-x   2 root     root        2 Jun 15 22:43 srv
dr-xr-xr-x  13 nobody   nogroup     0 Jun 28 23:12 sys
drwxrwxrwt  11 root     root      220 Jun 28 23:04 tmp
drwxr-xr-x  12 root     root       12 Jun 15 22:43 usr
drwxr-xr-x  13 root     root       16 Jun 28 20:06 var

workshop@dev:/project$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 24.04.4 LTS
Release:	24.04
Codename:	noble

この実行結果から、次のことがわかります。

  • カレントディレクトリが/projectになっている、ホスト側のプロジェクトディレクトリがここに自動でマウントされている
  • 実行ユーザーはworkshopという非rootユーザー

ls -la /で見えている/は、コンテナ自身のOS一式です。ホストのファイルシステムとは完全に分離されており、/homeの中身もコンテナのworkshopユーザーのものだけで、ホストのホームディレクトリではありません。

ホスト側とつながっているのは、自動マウントされた/projectだけです。
そのため仮にコーディングエージェントが危険な操作を実行しても、被害はコンテナの中で済みます。

あとは任意の方法でログインすれば、Claude Codeが使えるようになります。
超簡単ですね。

claude login

補足:WARNINGについて

セットアップ時に出ていたWARNINGについて確認してみます。

workshop warnings

どうやら「ネットワーク通信が遮断されているかもしれない」という警告のようで、メッセージにあるとおり、原因はDockerと思われます。

last-occurrence:  today at 22:57 JST
warning: |
  firewall rules may be blocking network traffic on the workshopbr0 bridge: the FORWARD chain policy
  is set to DROP with no rules allowing traffic through the bridge. This is likely caused by Docker.
  To resolve, run: sudo nft insert rule ip filter DOCKER-USER iifname workshopbr0 accept \; sudo nft
  insert rule ip filter DOCKER-USER oifname workshopbr0 ct state related,established accept (see
  https://documentation.ubuntu.com/lxd/latest/howto/network_bridge_firewalld/)

DockerはnftablesのFORWARDチェーンのポリシーをDROPにするため、Workshop(LXD)が使うworkshopbr0ブリッジ経由の通信までブロックされ、コンテナの中から外部に出られなくなることがあるようです。

https://canonical.com/lxd/docs/latest/howto/network_bridge_firewalld/

対処は、警告に書かれているとおり、DOCKER-USERチェーンにworkshopbr0の通行を許可するルールを追加するだけです。

# workshopbr0 からの通信を許可
sudo nft insert rule ip filter DOCKER-USER iifname workshopbr0 accept

# workshopbr0 への戻りの通信(確立済み・関連)を許可
sudo nft insert rule ip filter DOCKER-USER oifname workshopbr0 ct state related,established accept

再度execコマンドを実行しても前述のWARNINGが出ないので、解消していそうです。

workshop exec dev -- claude --version
2.1.179 (Claude Code)

YAML定義をカスタマイズする

サンドボックスが立ち上がったら、あとは.workshop/dev.yamlを編集して環境を育てていきます。
ベースイメージを変える、SDKを足す、チャンネルを切り替える、といった調整はすべてこのファイルで宣言します。

たとえば、Pythonツールのuvを足してみます。

.workshop/dev.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: claude-code
    channel: latest/stable
  - name: uv

定義を変えたら、workshop refreshで環境に反映します。
launchと違ってrefreshは、途中で失敗しても直前の状態にロールバックして環境を壊さないようになっています。

workshop refresh

更新完了後、uvがインストールされていることが確認できます。

workshop exec dev -- uv --version
uv 0.11.24 (1e11c3925 2026-06-26 x86_64-unknown-linux-gnu)
WARNING: There is 1 new warning. See "workshop warnings".

ここまでにWorkshopが行った操作は、workshop changesで履歴として確認できます。

workshop changes
ID  STATUS  SPAWN                   READY                   SUMMARY
1   Done    yesterday at 20:04 JST  yesterday at 20:06 JST  Launch "dev" workshop
2   Done    yesterday at 20:08 JST  yesterday at 20:08 JST  Execute command "claude"
3   Done    yesterday at 22:57 JST  yesterday at 23:07 JST  Execute command "bash"
4   Done    yesterday at 23:07 JST  yesterday at 23:08 JST  Execute command "bash"
5   Done    yesterday at 23:10 JST  yesterday at 23:16 JST  Execute command "bash"
6   Done    yesterday at 23:17 JST  yesterday at 23:18 JST  Refresh "dev" workshop
7   Done    yesterday at 23:18 JST  yesterday at 23:18 JST  Execute command "uv"
8   Done    yesterday at 23:56 JST  yesterday at 23:56 JST  Execute command "curl"
9   Done    yesterday at 23:57 JST  yesterday at 23:57 JST  Refresh "dev" workshop
10  Done    yesterday at 23:58 JST  yesterday at 23:58 JST  Execute command "claude"

最初のlaunchから、claudebashの実行、uvを足したときのrefreshまで、これまでの操作が時系列で並んでいます。
1行がchangeという操作の単位で、STATUSDoneになっていれば正常に完了しています。
Workshopは変更をアトミックに適用し、失敗時は元の状態へ巻き戻すので、この履歴が「いつ何をして環境がどう変わったか」の記録になります。

個々の操作をさらに掘り下げたいときは、workshop tasks <ID>を使うと、その変更の中で実際に走った細かいタスク(ベースイメージのダウンロード、SDKの取得、フックの実行など)まで追えます。

workshop tasks 7
STATUS  DURATION  SUMMARY
Done       129ms  Exec command "uv"

Plug/Slotでホスト資源へのアクセスを制御する

Workshopの重要なセキュリティ機能の一つが、「インターフェース」の仕組みです。

これは、SDKが資源をslotとして公開し、それをplugとして消費する形で接続するというものです。
例えばカメラやGPUといったホスト側の機能は、systemというSDKを通じてslotとして公開されます。

  • plug
    • SDK側が要求する側(例: gpu, mount, ssh-agent, tunnel)
  • slot
    • 資源を提供する側(systemSDKやほかのSDKが提供)

https://ubuntu.com/workshop/docs/explanation/interfaces/concepts/
https://ubuntu.com/workshop/docs/explanation/interfaces/plugs-and-slots/

どのplug/slotを持つかはSDK側で定義されており、接続状態はコマンドで確認・変更します。

# 現在の接続状態を一覧
workshop connections
INTERFACE  PLUG                           SLOT              NOTES
mount      dev/claude-code:claude-config  dev/system:mount  -
mount      dev/uv:cache                   dev/system:mount  -

以下のコマンドで接続を有効化したり無効化したりできます。

# 接続 / 切断 (plug と slot を指定)
workshop connect dev/<sdk>:<plug> :<slot>
workshop disconnect dev/<sdk>:<plug>

ポイントは、すべてが自動でつながるわけではないことです。
さきほどのclaude-code:claude-config(認証情報のmount)のように起動時に自動接続されるものもあれば、ssh-agentのように明示的に接続しないと使えないものもあります。
デフォルトで全部入りにしない、という安全に配慮した設計になっています。

ssh-agentでGithubの認証を通す

Claude Codeを使うならGitHubが欠かせないので、ssh-agentを足してみます。

https://ubuntu.com/workshop/docs/explanation/interfaces/ssh-interface/

まず、claude-code SDKにssh-agent plugを足します。

.workshop/dev.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: claude-code
    channel: latest/stable
    plugs:
      ssh-agent:
        interface: ssh-agent
  - name: uv

定義を反映しても、ssh-agentは自動では接続されません。workshop connectで手動接続します。

workshop refresh
workshop connect dev/claude-code:ssh-agent

接続できたかはworkshop connections --allで確認できます。ssh-agentの行がmanual付きで出ていればOKです。

workshop connections --all
INTERFACE  PLUG                           SLOT                  NOTES
mount      -                              dev/uv:venv           -
mount      dev/claude-code:claude-config  dev/system:mount      -
mount      dev/uv:cache                   dev/system:mount      -
ssh-agent  dev/claude-code:ssh-agent      dev/system:ssh-agent  manual

接続すると、workshopユーザーの$SSH_AUTH_SOCKにホストのSSHエージェントへ橋渡しするソケットが設定されます。コンテナの中から確認してみます。

workshop shell
echo $SSH_AUTH_SOCK
/var/lib/workshop/run/ssh-agent.sock

ssh-add -l
(ホスト側でロード済みの鍵が一覧表示される)

鍵が一覧表示されれば、コンテナの中からも同じエージェント経由でgit pushなどができます。
秘密鍵そのものはコンテナにコピーされず、エージェント越しに使うだけなので、コンテナ内に鍵を置かずに済むのがポイントです。
不要になったらworkshop disconnect dev/claude-code:ssh-agentで切断できます。

またGPUを使いたい場合も仕組みは同じです。
たとえばollamaSDKはgpu plugを持っていて、これはsystem:gpuへ自動接続されるので、対応チャンネル(cuda/stableなど)を選ぶだけでGPUが使えます。

https://ubuntu.com/workshop/docs/tutorial/part-2-work-with-interfaces/
https://ubuntu.com/workshop/docs/explanation/interfaces/gpu-interface/

VS Codeから接続できるようにする

コマンドラインだけでなく、使い慣れたVS Codeからサンドボックスにつないで開発することもできます。あらかじめVS Code側にRemote Development拡張(Remote-SSH)を入れておき、定義にvscode-remote SDKを足すと、Remote-SSH越しにコンテナの/projectを開けるようになります。

https://ubuntu.com/workshop/docs/how-to/develop-with-workshops/connect-vscode/

定義にvscode-remote SDKを追加します。

.workshop/dev.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: claude-code
    channel: latest/stable
    plugs:
      ssh-agent:
        interface: ssh-agent
  - name: uv
  - name: vscode-remote

あとは更新してタスクを見てみると、

workshop refresh
workshop tasks

以下のように接続用のアドレスとガイダンスが表示されます。

2026-06-29T00:51:58+09:00 INFO VS Code → Open Remote Window → Connect to host → workshop@XX.XX.XX.XX
or from the terminal,
code --folder-uri vscode-remote://ssh-remote+workshop@XX.XX.XX.XX/project

2種類ありますが、どちらでも繋げるので好きな方で繋いでください。

  • VS Codeの画面コマンドパレットで「Open Remote Window」→「Connect to Host」を選び、表示されたアドレスを指定する
  • ターミナルでcode --folder-uri vscode-remote://ssh-remote+workshop@XX.XX.XX.XX/project を実行する

接続すると、VS Codeのウィンドウがコンテナ側につながり、/projectをそのまま開けます。
エディタもターミナルも拡張機能もコンテナの中で動くので、ここからClaude Codeを起動すれば、いつものエディタの中でサンドボックス化されたエージェントを使えます。

スクリーンショット 2026-06-29 1.06.21

所感

Workshopが向いていそうなケース

  • LinuxやWSL2上で、Claude Codeなどのエージェントを自動承認で気軽に回したい
    • workshop initlaunchだけで、Claude Code入りの環境がすぐ立ち上がって手軽でした
    • ホスト資源はworkshop connectなどで明示的につながないと使えないので比較的安全そう
    • 認証情報などの永続化はSDK側で指定されていて、利用する側はマウント設定を気にせず済みます
  • GPUを使ったML/LLMの実験を、ホストを汚さずに始めたい(CUDA/ROCm)
    • 複数プロセスを常駐させる開発環境には、システムコンテナのLXDを土台にしているのが合っていると感じました
    • 取得済みのSDKはキャッシュされるためか、workshop refreshでの作り直しも早かった気がします

Workshopが向いていなさそうなケース

  • いろいろなOSで同じように使いたい
    • WorkshopはLinux(やWSL2)が前提なので、macOSなどでも広く使いたいなら、mac/Windowsでも動くDocker / Dev Containerのほうが汎用性で勝ります(Workshopをmacで使う場合はVMやリモートのLinux環境越しになります)
  • とにかく最軽量で隔離したい
    • 1台のシステムコンテナを立てるぶん、プロセス単位で隔離する手段よりは重めです
  • SDKが用意されていないツールも使いたい
    • SDKのラインナップはまだ少なめで、無いツールは自分でSDKを定義することになります(作り方はチュートリアルのsketch SDK・SDKcraftの章にあります)
    • sdk infoで分かるのは概要やpublisher程度で、信頼してよいSDKか判断に迷う場面がありました

さいごに

以上、WorkshopでClaude Codeのサンドボックス環境を作ってみました。

触ってみた感想として、WorkshopはDocker / Dev Containerと比べると、「安全に開発するマシンを1台まるごと立てる」ためのツールだと感じました。
そのためAIエージェントを隔離して走らせる用途とは特に相性が良さそうで、数コマンドでClaude Code入りの環境が立ち上がる手軽さも魅力でしょう。

一方で、その手軽さはSDKが用意されている範囲の話で、SDKに無いツールを足したいときは自分でSDKを作る必要があり、ここはちょっと面倒だなと感じました。
リリースされて日が浅いため、SDKのラインナップやエコシステムが充実してくればもっと使いやすくなりそうなので、今後に期待していきたいです。


Claudeならクラスメソッドにお任せください

クラスメソッドは、Anthropic社とリセラー契約を締結しています。各種製品ガイドから、業種別の活用法、フェーズごとのお悩み解決などサービス支援ページにまとめております。まずはご覧いただき、お気軽にご相談ください。

サービス詳細を見る

この記事をシェアする

関連記事