とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど
読者登録と各種SNSのフォローもよろしくお願いいたします。

textlintによる文書校正環境をコンテナ化した

このブログで数回、textlintの話題を上げました。 textlintは手軽に無料で使える良いツールなのですが、Node.jsを実行環境として使います。

Node.jsは色々なOSで動かすことができ、初心者にも扱いやすい言語です。 ただ、最近サプライチェーン攻撃の標的にされることも多くなってきました。

  • もともとの問題として、一つのパッケージをインストールするのに山のような依存ライブラリがインストールされてしまう
  • Node.jsだけではないが、サプライチェーン攻撃でnpmは狙われがち
  • 使いたいライブラリは問題ないかもしれないが、依存パッケージの中に悪意のあるコードが含まれたライブラリーがあるかもしれない
  • 使いたいライブラリの特定のバージョンが侵害されて汚染したコードが含まれたライブラリーかもしれない

直近では、trivyとaxiosの事例なんかもありましたよね。

www.publickey1.jp

というわけで、なるべく普段使いのマシンにNode.jsをインストールするのはなあと言う気持ちになってきました。

そこで、ほかの言語ベースで使えるtextlintの代替ツールを調べてみました。

色々な言語で使える文書校正ツールまとめ

Vale (Go言語)

textlintの最も有力な代替候補。多くのテック企業(Google、Microsoft、GitLabなど)がドキュメント校正に採用しています。シングルバイナリ: Goで書かれており、実行ファイルを一つ置くだけで動作します。Node.jsのように数千の小さなパッケージをインストールする必要がないため、サプライチェーン攻撃のリスクを大幅に抑えられます。標準では英語がメインですが、正規表現ベースのルールを記述することで日本語の校正も可能です。

Redpen (Java)

技術文書に特化した日本発のオープンソース・ツールです。開発者が日本人のため、日本語特有の文章ルール(「です・ます」の混在チェック、一文の長さ、二重否定など)が標準で豊富に用意されています。文章を単なる文字列ではなく、セクションや段落として構造的に解析します。Javaの実行環境(JRE)が必要ですが、Node.jsに比べるとライブラリ管理が厳格であり、予期せぬ脆弱性の混入を管理しやすい側面があります。

proselint (Python)

「文章の質」を高めることに特化したリンターです。文法ミスだけでなく、不必要な専門用語、冗長な表現、使い古された表現(クリシェ)などを指摘してくれます。Python環境があれば pip install で手軽に導入できます。主に英語のライティングスタイルを基準としているため、日本語の文章を直接校正する用途には不向きです。

どれも一長一短あります。この中ではRedpenが一番良さそうですね。 ただ、Redpenは公式のドキュメントが全部リンク切れしているのが気になる...

...ただ、textlintの手軽さも捨てがたい。 というわけで、「じゃあコンテナ化すればいいじゃん!」と言うことで、そうしてみました。

まずはイメージを作る

試行錯誤の末、こうするのが一番まともに動きました。ルールは最低限にします。

FROM node:22-alpine

WORKDIR /opt/textlint

# 1. 本体、技術文書向けルール、そして「見出しチェックルール」をインストール
RUN npm install \
    textlint \
    textlint-rule-preset-ja-technical-writing \
    textlint-rule-incremental-headers

# 2. 設定ファイルで incremental-headers を有効化する
RUN echo '{ \
  "rules": { \
    "preset-ja-technical-writing": true, \
    "incremental-headers": true \
  } \
}' > /opt/textlint/.textlintrc.json

# 3. パスを通し、作業ディレクトリを本来の /work に戻す
ENV PATH $PATH:/opt/textlint/node_modules/.bin
WORKDIR /work

# 4. 生成した設定ファイルを明示的に読み込んで実行
ENTRYPOINT ["textlint", "--config", "/opt/textlint/.textlintrc.json"]

イメージをビルド

ここは普通です。次はPodmanを使っている場合の例ですが、Dockerユーザーの場合はPodmanをDockerに置き換えれば良いです。

podman build -t my-safe-textlint .

動かしてみる

以前の記事でも使いましたが、テストファイルを作って、それに対して文書校正してみます。 次のようなファイルを作っておいてください。

% cat sample.txt
吾輩は猫である。名前はまだないです。
猫ですが、鼠は食べれません。

% cat sample.md
# 吾輩は猫である 夏目漱石

### 一

吾輩は猫である。名前はまだ無いです。
猫ですが、鼠は食べれません。

後はビルドしたイメージを使ってコンテナを動かすだけです。 まずはテキストファイルの方。

きちんと、「ですます」と「だである」の混在がチェックされました。

% podman run --rm -v "$(pwd):/work:Z" my-safe-textlint sample.txt

/work/sample.txt
  1:5   error  本文: "ですます"調 でなければなりません
=> "ですます"調 であるべき箇所に、次の "である"調 の箇所があります: "である。"
Total:
である  : 1
ですます: 1
  ja-technical-writing/no-mix-dearu-desumasu
  2:10  error  ら抜き言葉を使用しています。                                                    ja-technical-writing/no-dropping-the-ra

✖ 2 problems (2 errors, 0 warnings, 0 infos)

では次に、markdownの方。 こっちはさっきと同じ混在の他、見出しのレベルの不備も検知してくれました。

私の場合、これだけで十分です。

% podman run --rm -v "$(pwd):/work:Z" my-safe-textlint sample.md

/work/sample.md
  3:1   error  #の後に###が来ています。段落は1つずつ下げてください。                          incremental-headers
  5:5   error  本文: "ですます"調 でなければなりません
=> "ですます"調 であるべき箇所に、次の "である"調 の箇所があります: "である。"
Total:
である  : 1
ですます: 1
  ja-technical-writing/no-mix-dearu-desumasu
  6:10  error  ら抜き言葉を使用しています。                                                    ja-technical-writing/no-dropping-the-ra

✖ 3 problems (3 errors, 0 warnings, 0 infos)

まとめ

Node.jsもtextlintも非常に便利なソフトウェアです。

しかし、AIなどの技術によって開発が便利になった反面、サプライチェーンの脆弱性を狙った攻撃は、今後ますます増えていくと思われます。

便利なツールは積極的に活用しつつも、ユーザー側ができる対策はしっかりと講じていく必要があります。

今回、ツールをコンテナ化したことで、普段使いの環境に悪意のあるモジュールが入り込むリスクを最小限に抑えることができました。当然、その隔離された環境自体に侵入されれば被害は出ますが、最悪の事態を防ぐためにも、普段からできるセキュリティ対策を怠らないようにしたいと改めて思いました。