読者です 読者をやめる 読者になる 読者になる

go getで取得したcliツールのバイナリを持った軽量なDockerイメージをつくる

諸事情で欲しかった。

動機

といったところ。ちなみにAlpine Linuxはもともと組込系用途で利用されていたディストリビューションで、最近ではDockerイメージのベースディストリビューションとして広く利用されてます。

alpinelinux.org

Alpine glibc問題

Alpine Linuxを駆使してDockerイメージのダイエットに腐心されてる人ならわかると思いますけど、GoのバイナリをビルドしてAlpineコンテナ上で実行させるにはglibc問題を突破しなくてはならない。glibc問題によって何が起こるかというと、go getで取得してきたバイナリをシュッとAlpineベースのイメージに放り込んでも以下のようなエラーで実行できないというもの。

standard_init_linux.go:178: exec user process caused "exec format error"

Alpine glibc問題についてはちょくちょくWeb上で散見されて、皆が通るハマりどころみたいな感じになってます。

qiita.com

Alpine用のバイナリを錬成する

というわけで作ったのでどうやってるか説明。調理器具としてDockerとCircleCIを使う。

github.com

ビルド用のイメージを作る

まず、ビルド用のDockerfileを要してgo getしてgooseのバイナリを錬成するためだけのDockerイメージを作る。ベースイメージはgolangの公式イメージでAlpineベースのものを選べば手堅いだろうという考え。

Dockerfile.buildという名で用意してある。

FROM golang:1.7.4-alpine
MAINTAINER stormcat24 <stormcat24@stormcat.io>

RUN apk update && \
    apk add --virtual build-dependencies build-base git && \
    go get bitbucket.org/liamstask/goose/cmd/goose && \
    apk del build-dependencies && \
    rm -rf /var/cache/apk/*

リポジトリをアップデートし、ビルドに必要なものを取得し、bitbucketからgooseをgo getしてます。

次に、ベースイメージとして利用するgolang:1.7.4-alpineの全容を確認しておきます。

RUN set -ex \
    && apk add --no-cache --virtual .build-deps \
        bash \
        gcc \
        musl-dev \
        openssl \
        go \
    \
    && export GOROOT_BOOTSTRAP="$(go env GOROOT)" \
    \
    && wget -q "$GOLANG_SRC_URL" -O golang.tar.gz \
    && echo "$GOLANG_SRC_SHA256  golang.tar.gz" | sha256sum -c - \
    && tar -C /usr/local -xzf golang.tar.gz \
    && rm golang.tar.gz \
    && cd /usr/local/go/src \
    && patch -p2 -i /no-pic.patch \
    && patch -p2 -i /17847.patch \
    && ./make.bash \
    \
    && rm -rf /*.patch \
    && apk del .build-deps

着目して欲しいのはapk addでインストールしているmusl-dev。muslはCライブラリでAlpine Linuxではglibcではなくmuslを標準としてます。ちなみにAlpine Linux3.4ではapkからglibcをインストールすることも可能。 ちなみに前にCircleCI上でビルドしたGoのバイナリを動かすために、Alpineでゴリゴリっとglibcをインストールして実行するっていうのをやってた。今はそこまで苦労はしない。最終的にはAlpineでビルドしたバイナリを、別のAlpineのコンテナで動かすので今回はglibcの存在は気にせずビルドする。 

錬成したバイナリをコンテナから取得する

ここからはCircleCIの出番。Alpineでビルドしたバイナリは、当然Dockerコンテナ内に閉じられており、これを取り出す作業を行う。

dependencies:
  override:
    - "docker build -f Dockerfile.build -t $CIRCLE_PROJECT_USERNAME/goose-build:latest ."
    - "docker run $CIRCLE_PROJECT_USERNAME/goose-build:latest sleep 10":
        background: true
    - "docker cp `docker ps | grep goose-build | cut -f1 -d' '`:/go/bin/goose ."
    - ls -l

手順を解説すると、 * バイナリビルド用のDockerイメージをビルドする * 出来上がったイメージをrun。常駐するようなコンテナではないので、sleepで適当な秒数指定してwaitさせる * sleepはバックグラウンドで実行させる * sleep中に、docker cpを使ってコンテナからgooseのバイナリをホスト(ここではCircleCIのコンテナ)へコピーする

これでgooseのバイナリをコンテナから取り出せた。

実行用のイメージを作る

取り出したバイナリを実行用のイメージにシュッと放り込むことで最終成果物の完成。

これが本命のDockerfile

FROM gliderlabs/alpine:3.4
MAINTAINER stormcat24 <stormcat24@stormcat.io>

COPY goose /usr/local/bin

このDockerイメージをCircleCI上で生成し、DockerHubにPushしてる。

使ってみる

DockerHubに上がってるのでdocker runで以下のようにピロッと実行できる。 

docker run stormcat24/goose:latest goose --help

goose is a database migration management system for Go projects.

Usage:
    goose [options] <subcommand> [subcommand options]

Options:

Commands:
      -env string
        which DB environment to use (default "development")
  -path string
        folder containing db info (default "db")
  -pgschema string
        which postgres-schema to migrate (default = none)
up         Migrate the DB to the most recent version available
    down       Roll back the version by 1
    redo       Re-run the latest migration
    status     dump the migration status for the current DB
    create     Create the scaffolding for a new migration
    dbversion  Print the current version of the database

イメージサイズ

ビルド用イメージと、実行用イメージとではこれくらいの差ができた。ビルド用はもちろんGoがまるまる入ってるので300MB近くなった。実行用イメージの方は約17MBに💪

$ docker images | grep goose
stormcat24/goose         latest              30aba3bf1d17        56 minutes ago      16.8 MB
stormcat24/goose-build   latest              1c1103cadeb1        2 hours ago         299 MB

ビルド用のイメージから産業廃棄物を片っ端から削除する方法もあるが、かなりめんどくさいのでこれでいいと思う。

まとめ

ビルド用イメージ+CircleCI(別にCircleCIじゃなくてもいい)のあわせ技になるが、目的の軽量なイメージはこれで作れた。

本来はビルド、実行含めて1枚のDockerfileで完結することがポータビリティ的には良いわけだけど、ポータビリティとイメージの軽さはトレードオフな面があるので、ビルド用イメージをかますことで軽さとポータビリティ(COPYしてるので100点満点ではないが)をある程度確保できたと思ってる。

昼COMP生活を始めた

タイトルの通り、昼COMP生活をはじめました。

その前にCOMPって何やねんって方はこちらを参照されるとよろしい。

www.comp.jp

所謂、日本版ソイレントと言われているやつでヒトが生きるために必要な栄養素を一食で賄うことができるといわれている完全食である。

とりあえず会社に行ってるときの昼食をCOMPに置き換えることにした。昼はいつも軽食をコンビニで買ってきていたけど、ビルのエレベーター待ち時間が長くて往復する時間がタルいという事情もあった。というわけで、効率的に摂取できかつ栄養的にも良いと言われているCOMPに白羽の矢が立った次第。

これがCOMPのパッケージ。

f:id:a-yamada:20170110125614j:plain:w400

何で割るか

ポンジュース

オレンジジュース系も悪くないという体験談をチラホラ聞いたので、自宅では普段から愛飲しているポンジュースをキメた。

ポン ポンジュース 1L×6本

ポン ポンジュース 1L×6本

旨い。ただポンジュースは果汁100%で多少水溶性に難があるので、喉越しは多少重い感。それが気になるのであればちょっと水を加えるのが良いかもしんないです。

コーヒー

会社のディスカウント自販機にブラックコーヒーがあったのでこれで試した。

COMPが持つ豆乳の甘さも相まって、混ぜると甘さ控えめのカフェラテみたいな感じになった。自分はこれで十分旨いと感じたけど、もうちょっと甘みが欲しいという人はカフェラテで割っちゃうとか、シュガースティックとかガムシロップで甘みを追加すれば良さそう。

f:id:a-yamada:20170110122008j:plain:w500

感想

この手のもの、プロテインとかもそうで不味いのが普通な気がしているのだが不味くないのが良い。組み合わせ次第では十分満足できる気がしているので、自分にとって合う割り方を見つけると良いでしょう。あと、お腹が満たされる感がなかなか凄い。

とは言え食はそこそこ重要視してるので、さすがに3食COMPにするつもりは無い。噛むことはかなり重要なので今まで以上に朝夜で良い食事をすることを心がけたいところ。

最近のHTTP/2のproductionでの対応状況を雑に調べた

HTTP/2のプロダクションにおける採用状況を調べてみたかったので、有名どころのServiceを色々と巡回して対応状況を確認してみた。

調べ方は色々あるが、Chrome拡張のHTTP/2 and SPDY indicatorを使えばいい。青いイナズマ表記になればOK。

chrome.google.com

もちろんバックエンドのプロトコルについてはわからないので、Web面で対応されているものをHTTP/2対応として紹介します。

開発支援系

Slack

slack.com

Dropbox

www.dropbox.com

Mackerel

はてなは違うが、MackerelはHTTP/2。いつもお世話になっております。 

mackerel.io

SNSWebサービス

Twitter

まあそうですよね。

twitter.com

Facebook

まあそうですよね。

www.facebook.com

Instagram

Facebookがそうならインスタもまあそうですよね。

Instagram

メルカリ

さすがはメルカリといった感じ。

www.mercari.com

メルカリ アッテ

アッテもそうですよね。

www.mercariatte.com

AbemaTV

弊社グループのAbemaTVもHTTP/2。

abema.tv

FRESH!

我がFRESHもHTTP/2です。

freshlive.tv

Amestage

CA系でいえばAmestageもそう。

amestage.com

Twitch

ゲーム配信の雄、TwitchもHTTP/2。

www.twitch.tv

Wantedly

最近のリクルーティング市場といえばWantedly。GCPですよね確か。

www.wantedly.com

Moneytree

家計簿アプリで有名なMoneytree。こちらもWebがHTTP/2。

moneytree.jp

Suumo(スマホ

Suumo(スマホ版)はHTTP/2対応の模様。PC版は違った。

smp.suumo.jp

企業サイト・ブログ系

Developers.IO

天下のクラスメソッド様。Developers.IOはやはりHTTP/2対応

dev.classmethod.jp

CyberAgent Developers Blog

昨年リニューアルした弊社の開発者ブログ。アメブロじゃなくなったので。

developers.cyberagent.co.jp

Yahoo! JAPAN Tech Blog

Yahooさんのブログ。Yahoo! JapanはHTTPです。

techblog.yahoo.co.jp

面白法人カヤック

コーポレートサイトはまだそこまでHTTP/2の波が来てない印象だが、カヤックさんはされてた。

www.kayac.com

ヌーラボブログ

こちらはヌーラボさんのブログ。コーポレートも同ドメインなので、ブログと共にまるっとHTTP/2化されてる。

nulab-inc.com

Hashicorp

世界のHashicorp。サイトもカコイイ。

www.hashicorp.com

感想

HTTP/2はそもそもHTTPSが必須なので、まずフルHTTPS化を実現しないといけない。そのためそこそこ老舗のサービスになるとHTTP/HTTPS共存なんてのが普通なので、当たり前だがHTTP/2対応は新興のサービスの方がしやすい。

Webのパフォーマンスという意味で優位性のあったHTTP/2ですが、

www.seroundtable.com

どうやらSEO的にもお墨付きが来たと言っても良さそう。2017年は一気に対応サービスが増えるんじゃないかなー。