Docker で overlay2 や stale NFS file handle のエラーを消す

# `docker-compose up` で `overlay2` のエラーがでた

新しいWindows PCにDocker Desktopを導入して、とあるプロジェクトで `docker-compse up` をやってみたところ、以下のエラーが発生しました。

```bash
$ docker-compose up
ERROR: readlink /var/lib/docker/overlay2: invalid argument
```

エラー解消するまでに実施したことを順番に紹介します。

結論を先に書くと、 **Docker Desktopを工場出荷状態まで戻す** ことで解決しました。



# ファイル構成

まず、ファイル構成を確認します。 `docker-compose.yaml` と `Dockerfile` は同じフォルダ階層にあります。

```bash
hello/
　├ docker-compose.yaml
　└ Dockerfile
```

中身は以下のようになっています。



```docker-compose.yaml
version: '3'
services:
  hello:
    build:
      context: ./
      dockerfile: ./Dockerfile
```

```docker:Dockerfile
FROM node:12.3.1-alpine
WORKDIR /src/hello
```

説明のため、実際の業務データではありませんが、この内容のファイルでも同じエラーが発生しました。



# `ERROR: readlink /var/lib/docker/overlay2: invalid argument` の意味

エラーメッセージの意味を調べてみました。

`readlink` というのは、シンボリックリンクの実体へのパスを取得するコマンドです。
参考：[Debian / readlink(1)](https://manpages.debian.org/testing/coreutils/readlink.1.en.html)

`overlay2` の実体パスを取得しようとしたところ、「そんなものはない」と怒られたようです。

`overlay2` というのはDockerのストレージドライバ（？）の１つのようです。
参考：[Overlay2 について調べてみた](https://qiita.com/toshihirock/items/e99889e4a77a76f28455)

`readlink` も `overlay2` も自分で設定した記憶がありません。。。



# イメージを削除したら `stale NFS file handle` のエラーになった

エラーメッセージで調査したところ、同じエラーメッセージの事例を見つけました。
[dockerで ERROR: readlink /var/lib/docker/overlay2/l: invalid argument と表示された時の対処法](https://qiita.com/robox0917@github/items/032ed9fc6b1112e275e5)

`docker-compose down --rmi all` でイメージを削除すれば解決するようです。

やってみたところ、、、別のエラーが発生するようになりました！

```bash
$ docker-compose up
Building hello
Step 1/2 : FROM node:12.3.1-alpine
 ---> xxxxxxxxxxxxx
Step 2/2 : WORKDIR /src/hello
 ---> Running in xxxxxxxxxxxx
ERROR: Service 'hello' failed to build: lstat /var/lib/docker/overlay2/xxxxxxxxxxxx/merged/src: stale NFS file handle
```

> lstat /var/lib/docker/overlay2/xxxxxxxxxxxx/merged/src: stale NFS file handle

このエラーメッセージの意味を調べてみました。

`lstat` はファイルの状態を取得するコマンドです。
参考：[Debian / STAT(2)](https://manpages.debian.org/testing/manpages-ja-dev/lstat.2.ja.html)

`stale NFS file handle` は、「ファイルまたはディレクトリがサーバー上で削除されたか置き換えられました」という意味のエラーメッセージのようです。
参考：[Stale NFS file handle](https://docs.oracle.com/cd/E19455-01/806-2720/msgs-768/index.html)



https://www.scriptlife.jp/contents/programming/2018/11/02/docker-pull-error-response-from-daemon/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/9fadc995-b684-9df0-4391-47c8245ea1d4.png)



# `WORKDIR` を `mkdir` に変えてみたら `container_linux.go:346` のエラーになった

`WORKDIR /src/hello` がダメなのか？と思い、以下のように変えてみました。

```docker:Dockerfile
FROM node:12.3.1-alpine
RUN mkdir /src
```

実行してみたところ、別のエラーになりました！

```bash
$ docker-compose up
Building hello
Step 1/2 : FROM node:12.3.1-alpine
 ---> xxxxxxxxxxxxx
Step 2/2 : RUN mkdir /src
 ---> Running in xxxxxxxxxxxx
ERROR: Service 'hello' failed to build: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown
```

> OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown

このエラーメッセージについて調べたところ、以下のページを見つけました。

[docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "open /proc/self/fd: no such file or directory"](https://github.com/docker/cli/issues/297)

> You should go to Settings\Shared Drives and Reset credentials.

という助言があったので、やってみます。
この `Shared Drives` というのは Docker for Windows の設定項目で、Docker Desktop の場合は、 `File Sharing` を見に行くことになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/3c27b4b0-9233-67d2-b53c-d60c8b36ea5d.png)

`Resources > FILE SHARING > Reset credentials` をクリックします。
すると、 `C` や `D` のチェックが外れるので、もう一度チェックを入れ直し、 `Apply & Restart` をクリックします。

すると、以下のようにWindowsのユーザー名とパスワードを聞かれるので入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/1cf7bfc2-314d-9e49-6710-c9c6763424d7.png)

`Save` を押してリセットできるかと思いきや、なぜかもう一度同じダイアログが表示されました。
パスワードの入力ミスかな？と思い、正確にパスワードを入力しますが、何度やっても同じダイアログが繰り返し表示されました。



# 工場出荷状態までリセットしたらうまくいった

似たような事例がないか探したところ、少し違いますが、以下の記事を見つけました。
[Docker for Windows で Shared Drives のチェックが入らないときの対処法](https://qiita.com/Targityen/items/2c4840fc900d8f9ce11f)

どうやら、工場出荷状態まで戻して、設定しなおせば良いそうです。

**この先の手順通りに進めると、Dockerに関するすべての設定が消えますので、ご注意ください。**

まず、 `Reset to factory defaults` で、工場出荷状態までリセットします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/b5b446d9-54a6-6f60-ec32-557b80bf5208.png)

まっさらな状態になったら `FILE SHARING` 以外の項目（`ADVANCED` `PROXIES` `NETWORK`等）の設定をまず行ってから、 `Apply & Restart` をします。

リスタートが完了したら、 `FILE SHARING` の設定を行います。

先ほど同じ、 `Enter filesystem credentials` のダイアログが出ましたが、今度は１回だけでした！

先ほどのプロジェクトで `docker-compose up` を実行してみたところ、今度はエラーになりませんでした！



# さいごに
すごく遠回りしてしまいましたが、解決できてよかったです。

まとめると、以下の２点を守ればよさそうです。

- Docker Desktopを工場出荷状態まで戻す。
- `FILE SHARING` の設定は最後に実施する。

また、本記事の作成にあたり、以下の記事を参考にさせていただきました。ありがとうございました。

- [dockerで ERROR: readlink /var/lib/docker/overlay2/l: invalid argument と表示された時の対処法](https://qiita.com/robox0917@github/items/032ed9fc6b1112e275e5)
- [Docker for Windows で Shared Drives のチェックが入らないときの対処法](https://qiita.com/Targityen/items/2c4840fc900d8f9ce11f)
- [docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "open /proc/self/fd: no such file or directory"](https://github.com/docker/cli/issues/297)