[Google Cloud] Container-Optimized OSでDocker Compose v2を使えるようにする (2023/11更新)

# はじめに
去年、[Docker Compose v2がGA](https://www.docker.com/blog/announcing-compose-v2-general-availability)となり、Compose v1は非推奨となっています。それに伴い `docker-compose` コマンドから `docker compose` コマンドへの移行が必要です。

Google CloudのCompute Engineにて「Container-Optimized OS (COS) 」を使ってコンテナアプリを動かす上で、OSにはDocker Composeが入っていないため別途インストールしないといけません。
これまでは [docker/compose](https://hub.docker.com/r/docker/compose) imageを使った方法がありましたが、v2への移行に伴ってこちらの更新は止まっている状況。

Container-Optimized OSのそのままのdockerコマンドでは `docker compose` は利用できないため、「Compose plugin」をインストールします。

https://docs.docker.com/compose/install/linux/#install-using-the-repository

# Compose Pluginをインストール
Container-Optimized OSにはapt-getやyumといったパッケージマネージャーが搭載されていないため、マニュアルでのインストールします。

## マニュアルでダウンロード

公式ドキュメントの通りにホームディレクトリ内の `.docker/cli-plugins` に、docker compose pluginのバイナリファイルを格納します。

https://docs.docker.com/compose/install/linux/#install-the-plugin-manually

```sh
# docker-composeをダウンロード
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.23.1/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose

# 実行権限付与
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```

## マウント設定の変更

しかし、これだけではまだdocker compose pluginは実行できない状態です。

```sh
$ docker compose version
docker: 'compose' is not a docker command.
See 'docker --help'
```

ヘルプを見ると、以下のようなpermission deniedのエラーが出てました。

```sh
$ docker -h
...
Invalid Plugins:
  compose     failed to fetch metadata: fork/exec /home/username/.docker/cli-plugins/docker-compose: permission denied
...
```

実行権限を付与したはずですが権限エラーとなっているため調べてみると、COSでは、ホームディレクトリは実行不可でマウントされており、バイナリファイルの実行ができません。

https://cloud.google.com/container-optimized-os/docs/concepts/disks-and-filesystem?hl=ja

`mount` コマンドで確認すると、確かに `noexec` がついています。

```sh
$ mount | grep /home
/dev/sda1 on /home type ext4 (rw,nosuid,nodev,noexec,relatime,commit=30)
```

これによってdocker compose pluginのバイナリファイルを実行できないため、先ほどのエラーが発生していたようです。

この回避策としては `exec` オプションで再マウントすることというのがあります。

以下で再マウントすることで実行可能な状態に変更できます。

```sh
sudo mount -o exec,remount /home
```

再度マウントの状態を見ると `noexec` が外れています。

```
$ mount | grep /home
/dev/sda1 on /home type ext4 (rw,nosuid,nodev,relatime,commit=30)
```

これで `docker compose version` を実行すると先ほどのようにエラーが出ることなく正常に実行できることが確認できます。

```sh
$ docker compose version
Docker Compose version v2.23.0
```

これでDocker Compose v2が利用可能となりましたが、先ほどのマウントの設定はインスタンスを再起動するとリセットされてしまうため、自動反映させるためにインスタンスのメタデータにスクリプトを追加する必要があります。

> 補足
`/etc/fstab` によるマウント設定は、再起動すると設定がクリアされてしまうため使えません。

インスタンスの編集から「メタデータ」の設定で、キー `user-data` に以下の値を追加します、

```sh
#cloud-config

bootcmd:
- mount -o exec,remount /home

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/832b40c9-47d6-4c58-efe1-eb7b3834fdf1.png)

参考:

https://cloud.google.com/container-optimized-os/docs/concepts/disks-and-filesystem?hl=ja#mounting_and_formatting_disks

これで、再起動してもdocker compose pluginが実行されるようになります。

## おまけ
ちなみに、[Toolbox](https://cloud.google.com/container-optimized-os/docs/how-to/toolbox?hl=ja)を使えばapt-getを経由して導入が可能ですが、dockerコマンドもtoolbox内で実行することになってしまいます。

# まとめ
現状、COSでDocker Compose v2を利用したい場合はマニュアルでインストール & マウント設定を変更するという形で可能になります。

できれば標準で対応して欲しいですね...