AWS Elastic Beanstalk を使うと、インフラの構築や管理が楽になり、アプリケーションの開発に集中できるのでありがたいです。ただ、環境依存の設定管理が不便に感じたので、一工夫してみました。
Beanstalkの環境プロパティが使いにくい
Elastic Beanstalkでは環境プロパティを使用して、アプリケーションを実行している EC2 インスタンスの環境設定を指定できます(参考)。これにより、例えば本番環境と検証環境でDBのhostを変える等が、Beanstalkだけでできるのかなと最初は思いました。しかし、これがやっかいで、以下の問題点がありました(あくまでPHPプラットフォームの話です)。
$_SERVER
orget_cfg_var
関数でしか、参照できない(環境変数として設定されるわけではない)- コマンド実行時には参照できない(FastCGI実行時のみ参照可能)
特にコマンド叩く時に参照できないのは致命的です。ということで、Beanstalkの環境設定について考えました。
試した方法
1. S3に環境設定ファイルを置いておいてDL
.ebextensions
に以下を配置すれば、指定したバケットから.envをDLしてくることができます。
Resources:
AWSEBAutoScalingGroup:
Metadata:
AWS::CloudFormation::Authentication:
S3Auth:
type: "s3"
buckets: ["elasticbeanstalk-ap-northeast-1-000000000000"]
roleName:
"Fn::GetOptionSetting":
Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
DefaultValue: "aws-elasticbeanstalk-ec2-role"
files:
"/tmp/.env":
mode: "000644"
owner: root
group: root
authentication: "S3Auth"
source: https://elasticbeanstalk-ap-northeast-1-000000000000.s3-ap-northeast-1.amazonaws.com/.env
DLした後は適切な場所に置くだけです。ただ、これだと環境による使い分けができないです。。。
この方向で行くなら、複数のenvファイルをs3に置いておいて、環境プロパティを見てDLするファイルを変えれば、使い分けできると思います。しかし、それなら環境プロパティからenv作った方が楽かな?と思いました。
2. 環境プロパティの値から、環境設定ファイルを生成
環境プロパティに設定した値を参照して、.envを生成します。環境プロパティは環境ごとに設定できるので(当たり前)、これなら使い分けもできて管理も楽そうです。
#!/bin/sh
EB_META_DATA_FILE=/tmp/metadata.json
STACK_ID=`sudo cat /opt/elasticbeanstalk/config/ebenvinfo/stackid`
REGION=`sudo cat /opt/elasticbeanstalk/config/ebenvinfo/region`
sudo /opt/aws/bin/cfn-get-metadata -s ${STACK_ID} -r AWSEBBeanstalkMetadata --region ${REGION} -k "AWS::ElasticBeanstalk::Ext" > ${EB_META_DATA_FILE}
ENV_VARS=`jq -r '.Parameters.EnvironmentVariables' < ${EB_META_DATA_FILE}`
echo ${ENV_VARS} | jq -r 'to_entries[] | [.value] | join("")' > .env
rm ${EB_META_DATA_FILE}
ちょっと頑張ってますが、上記のスクリプトを配置してデプロイすればアプリケーションのルートディレクトリに.envが作成されます。
試してみる
環境プロパティの設定です。

デプロイ後、インスタンスに入って確認してみます。
$ cat /var/www/html/.env
EB_ENV=test
DB_HOST=hogehoge
SECRET=secretdayo
これで環境プロパティをLaravelやphpdotenvで便利に使うことができます。
まとめ
Elastic Beanstalkでの環境プロパティの使い方について検討しました。個人的には扱いやすくなったかと思います。ご参考までに。