Azure Container Instances でお手軽にクローラー実行環境を作成
はじめに
Azure Container Instancesは Docker コンテナを動作させることができる環境です。 Azure Container Service(AKS)は複数コンテナのオーケストレーションを可能にしますが、 Azure Container Instances は単一のコンテナをデプロイして実行するのに向いています(注:複数のコンテナを実行ができないという意味ではありません)。本稿では、 Azure Container Instances を利用して、簡単にクローラーを作成する方法を紹介します。
なお、 Azure Container Instances は 2018 年 3 月現在プレビュー版での提供となっているため、今後本稿の手法が再現できなくなることもありますが、あらかじめご承知おきください。
作業の流れ
以下の流れでクローラーを作成します。なお、 Azure CLI および Docker はすでにインストールされているものとします。
- Docker イメージの準備
- ストレージの準備
- インスタンスの作成
- クローラーの作成と実行
下記では主に Azure CLI のコマンドラインで実行していますが、ポータルでも簡単なクリック操作で実行することができます(例外あり)。
Docker イメージの準備
クローラーを実行する基盤は Jupyter Notebook とします。コンテナ化させた Jupyter Notebook 上クローラーの処理を作成し、実行させることでデータの収集を行います。
Dockerfile を作成します。ここでは miniconda を利用して Jupyter Notebook をインストールする例を示します。必要に応じてフォントなど必要なパッケージがあれば追加してください。
FROM ubuntu
# install
ENV JUPYTER_NOTEBOOK_DIR=/notebooks \
PATH=/opt/conda/bin:$PATH
RUN apt-get -qq -y update \
&& apt-get -q install -y --no-install-recommends \
curl bzip2 language-pack-ja ca-certificates libcurl4-openssl-dev sqlite3 libsqlite3-dev \
&& update-locale LANG=ja_JP.UTF-8 \
&& apt-get -qq clean -y \
&& rm -rf /var/lib/apt/lists/* \
&& curl --silent -o /tmp/miniconda.sh "https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh" \
&& bash /tmp/miniconda.sh -b -p /opt/conda \
&& rm /tmp/miniconda.sh \
&& ln -sf /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh \
&& echo ". /opt/conda/etc/profile.d/conda.sh" >>~/.bashrc \
&& echo "conda activate base" >>~/.bashrc \
&& mkdir -p $JUPYTER_NOTEBOOK_DIR \
&& . /opt/conda/etc/profile.d/conda.sh \
&& conda activate base \
&& conda install jupyter \
&& mkdir -p ~/.jupyter \
&& echo "c.ExecutePreprocessor.timeout=0" >>~/.jupyter/jupyter_notebook_config.py
# tini
ARG TINI_VERSION=v0.17.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
# settings
WORKDIR $JUPYTER_NOTEBOOK_DIR
EXPOSE 8888
ENTRYPOINT ["/tini", "--"]
CMD [ "jupyter", "notebook", "--allow-root", "--no-browser", "--ip=0.0.0.0", "--port=8888"]
作成した Dockerfile をビルドします。
$ docker build -t jupyter .
作成した Docker イメージをレジストリーに登録します。ここでは登録先に Azure Container Registry を選択します。
現時点では Azure Container Instances が Azure Container Registry から Docker イメージを pull できるためには、 Azure Container Registry の admin user を有効にする必要があります。以下は Azure CLI を用いて Azure Container Registry を新規作成し、作成した Docker イメージを push するまでの例です。
$ az login $ az acr create --resource-group <リソースグループ名> --name <レジストリー名> --sku Basic $ az acr login -n <リソースグループ名> $ docker tag jupyter <レジストリー名>.azurecr.io/jupyter:latest $ docker push <レジストリー名>.azurecr.io/jupyter:latest
ストレージの準備
Docker のコンテナを用いる際に、データの永続化が必要な場合にデータボリュームコンテナを作成するように、 Azure Container Instances もデータの永続化が必要であればストレージを作成する必要があります。
Azure Container Instances がデータの永続化を可能にする方法は複数ありますが、 Azure Files 経由で行うのが最も単純でしょう。 Azure Files はストレージアカウントを作成してファイル共有を作成します。
$ az storage account create -g <リソースグループ名> -n <ストレージアカウント名> --sku Standard_LRS $ AZURE_STORAGE_CONNECTION_STRING=<コネクション文字列> az storage share create -n <ファイル共有名>
ファイル共有は最大 5 TiB(5,120 GB)で、それ以上のデータの蓄積はできないことに注意しましょう。
ちなみにファイル共有のポータルでの作成方法は、本ブログの「Azure Files でお手軽ファイル共有」に詳しく書かれています。
インスタンスの作成
登録した Docker イメージを Azure Container Instances にデプロイします。この際、先程作成したファイル共有に接続してインスタンスからファイルを保存できるようにします。
$ az container create \
-g <リソースグループ名> -n <コンテナグループ名> \
--image <レジストリー名>.azurecr.io/jupyter:latest \
--registry-username <レジストリー名> \
--registry-password <レジストリーアクセスキー> \
--cpu 1 --memory 1 \
--dns-name-label <Azure全体でユニークな名前> \
--ports 8888 \
--azure-file-volume-account-name <ストレージアカウント名> \
--azure-file-volume-account-key <ストレージアカウントアクセスキー> \
--azure-file-volume-share-name <ファイル共有名> \
--azure-file-volume-mount-path /notebooks/data/
現時点では、インスタンス作成時にファイル共有への接続を行うことはできませんので、この操作はコマンドラインで実行する必要があります。なお、ファイル共有(つまりインスタンスを停止してもファイルが残る状態にする)が不要であれば、ポータルからも実行できます。
しばらくすると、インスタンスが動き出すので、ウェブブラウザーからコンテナにアクセスします。上記コマンドの結果に fqdn という完全なドメイン名が含まれるので、 http://<ドメイン名>:8888 にアクセスすると Jupyter Notebook のログイン画面が表示されます。 Jupyter Notebook にログインするための必要なトークンはコンソールに出力されるため、 Azure CLI でログを取得します。
$ az container logs \
-g <リソースグループ名> -n <コンテナグループ名>
[I 08:11:37.608 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
[I 08:11:38.108 NotebookApp] Serving notebooks from local directory: /notebooks
[I 08:11:38.108 NotebookApp] 0 active kernels
[I 08:11:38.108 NotebookApp] The Jupyter Notebook is running at:
[I 08:11:38.108 NotebookApp] http://0.0.0.0:8888/?token=<アクセストークン>
[I 08:11:38.108 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 08:11:38.109 NotebookApp]
Copy/paste this URL into your browser when you connect for the first time,
to login with a token:
http://0.0.0.0:8888/?token=<アクセストークン>
クローラーの作成と実行
Jupyter Notebook にアクセスすると、 data というフォルダーが表示されます。 Docker イメージの設定で /notebooks をワーキングフォルダーに設定し、インスタンスの作成時に /notebooks/data をファイル共有のマウントパスに指定しているため、この data フォルダーにファイルを保存すると、ストレージアカウント上のファイル共有にもファイルが保存されます。
Jupyter Notebook はバックグラウンド実行が可能であるため、クローラースクリプトを記述し、実行・保存すればあとはインスタンス上で実行が継続し、データは自動でストレージアカウントに保存されます。以下にサンプルとして単純な JSON を 1 分おきにファイルに吐き出すだけの例です。
import json
import logging
import uuid
from time import gmtime, strftime, sleep
logging.basicConfig(
filename='data/crawler.log',
format='[%(asctime)s] %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
level=logging.INFO
)
def save_data(data):
timestamp = strftime("%Y%m%d-%H%M%S", gmtime())
random_suffix = uuid.uuid4()
filepath = "data/{}_{}.json".format(timestamp, random_suffix)
with open(filepath, "w") as f:
json.dump(data, f)
logging.info("data saved")
def fetch_data():
return {"message": "Hello, Azure Container Instances!"}
while True:
try:
data = fetch_data()
save_data(data)
except:
logging.exception("something went wrong")
# 1 分待機
sleep(60)
何かストレージに接続するための特別な記述もなく、ローカルマシンで実行するのと完全に同じように記述できることがわかると思います。 Jupyter Notebook はファイルのアップロード機能もあるので、ローカルマシン上で作成した試験用のノートブックを、 Azure Container Instances にアップロードして継続実行させるようなことも簡単ですね。必要なライブラリーは Dockerfile であらかじめイメージに含めておく、ノートブック上で pip 経由でインストールさせれば良いでしょう。
まとめ
本稿では、 Azure Container Instances を中心にしたクローラーの作成方法を解説しました。 Azure Container Instances は単純な Docker コンテナの実行環境であり、 Jupyter Notebook 上でクローラーを実現することが簡単にできます。コンテナで面倒なファイルの永続化もファイル共有を利用することで、クローラーのコードに特別な変更を加えることなく実現できます。
Azure Container Instances はまだプレビュー版でポータルで実現できないことも多いのですが、そのうち改善されていくことと思います。今の段階でも少しのコマンドを要求されるだけで便利になるので、ぜひ使ってみて下さい。