container-useやってみた

ロゴが可愛いと評判のcontainer-useをやってみました。

https://x.com/solomonstre/status/1931216224047997096

GitHubリポジトリはこちら

https://github.com/dagger/container-use


## container-useとは

READMEより

> Container Use lets each of your coding agents have their own containerized environment. Go from babysitting one agent at a time to enabling multiple agents to work safely and independently with your preferred stack.

コンテナの使用により、コーディングエージェントごとにコンテナ化された環境を持つことができます。エージェントを個別に管理するのではなく、複数のエージェントが好みのスタックを使用して安全かつ独立して作業できるようにすることができます。

**MCPサーバーとして利用が可能です** ので、Amazon Q Developer CLIと組み合わせて使ってみました。
Claude Codeとかでも、おそらく同じような感じになると思います。

## container-useバイナリのインストール

Dockerがインストールされている必要があります。

```shell
git clone https://github.com/dagger/container-use.git
cd container-use
```

ビルドしてインストールします

```shell
make install
```

:::note
ビルドはコンテナ内で行われているようです。

```sh:build.sh
#!/usr/bin/env bash
set -uoe pipefail

: ${TARGETPLATFORM:=local}
which docker >/dev/null || ( echo "Please follow instructions to install Docker at https://docs.docker.com/get-started/get-docker/"; exit 1 )
docker build --platform "$TARGETPLATFORM" -o . .
ls cu
```
:::


## 環境のセットアップ

Ubuntu（WSL上）で試しました。

container-useの動作にはGitリポジトリが必要です。

```shell
mkdir work
cd work

git init
echo "Hello" > README.md
git add .
git commit -m "initial"
```

続いて、MCPサーバーの設定です。workディレクトリ内で`q`を起動するので、`work/.amazonq/mcp.json`を作成し、設定を記述します。

```json:work/.amazonq/mcp.json
{
    "mcpServers": {
        "container-use": {
            "command": "cu",
            "args": [
                "stdio"
            ]
        }
    }
}
```

そして、AmazonQ.mdを作成します。記述内容はcontainer-useが用意してくれているルールです。

また、Amazon Q Developer CLIの既存のファイル書き込みなどが誤動作することがあったので、それを防ぐ記述を追加しています。

:::note
Claude Codeの場合は`CLAUDE.md`に記述します
:::

```text:work/AmazonQ.md
ALWAYS use ONLY Environments for ANY and ALL file, code, or shell operations—NO EXCEPTIONS—even for simple or generic requests.

DO NOT install or use the git cli with the environment_run_cmd tool. All environment tools will handle git operations for you. Changing ".git" yourself will compromise the integrity of your environment.

You MUST inform the user how to view your work using `git checkout <branch_name>`. Failure to do this will make your work inaccessible to others.

---

以下のツールは使用禁止です。使ってはいけません。

- execute_bash
- fs_read
- fs_write
- report_issue
- use_aws

使っていいのは以下のツールのみです。

- container_use___environment_checkpoint
- container_use___environment_file_delete
- container_use___environment_file_list
- container_use___environment_file_read
- container_use___environment_file_write
- container_use___environment_open
- container_use___environment_run_cmd
- container_use___environment_update
```

これで準備環境です。

## 動作確認

それでは、`q chat`でAmazon Q Developer CLIを起動します。

:::note
Claude Sonnet 4使えるよ
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/86503120-4adb-4730-948c-60deafa2f80d.png)

READMEに記載のサンプルを試します。

> create a simple flask app

ちょっと長いですが、動作のログがこちらです。

<details><summary>動作のログ</summary>

```
> create a simple flask app
```
```
I'll help you create a simple Flask application. First, let's set up a development environment with Python and Flask, then create the necessary files.

Let's start by creating a Python environment:


🛠️  Using tool: environment_open from mcp server container_use
 ⋮ 
 ● Running environment_open with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "explanation": "Creating a Python environment for Flask application development",
 ⋮      "name": "flask-app",
 ⋮      "source": "/workspaces/workspace/container-use/work"
 ⋮    },
 ⋮    "name": "environment_open"
 ⋮  }
Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:

> t

 ⋮ 
 ● Completed in 3.43s
```
```
Now let's update the environment with Python and Flask:


🛠️  Using tool: environment_update from mcp server container_use
 ⋮ 
 ● Running environment_update with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "base_image": "python:3.11-slim",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Setting up Python environment with Flask for web application development",
 ⋮      "instructions": "Python Flask development environment with Flask installed. Use 'python app.py' to run the Flask application. The app will be available on port 5000.",
 ⋮      "secrets": [],
 ⋮      "setup_commands": [
 ⋮        "pip install flask"
 ⋮      ]
 ⋮    },
 ⋮    "name": "environment_update"
 ⋮  }
Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:

> t

 ⋮ 
 ● Completed in 10.287s
```
```
Now let's create a simple Flask application:


🛠️  Using tool: environment_file_write from mcp server container_use
 ⋮ 
 ● Running environment_file_write with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "contents": "from flask import Flask, render_template, jsonify\n\n# Create Flask application instance\napp = Flask(__name__)\n\n# Home route\n@app.route('/')\ndef home():\n    return render_template('index.html')\n\n# About route\n@app.route('/about')\ndef about():\n    return render_template('about.html')\n\n# API route that returns JSON\n@app.route('/api/hello')\ndef api_hello():\n    return jsonify({\n        'message': 'Hello from Flask API!',\n        'status': 'success'\n    })\n\n# Route with parameter\n@app.route('/user/<name>')\ndef user_profile(name):\n    return f'<h1>Welcome, {name}!</h1>'\n\nif __name__ == '__main__':\n    # Run the app in debug mode\n    app.run(debug=True, host='0.0.0.0', port=5000)",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating the main Flask application file with basic routes",
 ⋮      "target_file": "app.py"
 ⋮    },
 ⋮    "name": "environment_file_write"
 ⋮  }
Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:

> t

 ⋮ 
 ● Completed in 0.357s
```
```
Let's create a templates directory and add HTML templates:


🛠️  Using tool: environment_run_cmd from mcp server container_use
 ⋮ 
 ● Running environment_run_cmd with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "command": "mkdir -p templates",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating templates directory for HTML files"
 ⋮    },
 ⋮    "name": "environment_run_cmd"
 ⋮  }
Allow this action? Use 't' to trust (always allow) this tool for the session. [y/n/t]:

> t

 ⋮ 
 ● Completed in 1.118s
```
```
🛠️  Using tool: environment_file_write (trusted) from mcp server container_use
 ⋮ 
 ● Running environment_file_write with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "contents": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>{% block title %}Flask App{% endblock %}</title>\n    <style>\n        body {\n            font-family: Arial, sans-serif;\n            max-width: 800px;\n            margin: 0 auto;\n            padding: 20px;\n            background-color: #f5f5f5;\n        }\n        .container {\n            background-color: white;\n            padding: 30px;\n            border-radius: 8px;\n            box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n        }\n        nav {\n            margin-bottom: 30px;\n        }\n        nav a {\n            margin-right: 20px;\n            text-decoration: none;\n            color: #007bff;\n            font-weight: bold;\n        }\n        nav a:hover {\n            text-decoration: underline;\n        }\n        h1 {\n            color: #333;\n            border-bottom: 2px solid #007bff;\n            padding-bottom: 10px;\n        }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <nav>\n            <a href=\"/\">Home</a>\n            <a href=\"/about\">About</a>\n            <a href=\"/api/hello\">API</a>\n        </nav>\n        {% block content %}{% endblock %}\n    </div>\n</body>\n</html>",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating base HTML template with common structure",
 ⋮      "target_file": "templates/base.html"
 ⋮    },
 ⋮    "name": "environment_file_write"
 ⋮  }
 ⋮ 
 ● Completed in 0.667s
```
```
🛠️  Using tool: environment_file_write (trusted) from mcp server container_use
 ⋮ 
 ● Running environment_file_write with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "contents": "{% extends \"base.html\" %}\n\n{% block title %}Home - Flask App{% endblock %}\n\n{% block content %}\n<h1>Welcome to Flask!</h1>\n<p>This is a simple Flask application with the following features:</p>\n<ul>\n    <li><strong>Home page</strong> - You are here!</li>\n    <li><strong>About page</strong> - Learn more about this app</li>\n    <li><strong>API endpoint</strong> - Returns JSON data</li>\n    <li><strong>Dynamic routes</strong> - Try visiting <code>/user/yourname</code></li>\n</ul>\n\n<h2>Quick Links</h2>\n<p>\n    <a href=\"/about\">Visit About Page</a> | \n    <a href=\"/api/hello\">Try API Endpoint</a> | \n    <a href=\"/user/Flask\">User Profile Example</a>\n</p>\n\n<h2>Getting Started</h2>\n<p>This Flask app demonstrates basic routing, templating, and API endpoints. \n   You can extend it by adding more routes, database integration, or additional features.</p>\n{% endblock %}",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating home page template",
 ⋮      "target_file": "templates/index.html"
 ⋮    },
 ⋮    "name": "environment_file_write"
 ⋮  }
 ⋮ 
 ● Completed in 0.676s
```
```
🛠️  Using tool: environment_file_write (trusted) from mcp server container_use
 ⋮ 
 ● Running environment_file_write with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "contents": "{% extends \"base.html\" %}\n\n{% block title %}About - Flask App{% endblock %}\n\n{% block content %}\n<h1>About This Flask App</h1>\n<p>This is a simple Flask web application that demonstrates:</p>\n\n<h2>Features</h2>\n<ul>\n    <li><strong>Template Inheritance</strong> - Using Jinja2 templates with base template</li>\n    <li><strong>Static Routes</strong> - Home and About pages</li>\n    <li><strong>Dynamic Routes</strong> - User profile pages with URL parameters</li>\n    <li><strong>JSON API</strong> - RESTful endpoint returning JSON data</li>\n    <li><strong>CSS Styling</strong> - Basic responsive design</li>\n</ul>\n\n<h2>Technology Stack</h2>\n<ul>\n    <li>Python 3.11</li>\n    <li>Flask web framework</li>\n    <li>Jinja2 templating engine</li>\n    <li>HTML5 & CSS3</li>\n</ul>\n\n<h2>File Structure</h2>\n<pre>\nflask-app/\n├── app.py              # Main Flask application\n├── templates/          # HTML templates\n│   ├── base.html      # Base template\n│   ├── index.html     # Home page\n│   └── about.html     # About page\n└── requirements.txt   # Python dependencies\n</pre>\n\n<p><a href=\"/\">← Back to Home</a></p>\n{% endblock %}",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating about page template",
 ⋮      "target_file": "templates/about.html"
 ⋮    },
 ⋮    "name": "environment_file_write"
 ⋮  }
 ⋮ 
 ● Completed in 0.389s
```
```
Let's also create a requirements.txt file:


🛠️  Using tool: environment_file_write (trusted) from mcp server container_use
 ⋮ 
 ● Running environment_file_write with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "contents": "Flask==2.3.3\nWerkzeug==2.3.7\nJinja2==3.1.2",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Creating requirements file for Python dependencies",
 ⋮      "target_file": "requirements.txt"
 ⋮    },
 ⋮    "name": "environment_file_write"
 ⋮  }
 ⋮ 
 ● Completed in 0.439s
```
```
Now let's run the Flask application:


🛠️  Using tool: environment_run_cmd (trusted) from mcp server container_use
 ⋮ 
 ● Running environment_run_cmd with the param:
 ⋮  {
 ⋮    "arguments": {
 ⋮      "background": true,
 ⋮      "command": "python app.py",
 ⋮      "environment_id": "flask-app/touching-collie",
 ⋮      "explanation": "Starting the Flask development server",
 ⋮      "ports": [
 ⋮        5000
 ⋮      ]
 ⋮    },
 ⋮    "name": "environment_run_cmd"
 ⋮  }
 ⋮ 
 ● Completed in 0.893s
```
```
Perfect! I've created a simple Flask application for you. Here's what I've built:

## Flask App Structure

The application includes:

1. Main Application (app.py):
   • Home route (/) - displays the main page
   • About route (/about) - shows information about the app
   • API route (/api/hello) - returns JSON data
   • Dynamic route (/user/<name>) - personalized user pages

2. HTML Templates:
   • base.html - base template with navigation and styling
   • index.html - home page with app overview
   • about.html - detailed information about the app

3. Dependencies (requirements.txt) - lists Flask and related packages

## Features

• Template inheritance using Jinja2
• Responsive CSS styling
• JSON API endpoint
• Dynamic URL routing
• Navigation between pages

## Access Your App

Your Flask application is now running and accessible at:
• **External URL**: http://127.0.0.1:5669

You can visit these endpoints:
• / - Home page
• /about - About page  
• /api/hello - JSON API endpoint
• /user/yourname - Dynamic user profile (replace "yourname" with any name)

## View Your Code

To view and work with your Flask application code, use:
bash
git checkout flask-app/touching-collie


The app is running in debug mode, so any changes you make to the code will automatically reload the server. You can extend this basic Flask app by adding more 
routes, database integration, forms, or additional features as needed!
```

</details>

なにか作ってくれまして、`http://localhost:5669/`にアクセスするとWebアプリが出来上がってました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/76369b4f-e8a1-47f8-90c2-e8c69305f6de.png)

## で？なんなの？

Claude Codeなどをすでに使ってる方は、「で？なにが違うの？」と思ったと思います。

違うんです。ほら、ソースが存在しません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/3cfdfec1-fb7f-453d-b9db-5842f6684f50.png)

:::note
ホラーではありません（笑）
:::

Flaskはいずこへ。。。？

実は、Gitの中にいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/57fef04b-1462-4562-8da1-43cfded1c8b4.png)

`master`ブランチがこれまでの手順でinitしたブランチで、`flask-app/touching-collie`というブランチは私が作ったものではありません。

:::note
どこにあるかわかりませんがリモートブランチまであります。（どいうこと。。？？）
:::


`flask-app/touching-collie`ブランチに切り替えると履歴が確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/818a8d60-ae82-433d-8d9a-0e464ce81ad8.png)

リモートブランチからプルすることで、無事ソースに出会うことができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/5262954a-0f17-4aca-88f5-0630f74fcc95.png)


これがcontainer-useなんですね。ローカルに影響を与えずソースコード生成と動作確認ができます。

:::note
なんか、未来的
:::