【Docker】で【Browser use】を使う

# 概要

便利なBrowser Useですが、Dockerで動かすときは設定が大変です（主にPlaywrightをインストールするところが）。

筆者はBrowser Useを使うためのplaywrightのインストールで結構躓きました。



## この記事で扱うこと
- ①Dockerを使って
- ②Ubuntu22.04でPython実行環境を構築し、
- ③Browser Useを利用する。

# ①②③を作る

大きく2ステップで説明します。

1. Dockerfileとdocker-compose.yamlを作成する。
2. browser-useのためのpythonファイルを作成する。


## 1. Dockerfileとdocker-compose.yamlを作成する

### docker-compose.yaml

```yaml:docker-compose.yaml
services:
  ubuntu:
    container_name: ubuntu_server
    build:
        context: .
        dockerfile: Dockerfile
    volumes:
      - ./:/app
    tty: true
```

### Dockerfile
```Dockerfile:Dockerfile
# ベースイメージとしてUbuntu 22.04を指定
FROM ubuntu:22.04

# タイムゾーン設定を自動化するための環境変数を設定
ENV DEBIAN_FRONTEND=noninteractive
# システムのロケールを設定
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    wget \
    curl \
    git \
    make \
    unzip \
    build-essential \
    zlib1g-dev \
    libssl-dev \
    libbz2-dev \
    libreadline-dev \
    libsqlite3-dev \
    llvm \
    libncurses5-dev \
    libncursesw5-dev \
    xz-utils \
    tk-dev \
    libffi-dev \
    liblzma-dev \
    tzdata \
    ca-certificates \
    libnss3 \
    libnspr4 \
    libdbus-1-3 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libxdamage1 \
    libgbm1 \
    libxkbcommon0 \
    libpango-1.0-0 \
    libcairo2 \
    libasound2 \
    libatspi2.0-0 \
    && apt-get clean

# CA証明書を更新
RUN update-ca-certificates

# pyenvのインストール
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# pyenvを使用するための環境変数を設定
ENV PYENV_ROOT="/root/.pyenv"
ENV PATH="$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"

# Python 3.12のインストール
RUN pyenv install 3.12.0 && pyenv global 3.12.0

# PIPのアップグレードとPlaywrightのインストール
RUN pip install --no-cache-dir --upgrade pip && pip install playwright && playwright install

# Playwright以外ライブラリをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 作業ディレクトリの設定
WORKDIR /app
```

### 解説

```dockerfile
# ベースイメージとしてUbuntu 22.04を指定
FROM ubuntu:22.04

# タイムゾーン設定を自動化するための環境変数を設定
ENV DEBIAN_FRONTEND=noninteractive
# システムのロケールを設定
ENV LANG=C.UTF-8
ENV TZ=Asia/Tokyo
```
Ubuntuの22.04をインストールするための設定です。
`ENV DEBIAN_FRONTEND=noninteractive`を入れているのは、インストール途中で各種設定に対してyesをしないといけないのが面倒くさく、自動で設定して欲しいためです。
`ENV LANG=C.UTF-8`、`ENV TZ=Asia/Tokyo`はシステムに関する設定です。これらを記載しないままだと、例えば時刻はUTCなどに設定されてしまい、不便です。

```Dockerfile
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
    wget \
    curl \
    git \
    make \
    unzip \
    build-essential \
    zlib1g-dev \
    libssl-dev \
    libbz2-dev \
    libreadline-dev \
    libsqlite3-dev \
    llvm \
    libncurses5-dev \
    libncursesw5-dev \
    xz-utils \
    tk-dev \
    libffi-dev \
    liblzma-dev \
    tzdata \
    ca-certificates \
    libnss3 \
    libnspr4 \
    libdbus-1-3 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libxdamage1 \
    libgbm1 \
    libxkbcommon0 \
    libpango-1.0-0 \
    libcairo2 \
    libasound2 \
    libatspi2.0-0 \
    && apt-get clean
```
たくさんインストールしていますが、pkaywrightを入れるためにはこれだけのパッケージを入れる必要があります。

ぱっと見でこのDockerfileを見ると、このパッケージの量に圧倒されてしまいますが、コピペすれば動きます。


```Dockerfile
# CA証明書を更新
RUN update-ca-certificates
```

CA証明書とは、（Claudeの説明によれば）

> CA証明書（Certificate Authority Certificate）は、デジタル証明書を発行し、インターネット上の通信を安全に行うための信頼できる第三者機関（CA）が発行する電子証明書です。
主な役割:
・ウェブサイトの信頼性を検証
・SSL/TLS暗号化通信の安全性を確保
・サーバーやクライアント間の通信を保護

> システムでは、これらの証明書を使用して:
・セキュアな接続を確立
・データの暗号化
・なりすまし攻撃から保護
`update-ca-certificates`コマンドは、最新のCA証明書をシステムに追加し、セキュリティを最新の状態に保ちます。

`playwright`をインストールして`browser-use`利用する時は、証明書を使うことで、各種ウェブサイトに安全に接続できます。（多くのwebサイトはHTTPS通信をしているため、CA証明書が必要）。


```Dockerfile
# pyenvのインストール
RUN git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# pyenvを使用するための環境変数を設定
ENV PYENV_ROOT="/root/.pyenv"
ENV PATH="$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH"

# Python 3.12のインストール
RUN pyenv install 3.12.0 && pyenv global 3.12.0
```

Pythonのインストールをしています。今回は、pythonの3.12.0をインストールしています。

```Dockerfile
# PIPのアップグレードとPlaywrightのインストール
RUN pip install --no-cache-dir --upgrade pip && pip install playwright && playwright install

# Playwright以外ライブラリをインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 作業ディレクトリの設定
WORKDIR /app
```
playwirghtをインストールし、その後それ以外で必要なライブラリをインストールしています。それ以外で必要なライブラリは、`requirements.txt`に記載しています。

```text
langchain-openai
browser-use
```


## 2. browser-useのためのpythonファイルを作成する


pythonファイルと同じ階層に`.env`ファイルを作成する必要があります。
今回は、ChatGPTを使いたいので、`OPENAI_API_KEY`を設定しました。
```.env
OPENAI_API_KEY=sk-******
```



browser-useを使ったpythonファイルを作成します。


```python:main.py
from langchain_openai import ChatOpenAI
from browser_use import Agent
from browser_use.browser.browser import Browser, BrowserConfig
import asyncio
from dotenv import load_dotenv

# APIキーを読み込む
load_dotenv()


# ブラウザを起動せずに動かす
browser = Browser(
	config=BrowserConfig(
		headless=True,
	)
)

async def main():
    task = "phpを勉強するためにオススメの本を調べて5個提示してください。オススメの理由もつけてください。"
    
    agent = Agent(
        task=task,
        llm=ChatOpenAI(model="gpt-4o"),
        browser=browser,
    )
    result = await agent.run()

    # 調べものをした結果
    print("↓"*30)
    print("Final Result:", result.final_result())
    print("↑"*30)
    for _ in range(3):
        print()
    
    # モデルの出力を取得
    print("↓"*30)
    model_outputs = result.model_actions()
    print("Model Outputs:", model_outputs)
    print("↑"*30)
    for _ in range(3):
        print()

    # モデルの思考プロセスを取得
    print("↓"*30)
    thoughts = result.model_thoughts()
    print("Thoughts:", thoughts)
    print("↑"*30)
    for _ in range(3):
        print()
    

    # エラーがあれば取得
    errors = result.errors()
    if errors:
        print("Errors:", errors)
    
    await browser.close()


if __name__ == "__main__":
    asyncio.run(main())
```

### 解説

```python
# ブラウザを起動せずに動かす
browser = Browser(
	config=BrowserConfig(
		headless=True,
	)
)
```
Browser Useを動かすと言っても、DockerでUbuntu環境下では動かせるブラウザがない。そのため、ブラウザを起動せずに（ある意味バックエンド的に）ブラウザの操作をしてもらうための設定が必要である。そのための設定（`headless=True`）を記載している。


```python
async def main():
    task = "phpを勉強するためにオススメの本を調べて5個提示してください。オススメの理由もつけてください。"
    
    agent = Agent(
        task=task,
        llm=ChatOpenAI(model="gpt-4o"),
        browser=browser,
    )
    result = await agent.run()

    # 調べものをした結果
    print("↓"*30)
    print("Final Result:", result.final_result())
    print("↑"*30)
    for _ in range(3):
        print()
    
    # モデルの出力を取得
    print("↓"*30)
    model_outputs = result.model_actions()
    print("Model Outputs:", model_outputs)
    print("↑"*30)
    for _ in range(3):
        print()

    # モデルの思考プロセスを取得
    print("↓"*30)
    thoughts = result.model_thoughts()
    print("Thoughts:", thoughts)
    print("↑"*30)
    for _ in range(3):
        print()
    

    # エラーがあれば取得
    errors = result.errors()
    if errors:
        print("Errors:", errors)
    
    await browser.close()
```

時間がかかるため、非同期で関数 `main`を呼び出している。

```python
task = "phpを勉強するためにオススメの本を調べて5個提示してください。オススメの理由もつけてください。"
    
agent = Agent(
    task=task,
    llm=ChatOpenAI(model="gpt-4o"),
    browser=browser,
)
result = await agent.run()
```
エージェントを作成している。
ブラウザを操作するためのタスクを設定しているので、プロンプト（`prompt`や`messages`）ではなく、`task`という変数に指示を書く。

今回は、OpenAIのChatGPT4oを使いたいので、ChatOpenAIの引数として、`"gpt-4o"`を指定している。


### BrowserUseを動かした結果を受け取る

#### 最終的な出力を文字列で取得する
```python
print("Final Result:", result.final_result())
```
結果
```shell
Final Result: Here are 5 recommended books for learning PHP with their reasons:

1. **初心者からちゃんとしたプロになる PHP基礎入門**
   - **Reason:** Suitable for beginners to professional levels. Introduces basic syntax and web application development, making it ideal for those new to programming.

2. **スラスラ読める PHPふりがなプログラミング**
   - **Reason:** Unique approach with furigana for code, making it easy to understand for first-time learners. Great for visual and contextual learning.

3. **誰もがあきらめずにすむPHP超入門**
   - **Reason:** Helps beginners learn PHP without prior web or database knowledge. Includes practical web application exercises.

4. **レベルアップPHP ～言語を理解して中級者へ～**
   - **Reason:** Perfect for intermediate learners wanting to deepen their knowledge and understand PHP nuances not covered in basic tutorials.

5. **気づけばプロ並みPHP 改訂版--ゼロから作れる人になる!**
   - **Reason:** Focuses on developing a professional-level system, such as a shopping site, enhancing practical programming skills.
```

Browser Useがいろいろ探索した後の、最終的な結果を出力してくれた。
指示した通り、オススメのPHP本を5冊、そしてそのおすすめ理由も併せて出力してくれている

#### 最終結果を得るまでにエージェントがとったアクションの一覧を取得する
```python
print("Model Outputs:", model_outputs)
```
結果

```shell
Model Outputs: [{'search_google': {'query': 'PHP 入門 おすすめ本'}}, {'extract_content': {'include_links': False}}, {'click_element': {'index': 18}}, {'extract_content': {'include_links': False}}, {'scroll_down': {'amount': 1000}}, {'extract_content': {'include_links': False}}, {'done': {'text': 'Here are 5 recommended books for learning PHP with their reasons:\n\n1. **初心者からちゃんとしたプロになる PHP基礎入門**\n   - **Reason:** Suitable for beginners to professional levels. Introduces basic syntax and web application development, making it ideal for those new to programming.\n\n2. **スラスラ読める PHPふりがなプログラミング**\n   - **Reason:** Unique approach with furigana for code, making it easy to understand for first-time learners. Great for visual and contextual learning.\n\n3. **誰もがあきらめずにすむPHP超入門**\n   - **Reason:** Helps beginners learn PHP without prior web or database knowledge. Includes practical web application exercises.\n\n4. **レベルアップPHP ～言語を理解して中級者へ～**\n   - **Reason:** Perfect for intermediate learners wanting to deepen their knowledge and understand PHP nuances not covered in basic tutorials.\n\n5. **気づけばプロ並みPHP 改訂版--ゼロから作れる人になる!**\n   - **Reason:** Focuses on developing a professional-level system, such as a shopping site, enhancing practical programming skills.'}}]
```

各ステップでのBrowserUseが起こしたアクションを取得できる。

#### 最終結果を得るまでにエージェントが考えたことの一覧を取得する
```Python
print("Thoughts:", thoughts)
```
結果

```shell
Thoughts: [AgentBrain(evaluation_previous_goal='Unknown - There are no previous actions to evaluate. The page is currently empty.', memory='Started with an empty page. Need to find recommended PHP books.', next_goal='Search for recommended PHP books that are suitable for learning, providing reasons for each recommendation.'), AgentBrain(evaluation_previous_goal='Success - Found potential sources for recommended PHP books.', memory='Identified sources for PHP book recommendations. Need to explore these for details.', next_goal='Click and explore the links to extract recommended PHP books and reasons for their recommendation.'), AgentBrain(evaluation_previous_goal='Success - Successful navigation to a page listing recommended PHP books.', memory='Landed on a page listing recommended PHP books. Need to scroll and extract information on these books with reasons for recommendations.', next_goal='Scroll down to find the list of recommended PHP books with their descriptions and reasons.'), AgentBrain(evaluation_previous_goal='Success - Successfully scrolled and found the list of recommended books.', memory='Found the list of recommended PHP books and their descriptions.', next_goal='Extract information about the recommended PHP books and the reasons for their recommendations from the page.'), AgentBrain(evaluation_previous_goal='Success - Extracted details about recommended PHP books for different levels.', memory='Identified recommended PHP books with reasons for recommendation.', next_goal='Summarize and present the top 5 recommended PHP books with reasons.')]
```

Browser Useの思考（Thoughts）を取得できた。


上記を踏まえて、Browser Useが何を考えて（`thoughts`）同アクションしたのか（`model_outputs`）何をして、最終的にどんな結果となった（`result.final_result()`）のか、を確認することができた。



# まとめ

- playwrightのインストールが難しく、DockerでBrowserUseを使えなかったのだが、ClineやChatGPT、Claudeの力を借りて、動かせるようになった。
- BrowserUse自体も強力なツールで、情報収集などを目的に使うさいに勝手に情報を調べてまとめてきてくれるのは非常にありがたい。何かしら面白いツール（例：技術周りのブログをクローリングして良い感じにまとめて日次でLINEで教えてくれるツールなど）を開発できると思う。