リモートサーバーで動いているrootless docker上でdindを使ってrootful dockerを動かしてrootful dockerにMacからアクセスする

# はじめに
タイトル長い上にわかりにくいんだけど、わかりにくいことをやっているということ。
社内サーバーで`rootless docker`を展開しているのですが、`VSCode`の`devcontainer`機能が`rootless docker`だと使えないんだよ、とエンジニアから指摘されました。
この問題を回避すべく`dind`を使った話です。

# 構築手順
`rootless docker`の構築・設定は終わっている前提です。
`docker ps`や`docker info`で`docker`が動作し、`rootless`で動いていることを確認します。

## dindをセットアップする
リモートサーバーにアクセスして作業します。

ミソは`dind`コンテナの`/var/run`をバインドしていることです。
これによって`docker.socket`がホスト上にバインドされます。
```bash:dindコンテナを動かす
docker run -it -d --rm --privileged --name dind -v $(pwd)/my-dind:/var/run docker:20-dind
```

もし、`dind`コンテナ内でマウントしたいディレクトリがある場合は、この時点でマウントしておいてください。
```bash:ディレクトリをマウントする場合
docker run -it -d --rm --privileged --name dind -v $(pwd)/my-dind:/var/run -v /nfs/my-data:/work docker:20-dind
```

`dind`コンテナが動作していることを確認します。
```bash:docker psで確認する
$ docker ps
CONTAINER ID   IMAGE            COMMAND                  CREATED          STATUS          PORTS           NAMES
1...6   docker:20-dind   "dockerd-entrypoint.…"   34 seconds ago   Up 33 seconds   2375-2376/tcp   dind
```

`my-dind`ディレクトリが作成されていることを確認します。
```
$ ls -l my-dind
total 8
drwx------ 6 hoge hoge 4096 Aug 28 16:27 docker
-rw-r--r-- 1 hoge hoge    2 Aug 28 16:27 docker.pid
srw-rw---- 1 hoge hoge    0 Aug 28 16:27 docker.sock
-rw------- 1 hoge hoge    0 Aug 28 16:26 xtables.lock
```

`context`を作成/切替してリモートサーバーが`dind`の`docker`を掴むようにします。
```bash:contextを作る
docker context create --docker host=unix://$(pwd)/my-dind/docker.sock my-local-dind
```

```bash:contextを切り替える
docker context use my-local-dind
```

`docker`デーモンが掴んでいる`docker`が切り替わっていることを確認します。
先程は`dind`コンテナが動いていることが確認できたのですが、`dind`コンテナ内の`docker`デーモンに接続しているため動いているコンテナが見えなくなります。

```bash:docker psでコンテナが動いていないことを確認する
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

## Macをセットアップする
Docker Desktopをインストールして動作することを確認してください。
公式URLはこちらです。
https://www.docker.com/products/docker-desktop/

リモートサーバーの`docker`デーモンに接続するための`context`を作成/切替します。

```bash:contextを作る
docker context create --docker host=ssh://<remote server> my-remote-docker
```

```bash:contextを切り替える
docker context use my-remote-docker
```

構築手順は以上です。
あとはVSCodeのContainer拡張機能を開けばdocker関連の機能が使えることがわかります。
devcontainer機能で作成したコンテナが表示されることも確認できます。

`dind`コンテナにマウントしたディレクトリを`dind`内のコンテナにマウントさせる場合は、マウントポイントをあわせる必要があることに注意してください。
前述の例では`-v /nfs/my-data:/work`とマウントしているので、`dind`内のコンテナからは`/work`をマウントする必要があります。
```
docker run -it -v /work:/my-data ubuntu:latest bash
```

# dindを消したい
リモートサーバー上の`dind`を削除したい場合は、`docker context use`でコンテキストを戻し、`dind`コンテナを停止すれば永続化していないデータはすべて消えます。
```bash:dindを削除するコマンドの例
$ docker context ls
$ docker context use rootless
$ docker stop dind
```

`dind`コンテナが作成するソケットファイルを削除するには次のコマンドで削除してください。
```bash:dindが作成したファイルを削除する
$ chmod -R 770 my-dind
$ rm -rf my-dind
```

# 最後に
理屈上は`rootful docker`を`rootless docker`でラップしているので、`rootful`に見えるだけで実質は`rootless`になっているはずです。
しかし、`rootless`であること保証できるわけではないことをご理解ください。

同様に各種機能が`rootful`かのように使えるはずですが、`rootless`を間に挟む関係でデバイスのマウントやネットワーク経由のアクセスは複雑怪奇となり混乱を極めるおそれがあります。
用途や物理構成を見極め適切なアーキテクチャを選定ください。

私が試した限り、VSCodeに残っている認証キャッシュを使ってGitHubにログインでき、プライベートリポジトリをpullできました。
また、devcontainerも動作することを確認でき、VSCodeを活かせていることを確認できました。
この内容で誰かが幸せになると嬉しいです。