ARM CPU の Synology NAS で Docker を使う。

## この記事の概要 (tl;dr)

DS220j や DS120j 以降の Synology NAS であれば ARM CPU でも `Container Manager` (旧パッケージ名 `Docker`)が使えますが、それ以前の ARM CPU の Synology NAS では、 Docker は正式にサポートされていません。

この記事では Docker 非対応の Synology NAS で Docker を使うための手順を説明します。

https://www.synology.com/ja-jp/dsm/feature/docker

## 制限事項

`Container Manager` 非対応の Synology NAS でも Docker は使えますが、以下の制限事項が存在します。

1. [ポートマッピング](https://docs.docker.com/network/#published-ports)が使用できない。  
   そのため、全て `--network=host` での対応となります。
1. `Container Manager` 非対応の Synology NAS では、 `Docker Compose` は遅すぎるため、「使用可能ではあるが実用的ではない」と考えてください。  
   そのため、この記事では `Docker Compose` のインストール方法は説明しません。
1. メモリ 512MB の Synology NAS で、[Home Assistant コンテナ](https://hub.docker.com/r/homeassistant/home-assistant)を稼働させている猛者を見ましたが、実用に耐えるメモリサイズは 1GB 以上です。

## 手順概要

Docker 非対応の Synology NAS で Docker を利用するための手順は以下の通りです。

1. SSH で Synology NAS にログイン
1. CPU のアーキテクチャを確認
1. Docker の最新バージョンを確認
1. Docker の最新ファイルをダウンロード
1. ダウンロードしたファイルを解凍し、`/usr/local/bin` に保存
1. Docker のデータが保存されるディレクトリを作成
1. 設定ファイル( `/etc/docker/daemon.json` )を作成
1. NAS 起動時に `dockerd` が実行されるように設定

さらに本記事では、コンテナ管理を簡単にする以下の 2 つのツールのインストール方法を説明します。

1. [Portainer-CE](https://www.portainer.io/)  
   (👉 コンテナやイメージ、ボリューム等の状態をブラウザで簡単に確認・操作できるため、コンテナの管理が非常に楽になります。)
1. [Dozzle](https://dozzle.dev/guide/getting-started)  
   (👉 各コンテナのログを簡単に確認できるため、コンテナが正常に動作しない場合の原因究明が楽になります。)

## 手順 1. SSH で Synology NAS にログイン

Synology NAS への SSH 接続は、公開鍵認証方式がお勧めです。  
設定方法は以下のページを参照してください。

https://qiita.com/shimizumasaru/items/56474d98e723ea1b5ae3

## 手順 2. CPU のアーキテクチャを確認

以下のコマンドを実行します。

これで `ARCH` という変数に、CPU のアーキテクチャが保存されます。  
最初の行は、`uname -m` の動作確認です。

```shell
uname -m
ARCH=$(uname -m)
```

## 手順 3. Docker の最新バージョンを確認

以下のコマンドを実行します。

これで `DOCKER_VERSION` という変数に、Docker の最新バージョン(e.g. `27.3.1`)が保存されます。  
最初の行は、`DOCKER_VERSION` に格納される値の確認です。

```shell
curl -s https://api.github.com/repos/moby/moby/releases/latest \
  | grep '"tag_name":' | sed -e 's/[^0-9.]//g'
DOCKER_VERSION=$(curl -s https://api.github.com/repos/moby/moby/releases/latest | grep '"tag_name":' | sed -e 's/[^0-9.]//g')
```

## 手順 4. Docker の最新ファイルをダウンロード

以下のコマンドを実行します。

最初の行では、ダウンロードするファイルの URL を表示します。  
ダウンロードに失敗する場合、ブラウザから URL にアクセスし、ファイルがダウンロードできるか確認してください。

```shell
echo "https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz"
wget "https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz"
```

## 手順 5. ダウンロードしたファイルを解凍し、`/usr/local/bin` に保存

以下のコマンドを実行します。

```shell
sudo tar -zxvf "docker-${DOCKER_VERSION}.tgz" -C /usr/local/bin --strip-components=1
```

2024 年 10 月時点では、`/usr/local/bin` 以下に以下の 8 つのファイルが作成されます。

- `containerd`
- `containerd-shim-runc-v2`
- `ctr`
- `docker`
- `docker-init`
- `docker-proxy`
- `dockerd`
- `runc`

上記手順 2 ～ 5 のコマンドを一度に実行する場合は以下のコマンドを使用してください。  
(👉 下記コマンドは、 Docker のアップデートスクリプトとしても使用できます。)

```shell
uname -m
ARCH=$(uname -m)

curl -s https://api.github.com/repos/moby/moby/releases/latest \
  | grep '"tag_name":' | sed -e 's/[^0-9.]//g'
DOCKER_VERSION=$(curl -s https://api.github.com/repos/moby/moby/releases/latest | grep '"tag_name":' | sed -e 's/[^0-9.]//g')

echo "https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz"
wget "https://download.docker.com/linux/static/stable/${ARCH}/docker-${DOCKER_VERSION}.tgz"

sudo tar -zxvf "docker-${DOCKER_VERSION}.tgz" -C /usr/local/bin --strip-components=1
rm "docker-${DOCKER_VERSION}.tgz"
```

## 手順 6. Docker のデータが保存されるディレクトリを作成

以下のコマンドを実行します。

```shell
DOCKER_DIR=/volume1/docker/var
mkdir -p "$DOCKER_DIR"
```

👉 `Container Manager` が利用できる機種では、Docker のイメージやボリュームなどのデータは `/var/packages/ContainerManager/var/docker` に保存されます。  
(👉 `/var/packages/ContainerManager/var/docker` の実体は `/volume1/@docker` です。)

## 手順 7. 設定ファイル( `/etc/docker/daemon.json` )を作成

以下のコマンドを実行します。

```shell
sudo mkdir -p /etc/docker
sudo cat <<EOT > /etc/docker/daemon.json
{
  "data-root": "${DOCKER_DIR}",
  "storage-driver": "vfs",
  "iptables": false,
  "bridge": "none"
}
EOT
```

👉 `Container Manager` が利用できる機種では、上記設定ファイルは `/var/packages/ContainerManager/etc/dockerd.json` となります。

## 手順 8. NAS 起動時に `dockerd` が実行されるように設定

ブラウザから Synology NAS にログインし、 [コントロールパネル] の [タスクスケジューラー] から [トリガーされたタスク] を作成します。

スクリプトの内容は `dockerd &` です。 (👉 末尾の `&` は**必要**です。)

DSM の操作は画像の方が分かりやすいと思いますので、以下の図で確認してください。

![user: root](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566576/0b1fef6c-41e9-1544-42bf-8dfa93753df6.png)

![firefox_ii1v1BfuJn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566576/58018ef5-7122-191c-4f6a-32584e137142.png)

## コンテナ管理ツールのインストール

### 1. [Portainer-CE](https://www.portainer.io/)

上記手順 8.の設定を行った後、一度 NAS を再起動します。  
(Docker について知識があるなら、再起動しなくても `sudo dockerd &` を実行するだけで十分です。)

NAS の再起動後、以下のコマンドを実行します。

```shell
mkdir -p /volume1/docker/portainer-ce

sudo docker run -d \
  --net=host \
  --name portainer-ce \
  --restart=always \
  -v /volume1/docker/portainer-ce:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  portainer/portainer-ce:latest
```

Portainer のイメージがダウンロードされ、コンテナが起動されたら、Portainer の GUI パスワードを設定するため、以下のどちらかの URL を使用して Portainer のコンソール画面を表示します。  
( [SYNOLOGY_NAS_IP] の部分は自分の NAS の IP アドレスに変更してください。)

- `http://[SYNOLOGY_NAS_IP]:9000`
- `https://[SYNOLOGY_NAS_IP]:9443`

(👉 [Portainer の説明](https://docs.portainer.io/start/install-ce/server/docker/linux#deployment)では `port 9000` は legacy とされていますが、[Chromium 系のブラウザ](<https://en.wikipedia.org/wiki/Chromium_(web_browser)>) では `Not Secure` な接続ではパスワードが保存できないため、パスワードが保存できる `port 9000` を使用する方が便利でしょう。)

Portainer の起動が完了していれば、コンソール画面が表示され、以下のようなパスワードの設定画面が表示されるはずです。  
好きなパスワードを設定してください。

![Portainer Password](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566576/fada49da-d7a7-722c-d7a2-b386023be3c5.jpeg)

Portainer の実行画面は以下のようになります。  
( [tailscale](https://tailscale.com/kb/1017/install) の [MagicDNS](https://tailscale.com/kb/1081/magicdns) を使用しているため、`http://ds218play:9000` でアクセスしています。)

![Portainer CE](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566576/4957b834-0539-e63d-72c4-458b8056ddd2.png)

### 2. [Dozzle](https://dozzle.dev/guide/getting-started)

Portainer の GUI のパスワードの設定が終わったら、以下のコマンドを実行します。

```shell
sudo docker run -d \
  --net=host \
  --name dozzle \
  --restart=unless-stopped \
  --volume=/var/run/docker.sock:/var/run/docker.sock:ro \
  amir20/dozzle:latest \
  --enable-actions
```

Dozzle のイメージがダウンロードされ、コンテナが起動されたら、以下の URL にアクセスします。  
( [SYNOLOGY_NAS_IP] の部分は自分の NAS の IP アドレスに変更してください。)

- `http://[SYNOLOGY_NAS_IP]:8080`

Dozzle の実行画面は以下のようになります。  
( [tailscale](https://tailscale.com/kb/1017/install) の [MagicDNS](https://tailscale.com/kb/1081/magicdns) を使用しているため、`http://ds218play:8080` でアクセスしています。)

![Dozzle](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566576/9127f916-fb36-4dc7-dad8-2f5d5c5f5bd9.png)

## 参考

https://qiita.com/AtsushiYokokawa/items/72157a676866296d8bbe

https://github.com/412999826/docker-arm-based-synology

https://stackoverflow.com/questions/52520008/can-i-install-docker-on-arm8-based-synology-nas

https://wiki.servarr.com/docker-arm-synology