Rancher Desktopに乗り換えたらAWS SAM CLIでDocker未起動扱いになっていたのでトラブルシュートした

2023.08.18

初めに

Docker DesktopからRancher Desktopに切り替えてdockerコマンド周りは今までと同じように使えるな、
ということで見てたのですがふとSAM CLIを動かしてみようとした時にdockerを利用するlocal invokeサブコマンド動かない...となったのでトラブルシュートを備忘録として置いておきます。

% sam local invoke
Error: Running AWS SAM projects locally requires Docker. Have you got it installed and running?

原因

管理者権限でRnacher Desktopが実行されておらず所定の位置(/var/run/docker.sock)にソケットが作成していないためSAM CLI側からDockerが取り扱えていないことが原因でした。

詳細

Rancher Desktopを起動している状態でdockerコマンド自体は通るものの、SAM CLIの実行時にDockerが立ち上がっていない扱いとなっていました。

--debugオプションをつけてTracebackを見たところ以下のようになっていました。

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/aws-sam-cli/1.95.0/libexec/lib/python3.11/site-packages/urllib3/connectionpool.py", line 714, in urlopen
    httplib_response = self._make_request(
                       ^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/aws-sam-cli/1.95.0/libexec/lib/python3.11/site-packages/urllib3/connectionpool.py", line 415, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/opt/homebrew/Cellar/aws-sam-cli/1.95.0/libexec/lib/python3.11/site-packages/urllib3/connection.py", line 244, in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1286, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1332, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1281, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 1041, in _send_output
    self.send(msg)
  File "/opt/homebrew/Cellar/python@3.11/3.11.4_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/http/client.py", line 979, in send
    self.connect()
  File "/opt/homebrew/Cellar/aws-sam-cli/1.95.0/libexec/lib/python3.11/site-packages/docker/transport/unixconn.py", line 28, in connect
    sock.connect(self.unix_socket)
FileNotFoundError: [Errno 2] No such file or directory

No such file or directory???と思いながら直接コードにprint文を書き込んだところ、unix_socketで参照していた/var/run/docker.sock(Dockerのデフォルトで使われるパス)が存在していないことがわかりました。

% ls /var/run/docker.sock
ls: /var/run/docker.sock: No such file or directory

docker context lsを確認したところホームディレクトリ配下で動いているようです。

$ docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                              ERROR
default             Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rancher-desktop *   Rancher Desktop moby context              unix:///Users/xxxxx/.rd/docker.sock
# 別件ですがAPI動かないんですね...
% curl --unix-socket unix:///Users/xxxxx/.rd/docker.sock http://localhost/containers/json
curl: (7) Failed to connect to localhost port 80 after 0 ms: Couldn't connect to server

defaultに切り替える当然通信できない

% docker context use default
default
Current context is now "default"
% docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

解決

Rancher Desktopがユーザ権限で動いていると/var/run/ではなくホームディレクトリ配下にUNIXソケットが作られ稼働するようです。

# rootユーザ or deamonグループのみ書き込める
% ls -ld /var/run/
drwxrwxr-x  42 root  daemon  1344  8 17 19:47 /var/run/

Preferencesから変更できます。

確認のチェックは"without"です。
チェックを入れると管理者権限で起動しないことになるのでチェックを入れずにOKを入れる必要があります。

上記の設定をして起動し直すと切り替わっていました。

$ ls /var/run/docker.sock
/var/run/docker.sock
$ docker context ls
NAME              DESCRIPTION                               DOCKER ENDPOINT                              ERROR
default *         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rancher-desktop   Rancher Desktop moby context              unix:///Users/xxxxx/.rd/docker.sock
# こっちもcurlは通らなかった
$ curl --unix-socket unix:///var/run/docker.sock http://localhost/containers/json
curl: (7) Failed to connect to localhost port 80 after 0 ms: Couldn't connect to server

Runcker Desktopを停止しても/var/run/docker.sockは消えないようで、先ほどの管理者権限での起動のチェックを外して起動してもdefault側でも受け付けられるようです。

# 管理者起動を無効にして確認すると`rancher-desktop`側を使うようになっている
% docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                              ERROR
default             Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rancher-desktop *   Rancher Desktop moby context   
# ただしdefault側に切り替えても使える  
% docker context use default
default
Current context is now "default"
% docker context ls
NAME              DESCRIPTION                               DOCKER ENDPOINT                              ERROR
default *         Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
rancher-desktop   Rancher Desktop moby context              unix:///Users/xxxxx/.rd/docker.sock
% docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

無事local invokeも動きました。

$ sam local invoke
Invoking app.lambda_handler (python3.9)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.

Mounting /Users/xxxx/git/sam-app-default/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container
START RequestId: 875aeba1-b4e3-4885-9cee-a0aa67ded7e3 Version: $LATEST
END RequestId: 875aeba1-b4e3-4885-9cee-a0aa67ded7e3
REPORT RequestId: 875aeba1-b4e3-4885-9cee-a0aa67ded7e3	Init Duration: 1.42 ms	Duration: 516.23 ms	Billed Duration: 517 ms	Memory Size: 128 MB	Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world!!\"}"}%

終わりに

権限不足という初歩的なところですがSAM CLIに限らずDockerに依存するもので/var/run/docker.sockを固定で利用することはあるかと思いますので、起動しているのにうまく認識されていない?となった時はどこで通信を受け付けているかを一度確認してみてください。

付録: シンボリックリンクを貼ると

権限の問題だと気づかずRancher Desktopのしよう起因だと思い込んでいた時に実施していました。

# ユーザ権限で実行中
$ sudo ln -s /Users/xxxxx/.rd/docker.sock /var/run/docker.sock
$ docoker context use default
default
Current context is now "default"
# 一応動くらしい。
$ sam local invoke
Invoking app.lambda_handler (python3.9)
Local image is up-to-date
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.

Mounting /Users/xxxxx/git/sam-app-default/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container
START RequestId: 3bb0d2c0-82ad-4575-b832-6274c9c9e324 Version: $LATEST
END RequestId: 3bb0d2c0-82ad-4575-b832-6274c9c9e324
REPORT RequestId: 3bb0d2c0-82ad-4575-b832-6274c9c9e324	Init Duration: 1.71 ms	Duration: 456.87 ms	Billed Duration: 457 ms	Memory Size: 128 MB	Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world!!\"}"}%

色々やっているうちに再現しなくなりましたが特定の拡張機能か何かが足りずdocker-credential-helperをbrewでインストールしたら動いた...ということがあったので一応注意した方が良いかもしれないです。