レイヤーとルビー


最近、Rubyでラムダ関数を使っていくつかのことを作ってきました.これらのいくつかはスタンドアロン機能であり、いくつかはより複雑なスタックとして機能し、複数の関数が一緒に動作し、通常多くの一般的な依存関係を持ちます.
これは、それぞれの上で以来、仕事に迷惑ですsam build 呼び出しバラーは、これらの依存関係を再ダウンロードして再インストールすることでした.
あなたが機能のうちの1つだけを変えたとしても.私がスタックで4 - 5の機能に着いた頃には、それは本当に速い反復を遅くし始めていました
それはとても有益です.これは私の考えを得た-私はすべての機能によって使用された層にベンダーバンドルを置くことができる?

それらをすべて支配する1つの宝石ファイル
初めに、私のディレクトリはこれのようにほとんど見えませんでした1
.
├── Gemfile
├── Gemfile.lock
├── function1
│   ├── Gemfile
│   ├── Gemfile.lock
│   └── app.rb
├── function2
│   ├── Gemfile
│   ├── Gemfile.lock
│   └── app.rb
└── template.yaml
私が最初にしたことは、レイヤーをビルドするために使うことができる一つのファイルにジェムファイルをマージしたことです.これが機能を使用しているものから決して発散しないことを確認するために、私はトップレベルでこれを加えて、各々の機能にそれをシンボリックにしました2 . それからフォルダを追加しましたdependencies 私のレイヤーでは、gemfileとgemfileだけを含んでいます.ロック(シンボリックリンクとしても)、テンプレートにレイヤ自体を追加します.
Dependencies:
  Type: AWS::Serverless::LayerVersion
  Properties:
    LayerName: !Sub "${AWS::StackName}-dependencies"
    ContentUri: dependencies/
    CompatibleRuntimes:
      - ruby2.7
    LicenseInfo: 'MIT'
    RetentionPolicy: Retain
  Metadata:
    BuildMethod: ruby2.7
それぞれの関数は、この新しいレイヤーを使用するように言わなければなりません.
Layers:
  - !Ref Dependencies
sam build / sam deploy ランOK -これはすべて簡単すぎるようだ!

楽園のトラブル
残念なことに、私は同時に壊れて、彼らを遅くしました:
  • sam build それでも、私の関数ディレクトリの各々にバンドルを走らせたいです
  • レイヤーはルビーがそれらを探している宝石を置かないthis issue )
  • 層は、テスト/開発ものを含むすべての宝石をインストールしました
  • それぞれの関数からGemfileを削除するだけで最初の問題を修正することができますが、私はそれをしたくなかった
    GemとRubyの正しいバージョンがインストールされ、依存関係のヘルの様々な形式を回避するために動作します.
    幸運にも道があります:一方sam build 指定されたランタイム(Ruby用のバンドルを走らせる、PythonなどのPIPを実行する)の既定の構築方法を持っている場合、ビルドメソッドを「makefile」に設定することでこれをオーバーライドできます.この場合、代わりにmakeを実行します.これはcustom runtimes しかし、ここでもかなり便利です.
    この結果、次のようになります
    Function1:
      Type: AWS::Serverless::Function
      Properties:
        CodeUri: function1/
        Handler: app.lambda_handler
        Runtime: ruby2.7
        Layers:
          - !Ref Dependencies
      Metadata:
        BuildMethod: 'makefile'
    
    そして、ソースをコピー先ディレクトリにコピーする
    build-Function1:
      cp -pLR . "$(ARTIFACTS_DIR)"
    
    あなたはほとんど面倒なしかし、OKであるほぼ同一のMakefileの束で終わる.Makefileは、タブではなく、スペースを使用する必要があることを忘れないでください!

    ファインディングニモ
    第二の問題を研究しながらpost
    ジョシュカーンによって、まさに私が欲しかったように思えました:バンドルを走らせるカスタムメイドのMakefileを使っている層を構築してください、そして、宝石がルビーの検索経路にあるように、出力をまわりに動かしてください.
    閉じるこの動画はお気に入りから削除されています.残念ながら、gitからgemsビルドとしてインストールするプライベートコードがありますので、アプローチは全く動作しません.結局、バンドルはほとんどそのことをやります.
    build-Dependencies:
      BUNDLE_WITHOUT="development:test" bundle install "--path=$(ARTIFACTS_DIR)/ruby/lib/vendor/bundle"
      rm -rf "$(ARTIFACTS_DIR)/ruby/lib/vendor/bundle/ruby/2.7.0/cache"
      rm -rf "$(ARTIFACTS_DIR)/ruby/lib/vendor/bundle/ruby/2.7.0/bin"
    
    この用途BUNDLE_WITHOUT 不要な宝石のインストールを避ける--path インストール場所を制御します.最後の二つrm-rf 不要なファイルを削除するだけで展開パッケージを少し小さくします.
    ラムダ関数ではGemを見ることができないので、これは十分ではありません.また、開発/テスト専用の宝石を見つけることを期待すべきではないことを知っていないので、それについても文句を言うでしょう.マジックステップを作成することです.これらの内容を持つそれぞれのラムダ関数のバンドル/設定
    ---
    BUNDLE_DEPLOYMENT: "true"
    BUNDLE_WITHOUT: "development:test"
    BUNDLE_PATH: "/opt/ruby/lib/vendor/bundle"
    
    これは三つあります.
  • 展開モードにバンドルを置きます.ロックは同期しない
  • Bunlerが開発/テストグループでgemsを無視するように伝えます
  • Gemがインストールされていることを示す
  • ラムダ関数は、層から宝石を読み込むことができます.

    概要
    私はこれでかなり満足です-私が始めたとき、それは私が持っていたすべてのゴールを達成しました:
  • 機能と生産における一貫した一貫した宝石ファイル
  • バンドルは1回だけの呼び出しの実行sam build
  • バンドルはまだ宝石バージョンなどを実施する.
  • 最近組み合わせるsam build --cached 機能(サム1.9.0以降)より良い取得:バンドルは、Gemfile/Gemfile場合のみ実行されます.ロックが変更されました.中--cached このやり方で隔離された依存関係がなくても、独自にすべてクールになっているので、少なくとも1つのファイルが変更されている関数ごとにバンドルを実行しますsam has
    ファイルの変更についての知識はない.
    あなたがこれで遊ぶことを望むならば、私はAを作りましたvery simple repo これはこれを示している.
    私は別のgemfilesが好きではありません.一度に私はToplevel Gemfileに何かを追加しました(仕様を走らせるために使用されます)が、関数ごとのgemfileではないので、私の眼鏡が緑であったけれども、依存症は展開されるとき、依存しませんでした.関数ごとにエラーが発生しました.なぜなら、関数ごとのファイルにはRubyの制約がありますが、トップレベルのものがなかったか、2つの関数が誤って同じ依存関係の異なるバージョンで終わるからです.理論的には何も間違っていませんが、関数間のそれらの変化が存在しない場合、私はそれをはるかに容易に見つける.畝
    あなたが走る必要があるならば、これらのシンボリックリンクは壊れますsam build -u - 私の回避策は、全てのSAMビルドプロセスをDocker-u でね.畝