環境変数の管理
ECSでは、タスク定義の環境変数にセキュリティな情報を設定するのは推奨されてない。
http://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html#container_definition_environment
認証情報データなどの機密情報にプレーンテキストの環境変数を使用することはお勧めしません。
そこでAmazon EC2 Systems Managerのパラメーターストアで管理することにした。
パラメーターストアを使うことでKMSによる暗号化して管理できる。
コンテナがAWS環境のみでしか動かせなくなってしまうため、PARAMETER_STORE_PREFIXが設定されてる場合のみパラメーターストアで取得するようにした。
例
#!/bin/bash
set -e
PARAMETER_STORE_PREFIX=${PARAMETER_STORE_PREFIX:-}
if [ -n "$PARAMETER_STORE_PREFIX" ]; then
export SECRET_KEY_BASE=$(aws ssm get-parameters --name ${PARAMETER_STORE_PREFIX}.secret.key.base --with-decryption --query "Parameters[0].Value" --output text)
export DATABASE_URL=$(aws ssm get-parameters --name ${PARAMETER_STORE_PREFIX}.database.url --no-with-decryption --query "Parameters[0].Value" --output text)
export RAILS_LOG_TO_STDOUT=true
export RAILS_SERVE_STATIC_FILES=true
fi
exec "$@"
.bundle
log
tmp
node_modules
yarn-error.log
.byebug_history
app/assets/javascripts/bundle.js
config/database.yml
.env
.env.app
.env.db
.git
FROM alpine:3.7
ENV RAILS_ENV="production" \
NODE_ENV="production" \
NPM_CONFIG_PRODUCTION="false" \
RUNTIME_PACKAGES="bash ruby ruby-irb ruby-json ruby-rake ruby-bigdecimal ruby-io-console ruby-dev nodejs yarn libxml2-dev libxslt-dev mariadb-client-libs tzdata py-pip" \
DEV_PACKAGES="build-base mariadb-dev"
RUN apk add --update --no-cache $RUNTIME_PACKAGES && \
pip install --no-cache-dir awscli && \
mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN apk add --update --virtual build-dependencies --no-cache $DEV_PACKAGES && \
gem install bundler --no-document && \
bundle config build.nokogiri --use-system-libraries && \
bundle install --without development test heroku && \
apk del build-dependencies
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
RUN yarn install --network-concurrency 1 && \
yarn cache clean
COPY . /app
RUN yarn run build && \
bundle exec rake assets:precompile DATABASE_URL=nulldb://localhost SECRET_KEY_BASE=secret_key_base
EXPOSE 3000
ENTRYPOINT ["./docker-entrypoint.sh"]
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
新しいコンテナと切り替え
フロントにALBを置いて、動的ポートマッピングを有効にしておくと新しいコンテナを起動して古いコンテナを停止するとダウンタイムなしで切り替えられる。
デフォルトの一時ポート範囲は 49153 〜 65535 で、この範囲は 1.6.0 より前の Docker バージョンで使用されます。Docker バージョン 1.6.0 以降では、Docker デーモンは /proc/sys/net/ipv4/ip_local_port_range の一時ポート範囲 (最新の Amazon ECS 最適化 AMI では 32768 ~ 61000) を読み取ろうとします。
となっているので最新のDockerを使う場合はセキュリティグループのALBからのインバウンドを32768-65535番を許可すれば良い。
タスク定義
- 動的ポートマッピングを有効にさせるため、portMappingsにhostPortは設定しない
- awslogs-groupに指定した名前のCloudWatch Logsのロググループを作成しておく必要がある
例
[
{
"image": "<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/ktbpard-prod",
"name": "kptboard-prod",
"memory": 512,
"essential": true,
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"": "kptboard",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "kptboard"
}
},
"portMappings": [
{
"containerPort": 3000
}
],
"environment": [
{
"name": "AWS_DEFAULT_REGION",
"value": "ap-northeast-1"
},
{
"name": "PARAMETER_STORE_PREFIX",
"value": "kptboard.prod"
}
]
}
]
IAM ロール
AmazonEC2ContainerServiceforEC2RoleとSSMから取得できるポリシーを付ける
SSMから取得できるポリシー例
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "ssm:GetParameters",
"Effect": "Allow",
"Resource": [
"arn:aws:ssm:ap-northeast-1:<account-id>:parameter/kptboard.prod.*"
]
},
{
"Action": "kms:Decrypt",
"Effect": "Allow",
"Resource": [
"arn:aws:kms:us-east-1:<account-id>:key/alias/aws/ssm"
]
}
]
}