dockerhubで利用可能なnarou.rbイメージを作成する

# 目的
1. dockerイメージの作成手順を整理


## 対象の記事
https://qiita.com/kokotaro@github/items/f429a235b4c962ba6c77

## 環境
* Ubuntu 24.04
* dockerの構築は導入記事に記載済みなので割愛

## 今回作成するnarou.rbのdockerイメージの構成
* OS: Debian12 "Bookworm"
* ruby: 3.4.1
* Java: Adoptium OpenJDK 21.0.6+7-LTS
* AozoraEpub3: AozoraEpub3-1.1.1b30Q
* narou: 3.9.1 (tilt=2.4.0固定)

## dockerイメージの構築
### イメージのリンクとファイルのリンク
使用したdockerのイメージはrubyの公式ビルドにあるDebian12ベースのものを使用した。また容量削減のために最終的にslim版へマルチステージビルドを利用しファイルを統合している。

* [RubyのDocker Official Image](https://hub.docker.com/_/ruby)から 3.4.1-bookworm
* [RubyのDocker Official Image](https://hub.docker.com/_/ruby)から 3.4.1-slim-ookworm
* [Adoptium OpenJDK](https://adoptium.net/temurin/archive/)からOpenJDK21U-jdk_x64_linux_hotspot_21.0.6_7.tar.gz
* [改造版AozoraEpub3](https://github.com/kyukyunyorituryo/AozoraEpub3)から AozoraEpub3-1.1.1b30Q.zip 

### dokcerfileの準備
```vim:dockerfile
FROM ruby:3.4.1-bookworm AS builder

ARG NAROU_VERSION=3.9.1
ARG AOZORAEPUB3_VERSION=1.1.1b30Q
ARG AOZORAEPUB3_FILE=AozoraEpub3-${AOZORAEPUB3_VERSION}

RUN apt update && \
    curl -LO https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.6%2B7/OpenJDK21U-jdk_x64_linux_hotspot_21.0.6_7.tar.gz && \
    mkdir jdk-21 && tar zxf OpenJDK21U-jdk_x64_linux_hotspot_21.0.6_7.tar.gz -C ./jdk-21 --strip-components 1 &&\
    mv jdk-21 /usr/local/jdk-21 && \
    export JAVA_HOME=/usr/local/jdk-21 && \
    export PATH=$PATH:$JAVA_HOME/bin && \
    jlink --no-header-files --no-man-pages --compress=2 --add-modules java.base,java.datatransfer,java.desktop --output /opt/jre && \
    gem install tilt -v 2.4.0 && \
    gem install narou -v ${NAROU_VERSION} --no-document && \
    wget https://github.com/kyukyunyorituryo/AozoraEpub3/releases/download/v${AOZORAEPUB3_VERSION}/${AOZORAEPUB3_FILE}.zip && \
    unzip ${AOZORAEPUB3_FILE} -d /opt/aozoraepub3

FROM ruby:3.4.1-slim-bookworm

ARG UID=1000
ARG GID=1000

COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY --from=builder /opt/aozoraepub3 /opt/aozoraepub3
COPY --from=builder /lib/x86_64-linux-gnu/libjpeg* /lib/x86_64-linux-gnu/
COPY --from=builder /usr/lib/x86_64-linux-gnu/libjpeg* /usr/lib/x86_64-linux-gnu/
COPY --from=builder /opt/jre /opt/jre
COPY init.sh /usr/local/bin

ENV JAVA_HOME=/opt/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}"

RUN groupadd -g ${GID} narou && \
    adduser narou --shell /bin/bash --uid ${UID} --gid ${GID} && \
    chmod +x /usr/local/bin/init.sh

USER narou

WORKDIR /home/narou/novel

EXPOSE 33000-33001

ENTRYPOINT ["init.sh"]
CMD ["narou", "web", "-np", "33000"]
```

### dockerfile内で使用するinit.sh

```shell:init.sh
#!/bin/sh

if [ ! -e /home/narou/novel/.narou ]; then
  mkdir .narou
  mkdir -p .narousetting
  {
    echo "---";
    echo 'aozoraepub3dir: "/opt/aozoraepub3"';
    echo 'over18: true';
    echo 'server-port: 33000';
    echo 'server-bind: 0.0.0.0';
  } | tee .narousetting/global_setting.yaml

  {
    echo "---";
    echo "already-server-boot: true";
  } | tee .narousetting/server_setting.yaml

  narou s convert.no-open=true
fi

exec "$@"
```

## dockerイメージの作成
dockerfileとinit.shが存在するディレクトリで以下のコマンドを実行
```shell
$ docker build -t narou:3.9.1 .
```
コマンド完了後にイメージが作成されたか確認
```shell
[+] Building 127.5s (7/16)
 => [internal] load build definition from dockerfile
[+] Building 131.2s (17/17) FINISHED
略
=> => naming to docker.io/library/narou:3.9.1 

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
narou        3.9.1     15d925cae414   6 minutes ago   310MB
```

## コンテナの起動

### compose.yamlの準備

```yaml:compose.yml
services:
  narou:
    build:
      context: .
      dockerfile: dockerfile
      args:
        NAROU_VERSION: 3.9.1
        AOZORAEPUB3_VERSION: 1.1.1b30Q
        UID: 1000
        GID: 1000
    image: narou:3.9.1
    command: ["narou", "web", "-np", "33000"]
    volumes:
      - type: bind
        source: .
        target: /home/narou/novel
    tty: true
    stdin_open: true
    ports:
      - 9200:33000
      - 9201:33001
```

compose.ymlが存在するディレクトリで以下のコマンドを実行
```shell
$ docker compose up -d
[+] Running 1/1
 ✔ Container narou-docker-narou-1  Started 
```

実行後、以下のコマンドでコンテナの起動状況を確認
STATUSがUpを維持していればコンテナとしてエラーなく実行されている状態
```shell
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                   CREATED          STATUS          PORTS                                                                                          NAMES
5b1a574a465f   narou:3.9.1   "init.sh narou web -…"   16 seconds ago   Up 15 seconds   0.0.0.0:9200->33000/tcp, [::]:9200->33000/tcp, 0.0.0.0:9201->33001/tcp, [::]:9201->33001/tcp   narou-docker-narou-1
```

### WEB UIへのアクセス
この手順ではVirtualBox環境を使用し、Ubuntu24.04にdocker環境を構築している。またネットワークはブリッジ接続としているため、VirtualBoxを実行しているPCからUbuntu24.04へアクセス可能な状態にしています。

コンテナはポート転送しているので以下をブラウザへ入力するこでdokcerコンテナとして起動しているnarou.rbへアクセス可能になります。
```
192.168.0.XXX:9200
```

:::note
コンテナ内部のポートやUbuntuにアクセスする際のポートはcompose.ymlやdockerfile内の該当箇所を修正することで変更可能
:::

![dokcer01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21516/346939e5-0f8c-daa4-438e-79f5a2081b8b.png)

### 使い方
基本的にWEB UIに限定して使うことになるが、ダウンロードしたファイル、変換されたファイルはコンテナを起動したディレクトリに同期されるディレクトリが生成される。
今回のケースでは「小説データ」というディレクトリが生成され、ダウンロードした無職転生のファイル、epub等々のファイルが実行元でも確認出来るようになっている。
必要に応じてファイルを転送するか、仮想環境にkindle等を接続してconvert後に自動的に転送するようにするかは各々のスタイルに左右されるのでおまかせで

:::note info
ここから先コンテナへログインしてコマンド叩きたいとかはdockerの使い方の説明になってくるので割愛
:::

## dockerfileの修正によるイメージの更新

### AozoraEpub3のバージョンアップ
dockerfileの該当箇所を変更することで対応可能
```dockerfile
ARG AOZORAEPUB3_VERSION=1.1.1b30Q
```

### narou .rbのバージョンアップ

同じくdockerfileの該当箇所を変更することで対応可能
```dockerfile
ARG NAROU_VERSION=3.9.1
```
:::note warn
現時点(2025/01/29)では gem install tilt -v 2.4.0 && \をnarou.rbのインストール前に実施する必要があるが、narou.rb側で対処されるとこの処理も不要になる見込み
:::

### JDKとrubyの変更
JDKはcurlのダウンロードリンク、tarのファイル名を変更することで対応出来そうも変数にしにくいので放置
rubyはrubyの公式イメージに希望するバージョンイメージがあればFROM行のイメージ名を変更することで対応可能

# 結論
ブラウザ越しにdockerコンテナのnarou.rbへアクセスできダウンロードも完了しているので作成したイメージが動作していることを確認できた。