Windowsで"context requires credentials to be passed as environment variables"と表示された際のトラブルシューティング

# この記事は誰向けのものか

- WindowsでWSL2（Windows Subsystem for Linux）を導入済みである
- WindowsでDocker Desktopを導入済みで、WSLと連携してDockerコンテナを運用している
- WindowsでAWS Cliを導入済みで、WSLで運用しているDockerコンテナをAmazon ECSにデプロイしようとしている

上記の環境にて難題に苛まれた同僚を救うべく、奔走した際の記録を情報資産として書き残す。
仮に取り扱うOSがMac OSやLinuxであった場合にも、一部は参考となるので困ったら読んでほしい。

# ”Too Long; Didn't Read.”が欲しい方へ

- このエラーはdockerについて適切でないコンテキストが指定されている場合に発生するエラーメッセージである。AWSは関係があるようでない
- 安全かつ簡単確実な方法で解決するので安心してほしい
- `~/.docker/config.json` を編集して、利用するdocker contextを `"default"` にすれば治る

# 発生の経緯と症状

AWS Cliを導入したWindowsマシンでAmazon ECSの理解を深めるにあたり、Docker Docsの下記トピックにあるチュートリアルを順番にこなしていた。

https://matsuand.github.io/docs.docker.jp.onthefly/cloud/ecs-integration/

> **AWS コンテキストの生成**
`docker context create ecs myecscontext` コマンドを実行して AWS コンテキストを生成します。 すでに AWS CLI をインストールし設定を行っているのであれば、このセットアップコマンドにより、既存の AWS プロファイルを選んで Amazon への接続を行います。

その後、チュートリアルに従ってコマンドを入力しようとしたが、dockerを操作しようとしてもエラーが発生するようになってしまった。

```shell-session
PS C:\Users\owner> docker context use myecscontext

PS C:\Users\owner> docker context ls
context requires credentials to be passed as environment variables
```

こうなってしまうとDocker Desktopでもerror code 1が発生してしまい、操作できない。
WSL上でdockerの操作や復元を試みるも、効果なし。
「認証情報が必要だ」というエラーメッセージの内容に沿って `aws configure` での設定を行ったが、それでも改善しない。

```shell-session
PS C:\Users\owner> aws configure
AWS Access Key ID [****************AbCd]:
AWS Secret Access Key [****************dEfg]:
Default output format [json]:

PS C:\Users\owner> docker context ls
context requires credentials to be passed as environment variables
```

参考となる記事をようやく見つけ、認証情報を"dummy"と指定してdocker contextの設定変更を試みたが、今度はWindowsが「そのようなコマンドは知らない」とお手上げ状態になった。
```shell-session
PS C:\Users\owner> AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGION=dummy docker context ls
AWS_SECRET_ACCESS_KEY=dummy : 用語 'AWS_SECRET_ACCESS_KEY=dummy' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラ
ムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行
してください。
発生場所 行:1 文字:1
+ AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGIO ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (AWS_SECRET_ACCESS_KEY=dummy:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    + 
```
それもそのはず、参考とした記事はMac OSユーザー向けの情報、つまりUNIXベースだからWindowsが受け付けるコマンドではない。
試しにWSL上で入力すると適切にdocker contextの情報が表示される。そりゃ当たり前だが解決したいのはWindows上のDocker Desktopを操作できないという問題だ。これじゃない。

```shell-session
wsl@DESKTOP-ALQ1CMV:~$ AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGION=dummy docker context ls
NAME            DESCRIPTION                               DOCKER ENDPOINT                             KUBERNETES ENDPOINT   ORCHESTRATOR
default *       Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                       swarm
desktop-linux                                             npipe:////./pipe/dockerDesktopLinuxEngine
```

# 色々な解決策を試みた際に遭遇してしまった別の症状 "protocol not available"

「成る程、このdocker contextというものを`"default"`に再設定してやれば治るはずだ」と理解したのち、WSL上で設定を行ってみたが、WindowsのPowershellで操作するdockerコマンドには何も変化が現れなかった。

```shell-session
wsl@DESKTOP-ALQ1CMV:~$ AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGION=dummy docker context use default
default
Current context is now "default"

～～exit wsl～～

PS C:\Users\owner> docker context ls
context requires credentials to be passed as environment variables
```

「あれ？おかしいな。WSLが絡むと一筋縄ではいかないのか。ならばこちらでどうだろう」と`desktop-linux`に設定してみたが、そうすると今度はWSL上のdockerが **"protocol not available"** というエラーで一切動かなくなってしまった。一見、事態が悪化したように思えて「これはしまった」と内心焦った。

```shell-session
wsl@DESKTOP-ALQ1CMV:~$ docker context use desktop-linux
desktop-linux
Current context is now "desktop-linux"

wsl@DESKTOP-ALQ1CMV:~$ docker context ls
protocol not available
```

この状況を解決する方法を探ったところ、そもそもコンテキストを柔軟に切り替えることが可能なこと、その切り替えをコマンドで適切に行えなくなった場合は設定ファイルを書き換えればよいことがわかった。

https://matsuand.github.io/docs.docker.jp.onthefly/engine/context/working-with-contexts/
> 各コンテキストには、さまざまなクラスターやノードの管理に必要となる、エンドポイント情報やセキュリティ情報が含まれています。 `docker context`コマンドを使うと、そういったコンテキストを簡単に設定したり切り替えたりすることができます。

"protocol not available"の解決方法については「ホームディレクトリの `~/.docker/config.json` にコンテキストの指定が追記されているはずだから `"currentContext": "hoge-hoge"` の所を消してやればいいよ、ただしそれで前の行に余計なカンマが生まれてしまったらjsonの規則に合わせて削るんだぜ」という男前なコメントがstack overflowに残されている。

https://stackoverflow.com/questions/68764259/docker-protocol-not-available-after-context-change

たしかにWSLのホームディレクトリに `~/.docker/config.json` は存在し、`"currentContext": "desktop-linux"` の行は書き込まれていた。これを`"default"`に変更することでWSL上の問題は解決した。

ふむ…つまり？というわけでWindows側のホームディレクトリを確認してみる。すると果たしてそこに `~/.docker/config.json` は存在した。 **あるのか。WSL上のものとは別に。** [^1]

[^1]:Docker DesktopはWindows上にフロントエンドのアプリケーションを提供すると共に、dockerも同時に導入を行うためWSLとは別にconfig.jsonが生成されるのは自明の理なのであるが、WSL上のdockerばかり活用していたのですっかり失念してしまっていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/3bacbcbf-2c0b-8174-8abc-bb73b5e6e967.png)

# 問題の解決と「何が起こっていたのか」の図解

かくして、windows上のdocker configをvs codeで開き
```shell-session
PS C:\Users\owner> code .docker/config.json
```

`"currentContext": "myecscontext"` となっていた箇所を修正することでpowershellやDocker Desktopでのコンテナ操作が再び行えるようになった。一件落着した。


```json
{
  "credsStore": "desktop",
  "currentContext": "default"
}
```

そもそもの問題は、dockerが根本的に不備のあるcontextであっても「環境変数から渡される認証情報が必要です」というズレたエラーメッセージでミスリードを誘ってしまうことと、その異常事態についての代替案（defaultで動作させますか？など）を示さないこと、そしてそれが起きるとわかっていながら未指定のプレーンな `docker context create` のコマンド＝事の発端となるオペレーションミスを `Successfully` と言って通してしまうことだ。さらには `docker context use <コンテキスト名>` で切り替える際にもコンテキストファイルについて検証しない。 **もしも不備があれば一切の操作を受け付けなくなるという爆弾が仕込まれているというのに。** 
例えば、ファイルを生成するコマンドで必須の値がNULLだった場合でも「できました」と作成してしまうプログラムであれば、ぶっちゃけtouchコマンドで中身が空っぽの.sockファイルを作成するアレとやっていることは大差ない。そんなことでは前述のような症状に悩まされる開発者も多く発生するし、そのトラブルシューティングにかける人的リソース及び工数は開発のスケジューリングに確実な軋みを生じさせる。どれだけdockerおよびAmazon ECSの開発者の方々に正義や大義名分があったとしても、不親切な案内で入門者に苦労をかけるのは **同じ開発者として勘弁してくれ。** 私たちが人生で最も長く向き合うのはソースコードでも詳細設計書でも作業工程表でもガントチャートでもデバッグシートでもReadme.mdでもなく、誰かが残したダイイングメッセージとも取れるエラーメッセージなのだ…。

さて図解のほうだが、WindowsにWSLとDocker、さらにそれを管理するためのDocker Desktopを導入した状態のシステム構成をざっくりと図に表すと下図のようになる。
Docker Desktopのみをインストールした場合はWSLにDockerは付いてこないのだが、運用上WSLにもDockerをインストールしておくことが望ましい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/e8c68059-882e-d91b-f78b-f7d0c46103d0.png)
上記のような環境を構築すると、各OS毎にDockerがインストールされているので`./docker`フォルダにconfig.jsonがそれぞれ生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/f650b268-1387-7a0d-cac9-0addfc2801dc.png)
その状態で不備のあるdocker contextを作成して設定してしまうと、その環境ではdockerの操作を行えなくなってしまう。簡潔に言えば不正なプロファイルに切り替えてしまったので正しく動かない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/1d9d4d02-e1ca-b959-3154-353fcd3ec649.png)
今回は、不適切な設定を行ってしまったコンテキストを指定されたconfigファイルを直接編集してデフォルトのコンテキストを呼び出せるようにすることで、元の状態に戻すことができた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391505/d84c1f17-1983-93bb-7f22-98bc7982d1ab.png)
WSLとDockerという環境に慣れ親しんでいる人が少ない以上、こういった情報はニーズが少ないものと思われるが、まず調べるにあたってしばらく有益な関連情報が出てこなかったことを見るに困っている人は多いだろう。だいぶ情報量の多い、ディープな記事になってしまったけども役に立てられる人は役に立ててほしい。

# 参考とさせていただいた記事、Webサイト

問題の解決にあたり、次の記事を参考にさせていただいた。

直接な解決こそ至らなかったものの、これらの情報がなければWindows+WSL+Docker+AWS Cliという多くのエンジニアが挫折を経験するベリーハードモードな環境への知見を高められなかったのは事実である。ここに謝辞を示したい。どうもありがとう。



https://qiita.com/borashisan/items/c132ce30c01b292455c4