S3 + CloudFrontで静的サイトホスティングしたので作業ログを残す
AWSで静的サイトをホスティングする際の王道パターンと呼ばれているS3 + CloudFrontの構成、 今更ながら初めて構築したので作業ログを残しておく。
構成
こんな構成。
S3
まずはバケットを作る。本番用とStage用。
後から上書きするが、まずはローカルでindex.htmlファイルを作ってアップロードしておく。
今回はS3のファイルはpublicにせずCloudFront経由のみアクセスを許可するようにしたので、 S3の設定で「ホスティングの有効」はしない。
自分が作ってるときこの設定を有効にしていて、 CloudFront経由でAccess deniedで弾かれてハマった。
CloudFront
Distributionを作る
「Create Distribution」からWebの「Get Started」と遷移していく。
設定入力画面ではこんな感じの設定になった。
Origin Domain Name: テキストフィールドにフォーカスするとバケットがサジェストされるので何も考えずにそれを選択。
Restrict Bucket Access: Yesを選ぶと「Origin Access Identity」に自動で値がセットされる。
Grant Read Permissions on Bucket: 「Yes, Update Bucket Policy」を選ぶことでバケットポリシーも更新してくれる。
TTL: 普通にS3の静的ファイルを配信するだけなのでCloudFrontにキャッシュさせる時間を入れる。自分の場合は一ヶ月にした。
Compress Objects Automatically: Yes, ファイルのgzip配信を有効にする。
SSL Certificate: 独自ドメインを取ってSSLで配信する場合は設定する必要があるが今回は省略。
「Create Distribution」ボタンを押すとDistributionの作成が始まる。
完了するまでだいたい20~30分ほどかかる。
GitHub
普通にリポジトリ作る。
CircleCI
CircleCIからS3にファイルをアップロードする用のiamユーザーを事前に作っておく。
自分はユーザー名を「circleci」にした。
CircieCIのページに行って Add Project -> 設定 -> AWS Permission と遷移して 上記iamユーザーのAccess Key ID と Secret Access Keyを入力して保存しておく。
最終的に .circleci/config.yml はこんな感じになった。
version: 2 jobs: deploy: working_directory: ~/circle-ci docker: - image: circleci/node:latest steps: - checkout - run: name: Setup AWS credentials command: | sudo apt-get update && sudo apt-get install -qq -y python-pip libpython-dev curl -O https://bootstrap.pypa.io/get-pip.py && sudo python get-pip.py sudo pip install -q awscli --upgrade mkdir -p ~/.aws printf "[default]\nregion = ap-northeast-1\nnoutput = json" > ~/.aws/config printf "[default]\naws_access_key_id = ${AWS_ACCESS_KEY_ID}\naws_secret_access_key = ${AWS_SECRET_ACCESS_KEY}" > ~/.aws/credentials chmod 600 ~/.aws/* - run: name: deploy static files to s3 stage command: | if [ "${CIRCLE_BRANCH}" == "stage" ]; then aws s3 sync ./public s3://<your stage bucket>/ --delete fi if [ "${CIRCLE_BRANCH}" == "master" ]; then aws s3 sync ./public s3://<your prod bucket>/ --delete fi workflows: version: 2 deploy: jobs: - deploy
解説としては
- 無駄なファイルをS3に上げないように公開用のディレクトリを用意してそれをS3と同期するようにした
- stage, masterで別々のjobを用意する方法はうまくいかなかったので、commandでブランチの分岐を書いた
- awscli用のimageを用意しておけばよかったっぽい
いずれにしても、これでGitHubでstage, masterにマージされたタイミングでS3にファイルがアップロードされるようになった。
Lambda
CircleCIからS3にアップロードするだけだと不十分で、最新のファイルを配信するためにはS3のファイル更新時にCloudFrontのキャッシュをinvalidationしたい。 ので、S3のファイル更新をLambdaで検知してLambdaからCloudFrontにinvalidationする。
以下、lambdaのコード。
import json import urllib.parse import boto3 import os import time s3 = boto3.client('s3') def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) bucket = '<your bucket name>' key_orig = event['Records'][0]['s3']['object']['key'] key_path = "/" + urllib.parse.unquote_plus(key_orig, encoding='utf-8') print("bucket: " + bucket) print("key path: " + key_path) client = boto3.client('cloudfront') invalidation = client.create_invalidation(DistributionId=os.environ['CLOUDFRONT_DISTRIBUTION_ID'], InvalidationBatch={ 'Paths': { 'Quantity': 1, 'Items': [key_path] }, 'CallerReference': str(time.time()) })
stage, masterそれぞれのDistribution用にfunctionも作った。
おわり
書き疲れたのでこのへんで。
S3にファイルを上げるためにCIでコンテナ立ち上げるのはリソースの無駄使いな気がしてならないが、
まあ凝ったことしなければ無料で使えるから、自動化できる部分はできるだけ自動化しましょうということで。
「現場で役立つシステム設計の原則」読んだ
現場で役立つシステム設計の原則 〜変更を楽で安全にするオブジェクト指向の実践技法
- 作者: 増田亨
- 出版社/メーカー: 技術評論社
- 発売日: 2017/07/05
- メディア: Kindle版
- この商品を含むブログ (2件) を見る
読んだ。内容としてはDDD本の実践編という感じで非常に勉強になった。
自分は仕事でも趣味でも MVC + Service でレイヤを組んでwebアプリを作ることが多いんだけど、雰囲気でServiceをやってるように感じていつもモヤモヤしてた。
特にRailsだとどうしてもActiveRecordを中心とした作りになるから、業務ロジックがテーブル設計に引っ張られて疎結合にならない。
それに画面の設計にも引っ張られるとデータの加工なんかもServiceでゴリゴリやっちゃってコードの見通しが悪くなる。
そもそも自分が理解してたモデルの上位層としてのService、という位置付けがよくないのかもしれない。
オブジェクト指向設計の他には、プロジェクトにおける上流工程、テーブル設計、Web Api、マイクロサービスなどweb開発において抑えておくべきトピックをオブジェクト指向の観点から網羅的に書かれていて勉強になった。
Macでzipファイルにパスワードをかける
$ zipcloak <zip file> Enter password: Verify password:
ファイルの内容をgrepして行を絞り込む
Apacheのログを調べる必要があったのでメモ。
賢い人はFluentdやElasticsearchやKibanaを使ってます。使いたい。
$ grep -i <検索文字> <ファイル名> | cat $ grep -i "get /***" /var/log/httpd/access_log | cat
-i
オプションがあると大文字小文字を区別しない。
catする前に絞り込んだ行数を確認すると良いかも。
$ grep -i <検索文字> <ファイル名> | wc -l $ grep -i "get /***" /var/log/httpd/access_log | wc -l 10
Ubuntuでシステム日時を変更する
webサービスをテストするときに行ったオペレーション覚え書き
現在日時確認
$ date Wed Sep 13 05:03:32 UTC 2017
変更
$ date -s "09/30 18:00 2017" Sat Sep 30 18:00:02 UTC 2017 # 2017年9月30日18:00 にセット
変更確認
$ date Sat Sep 30 18:00:02 UTC 2017
Ubuntuでインストール済みのパッケージを確認する
ぜんぶ出す
$ dpkg -l
特定のパッケージだけ確認
$ dpkg -l | grep mysql
iTerm2起動時に複数窓を開く
1. 複数窓を開く
2. Window -> Save Window Arrangement
名前入力ボックスが出るので適当に設定。
3. Preferences -> General
Startup欄の「Open Default Window Arrangement」 を選択
Open profiles window を選択
4. Preferences -> Arrangements
先ほど設定した Window Arrangement を選択、Set Default で設定完了。