暇人がPodman Desktop + devcontainerでlambdaをデバッグ実行できる環境を作る

記事タイトルとURLをコピーする

CI1の石井です。

年末年始は日頃溜め込んでたやりたいことを一気に消化できるため、昔からクリスマスもお正月も好きなイベントです。

今回は2022/11にリリースされたPodman Desktopというツールを試してlambdaをデバッグするところまでやってみたいと思います。

対象

本記事はVisual Studio Code(以下VScode)とその拡張のdevcontainerをある程度理解している前提で記載しています。

コンテナ初めての人でも画面や設定ファイルをコピーするだけでデバッグまで出来ればいいかなぁと思って記載しています。

Podmanについて

Podmanはコンテナエンジンの一つです。Red Hat社が中心に開発しています。 コンテナエンジンではDockerが有名ですが、大きな違いはデーモンプロセスの有無だと思います。 Dockerの場合、Dockerデーモンの上に各コンテナのプロセスが起動しますが、Podmanの場合は各コンテナのプロセスが独立して起動するという特徴があります。

参考:https://www.redhat.com/ja/topics/containers/what-is-podman

※RHEL8からはPodmanが使用でき、「docker」というコマンドが「podman」のエイリアスなので、既に使っている人も多いかもしれません

Podman DesktopはPodmanをGUIで操作できるソフトです。 無料で使えるため、Docker Desktopの代替品を探していた人はぜひお試しください。

Podman Desktopのインストール

公式の手順を見るとbrewを使った手順があるため、brewコマンドでインストールします。

brew install podman-desktop

※Windowsの方は公式手順の記載を参照してください。

※インストール後にアップデートが入っていたため、brewからアップデートを実行し無事起動完了、問題なければ下記の画面が表示されているはずです。

Podman Machineの設定変更

初期に起動しているVMのサイズが10GBしかなかったため、何回かbuildした所「no space left on device」のアラートが出てしまいました。 そのためディスクの容量を300GBまで増やしておきます。 またスペック的に余裕があるので特に理由はありませんがCPUとメモリも増やします。

podman machine stop
podman machine set --disk-size 300
podman machine set --memory 8000
podman machine set --cpus 4
podman machine start

これでコンテナを動かすPodman Machineのスペックに心配はなさそうです。 なお、Podman Machineは podman machine sshでログインすることができます。

podman machine ssh

[root@localhost ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           985M  168K  985M   1% /dev/shm
tmpfs           394M  5.6M  389M   2% /run
/dev/vda4       300G   12G  288G   4% /sysroot
tmpfs           985M     0  985M   0% /tmp
/dev/vda3       350M   96M  232M  30% /boot
tmpfs           197M  8.0K  197M   1% /run/user/501
vol0            932G  107G  743G  13% /Users/ishiinobuaki
tmpfs           197M     0  197M   0% /run/user/0
[root@localhost ~]# 

環境準備

Podmanの準備整ったところでlambdaのデバッグ環境を整備したいのですが、他の人と一緒にやるときに環境差分で時間食うことが嫌なので、基本開発は全てコンテナの中だけでやりたいと思っています。

つまり、pyhonのコンテナイメージを起動し、そこにLambdaを記載します。 そのためLambdaのデバッグはDocker in Dockerとなります。

なんだかめんどくさそう、と最初思ったのですがdevcontainer.jsonの記載だけでシンプルDocker in Dockerを実行できる環境を作れるみたいです。 https://github.com/devcontainers/features/tree/main/src/docker-in-docker

VScode設定変更

まずはdevcontainerにpodman経由でコンテナを起動させるように設定します。 VScodeの設定からDockerPathで検索してpodmanを入力します。

devcontainerの編集

ローカルのPCで適当にデモ用のディレクトリを準備します。

cd ~
mkdir PODMANdemo && cd $_
mkdir .devcontainer && touch $_/devcontainer.json $_/Dockerfile

devcontainer.jsonは下記で作成しました。

mountsの部分を見るとわかりますが、自身のローカルPCの.awsディレクトリをコンテナにマウントしてcredentialsをコンテナからアクセスできるようにしています。

特にAWSの環境に接続する必要がないならmountsは不要です。

{
    "name": "Existing Dockerfile",
    "build": {
        // Sets the run context to one level up instead of the .devcontainer folder.
        "context": "..",
        // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
        "dockerfile": "Dockerfile"
    },
        //いつも使いそうな拡張機能
    "extensions": [
        "ahebrank.yaml2json",
        "redhat.vscode-yaml",
        "amazonwebservices.aws-toolkit-vscode",
        "bibhasdn.unique-lines",
        "GrapeCity.gc-excelviewer",
        "janisdd.vscode-edit-csv",
        "kddejong.vscode-cfn-lint",
        "MS-CEINTL.vscode-language-pack-ja",
        "ms-pyright.pyright",
        "ms-python.python",
        "ms-python.vscode-pylance",
        "yzhang.markdown-all-in-one"
     ],
         //ローカルの~/.awsをコンテナの/root/.awsにマウント。
    "mounts": [
        "source=${localEnv:HOME}/.aws,target=/root/.aws,type=bind,consistency=cached"
    ],
         //lambdaのデバッグはDocker in Dockerで実行するため
    "features": {
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
    }
}

少し起動が遅くなりますがcloud9っぽい環境が欲しいと思い、Dockerfileは以下で作成しました。

FROM nikolaik/python-nodejs:python3.9-nodejs16

RUN apt-get update && apt-get install -y curl unzip

RUN npm install -g aws-cdk
RUN python3 -m pip install https://github.com/boto/botocore/archive/v2.tar.gz
RUN python3 -m pip install https://github.com/aws/aws-cli/archive/v2.tar.gz
RUN python3 -m pip install aws-sam-cli

devcontainer実行

VScodeから先ほど作成したPODMANDEMOのディレクトリを開き コマンドパレットから「Dev Containers: Rebuild Container」を実行します。

問題なくコンテナが起動すれば下記画像のような左下のSSHのアイコンがコンテナーのアイコンになっているはずです。

ターミナルからもdockerコマンドが実行できるようなので、環境の準備は良さそうです。

Lambda作成とデバッグ

早速テスト用のpythonファイルを作成するため、適当にsam initからサンプルを呼び出してみます。

sam init --runtime python3.9 --dependency-manager pip --app-template hello-world --name sam-app

問題なくコマンドが実行できればsam-appというディレクトリ配下にサンプルのapp.pyが作成されると思います。

devcontainer.jsonに既にpythonの拡張が入っているため、適当にブレークポイントを設定しておきます。

※VScodeの拡張がうまく機能していない場合は再度コンテナをrebuildしてみてください。

ただし、これだけではデバッグ用の構成ファイル(lunch.json)がありません。

template.ymlを開きLambdaのリソースの部分で「AWS: Add Debug Configuration」というホバーをクリックしてdebugの設定ファイルを生成します。

※コマンドパレットから「add sam debug configuration」と打ってもOK

自動的に「.vscode/lunch.json」が生成されます。

再度app.pyに戻りF5でデバッグ実行を開始するとブレークポイントで停止しました。

ここまで来れればあとはなんとかなりそうです。

.vscode/lunch.jsonの使いっぷりでLambdaのデバッグを制御できそうな感じがします、公式の書き方をみながら下記のようにlunch.jsonを編集してeventに値を渡してみます。

{
  "configurations": [
    {
      "type": "aws-sam",
      "request": "direct-invoke",
      "name": "sam-app:HelloWorldFunction",
      "invokeTarget": {
        "target": "template",
        "templatePath": "${workspaceFolder}/sam-app/template.yaml",
        "logicalId": "HelloWorldFunction"
      },
      "lambda": {
        "payload": {"json": {"HOGE": "hoge", "FUGA": "huga"},
        "environmentVariables": {}
      }
    }
  ]
}

app.pyを再度デバッグ実行してデバッグコンソールから「event 」を打ち込むとlunch.jsonに設定したpayloadの内容が反映されているようです。

まとめ

今までLimaというツールでdevcontainerを起動してlambdaを書いてました。 個人的にdevcontainer使えればどれでもいいかなぁと思ってたのですが、LimaはMacに導入する手順がややこしかったので、導入のしやすさから今後はPodman Desktopになりそうです。

また、いつの間にかdevcontainerでDocker in Dockerの環境構築が簡単になってて驚きました、昔はスクリプト使ってたような気がするのですが、アップデート早い・・・色々ウォッチしてキャッチアップ早い人はすごいなぁと思いました。