Ubuntu上のdockerにnarou.rbを導入してみる

:::note info
2025/3/8
Pull Request 446：小説家になろうの作品情報取得処理の修正に対応
compose.yamlの取得イメージ名をkokotaro/narou:3.9.1-PR446-447へ変更
:::

:::note warn
変換のオプション次第で`mkdir': Permission deniedが発生していることを確認したので手順を修正予定
:::


# 目的 (いつものお題目)
1. 改造版AozoraEpub3の最新版を使用する (2025.01.27時点で 1.1.1b30Q)
1. 読書端末はKindle PaperWhiteとする
1. Javaも含めて最新版(あればLTS)を使用する
1. 無職転生　- 異世界行ったら本気だす - の変換がEPUBで完了すること
1. できる限りnarou.rbで設定しているCSSスタイルに準拠すること
1. dockerのコンテナを停止してもダウンロードしたファイルを永続化する

## 手順として参考にしたサイト

https://github.com/laprusk/narou-docker/tree/master

## 環境
* ubuntu-22.04.3-live-server-amd64.iso で構築したUbuntu Server
* 手製のdockerイメージ (Debianベース＋ruby3.4.1)
* Javaはopenjdk21-jdkを選択

## dockerの構築
基本的な流れは以下のサイトを参照しました

https://qiita.com/yoshiyasu1111/items/17d9d928ceebb1f1d26d

### 古いバージョンの削除
``` shell
$ for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
```

### Dockerリポジトリの準備と登録

``` shell
#鍵の登録作業
$ sudo apt update
$ sudo apt install ca-certificates curl
$ sudo install -m 0755 -d /etc/apt/keyrings
$ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc

# Apt sourcesへリポジトリを追加
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
```
### Dockerのインストール

``` shell
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
$ docker -v
Docker version 27.5.1, build 9f9e405
```

### 動作確認
``` shell
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:d000bc569937abbe195e20322a0bde6b2922d805332fd6d8a68b19f524b7d21d
Status: Downloaded newer image for hello-world:latest
略
Hello from Docker!
This message shows that your installation appears to be working correctly.
略
```

### 一般ユーザでDockerを実行できるようにする
``` shell
$ getent group | grep docker
docker:x:999:
$ sudo usermod -aG docker $USER
$ getent group | grep docker
docker:x:999:user
```
ここで一度ログアウトしログインし直します

### 動作確認
``` shell
$ docker run hello-world
中略
Hello from Docker!
This message shows that your installation appears to be working correctly.
```

## docker composeしnarou.rbを起動する為のファイルを準備する
:::note info
gitからクローンする処理を改め、compose.ymlを作成し、docker hubからイメージをダウンロードする方向へ手順を変更した
:::

``` shell
$ vim compose.yml
services:
  narou:
    build:
      context: .
      dockerfile: dockerfile
      args:
        NAROU_VERSION: 3.9.1
        AOZORAEPUB3_VERSION: 1.1.1b30Q
        UID: 1000
        GID: 1000
    image: kokotaro/narou:3.9.1-PR446-447
    command: ["narou", "web", "-np", "33000"]
    volumes:
      - .:/home/narou/novel:cached
    tty: true
    stdin_open: true
    ports:
      - 9200:33000
      - 9201:33001
```

## docker composeを使用しコンテナを起動する
``` shell
$ docker compose up -d
竜略
[+] Running 1/1
 ✔ Container narou-docker-narou-1  Started 
```

自動的にWEB UIがバックグラウンドで起動している状態なので
http://localhost:9200/ にアクセスしてください。
※検証環境はVirtualBoxを使用し仮想NICをブリッジ接続にしているので、Host PCからhttp://192.168.xxx.xxx:9200/ でアクセスし動作確認を実施

WEB UIの処理が以下のように出力されていればOkです。
```
第286部分　エピローグ「プロローグ・ゼロ」 (286/286)
ID:0　無職転生　- 異世界行ったら本気だす - は完結しているようです
ID:0　無職転生　- 異世界行ったら本気だす - の変換を開始
小説状態の調査結果を 調査ログ.txt に出力しました（エラー：0件、警告：43件、INFO：4件）
縦書用の変換が終了しました
AozoraEpub3でEPUBに変換しています........変換しました
[理不尽な孫の手] 無職転生　- 異世界行ったら本気だす -.epub を出力しました
EPUBファイルを出力しました
```

## docker内で処理された小説ファイルの確認
docker composeを実行したディレクトリに"小説データ"ディレクトリが生成されている。これは以下のようにdokcerコンテナを停止しても実体として保存されている状態
``` shell
$ find . -name "*.epub"
./小説データ/小説家になろう/n9669bk 無職転生　- 異世界行ったら本気だす -/[理不尽な孫の手] 無職転生　- 異世界行ったら本気だす -.epub

$ docker compose stop
[+] Stopping 1/1
 ✔ Container narou-docker-narou-1  Stopped 

$ find . -name "*.epub"
./小説データ/小説家になろう/n9669bk 無職転生　- 異世界行ったら本気だす -/[理不尽な孫の手] 無職転生　- 異世界行ったら本気だす -.epub

** 無事確認出来たので再度起動する
$ docker compose start
```

# 結論
kindlegenのLinux版を正規手順では入手出来ないがEPUB送信で一応Kindleでの閲覧は可能。他の目的もこれまでの手順と同じ程度に達成したと思っている。