どうもこんにちは。
AWS Elastic Beanstalk を使ってアプリケーションをデプロイしているときに、.ebextensions ディレクトリ内の設定ファイルで commands と container_commands の違いによってデプロイに失敗したので、備忘録として残しておきます。
commands でエラーが発生
Elastic Beanstalk のデプロイでエラーが発生しました。commands セクションに記述していた pecl install コマンドがうまく実行されていないようでした。
当初の設定は以下の通りです。
packages:
yum:
git: []
libyaml-devel: []
ImageMagick: []
ImageMagick-devel: []
commands:
01-wget:
command: "wget -O /tmp/ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/old-releases/ffmpeg-6.0-amd64-static.tar.xz"
02-mkdir:
command: "if [ ! -d /opt/ffmpeg ] ; then mkdir -p /opt/ffmpeg; fi"
03-tar:
command: "tar xvf /tmp/ffmpeg.tar.xz -C /opt/ffmpeg"
04-ln:
command: "if [[ ! -f /usr/bin/ffmpeg ]] ; then ln -sf /opt/ffmpeg/ffmpeg-6.0-amd64-static/ffmpeg /usr/bin/ffmpeg; fi"
05-ln:
command: "if [[ ! -f /usr/bin/ffprobe ]] ; then ln -sf /opt/ffmpeg/ffmpeg-6.0-amd64-static/ffprobe /usr/bin/ffprobe; fi"
06-pecl:
command: "if [ `pecl list | grep imagick` ] ; then pecl install -f imagick; fi"
container_commands に変更したら通った!
commands セクションを container_commands に変更したところ、無事にデプロイが成功しました。
変更後の設定はこちらです。
packages:
yum:
git: []
libyaml-devel: []
ImageMagick: []
ImageMagick-devel: []
container_commands: # ここが変わった!
01-wget:
command: "wget -O /tmp/ffmpeg.tar.xz https://johnvansickle.com/ffmpeg/old-releases/ffmpeg-6.0-amd64-static.tar.xz"
02-mkdir:
command: "if [ ! -d /opt/ffmpeg ] ; then mkdir -p /opt/ffmpeg; fi"
03-tar:
command: "tar xvf /tmp/ffmpeg.tar.xz -C /opt/ffmpeg"
04-ln:
command: "if [[ ! -f /usr/bin/ffmpeg ]] ; then ln -sf /opt/ffmpeg/ffmpeg-6.0-amd64-static/ffmpeg /usr/bin/ffmpeg; fi"
05-ln:
command: "if [[ ! -f /usr/bin/ffprobe ]] ; then ln -sf /opt/ffmpeg/ffmpeg-6.0-amd64-static/ffprobe /usr/bin/ffprobe; fi"
06-pecl:
command: "if [ `pecl list | grep imagick` ] ; then pecl install -f imagick; fi"
なぜ commands ではダメで container_commands ならOKだったのか?
この現象の鍵は、Elastic Beanstalk のデプロイプロセスにおける commands と container_commands の実行タイミングの違いにありました。
commands と container_commands の違いを理解する
AWS Elastic Beanstalk のドキュメントによると、これらのコマンドはデプロイの異なるフェーズで実行されます。
commands
- 実行タイミング: アプリケーションとウェブサーバーがセットアップされる前、かつアプリケーションコードが展開される前に実行されます。デプロイプロセスの非常に初期段階です。
-
用途: OSレベルのパッケージインストール (
yum,apt-getなど)、OS設定の変更、ユーザーの作成といった、アプリケーションコードに依存しない低レベルなシステム設定に適しています。 -
注意点: アプリケーションのコードがまだ展開されていないため、
commands内でアプリケーションのソースコードや、アプリケーションが依存するディレクトリ(例:/var/app/current)にアクセスしようとすると失敗します。また、環境変数も利用できない場合があります。
container_commands
-
実行タイミング: アプリケーションとウェブサーバーがセットアップされ、アプリケーションバージョンアーカイブが抽出された後、ただしアプリケーションバージョンがデプロイされる前に実行されます。つまり、アプリケーションコードが
/var/app/staging(またはcurrent) に展開された後に実行されます。 -
用途: アプリケーションコードに依存する操作、例えばデータベースマイグレーションの実行、アプリケーションのキャッシュディレクトリの作成、PHPの
pecl install、Node.js のnpm install、Python のpip installといった、アプリケーションのセットアップに必要なコマンドに適しています。 - 注意点: アプリケーションのソースコードにアクセスできます。環境変数も利用できます。
まとめ
Elastic Beanstalk の .ebextensions でコマンドを実行する際は、以下の点を覚えておきましょう。
-
commands: システムの初期設定やOSレベルのパッケージインストールなど、アプリケーション環境が整う前の処理に使う。 -
container_commands: アプリケーションコードのデプロイ後に実行されるため、アプリケーション固有のセットアップや依存関係のインストールに適している。
特に、特定の言語のパッケージマネージャ(PHPのpecl、Node.jsのnpm、Pythonのpipなど)を利用する場合は、そのランタイム環境が利用可能になっている必要があるため、container_commands を使用するのが正しいアプローチです。
もし、.ebextensions のコマンドでエラーが発生した場合は、そのコマンドが実行されるべきタイミングと、commands または container_commands のどちらがそのタイミングに合致しているかを改めて確認してみてください。