【Github Actions】md-to-pdf 実行時の「No usable sandbox!」エラー対応

# はじめに
GitHub のリポジトリで Markdown（.md）ファイルを PDF に変換したい場合、md-to-pdf を利用すると便利です。
このツールを GitHub Actions 上で実行したところ、以下のエラーが発生しました。
```
No usable sandbox! If you are running on Ubuntu 23.10+ or another Linux distro that has disabled unprivileged user namespaces with AppArmor
```
本記事では、このエラーの原因と GitHub Actions における解決方法を解説します。

# GitHub Actions とは？
GitHub Actions は、GitHub リポジトリの変更をトリガーにして、自動で処理を実行できる CI/CD（継続的インテグレーション / デリバリー）ツール です。
例えば、以下のようなタスクを自動化できます。

✅ ソースコードのビルド・テスト
✅ アプリのデプロイ
✅ ドキュメントの生成（今回のケース）

今回のケースでは、Markdown ファイルを PDF に変換する処理 を GitHub Actions で自動化しました。

# md-to-pdf を GitHub Actions で使う理由
Markdown を PDF に変換する理由として、以下のようなケースが考えられます。

・職務経歴書やドキュメントを PDF にして配布したい
・README.md を PDF に変換し、レポートや資料として活用したい
・CI/CD パイプラインの一環として Markdown から PDF を自動生成したい

GitHub Actions を使えば、リポジトリの変更をトリガーに PDF を自動生成 できます。

# リポジトリの構成と package.json のスクリプト
今回のリポジトリの構成は以下のようになっています。
```perl
my-repo/
│── docs/
│   ├── README.md  # PDF に変換する Markdown ファイル
│── pdf-configs/
│   ├── config.js  # md-to-pdf の設定ファイル
    ├── config.css
│── .github/
│   ├── workflows/
│   │   ├── md_to_pdf.yml  # GitHub Actions ワークフロー
│── package.json  # npm スクリプトを管理
│── ...
```

このリポジトリでは、docs/README.md を md-to-pdf を使って PDF に変換します。
変換コマンドは package.json の scripts に記載しています。
```package.json
"scripts": {
  "build:pdf": "md-to-pdf docs/README.md --config-file ./pdf-configs/config.js"
}
```
これを GitHub Actions 上で実行した際にエラーが発生 しました。

# エラーの発生条件
## 実際の GitHub Actions ワークフロー（yml）
以下のように md-to-pdf を実行する GitHub Actions ワークフローを作成しました。

```md_to_pdf.yml
name: Convert Markdown to PDF

on:
  push:
    branches:
      - master  # masterブランチにpushされたら実行

jobs:
  build:
    runs-on: ubuntu-latest
    
    steps:
      - name: チェックアウトリポジトリ
        uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 18
          cache: npm
      - run: npm install
      - run: npm run build:pdf
      - name: 成果物を保存
        uses: actions/upload-artifact@v4
        with:
          name: generated-pdf
          path: docs/README.pdf
```

## 発生するエラー
上記のワークフローを実行すると、以下のエラーが発生しました。
```
No usable sandbox! If you are running on Ubuntu 23.10+ or another Linux distro that has disabled unprivileged user namespaces with AppArmor
```

## エラーの原因
md-to-pdf は内部でPuppeteer（Chromium）を使用していますが、これが正常に動作しなかったことが原因です。

以下に今回のエラーに関する記述がありました。
https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#setting-up-chrome-linux-sandbox

> 信頼できないウェブコンテンツからホスト環境を保護するために、Chromeは何重ものサンドボックス機能を使用しています。
> この機能を正しく動作させるには、まずホストを設定する必要があります。Chromeが使用できる適切なサンドボックスがない場合、No usable sandbox！（使用可能なサンドボックスがありません）というエラーでクラッシュします。
> 
> Chromeで開くコンテンツを絶対に信頼したい場合は、--no-sandbox引数を指定してChromeを起動できます。
> 
>
> In order to protect the host environment from untrusted web content, Chrome uses multiple layers of sandboxing. For this to work properly, the host should be configured first. If there's no good sandbox for Chrome to use, it will crash with the error No usable sandbox!.
> 
> If you absolutely trust the content you open in Chrome, you can launch Chrome with the --no-sandbox argument:

また、GitHub Actions の runs-on: ubuntu-latest は 自動的に最新の Ubuntu（2025年3月時点で 23.10 以降） を使います。

以上を踏まえると、今回は以下のような挙動となり、エラーが起きたと考えられます。
　・Ubuntu 23.10 以降の実行環境で動作するPuppeteerでは、複数のサンドボックス層で構成される
　・対象コンテンツ（mdファイル）を信頼できるものと判断するサンドボックスがないとPuppeteerが判断
　・No usable sandbox！（使用可能なサンドボックスがありません）というエラーが起きた

# 解決策：--no-sandbox オプションを追加
この問題を解決するため、Puppeteer の起動オプションとして --no-sandbox を指定し、サンドボックスモードを使わないようにします。
これにより、Puppeteerが、Chromeで開くコンテンツを信頼できるものと判断し、エラーが解消されます。

今回はpackage.jsonにmd-to-pdfのコマンドを記載しているので、こちらに上記オプションを追記します。
（--launch-options の部分）
```package.json
"scripts": {
  "build:pdf": "md-to-pdf docs/README.md --config-file ./pdf-configs/config.js --launch-options '{ \"args\": [\"--no-sandbox\"] }'"
}
```

エラーが解消され、Github Actionsが正常に実行されるようになります。
![2025-04-05_21h48_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485934/e3b598b0-029c-489d-a8f2-5a7d5dc051ae.png)

# おわりに
GitHub Actions を使って md-to-pdf で Markdown を PDF に変換する際、Ubuntu 23.10 以降の環境では No usable sandbox! エラーが発生します。
解決策として、--no-sandbox オプションを追加することで、問題なく PDF を生成できるようになります。

これから GitHub Actions で Markdown から PDF を自動生成する方の参考になれば幸いです！