rista’s blog(旧)

株式会社リスタの技術?ブログ(旧)

Werckerでrails + elasticsearchのCI

CIにはwercker使っています。
werckerはDockerベースのCIサービスで、採用の理由は無料だからです。

werckerにはいろいろオシャレで便利な機能がある、
ようなのですが、すみませんぜんぜんわかりません。。。

最初はオシャレ機能を組み合わせていい感じに構築しようと思ったんですが、
ちょっとハマって面倒になって、けっきょく全部入りのDockerfileとwercker.ymlをベタ書きしました。。。

Dockerイメージ

githubにDockerfileにおいてDocker Hubに登録しています。

Dockerfileはこんな感じです。

FROM ubuntu:16.04

# OSのTimezoneをTokyoに
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo 'Asia/Tokyo' > /etc/timezone && date

# rubyとbundlerをインストール
RUN cat /etc/apt/sources.list | sed -e 's|http://[^ ]*|mirror://mirrors.ubuntu.com/mirrors.txt|g' > /tmp/sources.list && mv /tmp/sources.list /etc/apt/sources.list
RUN apt-get update && \
    apt-get install -y software-properties-common git-core build-essential autoconf curl \
      ruby ruby-dev zlib1g-dev libmysqlclient-dev imagemagick libmagickcore-dev libmagickwand-dev && \
    gem install bundler --no-doc

# elasticsearch用のjavaをインストール
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \
    echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" > /etc/apt/sources.list.d/webupd8team-java-trusty.list && \
    echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
    apt-get update && apt-get install -y oracle-java8-installer

# elasticsearchをインストール
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys D88E42B4 && \
    echo "deb http://packages.elastic.co/elasticsearch/2.x/debian stable main" > /etc/apt/sources.list.d/elasticsearch-2.x.list && \
    apt-get update && apt-get install -y elasticsearch=2.3.3

# rootパスワードを"root"に設定してmysql-serverをインストール
RUN echo "mysql-server mysql-server/root_password password root" | debconf-set-selections && \
    echo "mysql-server mysql-server/root_password_again password root" | debconf-set-selections && \
    apt-get -y install mysql-server mysql-client && \
    echo "character-set-server = utf8mb4" >> /etc/mysql/mysql.conf.d/mysqld.cnf && \
    echo "default-character-set = utf8mb4" >> /etc/mysql/conf.d/mysql.cnf

# feature spec用のphantomjsをインストール
ENV PHANTOMJS_VERSION 2.1.1
RUN apt-get install -y nodejs && \
    cd /tmp && \
    wget -q https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 && \
    tar jxf phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 && \
    mv phantomjs-$PHANTOMJS_VERSION-linux-x86_64/bin/phantomjs /usr/local/bin/phantomjs && \
    rm -rf phantomjs-$PHANTOMJS_VERSION-linux-x86_64.tar.bz2 phantomjs-$PHANTOMJS_VERSION-linux-x86_64

OS、MWのバージョンなどは極力本番環境に合わせてます。

wercker設定

githubと連携設定をして、レポジトリ直下に以下のようなwercker.ymlを置いています。

box: mikeda/rails-test-with-elasticsearch

build:
  steps:
    - script:
      name: start services
      code: |
        service elasticsearch start
        service mysql start

    - script:
      name: bundle install --without production
      code: bundle install --path $WERCKER_CACHE_DIR/bundle-install/

    - script:
      name: setup db
      code: |
        /bin/cp config/database-wercker.yml config/database.yml
        RAILS_ENV=test bundle exec rake db:create
        RAILS_ENV=test bundle exec rake db:migrate
        RAILS_ENV=test bundle exec rake joblist:db:import_master_tables

    - script:
      name: rspec
      code: bundle exec rspec

  after-steps:
    - slack-notifier:
      url: $SLACK_URL
      channel: dev
      username: wercker
      notify_on: "failed"

テスト用のdb設定(config/database-wercker.yml)はこんな感じ。

test:
  database: joblist_test
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_general_ci
  pool: 5
  username: root
  password: root
  socket: /var/run/mysqld/mysqld.sock

after-stepsではテストに失敗したときにだけslackに通知を送っていています。
SlackのIncoming WebHooksのURLはベタ書きせずにWerckerのEnvironmentで変数化していますが、
まぁincomingだしベタ書きでもいい気はします。

まとめ

CIにはWercker使っています。
無料でこれだけの機能が使えるのは非常にありがたいです。

普段はDocker全く使ってませんが、こういう外部サービスでも手元で動作確認した本番環境と同じOS、MWが使えるのは環境構築やデバッグが楽でいいですね。

初めての沖縄旅行

エンジニアの@mikedaです。
先日、人生初の沖縄旅行に行ってきました!

国際通りをぶらぶらして、
首里城みて、
那覇で豚しゃぶくって、
キングタコスでタコライス食って、
古宇利島でハートロック(嵐がCMに使ったハート型の岩)見て、
ちゅら海水族館いって、イルカショーみて、
いろんな沖縄料理とか、ソーキそばも食べて
夜はオシャレなコテージでゆっくりお酒飲んで、

という感じで2泊3日、沖縄を満喫してきました!!!




おっさん3人で!

不思議ですね、アタマに『おっさん3人で』をつけると全てがビミョウな感じにみえてきます。
※あと3日間ずっと雨降ってました

経緯

社長と営業の人と3人で飲んでたら、
自分『沖縄っていったことないですねー』、
社長『じゃあ今度いこうかー』、
自分『おー、いいですねー』
と、よくある飲み屋でのテキトーなやりとりがあったんですが、

次の日、社長からメールが。

9/7(水)~9/9(金)でどうでしょう。以下の便を予約して下さい
行き:9/7(水)13:00発
帰り:9/9(金)13:30発

自分は思いました。
本気だったのか。。。と。
※しかも平日3日w

まぁじゃあ行きますかということになったんですが、
ホテルやお店の予約、レンタカーの手配、運転まで全部社長がやってくれて、
自分はただただ沖縄を楽しませてもらいました。

f:id:mikeda:20160908110624j:plain:w500

f:id:mikeda:20160908132959j:plain:w500

f:id:mikeda:20160908150805j:plain:w500

f:id:mikeda:20160908164249j:plain:w500

まとめ

というわけで初めての沖縄旅行いってきました!

おっさん3人、ずっと雨、とちょっと残念な感じでしたが、
まぁ今回は予行演習ということで、次は彼女といきたいです。いないですが。

AWS、nginxでお手軽動的サムネイル

WEBサービスで使用するサムネイル画像、JOBLISTでは事前に作っておくのではなく、動的に生成しています。

オリジナル画像がhttps://d2ui2iytvnht76.cloudfront.net/sample.jpgだとすると、

f:id:mikeda:20160929094455j:plain

https://d2ui2iytvnht76.cloudfront.net/resize/100x100/sample.jpgで100px × 100pxに収まるように縮小した画像、

f:id:mikeda:20160929094501j:plain

https://d2ui2iytvnht76.cloudfront.net/crop/100x100/sample.jpgで100px × 100pxにピッタリ収まるように縮小&切り抜きをした画像、

f:id:mikeda:20160929094507j:plain

が取得できます。

やろうと思えばもっと複雑なことも出来ますが、今のところこのぐらいで事足りてます。

導入のためにやったことは、既に構築済みだったCloudFrontとnginxに設定を追加しただけです。

システム構成

前回のブログの構成図では画像配信部分の矢印を少しはしょりました。

実際はこんな感じで、

f:id:mikeda:20160929092606p:plain

/resize/、/crop/の場合だけ画像変換サーバを通るようになっています。

ELBと画像変換サーバはサービス用のELB、appサーバの流用です。

設定

CloudFront

CDN通さなくても動作はしますが、サーバ負荷や応答速度考えると使っておいたほうがいいかなと思います。

設定は手順としては、originにELBを追加して、

f:id:mikeda:20160929093224p:plain:w500

Behavior設定で/resize/、/crop/な場合のoriginをELBに変更するだけです。

f:id:mikeda:20160925181748p:plain:w500

画像変換サーバでVirtualHostを利用する場合は、Hostヘッダを転送してやるように設定します。

f:id:mikeda:20160929093642p:plain:w500

nginx

画像変換にはnginxのimage_filterモジュールを使っています。
このモジュールはubuntuやamazon linuxの標準のnginxパッケージに最初から入っているので、コンフィグ追加するだけで使えます。

server {
  listen 80;
  server_name xxx.cloudfront.net;

  location ~ ^/resize/(\d+)x(\d+)/(.*)$ {
    set $width $1;
    set $height $2;
    set $path $3;

    image_filter resize $width $height;
    image_filter_jpeg_quality 90;
    rewrite ^ /$path break;
    proxy_pass http://xxx.s3-website-ap-northeast-1.amazonaws.com;
  }

  location ~ ^/crop/(\d+)x(\d+)/(.*)$ {
    set $width $1;
    set $height $2;
    set $path $3;

    image_filter crop $width $height;
    image_filter_jpeg_quality 90;
    rewrite ^ /$path break;
    proxy_pass http://xxx.s3-website-ap-northeast-1.amazonaws.com;
  }
}

まとめ

AWS、nginxでお手軽に導入できる動的サムネイルについてでした。

昔は同じことするのけっこうたいへんでしたが、今はいろいろ楽になってありがたいです。

というわけでペタリ

JOBLISTのシステム構成と開発フロー

どうも最近おないた気味なエンジニアの@mikedaです。
今回はJOBLISTのシステム構成と開発フローについて書きます。

まず前提として、FWはRuby on Railsです。

システム構成

サービスインフラはAWS上に構築されていて、全体としてはざっくりこんな感じです。

f:id:mikeda:20160925174834p:plain

  • appサーバ上ではnginxとunicornが稼働
  • データストアはMySQL、Redis(セッション他)、Elasticsearch(検索)
  • 画像はS3に格納してCDN(CloudFront)経由で配信
  • AWS上の各コンポーネントはmulti-AZ冗長化
  • メール配信はPostfix -> SES。将来的には機能が豊富なSendgridに移行するかも
  • 監視はmackerelとNewRelic
  • itamae、roadwork等を使ってだいたいgithubでコード管理
  • フロント周りはjquery、coffeescript、scss、hamlなベーシックな感じ

要件が満たせるなら極力運用が楽なマネージドサービスを使っています。
ElasticsearchはAmazon Elasticsearch ServiceじゃなくEC2で自前運用ですが、
構築時は1系しか使えなかったのと独自辞書使いたかったのが理由です。

開発フロー

タスク管理にはzenhubを使っています。
タスクは全てgithubのissueにして担当者をアサイン、zenhub上で優先順位を調整します。

f:id:mikeda:20160925183529p:plain

開発はこんな感じで進めます。

  • ローカルで開発
  • githubにpush。Pull Request作成
  • werkerで勝手にCIが実行されて、失敗するとslackに通知が来る
  • CIとPull Requestのレビューが通ったらマージ
  • capistranoでデプロイ
  • issueをclose

デザインについても基本は同じです。
コーディングの前にデザイナさんとissue上で調整して、
固まったらSketchのデザインをzeplinにアップロードしてもらい、
開発者がzeplin見ながらコーディングします。

f:id:mikeda:20160925183757p:plain

まとめ

JOBLISTのシステム構成と開発フローについてざっくり書きました。
インフラの構築、運用も全て自分たちでやってます。

基本的にはあまり変わったことはしていなくて、よくあるちょいモダン環境だと思います。
現状は、

  • 自分(@mikeda)のスキルセット
  • 新しく入る人、突発的に手伝ってくれる人が極力少ない学習コストで作業に入れること

に最適化していますが、最適な技術は提供するサービスと状況、運用するメンバー次第だと思っているので、必要があればバシバシ変えていくつもりです。

ということで。

株式会社リスタの技術?ブログをつくりました

はじめまして、@mikedaです。
株式会社リスタでエンジニアをしてます。

というわけで、リスタの技術?ブログ作りました。

まぁ作ったのですが、株式会社リスタ求人サイト JOBLISTを立ち上げた、
ということについては昨日個人ブログで書いたので今日は挨拶だけです。

クックパッドを退職して株式会社リスタを立ち上げました

今後、会社とその技術のことについては、基本こっちで書いていきます。
よろしくお願いします!

※ブログやらスライドやらで見境なく採用アピールする人うっとうしいなー
と普段思ってるんですが自分のことになるとそんな余裕もないのでペタリ。。。