LimaでDocker

LimaというVM環境でDockerを構築する。

22年1月18日`シェル起動時にVM起動`追記

23年2月11日書き込み権限の箇所を修正。


> https://github.com/lima-vm/lima

## 検証環境

- Mac OS Monterey 12.1
- MacBook Pro (Intel CPU)
- [HomeBrew インストール済み](https://brew.sh/index_ja)

## 必要なパッケージをインストール

```bash
brew install lima docker
```

インストールが完了すると`limactl`というコマンドが使用可能になる

```bash
limactl --version
```

### 追加で入れておきたいパッケージをインストール

```bash
brew install docker-compose
```

## docker.yamlを用意する

構築用のyamlを適当なディレクトリに`docker.yaml`という名前で作成。

バージョンによって推奨する内容が微妙に変わるようなので、以下のURLへアクセスして内容を`docker.yaml`という名前でファイルとして保存する。

> github /lima-vm/lima/examples/docker.yaml
> https://github.com/lima-vm/lima/blob/master/examples/docker.yaml

もしくは、`wget`を使って以下のようにファイルをダウンロードする。

```bash
wget https://github.com/lima-vm/lima/raw/master/examples/docker.yaml
```

## docker.yamlに追記

### リソースを変更

docker.yamlに以下を追記してリソースを変更。

```yaml
cpus: 2
memory: "8GiB"
disk: "100GiB"
```

### ssh関係

docker.yamlに以下を追記してエラー回避。

`~/.ssh`のディレクトリ以下のファイル関係で問題がある場合、`loadDotSSHPubKeys`を`false`にしておかないと`limactl start`コマンドで`INFO[0003] [hostagent] Waiting for the essential requirement 1 of 5: "ssh"`のループに陥る。

```yaml
ssh:
  loadDotSSHPubKeys: false
```

また、ポートを指定する場合は、上記に追記してポート番号を指定する

```yaml
ssh:
  loadDotSSHPubKeys: false
  localPort: 60006
```

## 書き込み権限

デフォルトではユーザーのホームをマウントする設定になっているが、書き込みは出来ないようになっている。そのため、`writable: true`書き換え可能になる。権限が大きすぎるので、必要なディレクトリ以下にのみ権限をもたせたほうが良い。

https://github.com/lima-vm/lima/blob/41fd9cc6a1e2bac73666e1f2b11604c7c42227dc/pkg/limayaml/default.TEMPLATE.yaml#L33-L41

```yaml
mounts:
- location: "~"
  writable: false
# 開発環境に使うディレクトリのみを対象にする
- location: "~/work"
  writable: true
- location: "/tmp/lima"
  writable: true
```

## 実行

以下を実行して構築。

```bash
limactl start ./docker.yaml
# --debugをつけると、エラーが発生した際に原因がわかりやすくなる
# limactl start ./docker.yaml --debug
```

### 確認

構築出来ているか確認する

```bash
limactl ls
```

```
NAME      STATUS     SSH                ARCH      CPUS    MEMORY    DISK      DIR
docker    Running    127.0.0.1:60006    x86_64    2       8GiB      100GiB    /Users/ユーザ名/.lima/docker
```

### 仮想マシンに入る

#### limactl

Dockerが構築されている仮想マシンに直接入るには、以下のコマンドを実行する。

入ったあとは`exit`で仮想マシンから出る。

```bash
limactl shell docker
```

#### ssh

`ssh`コマンドでVMに入る場合は以下のようになる。ポート番号は作成したyamlに依拠する。

```bash
ssh ${USER}@localhost -p 60006 -i /Users/${USER}/.lima/_config/user
```

この場合、`known_hosts`に記録されるので、作成したVMの状態が変わった場合は、以下を実行して記録を消さないとエラーになる。

```bash
ssh-keygen -R "[localhost]:60006"
```

## DOCKER_HOST 環境変数

`.zshrc`や`.zprofile`（MacOSのバージョンによっては`.bash_profile`）に `DOCKER_HOST`環境変数を追記して、Dockerのベースをlimaの仮想マシンで使用するように変更する。（Limaのバージョンによっては内容が少々変わる可能性がある）

```bash
export DOCKER_HOST=unix:///${HOME}/.lima/docker/sock/docker.sock
```

### シェル起動時にVM起動

システムを再起動すると、作成した仮想環境はstopの状態になるので、先程の`.zshrc`に仮想環境を立ち上げるように追記する。

```bash
limactl start docker
```

## テスト

### nginxを構築

試しに`nginx`を構築

```bash
docker run --name nginx_test -d -p 8080:80 nginx
```

`http://localhost:8080/`でnginxにアクセス出来るようになる。

###  nginxを削除

```bash
docker stop $(docker ps -aqf "name=nginx_test")
docker rm $(docker ps -aqf "name=nginx_test")
```


## Docker outside of Docker

Dockerコンテナ内でDockerを使用する方法として、コンテナ内に内包する `Docker in Docker` とホスト側のDockerを利用する `Docker outside of Docker` がある。

Limaで`Docker outside of docker`を利用する場合は、**VM内**の`/var/run/docker.sock`に`chmod`コマンドで権限を付与する。

```bash
limactl shell docker sudo chmod 0666 /var/run/docker.sock
```

その後、例えば以下のような `docker-compose.yaml`を用意して動作確認ができる。

なお、`volumes`の`/var/run/docker.sock`のパスは、VM内のソケットを指定している。

```yaml
version: '3'
services:
  dood:
    image: docker:rc-git
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    tty: true
```

```bash
# コンテナ作成
docker-compose up -d
# docker infoコマンド
docker-compose exec dood docker info
# コンテナ等をまとめて削除
docker-compose down --rmi all --volumes --remove-orphans
```