Sphinx+Nginxでドキュメントを公開する

# Sphinxとは

SphinxとはPythonをベースにしたドキュメント生成ツールです。reStructuredTextという記法で記述していきます。Markdownの経験があれば抵抗なく書けると思います。

今回は、Sphinxを使ってPythonライブラリの公式ドキュメント風のページを、Nginxで公開する方法を書きました。

# 環境

- Ubuntu 20.04
- Docker version 20.10.14
- Docker Compose version v2.4.1
- Sphinx Docker Image：sphinxdoc/sphinx:5.3.0
- nginx version: nginx/1.23.1

# ソース
## Sphinxコンテナ内の設定ファイルをホストにコピー

Dockerfileとrequirements.txtは以下のような配置を想定しています。

```
.
├── Dockerfile
└── requirements.txt
```

```Dockerfile:Dockerfile
FROM sphinxdoc/sphinx

COPY requirements.txt /requirements.txt
RUN pip install -r /requirements.txt
```
色々入れていますが、最低限`sphinx`と`sphinx_rtd_theme`があればOKです。
```text:requirements.txt
# sphinxインストール
sphinx

# Sphinxにテーマをインストール
sphinx_rtd_theme

# markdownを読み込む用
myst-parser

# シーケンス図
sphinxcontrib-actdiag
sphinxcontrib-blockdiag
sphinxcontrib-nwdiag
sphinxcontrib-seqdiag
```

イメージをビルドします。

```bash
docker build -t sphinx-custom .
```

Sphinxの初期設定を行います。カレントディレクトリの`docs`とコンテナ内の`/docs`をマウントする設定をしているので、ホスト側に設定ファイルが保存されます。

```bash
docker run -it --rm -v ${PWD}/docs:/docs --name sphinx sphinx-custom sphinx-quickstart
```
指示通りに入力していきます。

```
Welcome to the Sphinx 5.3.0 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Selected root path: .

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: y

The project name will occur in several places in the built documentation.
> Project name: test
> Author name(s): yourname
> Project release []: 1

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language.
> Project language [en]: ja

Creating file /docs/source/conf.py.
Creating file /docs/source/index.rst.
Creating file /docs/Makefile.
Creating file /docs/make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file /docs/source/index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.
```

諸々の設定ファイルができました。

```bash
drwxr-xr-x 4 root root 4096 Mar 20 12:37 .
drwxr-xr-x 3 root root 4096 Mar 20 12:37 ..
-rw-r--r-- 1 root root  638 Mar 20 12:37 Makefile
drwxr-xr-x 2 root root 4096 Mar 20 12:37 build
-rw-r--r-- 1 root root  804 Mar 20 12:37 make.bat
drwxr-xr-x 4 root root 4096 Mar 20 12:37 source
```

ディレクトリ構成は以下のようになっています。

```
.
├── Dockerfile
├── requirements.txt
└── docs
    ├── Makefile
    ├── build
    ├── make.bat
    └── source
        ├── _static
        ├── _templates
        ├── conf.py
        └── index.rst
```

## conf.pyの更新

以下の通り更新します。

```diff_python:conf.py
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

+ import sphinx_rtd_theme

project = 'test'
copyright = '2023, yourname'
author = 'yourname'
release = '1'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

- extensions = []
+ extensions = [
+     'sphinxcontrib.blockdiag',
+     'sphinxcontrib.seqdiag',
+     'sphinxcontrib.actdiag',
+     'sphinxcontrib.nwdiag',
+     'sphinxcontrib.rackdiag',
+     'sphinxcontrib.packetdiag',
+     "myst_parser"
+ ]

templates_path = ['_templates']
exclude_patterns = []

language = 'ja'

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

- html_theme = 'alabaster'
- html_static_path = ['_static']
+ html_theme = 'sphinx_rtd_theme'
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

# blockdiag の設定
# https://qiita.com/yamionp/items/8f8d52d6b41bf9d4d16d
+ blockdiag_html_image_format = 'SVG'
+ seqdiag_html_image_format = 'SVG'
+ actdiag_html_image_format = 'SVG'
+ nwdiag_html_image_format = 'SVG'
+ rackiag_html_image_format = 'SVG'
+ packetdiag_html_image_format = 'SVG'
```
参考：[Sphinxでblockdiagを使って簡単にシーケンス図、ブロック図を含めたHTMLベースのドキュメントを生成する環境を整える](https://qiita.com/yamionp/items/8f8d52d6b41bf9d4d16d)

## Sampleドキュメントの作成

`docs/source`配下に`documents`フォルダを作成します。`documents`配下にサンプルのドキュメントを配置していきます。

```bash
mkdir docs/source/documents
```

Sampleドキュメントを作成します。

```bash
cat << EOF > docs/source/documents/test.rst
=============================================
Sample
=============================================

test1
=============================================

test2
---------------------------------------------

test2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EOF
```

## index.rstの更新

`docs/source/index.rst`に先ほど作成した`test.rst`を読み込ませる設定を追記します。

```diff:index.rst
.. test documentation master file, created by
   sphinx-quickstart on Mon Mar 20 03:37:43 2023.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to test's documentation!
================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

+  ./documents/test.rst

Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

```

ここまでのディレクトリ構成は以下の通りです。

```
.
├── Dockerfile
├── requirements.txt
└── docs
    ├── Makefile
    ├── build
    ├── make.bat
    └── source
        ├── _static
        ├── _templates
        ├── conf.py
        ├── documents
        │   └── test.rst
        └── index.rst
```

## ドキュメントをビルド

```bash
docker run --rm -it -v ${PWD}/docs:/docs --name sphinx sphinx-custom
```

実行結果。
```
Running Sphinx v5.3.0
loading translations [ja]... done
myst v1.0.0: MdParserConfig(commonmark_only=False, gfm_only=False, enable_extensions=set(), disable_syntax=[], all_links_external=False, url_schemes=('http', 'https', 'mailto', 'ftp'), ref_domains=None, fence_as_directive=set(), number_code_blocks=[], title_to_header=False, heading_anchors=0, heading_slug_func=None, html_meta={}, footnote_transition=True, words_per_minute=200, substitutions={}, linkify_fuzzy_links=True, dmath_allow_labels=True, dmath_allow_space=True, dmath_allow_digits=True, dmath_double_inline=False, update_mathjax=True, mathjax_classes='tex2jax_process|mathjax_process|math|output_area', enable_checkboxes=False, suppress_warnings=[], highlight_code_blocks=True)
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 2 source files that are out of date
updating environment: [new config] 2 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] index
generating indices... genindex done
writing additional pages... search done
copying static files... done
copying extra files... done
dumping search index in Japanese (code: ja)... done
dumping object inventory... done
build succeeded.

The HTML pages are in build/html.
```

`docs/build/`にHTMLファイルなどが生成されます。

```bash
drwxr-xr-x 5 root root 4096 Mar 20 13:05 .
drwxr-xr-x 4 root root 4096 Mar 20 13:05 ..
-rw-r--r-- 1 root root  230 Mar 20 13:05 .buildinfo
drwxr-xr-x 3 root root 4096 Mar 20 13:05 _sources
drwxr-xr-x 4 root root 4096 Mar 20 13:05 _static
drwxr-xr-x 2 root root 4096 Mar 20 13:05 documents
-rw-r--r-- 1 root root 3486 Mar 20 13:05 genindex.html
-rw-r--r-- 1 root root 5087 Mar 20 13:05 index.html
-rw-r--r-- 1 root root  290 Mar 20 13:05 objects.inv
-rw-r--r-- 1 root root 3882 Mar 20 13:05 search.html
-rw-r--r-- 1 root root 1067 Mar 20 13:05 searchindex.js
```

## Docker ComposeでNginxを起動

```
.
├── Dockerfile
├── requirements.txt
├── docker-compose.yaml
└── docs
    ├── Makefile
    ├── build
    │   ├── doctrees
    │   │   ├── documents
    │   │   │   └── test.doctree
    │   │   ├── environment.pickle
    │   │   └── index.doctree
    │   └── html
    │       ├── _sources
    │       │   ├── documents
    │       │   │   └── test.rst.txt
    │       │   └── index.rst.txt
    │       ├── _static
    │       │   ├── _sphinx_javascript_frameworks_compat.js
    │       │   ├── basic.css
    │       │   ├── css
    │       │   │   ├── badge_only.css
    │       │   │   ├── fonts
    │       │   │   │   ├── Roboto-Slab-Bold.woff
    │       │   │   │   ├── Roboto-Slab-Bold.woff2
    │       │   │   │   ├── Roboto-Slab-Regular.woff
    │       │   │   │   ├── Roboto-Slab-Regular.woff2
    │       │   │   │   ├── fontawesome-webfont.eot
    │       │   │   │   ├── fontawesome-webfont.svg
    │       │   │   │   ├── fontawesome-webfont.ttf
    │       │   │   │   ├── fontawesome-webfont.woff
    │       │   │   │   ├── fontawesome-webfont.woff2
    │       │   │   │   ├── lato-bold-italic.woff
    │       │   │   │   ├── lato-bold-italic.woff2
    │       │   │   │   ├── lato-bold.woff
    │       │   │   │   ├── lato-bold.woff2
    │       │   │   │   ├── lato-normal-italic.woff
    │       │   │   │   ├── lato-normal-italic.woff2
    │       │   │   │   ├── lato-normal.woff
    │       │   │   │   └── lato-normal.woff2
    │       │   │   └── theme.css
    │       │   ├── doctools.js
    │       │   ├── documentation_options.js
    │       │   ├── file.png
    │       │   ├── jquery-3.6.0.js
    │       │   ├── jquery.js
    │       │   ├── js
    │       │   │   ├── badge_only.js
    │       │   │   ├── html5shiv-printshiv.min.js
    │       │   │   ├── html5shiv.min.js
    │       │   │   └── theme.js
    │       │   ├── language_data.js
    │       │   ├── minus.png
    │       │   ├── plus.png
    │       │   ├── pygments.css
    │       │   ├── searchtools.js
    │       │   ├── sphinx_highlight.js
    │       │   ├── translations.js
    │       │   ├── underscore-1.13.1.js
    │       │   └── underscore.js
    │       ├── documents
    │       │   └── test.html
    │       ├── genindex.html
    │       ├── index.html
    │       ├── objects.inv
    │       ├── search.html
    │       └── searchindex.js
    ├── make.bat
    └── source
        ├── _static
        ├── _templates
        ├── conf.py
        ├── documents
        │   └── test.rst
        └── index.rst
```

Nginx 起動用の`docker-compose.yaml`を上記の通り、`docs`フォルダと同じ階層に保存します。

```yaml:docker-compose.yaml
version: '3'
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    hostname: nginx
    restart: always
    ports:
    - '18000:80'
    volumes:
    - ./docs/build/html:/usr/share/nginx/html
```

Sphinxで生成したHTML一式をNginxコンテナ内の`/usr/share/nginx/html`にマウントしてページを見られるようにします。

### コンテナ起動

```
docker-compose up -d
```

# アクセス確認

- http://localhost:18000/

ページにアクセスできればOKです。

![sphinx-page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518403/c4680357-aa2e-0378-9aaf-7e7480820706.png)

![sphinx-sample-page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518403/890410a9-5807-eaa6-743e-00706e88c2b7.png)

# まとめ

SphinxでHTMLをビルドして、Nginxで見せるところまで検証できました。Sphinxを使うと、綺麗なドキュメントを簡単に作ることができるので便利ですね。

Github Pagesでも利用できるので興味があれば試してみてください。

# 参考

- [Sphinxのインストール](https://www.sphinx-doc.org/ja/master/usage/installation.html#docker)

- [sphinxdoc/sphinx](https://hub.docker.com/r/sphinxdoc/sphinx)