Help us understand the problem. What is going on with this article?

【その弐】Apache/PandocでMarkdownをHTMLにして配信するDockerコンテナの作成 - リモート版

はじめに

先日ApacheとPandocを組み込んだDockerコンテナをご紹介しました → ローカル版

コンテナ内あるいはコンテナが動作するホストのディレクトリにソースファイルを置く方式でした。
そうではなく、提供したいMarkdownソースを含むWebリソースがコンテナホストの外部、つまりリモートにある場合に使えるコンテナ(リモート版)を作成したので公開します。

Dockerファイルほかソースはgithubで、作成済みのDockerイメージはDocker Hubで公開済みです(末尾参照)。

以下、前回のローカル版と共通の事柄は割愛します。

Apache

ローカル版の場合、Apache配下のディレクトリに実在するMarkdownソース(拡張子md)の内容がフィルタの標準入力に渡されます。
しかしMarkdownファイルがApache配下のローカルディレクトリに存在しない場合、この方式は使えません。

Apacheには、アクションハンドラという、特定の拡張子を持つURLパスの要求があると、あらかじめ指定しておいたCGIスクリプトを呼び出してくれる、というしくみがあります。
要求されたパスがローカルディレクトリになくてもかまいません。

このしくみを使って、コンテナとは別のWebサーバからMarkdownソースを読み込んで、HTML変換するハンドラを作成しました。

次のApache設定でpandoc-handlerという名前のアクションハンドラを指定します。

[local.conf]

LoadModule cgid_module modules/mod_cgid.so
LoadModule actions_module modules/mod_actions.so

AddHandler markdown-text .md
Action markdown-text /cgi-bin/pandoc-handler virtual

SetEnv REMOTE_DIR https://elsewhere.com/docker

説明します。

  • LoadModuleでアクションハンドラを利用可能とするmod_actionsと、CGIスクリプトを利用可能とするmod_cgidをロード。
  • AddHandlerActionディレクティブで、URLパスで指定されたファイルが拡張子mdを持つ場合にCGIスクリプトのpandoc-handlerを呼び出してもらうよう設定
  • SetEnvは次項で説明するリモートディレクトリの指定です。

ベースイメージのhttpd:2.4ではあらかじめURLの'/cgi-bin'がスクリプト実行可能ディレクトリの'/usr/local/apache2/cgi-bin'に対応づけられているのでこれを利用する。

Apacheハンドラ

Pandocを呼び出すApacheハンドラを作成しました。
ApacheからPATH_INFO環境変数で渡されるURLパスに応じて取得したMarkdownソースをPandocで変換、標準出力にHTMLを出力するBashシェルスクリプトです。

要求されたURLパスからMarkdownソースを読み込む(あるいは生成することも可)方法はアプリケーションによって様々考えられます。
クラウドのファイルサービスから読む、どこかのデータベースから読む、リモートのgitレポジトリから取得、sftpで取得、などです。

このサンプルは固定のURLが指すリモートディレクトリからMarkdownソースファイルを読み込みます。
前項で設定済みのREMOTE_DIR環境変数からcurlコマンドでMarkdownファイルを読み込みます。

[pandoc-handler]

 #!/bin/bash
BASENAME=$(basename -s .md $PATH_INFO)
curl -s $REMOTE_DIR$PATH_INFO | /usr/bin/pandoc -f gfm -t html5 -c "/pandoc-gfm.css" \
    -T "Converted" -M title=${BASENAME}

説明します。

  • 参照されたMarkdownソースのURLパスがPATH_INFO環境変数で渡される。
  • 前項のREMOTE_DIR環境変数で指定しておいたリモートのWebサーバからcurlで指定ファイルを取得。
  • pandocでHTMLに変換して標準出力へ出力

取得例:

Docker作成

上記のApache設定ファイルとハンドラスクリプトを組み込んだDockerコンテナを作成します。

$ ls
 Dockerfile
 usr-local-apache2/
$ ls usr-local-apache2
 local.conf
 pandoc-handler
$ cat Dockerfile
 FROM httpd:2.4
 RUN apt-get update && apt-get install -y \
  pandoc \
  curl \
  ca-certificates
 COPY ./usr-local-apache2 /usr/local/apache2/
 RUN echo 'Include local.conf' >> /usr/local/apache2/conf/httpd.conf
$ docker build -t pandoc:remote .

前回同様、FROMで公式DockerハブからLinuxとApacheを含むベースイメージhttpdを取得します。
前回とは異なり、RUNでpandocに加えてcurlを取得します。
ca-certificateはcurlでSSLを使うために必要だった。
前回同様、COPYでApache設定ファイルとアクションハンドラ(CGIスクリプト)をコンテナのしかるべき場所にコピーし、Dockerのビルドコマンドを実行します。

Dockerコンテナ実行

Dockerコンテナができたら作成したホスト上で実行してみます。

$ docker run --detach -publish 8080:80 pandoc:remote

前回のフィルタの場合と異なりローカルディレクトリは使わないので--mountオプションはありません。
前回同様--publicオプションでポートの割り当てを行います。

テスト

まずコンテナを実行しているホストマシン内から:

$ curl localhost:8080/test.md

続いてホストマシンの外部からブラウザでアクセスします。

http://example.com:8080/test.md

これで 'https://elsewhere.com/docker/test.md' に置いたはずのMarkdownファイルがHTMLになって表示されれば成功です。

続いてこのDockerコンテナをAmazon AWSのコンテナサービスのひとつECS(Elastic Container Service)で動かしてみました。
次回はその顛末を書こうと思います。


使用環境

  • Docker CE 19.03.12
  • ベースイメージ: 公式 httpd:2.4
  • テスト環境:
    • Raspberry Pi 3B (raspiban/debian10-buster)
    • クラウド上のVPS(同じくDebian10-Buster)
    • Amazon AWS - Elastic Container Service (ECS)

参考リンク

DockerfileやApache設定ファイル、Apacheフィルタのソースはgithubで公開しました。
git cloneしてdocker buildすればコンテナが作成できます。

作成したイメージはDocker Hubからも取得できます。

横浜工文社の関連ページ

Written 2020/09/22

abun-kobu
横浜工文社所属エンジニア。 MarkdownとApacheでWebオーサリング(文章執筆公開、データ投入編集表示)の実現技術を開発中。
https://kobu.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away