Azure Container InstancesでDockerコンテナを使用したWekan環境を構築する

# 概要

Azure Container Instancesを使用して、Wekan環境を構築するのに苦労したのでその時のメモです。

## 環境

Windows 10 (64bit)
Azure CLI

# 説明

作業を進める前に、関係する情報の説明をします。

## Wekanとは

OSSのかんばんの管理ツールです。
シンプルで使いやすい点がウリのツールです。
ドラッグ&ドロップでかんばんをサクサク動かせるのでちょっとしたタスク管理などで便利です。

![wekan2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149198/d16de074-61b6-acbe-5221-77d001278419.png)


## Azure Container Instancesとは

クラウドサービスのAzure上でコンテナ環境を構築できるサービスです。
一般的にDockerなどのコンテナを動かす際には、コンテナを動かすLinuxなどのサーバ管理も必要となりますが、本サービスを使用する事でコンテナだけの管理だけに注力できます。
いわゆるサーバレスと呼ばれるサービスになるかと思います。

## 必要なコンテナ

今回Wekanを環境を構築するには2つのコンテナを使用します。

1. Wekanコンテナ
2. MongoDBコンテナ


## 永続化

詳細は割愛しますが、Dockerコンテナは停止すると起動中にコンテナ内に保存された情報は消えます。
今回使用するMongoDBはWekanの各種情報を保存するDBとしての機能として使用するため、そのままではコンテナが停止する度にデータが消えてしまいます。

データを永続化するためには、Dockerにはボリュームといったコンテナ外にデータを保存する仕組みが存在します。
Azure Container Instancesは前述の通りサーバレスのサービスになるため永続化を行うために、サーバのストレージの代わりににAzure Storageといったサービスのファイル共有といった機能を使用します。

# 手順

## リソースグループの作成

Azureでは各サービスが所属するグループの作成が必要です。
今回はmygroup1といったグループを米国東部リージョンに作成します。
既にリソースグループがある場合には作成せずにそちらを利用しても問題ありません。

```powershell
az group create --name mygroup1 --location eastus
```

## ストレージ関連設定

永続化で必要となるストレージを作成します。

### ストレージアカウントの作成

下記コマンドを実行してストレージアカウントを作成します。
- name
 - 指定する値はユニークになるように設定をしてください。
(mystorage1234)


```powershell
az storage account create --resource-group mygroup1 --name mystorage1234 --location eastus --sku Standard_LRS
```

### ストレージアカウントキーの取得

下記のコマンドでストレージのアカウントキーを取得します。
コマンド実行後に表示される文字列を保存してください。

```powershell
echo $(az storage account keys list --resource-group mygroup1 --account-name mystorage1234 --query "[0].value" --output tsv)
```

### ファイル共有の作成

- name 
 - 任意の共有名を設定してください。(myshare1)
- account-key
 - 先ほど取得したアカウントキーを指定してください。

```powershell
az storage share create --name myshare1 --account-name mystorage1234 --account-key xxxxxxxx
```

以上で使用するストレージの構築は完了です。

## コンテナ関係の設定

コンテナ関連の設定を行なっていきます。

### 構成ファイルの作成

下記のようなyamlの構成ファイルを作成します。
docker-compose.yamlと似ていますが、Azure Container Instances専用の構成ファイルになるので注意が必要です。

[リファレンスはこちら](https://docs.microsoft.com/ja-jp/azure/container-instances/container-instances-reference-yaml)

```yaml:my-wekan.yml

apiVersion: 2018-10-01
location: eastus
# 任意のグループ名を指定
name: wekanGroup
properties:
  containers:
  # wekanコンテナ
  - name: wekan
    properties:
      # WWekanのコンテナのイメージ名を指定
      image:  wekanteam/wekan:v4.18
      # コンテナに渡す環境変数
      environmentVariables:
        # MongoDBのURL (localhostの27017ポート)
        - name: 'MONGO_URL'
          secureValue: 'mongodb://127.0.0.1:27017/wekan'
        # アプリのURL.かんばんの保存などの一部機能で使用する
        # my-wekan-app1234はdnsNameLabelで指定した値。
        - name: 'ROOT_URL'
          value: 'http://my-wekan-app1234.westus2.azurecontainer.io:8080'
      resources:
        requests:
          # コンテナに割り当てるCPUとメモリ
          cpu: 1
          memoryInGb: 1.5
      # このコンテナに対して硬化するポート。wekanは8080をデフォルトで使用するので開放。
      ports:
      - port: 8080
  # mongodb用コンテナ
  - name: db
    properties:
      # MongoDBのコンテナを指定
      image: mongo:4.2.8
      # MongoDB起動時の起動コマンドを指定。詳細は記事内にて説明。
      command:
        - 'mongod'
        - '--dbpath=/data/mongoaz'
      resources:
        requests:
          cpu: 1
          memoryInGb: 1.5
      # AzureStorage上で永続化するパスを指定
      # MongoDB上の/data/mongoazディレクトリを永続する
      volumeMounts:
        - mountPath: /data/mongoaz
          name: filesharevolume
      # Mongoはデフォルトで27017ポートを使用するので開放する
      ports:
      - protocol: tcp
        port: '27017'
  osType: Linux
  # インターネット上に公開するのでPublicとする。
  ipAddress:
    type: Public
    # 8080ポートをインターネット上に公開する
    ports:
    - protocol: tcp
      port: '8080'
    # ユニークな値を指定。下記の設定がインターネット上で公開されるURLに使用される。
    dnsNameLabel: my-wekan-app1234
  # 永続化するボリュームの設定
  volumes:
  - name: filesharevolume
    azureFile:
      # 先ほど作成したAzureのストレージアカウントの情報を指定
      sharename: myshare1
      storageAccountName: mystorage1234
      storageAccountKey: xxxxxx
tags: null
type: Microsoft.ContainerInstance/containerGroups


```

#### ファイルの補足説明

基本的に上記ファイル内のコメントを見ていただければわかると思いますが、一部説明を補足します。

#### MongoDBの接続先


```yaml
  - name: wekan
  
        - name: 'MONGO_URL'
          secureValue: 'mongodb://127.0.0.1:27017/wekan'
```

Azure Container Instancesでは同一グループのコンテナはlocalhost(127.0.0.1)でアクセスが可能になります。
ですので、Wekan側からMongoDBにアクセスするにはlocalhostの27017ポートを指定すれば良くなります。

#### MongoDBの永続化設定

```yaml
  - name: db
  - 
      command:
        - 'mongod'
        - '--dbpath=/data/mongoaz'
      # AzureStorage上で永続化するパスを指定
      # MongoDB上の/data/mongoazディレクトリを永続する
      volumeMounts:
        - mountPath: /data/mongoaz
          name: filesharevolume

```

MongoDBのデフォルト設定では、"/data/db"ディレクトリをデータ保存先とするので、多くの Dockerでの紹介例ではこのディレクトリを永続化しています。

当初私も
mountPath: /data/db
といった形でデフォルトのまま使用を試みましたが、MongoDBのコンテナ起動時にエラーが出てしまいうまく動きませんでした。

調べてみると似たような事例が見つかりました。
[Link1](https://stackoverflow.com/questions/59783143/unable-to-mount-azure-file-shares-as-mongodb-volume-in-azure-container-instances)
[Link2](https://jussiroine.com/2019/02/an-adventure-in-containers-and-command-line-tools-running-mongodb-in-azure/)

どうやら、/data/dbディレクトリをそのままマウントすると、本来永続化したいDBファイル以外もAzureストレージ上に共有されることでパーミッション関係の問題が生じるようです。

ということで、MongoDBの起動時にデータ保存のパス(/data/mongoaz)を指定してそのパスをマウントすることで解決ができました。

## デプロイ

後は作成したyamlファイルを指定してデプロイすれば完了です。

```powershell
az container create --resource-group mygroup1 --file my-wekan.yml
```

デプロイ後、コンテナの起動やDBの初期化等に時間がかかるのでしばらくしたらURLにアクセスしてみます。
URLが不明な場合には、AzureのポータルにWEBブラウザでアクセスしてAzure Container Instancesの該当グループを見つけて概要情報から確認できます。

![wekan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149198/ddeff502-a7a1-8259-dd3d-65552cb2bf87.png)

今回は8080ポートで公開しているのでURL末尾にポート番号の指定が必要な点が注意です。

なお、yamlファイルの修正を行った場合、上記のコマンドを再度実行すれば反映されます。

# まとめ

ということで、Azure Container InstancesでWekan環境を構築する手順を説明しました。
ストレージなどに関してはローカルでDockerを使用する場合と比較して一手間必要ですが、サーバレスでコンテナアプリを簡単に作れてしまうのは便利ですね。

docker-compose.ymlをそのまま使用できないのが残念ではありますが、設定値などは流用できるのでそこまで苦労はないかと思います。


# 参考
[Azure Doc](https://docs.microsoft.com/ja-jp/azure/container-instances/container-instances-volume-azure-files)