| @技術/プログラミング

docker-on-ecs.png

ブログを Docker 化して AWS ECS で運用するようにした。

なぜ Docker 化したか

  • 仕事で Docker を使う機会が増え知見がたまってきた
  • 仕事では Production 投入はできていないので個人ブログで Production 投入して知見を得ておきたかった

どうやったか

ローカルセットアップ編

  • Dockerfile & docker-compose.yml を作成した
    • Alpine Linux を使ってなるべくイメージを小さくする
  • Gem::LoadError 問題
    • Lokka の Gemfile には動的な読み込みを行っている部分があるため、 Dockerfile で単純に COPY するだけでは Gem::LoadError になってしまう。
      • Lokka のプラグインは Gem 化されておらずリポジトリ内に含める形式
      • プラグイン側で必要な gem はプラグイン内に Gemfile を配置して宣言する形式
      • Lokka 本体の Gemfile には Dir["public/plugin/lokka-*/Gemfile"].each {|path| eval(open(path) {|f| f.read }) } のようなコードがあって強引に eval で内容を取り込んでいる
    • 対策
      • Gemfile.docker を用意する
      • Gemfile.docker を生成するためのシェルスクリプトを用意して実行する
      • Dockerfile の COPY は以下のようにする
      • COPY Gemfile.docker /app/Gemfile
  • 他、 MySQL のコンテナを追加して手元でアプリが起動するところまでは確認済み

Production セットアップ編

  • ECR にリポジトリを作成し image を push (公式のチュートリアル通りにやればできる)
  • ECS にサービスやターゲットグループ、タスクの作成なども指示通りに行う
    • 土台となる EC2 インスタンスは手動で作るのではなく、 ECS の画面でポチポチやると勝手に作られる
    • 詳細コンテナ設定でエントリポイントを入力する欄に、 Dockerfile と同じように文字列で書いていたらコンテナが起動せずハマった
      • カンマ区切りで書かないといけないらしい
      • puma を起動したかったら bundle exec puma ではなく、 bundle,exec,puma というように書かないといけない スクリーンショット 2017-08-19 10.50.09.png
  • 諸々設定を済ませたらロードバランサー( ALB )を EC2 のパネルで作成してターゲットに Docker コンテナが動いている EC2 インスタンスを指定する
    • ECS の用語やサービス構成に慣れるのに時間がかかるが、歯を食いしばってがんばるしかない
  • DB に関しては RDS を使うことにした
    • 稼働中の VPS サーバーで mysqldump -ufoo -p db_name | mysql -ubar -p db_name -h foo.bar.ap-northeast-1.rds.amazonaws.com みたいな感じで雑に流し込んで移行する
  • ECS は VPC でしか使えないので、 VPC に慣れてない人は VPC に慣れるところから頑張るしかない
  • セキュリティグループの設定なども必要になるので頑張って下さい
  • Nginx を利用しないので SSL の復号を ALB で行う必要がある
    • ACM で無料で証明書を発行できるのを知らず、 Let's Encrypt の証明書を取り込んで使う
  • ここまでで一旦公開

運用して気づいた問題点

  • サイトが 503 や 504 になる
    • Docker コンテナがすぐ死ぬ
    • ALB から切り離されることしばしば
    • VPS 時代は Nginx に静的ファイルの配信をまかせていたが、 Nginx を挟まなくなったので puma が担当することになりアプリの負荷が高まったのではと推察
      • CloudFront を挟んでいい感じにキャッシュしてもらい、静的ファイルの配信は CloudFront にまかせることに

CloudFront 導入編

  • ALB で使っているのとは別に SSL 証明書を取得する必要がある
    • CloudFront <-> ALB 間の通信を HTTPS で行うため
    • Route53 で ALB に割り当てている A レコードをサブドメイン付きの別のものに変更
    • ALB 用にはワイルドカード証明書を使う(無料で証明書取得できる ACM 最高)
    • Let's Encrypt の証明書を使うのはやめ、ルートドメインの証明書も ACM で取得して CloudFront に設定
  • 動的コンテンツ( HTML など)はキャッシュしないようにしないといけない
    スクリーンショット 2017-08-19 11.32.04.png
    • 当初、設定がうまくいっておらず、以下のような問題が発生
      • POST, PUT, DELETE できない
      • Cookie が origin に転送されずセッションが維持できない
      • クエリストリングが無視されてしまい、ページ検索などができない

所感

  • 体感的にサイトの読み込みがチョッパヤになった
  • CloudFront 導入したが、まだ 503 にはなる
    • そもそもインスタンスを良いやつに変えないとダメなのかもしれない
    • タスク数を増やしてクラスタリングするなどいろいろ試してみる
      • クラスタリングするためには Cookie セッションではなく Redis や Memcached などをセッションストレージに使う必要が出てくる…
  • Deploy だるい問題
    • cap deploy しなくなり、イメージをビルドして push する感じになる
      • Alpine Linux でもそこそこイメージサイズはでかくなるので貧弱な回線では docker push にめっちゃ時間かかる
    • ECS 側でもサービスを更新するなどの作業が発生
      • Blue / Green Deployment できるがポチポチ作業が発生するのがだるい
      • Rails を運用する場合は migration なども発生するのでうまいことやる必要あり
    • git commit しなくても作りかけのコードの状態で docker-compose build してしまいがちになり、リポジトリのコードと動いてるコンテナイメージの間に差分が発生してしまいそう
      • ちゃんと CircleCI などを導入してイメージのビルドとプッシュは CI サービスでやる、というような運用にしないと破綻しそう
  • 手順書問題
    • こんな風にブログを書いて雑な手順書を作成するようではいけない。 Terraform 化しないと破滅する。
  • Lokka は CMS for Cloud です
    • git push heroku master するだけで使えることが売りの Lokka を AWS のガチな構成で運用するという皮肉
  • お金高い
    • 毎月 3000 円くらいかかる感じになりそう。 VPS は年払いで 16000 円くらいなのでだいぶ高い。払えなくなったら VPS に戻しそう。

謝辞

r7kamura さんの amakan Docker 化の一連の記事と Classmethod 社の ECS 関連の記事には大変お世話になりました。

| @WWW

Untitled

Docker で rep2 を動かす - portal shit!

なぜ 2016 年にもなって rep2 を使うのか。実は2ちゃんねるはほとんど見ていなくて、まちBBSを見ている。特に大人になってから他県から移り住んできたような人だと住んでる町に同級生や昔からの知り合いというのがいないので町のちょっとした情報というのがきわめて入って来にくい。近所の人たちは自分の親かそれよりも上の世代の人ばかりなのでなかなか気軽に情報交換するということもできない。となるとネットで情報収集したいと思うけど、そういうのができる場所はまちBBSしかないような気がする。

ブログは今どきやる気がある人しかやってないので情報が少ない。情報あったとしても福岡だと天神だとか博多だとか薬院だとか人が集まる場所の情報がほとんど。自分が住んでる町の情報にはなかなかたどり着けない。 Twitter は検索しても出てくる情報にばらつきがある。たとえば住んでる町の名前で検索しても、同じ地名が横浜や姫路にあったりして効率が悪い。そもそも Twitter は町の情報よりもその人の思ったこと、感じたこと、やってることがメインなので効率的に情報を収集できない。 Facebook は基本的に情報が閉じられているし、知らない人から情報を集めるというより知ってる人の近況を読む場所という感じ。 mixi はどうだろうかと思って、 10 年ぶりくらいにアカウントを作って自分が住んでいる町のコミュニティに参加してみたけど誰も人がいなくて閑古鳥が鳴いてた。

今年の梅雨頃、マチマチというウェブサービスできて地元の人とお店や病院の情報などをやりとりできるという話だったので、これこそ求めていたものだと思って飛びついたけど、お前がこの町の最初のユーザーだから一ヶ月以内に 5 人ユーザー集めろや、できなきゃマチマチ上のコミュニティは閉鎖な、という厳しいルールだった。嫁さんはこういうのは一切興味ないし近所の人はじいさんばあさんばかりなので当然 5 人もユーザーを集めることはできず終了した。そもそも近所に知り合いがいないからネットで情報を集めたいと思ってるのに知り合いはお前が人力で集めろというのは難易度が高いと思う。

まちBBSは30代以降みたいな人たちが皆好き勝手に自分が書きたいことを書いているけど、最近できたあの店はどうだとか、あそこの病院はよくないだとか、どこそこの店が閉店して別の店になる、移転する、などのような情報を仕入れることができる。当然匿名掲示板なので嘘やネイティブ広告(工作員による宣伝投稿)も時々はあるけど、まぁ読み手もそれは織り込み済みなので特に問題はない。少なくとも SNS よりかは格段に情報に触れやすい。掲示板はトピックが決まっていて、多少脱線することはあってもそのトピックについて話すので、福岡の今宿の話かと思っていたのに横浜の今宿だったみたいなことはないし、失恋してつらいさみしい、今年の夏に別れた彼氏と行った今宿の花火大会の写真です、みたいなおセンチツイートを目にすることもない。 2016 年になったいまでも掲示板が一番情報を集めやすいのかもしれないなぁと思った。

| @WWW

VPS 上で Docker を動かし、 rep2 1 入りのコンテナを運用するようにした。

ホストの 81 ポートをゲストの 80 ポートに向けてマッピングし、ホスト側の Nginx で localhost:81 にプロキシするようにした。

まちBBS のスレッドの >>1 の記事があぼーんになる現象を直したので快適に閲覧できるようになった。

https://github.com/yaasita/docker_rep2 を docker hub から pull してきて最新版の rep2 を使うようにちょこちょこっと修正し、共有ディレクトリ内のコンテンツを /var/www に置くように修正した。なのでホスト側で PHP を編集したものがゲスト側に反映されるし、コンテナを落としてもデータが残り続ける。最高便利。

Docker 、これまでなかなかユースケースが思いつかずいまいち便利さがわからなかったのだけど、手元に PHP 入れたくないとかごちゃごちゃしたセットアップしたくないとかいうときに異常に便利。 rep2 のようなレガシー PHP 環境が必要なソフトを動かすのにもってこいだと思う。

このブログも Docker で運用できないか考えてみたい。


  1. PHP 製のサーバーインストール型2ちゃんねるビューアー。 

| @ブログ

一時期に比べたら Lokka 使ってる人減ってて、 Jekyll/Octopress ブームのあとは Go lang 製のスタティックサイトジェネレーターかはてなブログに移っていってしまった。自分は自分で使うツールを自分でいじるのが好きなので Lokka 使い続けていきたい。ということでいろいろやった。

最近やったこと

テスト通るようにした

Lokka の master ブランチ、しばらくコミットされてなくて Travis CI のビルド 1 年半くらい走ってなかった。久々に Pull Request 出したらビルド成功しなかったので通るようにした。 Travis がコンテナベースの環境から Docker ベースに移行したぽくて、その影響で PostgreSQL がらみで bundle install がこけるようになってた。なのでテキトーに addon を追加しといた。

同じコミットでもうメンテナンスが終了している Ruby 1.9 系の CI をやめるようにした。

Ruby 2.2 に対応させた

json 1.5.5 は Ruby 2.2 系では install に失敗するようなのでいろいろ bundle update した。 ActiveSupport も 3.1 ではエラーが出てしまうので bundle udpate して 3.2 の edge にした。

XSS 直した

コメントで教えてもらったので直した。

ただ実はまだ完全には直せてないので近日中に直したいのだけどテンプレートをレンダリングする仕組みをまるっと変えないと直らなそうなので結構きびしい…。

これからやりたいこと

フロントエンドよくしたい

具体的にはプラグインに同梱された CSS や JavaScript とテーマのやつをくっつけて配信したい。 Asset Pipeline 的な。

高速化

なんか遅い。このブログのトップページのレスポンス返すのに 1 秒くらいかかってるの改善したい。 DB にインデックス張るのとクエリのチューニングかな。

ActiveRecord 化

Fjord の皆さんで開発が続けられていたけど停滞しているっぽい。 DataMapper 、耐えられないほど不便なわけでもないし ActiveRecord にない便利な機能もあるのだけど、 N+1 起こらないという触れ込みなのに N+1 起こったり、ちょっと込み入ったクエリを投げたいと思ったときにやり方がわからないもしくは出来ないということがあるので、 Ruby エンジニアの皆さんが日常的に使ってる ActiveRecord を使うようにするのが良いだろうと思った。そもそもあまりメンテもされてないし、 DataMapper に引きずられて Lokka が停滞するのも残念だし。高速化のためにも ActiveRecord 化有効そう。


最近「仕事外でコードを書かないエンジニアは人間のクズだ」、「いやクズはそっちだ、エンジニアの業務時間外の学習に依存する会社こそ真のクソ」みたいな議論多いけど、自分で使うツールのメンテナンスくらいやらないと本当にプログラマー廃業しないといけない気がするし、自分がプログラミングに触れたの自体 P_BLOG の改造がきっかけだったので、プライベートを犠牲にして歯を食いしばりながら取り組んでいきたい。