CDKのLambda Pythonを使う場合にRancher Desktopだけで動かなかったがPATHの指定方法が間違っていた

こんにちは。サービス部の武田です。CDKのLambda Pythonを使用する際、Rancher Desktopを使用していましたがPATHの指定方法によっては動かなかったので注意しましょう。
2022.12.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

2022-12-22 12:35 根本的なミスが発覚したため、本文の趣旨を変更しました。

こんにちは。サービス部の武田です。

新しいMacのセットアップをしていたところ、Rancher Desktopをインストールしてdockerコマンドは使えるようになったのに、CDKのビルドで失敗しました。いろいろ試してみたところ、Docker CLIを別途インストールすることで解決できました。Docker CLIのインストールでも解決できましたが、そもそもPATHの指定が間違っていました。

環境の前提

前提としてRancher Desktopはインストール済みです。

$ sw_vers
ProductName:	macOS
ProductVersion:	12.6.2
BuildVersion:	21G320

$ docker -v
Docker version 20.10.21-rd, build ac29474

$ type docker
docker はハッシュされています (/Users/username/.rd/bin/docker)

$ docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc., v0.9.1)
  compose: Docker Compose (Docker Inc., v2.14.0)

Server:
 Containers: 22
  Running: 22
  Paused: 0
  Stopped: 0
 Images: 17
 Server Version: 20.10.20
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc version: 5fd4c4d144137e991c4acebb2146ab1483a97925
 init version:
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 5.15.78-0-virt
 Operating System: Alpine Linux v3.16
 OSType: linux
 Architecture: aarch64
 CPUs: 2
 Total Memory: 3.829GiB
 Name: lima-rancher-desktop
 ID: IHQO:JWGB:5232:VBIQ:QLOL:VSSN:IGJ5:3UD5:T3QO:HME2:ZKFD:O2ND
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

CDKのビルド失敗

さて、この状態でユニットテストをしてみるとビルドに失敗します。

$ npm run test

> sample@0.1.0 test
> jest

 FAIL  test/sample.test.ts
  ● Snapshot Test

    spawnSync docker ENOENT

      68 |
      69 |     // Layers
    > 70 |     const layer = new lambdaPython.PythonLayerVersion(this, 'PythonLambdaLayer', {
         |                   ^
      71 |       layerVersionName: 'python-lambda-layer',
      72 |       entry: path.resolve(__dirname, './layer'),
      73 |       compatibleRuntimes: [lambda.Runtime.PYTHON_3_9],

      at dockerExec (node_modules/aws-cdk-lib/core/lib/bundling.js:1:5035)
      at Function.fromBuild (node_modules/aws-cdk-lib/core/lib/bundling.js:1:3660)
      at new Bundling (node_modules/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts:84:39)
      at Function.bundle (node_modules/@aws-cdk/aws-lambda-python-alpha/lib/bundling.ts:55:44)
      at new PythonLayerVersion (node_modules/@aws-cdk/aws-lambda-python-alpha/lib/layer.ts:63:22)
      at new SampleStack (lib/sample-stack.ts:70:19)
      at test/sample.test.ts:48:20

 PASS  test/sample-asset-bucket.test.ts

Test Suites: 1 failed, 1 passed, 2 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   1 passed, 1 total
Time:        3.434 s
Ran all test suites.

spawnSync docker ENOENT というエラーメッセージはDocker環境がない場合に出るエラーのようです。環境はあるはずなのに!ということでしばらくはまっていました。

Docker CLIをインストールして解決

Rancher Desktopを疑ったのですが、以前似た環境で動作していました。

当時の環境との差異を思い出してみて、以前はDockerをインストールしたあとでRancher Desktopをインストールしていました。というわけで、試しに次のコマンドを打ってインストールしてみました。

$ brew install docker

$ /opt/homebrew/bin/docker -v
Docker version 20.10.22, build 3a2c30b63a

再度実行。

$ npm run test

...
 PASS  test/sample.test.ts (33.107 s)

Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   2 passed, 2 total
Time:        33.339 s
Ran all test suites.

おお、動いた。

以下、追記

そもそもPATHの指定が間違っていた

Rancher Desktopをインストールした際、/Users/username/.rd/bin/にPATHを通します。自動設定を選択した場合は、.bash_profileなどに追加されます。今回私の場合は.bashrc管理の関係から手動で設定していました。

その際、次のように指定していました。

export PATH="~/.rd/bin/:$PATH"

しかしこれは間違いで、正しくは次のように指定します。

export PATH=~/.rd/bin/:$PATH

違いに気付いたでしょうか?"の有無が違います。実はシェル(ここではbash)では~"でくくるかどうかで出力が変わります。

$ echo "~"
~

$ echo ~
/Users/username

CDKの実行環境では~のままでは正しくPATHが解決できず、それでdockerコマンドを見つけられなかった。というのが真相のようです。

まとめ

似たモジュールであるLambda Nodejsでも同様のエラーが発生する可能性はあります。ただしNodejsの場合はesbuildをインストールするという方法もあり、Dockerに依存しない解決が可能です。Pythonの場合はそういった代替がないためきちんとDockerの環境を整える必要があります。

なぜDocker CLIをインストールすると解決できるのか、具体的な理由は追っていません。おそらくCDK内部でのコマンドの探索方法に原因があるものと思われます。

相対パスではなく絶対パスで指定すれば問題なく実行できました。指定方法には気をつけましょう。

なお、そもそもdockerコマンドではなく別の互換コマンドで実行したい場合にはCDK_DOCKERを使用する方法があります↓。