概要
AWS Codebuildで設定できる環境変数を使って、ビルド時にDjangoアプリ側へ変数を渡してあげる方法を紹介します。
前提
まず、Codebuild関連では環境変数の設定方法が2つあります。
①AWS CodePipelineのBuildステージでの環境変数
CodePipeline -> 編集する -> ステージを編集する -> 鉛筆マーク -> 環境変数
②AWS CodeBuildプロジェクトでの環境変数
CodeBuild -> ビルドプロジェクト -> ビルドの詳細 -> 「環境」編集 -> 追加設定 -> 環境変数の追加
今回は①の方で設定しています。
※上記設定手順について、以前書いた詳細な記事はこちら:
【AWS】CodePipelineからCodeBuildの環境変数を設定した場合の確認方法
AWS CodepipelineのBuildステージの環境変数は以下の通りです。
ちなみにここは入れすぎると以下のようにエラーになります。
環境変数の合計文字数は、1つのアクションに対して1,000文字がMAXみたいです。
[Member must have length less than or equal to 1000, Member must have length greater than or equal to 1]
②の「Codebuildプロジェクトレベルでの環境変数」でも設定できます。場所は上述の通りですが、画面では以下の箇所になります。
ビルドプロジェクトレベルで共通するものはそちらにする、とかでも良いかもしれませんが、あまりあちこちに環境変数があるのは後で面倒になりそうだなとも思いました。もし溢れてしまうほどある場合は、AWSのパラメータストアなど他のリソースを使って統一するのもありと思います。
ディレクトリ構成とbuildspec.yaml
構成は以下の通り(一部を抜粋)。
├── mysite
│ ├── manage.py
│ ├── sample(appディレクトリ)
│ └── mysite(projectディレクトリ)
│ ├── settings.py
│ └── constant.py
├── buildspec.yml
└── constant.py
mysite/mysite/constant.py
の中身はローカル環境で動くようにするため、以下のようにしています(ローカル用のdocker-compose.yaml
などでマウントしてあげればOK)。AWS環境にデプロイする際はこのファイルが上書きされる形になります。
HOST = 'mysql'
PORT = 3306
USER = 'root'
PASSWORD = 'root'
DATABASE = 'sample_db'
つまり、以下の順序ですね。
①buildspec.yaml
によってCodeBuildの環境変数が./constant.py
に書き込まれる
②そのconstant.py
がmysite/mysite/
下にコピーされる
③mysite/mysite/constant.py
のDB変数などに、Codebuildで設定されていた値が入る
(後述:④settings.py
などでfrom mysite.constant import DATABASE...
とすればDB情報がインポートできる)
version: 0.2
phases:
pre_build:
commands:
- echo DB_HOST=$DB_HOST >> constant.py
- echo DB_PORT=3306 >> constant.py
- echo DB_USER=$DB_USER >> constant.py
- echo DB_PASSWORD=$DB_PASSWORD >> constant.py
- echo DB_NAME=$DB_NAME >> constant.py
- cp constant.py mysite/mysite/
- echo Logging in to Amazon ECR...
- aws --version
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
commands:
- echo Build started on `date`
- echo Logging in to Docker Hub...
- docker --version
- docker login -u $USER_DOCKER -p $DOCKER_KEY
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:latest
- echo Writing image definitions file...
- printf '{"name:"mysite-web","imageURI":"%s"}' $REPOSITORY_URI:latest > imageDetail.json
- cat imageDetail.json
artifacts:
files:
- imageDetail.json
discard-paths: yes
どんな使い方があるのか
では、これらの変数は例えばどんな使い方があるのか?
まず、Djangoが接続するデータベース情報をsettings.py
で設定することができます。
以下のようにすれば、AWS環境にのみ重要な情報を保管しておける上、アプリケーションはmysite
ディレクトリにあるconstant.py
の情報を引っ張ってくることでDBに接続できます。
from mysite.constant import DATABASE, USER, PASSWORD, HOST
## 略
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': DATABASE,
'USER': USER,
'PASSWORD': PASSWORD,
'HOST': HOST,
'PORT': '3306',
'OPTIONS': {
'init_command':
'SET character_set_connection=utf8,collation_connection=utf8_unicode_ci'
}
},
}
もしくは、以下のようにpymysql
を使って接続することもできます。
import constant
import pymysql
def connect_db():
"""Return connection.
Returns:
connection (Connection class): Connection to the mysql
TypeError: Error when string is not Decimal
"""
return pymysql.connect(host=constant.DB_HOST,
user=constant.DB_USER,
passwd=constant.DB_PASSWORD,
db=constant.DB_NAME,
port=constant.DB_PORT,
charset='utf8mb4')