1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

この記事のポイント

  • Microsoft Execution ContainersをSDKでハンズオンしているよ
  • ハンズオンを通して実装を深堀りしているよ

はじめに

この記事にはMicrosoft Build 2026で発表されたMicrosoft Execution Containers(以下、MXC)について書かれています。登場したばかりのツールということもあり、今後のアップデート次第では、このブログに書かれているハンズオンが機能しなくなる可能性もあります。

前回はMXCの中でもNative Binaryに関する説明でしたが、今回はSDKに関する説明になります。

Microsoft Execution Containers(MXC)とは

ハンズオン

では、実際にハンズオンしていきましょう。今回はmacOS上でMXCを実行します。

macOSの環境

  • macOS
    • Tahoe 26.5.1
  • Visual Studio Code
    • Version: 1.124.0
  • node --version
    • v20.19.5
  • MXC SDK
    • v0.6.1

前回は実行するためにRust/Cargoをインストールしていました。今回は不要ですが、参考程度に前提を共有しておきます。

  • cargo
    • 1.96.0 (30a34c682 2026-05-25)

ハンズオンのおおまかな流れ

  • Setup
  • npm run devの実行
    • さまざまなスクリプトを試します

Setup

まずはリポジトリをクローンします。

GitHub CLIの場合
gh repo clone ymd65536/MXCSDKDemo && cd MXCSDKDemo
git cloneの場合
git clone https://github.com/ymd65536/MXCSDKDemo.git && cd MXCSDKDemo

Node.jsをnvmでインストールします。インストール手順

最後にパッケージをインストールします。

npm install

これでセットアップは完了です。

今回やること

5つの使い方を例にSDKの特徴をチェックしていきます。

  • 最初の一歩
  • pythonのHello World
  • ファイルシステムを試す
  • 環境変数を追加/参照する
  • ネットワーク機能を試す

最初は基本となるサンプルコードの実行、それからサンドボックス内でPythonを実行、ファイル・システム、環境変数、ネットワークの機能を確認します。

最初の一歩

まずはSDKのREADME.mdにあるソースコードを見てみましょう。
pythonで実行するとcommand not foundになってしまうためpython3に修正しています。

このスクリプトを実行してみましょう。まずはsamples/firstに保存されているスクリプトをコピーします。

# samples/first
cp ./samples/first/index.ts ./src

npm run devで実行します。

npm run dev

実行結果

Spawning sandbox with config: {
  "version": "0.7.0-alpha",
  "containerId": "21d8081e",
  "lifecycle": {
    "destroyOnExit": true,
    "preservePolicy": false
  },
  "process": {
    "commandLine": "python3 --version;which python3;uname -m",
    "timeout": 30000
  },
  "filesystem": {
    "readwritePaths": [
      "/var/folders/nk/26yk2_3d1dd382hvzshrs_3h0000gn/T/"
    ],
    "readonlyPaths": [
      ~長いので省略~
    ],
    "deniedPaths": []
  },
  "ui": {
    "disable": true,
    "clipboard": "none",
    "injection": false
  },
  "network": {
    "defaultPolicy": "block"
  },
  "containment": "seatbelt",
  "seatbelt": {}
}
Python 3.11.15
/opt/homebrew/opt/python@3.11/libexec/bin/python3
arm64
exit: 0

このPythonバージョンはホストOSのPythonバージョンと一致するはずです。確認コマンドは以下のとおりです。

python --version
# Python 3.11.15

ここでNative Binaryを触ったときのことを思い出すとSDKではプラットフォームを意識することがないという点が挙げられます。

ソースコードを追ってみるとgetPlatformSupportというファンクションを使って自動判定していることがわかります。順番に追ってくとまずはgetPlatformSupportPlatformSupportを返します。

このとき2つのPlatformSupportを返すようです。最初にcomputeSupportが実行されるようなのでこの実装を見てみましょう。※長いので一部省略

252行目から301行目にかけてプラットフォームの判定があります。これがまた奇妙な話なんですが、筆者としては先にWin32を判定して他のプラットフォームを判定しているかと思いきや結構変わった順番でした。※なんとWindowsの判定は最後!!

darwin => linux => win32という順番でプラットフォームを判定するようになっていました。

pythonのHello World

つぎにサンドボックス上でPythonを実行してみましょう。同様にスクリプトをコピーします。

cp ./samples/python_hello_world/index.ts ./src

npm run devで実行します。

npm run dev
Mon Jun 15 23:43:43 JST 2026
total 8
drwxr-xr-x   3 501  staff   96 Jun 15 21:04 .
drwxr-xr-x@ 18 501  staff  576 Jun 15 23:24 ..
-rw-r--r--   1 501  staff   22 Jun 15 21:04 hello_world.py
Hello, World
Mon Jun 15 23:43:43 JST 2026
exit: 0

これでリポジトリにあるHello WorldのPythonスクリプトが動きました。

ファイルシステムを試す

つぎにサンドボックス上のファイルシステムを操作してみましょう。同様にスクリプトをコピーします。

cp ./samples/filesystem/index.ts ./src

npm run devで実行します。

npm run dev

実行結果ですが、今回は以下のコマンドを実行しているのでリポジトリのルートにsample.logというファイルができているはずです。

date;echo "# sample file ${userHome}" > sample.log;date

ファイルシステムの操作は3つの設定項目があり、許可/禁止どちらにしてもパスが格納されたリストを共有することでファイルシステムへのアクセスを制御できます。

  • Read-write access
    • 読み込み書き込み可
  • Read-only access
    • 読み込み可
  • Blocked paths
    • Sandboxシステムでブロック

環境変数を追加/参照する

次にサンドボックス上に環境変数を追加しましょう。Pythonが実行できるのでホストOS上の環境変数を共有しているように見えますが、起動されたサンドボックスは環境変数を持っていません。

どういうことなのか確認してみましょう。同様にスクリプトをコピーします。

cp ./samples/environ/index.ts ./src

npm run devで実行します。

npm run dev

実行結果

Mon Jun 15 23:56:44 JST 2026
MY_VAR=hello world
PWD=/Users/{ユーザー名}/Desktop/MXCSDKDemo
SHLVL=1
_=/usr/bin/env

hello world
Mon Jun 15 23:56:44 JST 2026
exit: 0

実行結果を見てみるとデフォルトの環境変数と追加した環境変数しかありません。これはつまり、サンドボックスが本当に独立した環境で動作していることを暗に示唆しています。

MY_VAR=hello world
PWD=/Users/{ユーザー名}/Desktop/MXCSDKDemo
SHLVL=1
_=/usr/bin/env

なお、ソースコード内ではconfig.process!.env = ["MY_VAR=hello world"];という1行で環境変数を定義できています。

ネットワーク機能を試す

最後にサンドボックスのネットワーク制御を試してみましょう。同様にスクリプトをコピーします。

cp ./samples/network/index.ts ./src

今回はローカルホストに簡易的なサーバーを構築して試します。ターミナルを新しく起動して以下のコマンドを実行します。

cd web && npm start

実行するとlocalhost:3000にサーバーが起動します。
ちなみに起動したサーバーの仕様は以下のとおりです。

path レスポンス
/ {"message":"Hello from local Node.js JSON server","ok":true,"timestamp":"..."}
/health {"status":"ok"}
/not-found {"error":"Not Found","path":"/not-found"}

もとのターミナルでnpm run devを実行します。

npm run dev

実行結果

Tue Jun 16 00:09:01 JST 2026
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:3000...
* Connected to localhost (::1) port 3000
> GET /health HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/8.7.1
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Mon, 15 Jun 2026 15:09:01 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Transfer-Encoding: chunked
< 
* Connection #0 to host localhost left intact
{"status":"ok"}
Tue Jun 16 00:09:01 JST 2026
exit: 0

HTTP/1.1 200 OK{"status":"ok"}というレスポンスが返ってくればOKです。

ソースコードで今回注目すべきところはもちろんnetworkという項目です。

const config = createConfigFromPolicy({
  version: '0.7.0-alpha',
  // サンドボックスからみて外向けの通信を有効にする設定
  network: { allowOutbound: true },
});

なお、createConfigFromPolicynetworkNetworkConfigによって定義されています。

ちなみにスキーマではallowOutboundという設定がないことに注意が必要かもしれません。

参考:mxc-config.schema.0.7.0-alpha.json#L120-L191

ハンズオンを通してSDKを知る

ハンズオンは以上です。ここからはREADME.mdをベースにMXCのSDKがどんなものか見ていきます。参考:README.md

MXC(SDK)特徴

SDKを触ってみて感じた特徴をまとめようと思います。

  • Native Binaryのときより直感的でわかりやすく実装しやすい
  • 実行はマイクロVM上だが、参照するプログラムはホストOS側のプログラムであり、環境変数も異なる
  • ファイルシステムの設定はわりとアバウトでも許可できてしまう
    • /opt/homebrewという設定ではhomebrewよりしたのディレクトリは全許可判定
  • ネットワークの設定ではホスト/IP/ポート番号レベルでブロックできる
    • SDKの設定項目とNative Binaryの設定項目はひょっとすると名前が違うのでは?と思われるところがある
  • ファイルシステムの設定には許可と禁止があるが、同じパスを設定に入れていると禁止が優先される

そして、やはりTypeScriptで実行できる点は魅力的です。というのもたとえば、Next.jsやReactなどから実行が可能であることです。APIとして作成すれば、オレオレサーバーレスも可能になるという点は刺さるポイントです。

ただし、ファイルシステムやネットワークの設定を誤るとホストOSを壊す可能性もあります。
(例:ファイルシステムで許可している範囲が広い、許可していないネットワークへアクセスできるなど)

まとめ

今回はMicrosoft Execution ContainersをSDKから触ってみました。
TypeScript製のSDKでマイクロVMを手軽に構築できる点は魅了的です。まだ可能性を探りきれていないですが、高速で任意のコマンドを実行するような用途ではとても役に立つものでした。

一方で前回のNative Binaryとどのように棲み分けて使ったら良いかという点やTypeScriptで書いた設定をjsonに落としてNative Binaryで使うといったことも考えられますが、試したことがないのでもしかすると難儀するかもしれません。

※createConfigFromPolicyで作成したconfigをJSON.stringifyで変換してconsole.logで表示することによりSDKで設定ファイルの生成が可能であることは検証できました。

まだ発展途上ですが、とても夢のあるSDKでした。今後もアップデートを見ていきたいと思います。

参考

おまけ:トラブルシューティング

dyld[35322]: Library not loaded

次のようにdyld[35322]: Library not loadedというメッセージの出力がされる場合はSandboxの設定で読み込み先のパスがブロックされている可能性があります。

dyld[35322]: Library not loaded: /opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/Python
  Referenced from: <393B5A9B-A55D-34F9-8B71-DA53A86CB8FB> /opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/bin/python3.13
  Reason: tried: '/opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/Python' (file system sandbox blocked open()), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/Python' (no such file), '/opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/Python' (file system sandbox blocked open())
/bin/sh: line 1: 35322 Abort trap: 6           python3 --version

解決方法としてはcreateConfigFromPolicyにて生成されるfilesystemプロパティでreadonlyPathsを追加してください。今回はhomebrewのパスが原因ですので/opt/homebrew/Cellar/python@3.13/3.13.13_1/Frameworks/Python.framework/Versions/3.13/Pythonを追加します。
なお、WindowsやLinuxでも同様にパスが追加されていないとブロックされます。

import {
  spawnSandboxFromConfig, createConfigFromPolicy,
  getAvailableToolsPolicy, getTemporaryFilesPolicy,
  getPlatformSupport,
} from '@microsoft/mxc-sdk';

if (!getPlatformSupport().isSupported) {
  throw new Error('MXC not available on this host');
}

const tools = getAvailableToolsPolicy(process.env);
const temp  = getTemporaryFilesPolicy();

// ここでdirectories変数を作成し、homebrewのパスを追加する
const directories = tools.readonlyPaths;
directories.push('/opt/homebrew/Cellar/python@3.11/3.11.15_3/Frameworks/Python.framework/Versions/3.11/Python');

//あるいはhomebrewを丸ごと追加
// directories.push('/opt/homebrew/');

// directoriesをreadonlyPathsに追加する
const config = createConfigFromPolicy({
  version: '0.7.0-alpha',
  filesystem: {
    readonlyPaths:  directories,
    readwritePaths: temp.readwritePaths,
  },
  network: { allowOutbound: false },
  timeoutMs: 30_000,
});
config.process!.commandLine = 'python3 --version;which python3;uname -m';

console.log('Spawning sandbox with config:', JSON.stringify(config, null, 2));

const child = spawnSandboxFromConfig(config, { usePty: false });
child.stdout!.on('data', (d) => process.stdout.write(d));
child.on('close', (code) => console.log('exit:', code));

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?