GoサーバーをDockerでデプロイする
Deploying Go servers with Docker by Andrew Gerrand
はじめに
今週、DockerはGo言語や他の主要言語向けの公式ベースイメージを発表し、 プログラマがGoプログラム用のコンテナを構築するための信頼できる簡単な方法を提供しました。
この記事では、単純なGoのWebアプリケーション用のDockerコンテナを作成し、そのコンテナをGoogle Compute Engineに デプロイする一連の手順を見ていきます。Dockerに馴染みがない方は、読み進める前に Understanding Dockerを読んでおくとよいでしょう。
デモアプリケーション
デモには、Goのサンプルリポジトリにある outyetというプログラムを使います。これは、 次のバージョンのGoがリリースされたかどうかを報告する単純なWebサーバーです (isgo1point4.outyet.orgのようなサイトを支えるために設計されたものです)。 標準ライブラリ以外への依存はなく、実行時に追加のデータファイルも必要としません。 Webサーバーとしては、これ以上ないほど単純なものです。
「go get」を使って、outyetをワークスペースに取得してインストールしましょう。
$ go get golang.org/x/example/outyet
Dockerfileを書く
outyet ディレクトリの中に、Dockerfile という名前のファイルを次の内容で作成します。
# Debianイメージをベースに、最新版のGoがインストールされ、
# /go にワークスペース(GOPATH)が設定された状態から始める
FROM golang
# ローカルのパッケージファイルをコンテナのワークスペースにコピーする。
ADD . /go/src/golang.org/x/example/outyet
# コンテナの中でoutyetコマンドをビルドする。
# (依存パッケージの取得や管理は、ここで手動で、あるいは"godep"のような
# ツールを使って行うこともできる。)
RUN go install golang.org/x/example/outyet
# コンテナ起動時にデフォルトでoutyetコマンドを実行する。
ENTRYPOINT /go/bin/outyet
# このサービスがポート8080で待ち受けることを明示する。
EXPOSE 8080
この Dockerfile は、outyet を実行するコンテナをどのように構築するかを指定しています。
基本的な依存関係(GoがインストールされたDebianシステム。公式の golang Dockerイメージです)
から始めて、outyet パッケージのソースを追加し、それをビルドし、最後にそれを実行します。
ADD、RUN、ENTRYPOINT のステップは、どのGoプロジェクトにも共通する作業です。
これを簡略化するために、golang イメージには
onbuild バリアントというものが用意されており、
パッケージのソースを自動的にコピーし、アプリケーションの依存関係を取得し、プログラムをビルドし、
起動時に実行されるように設定してくれます。
onbuild バリアントを使うと、Dockerfile はずっとシンプルになります。
FROM golang:onbuild
EXPOSE 8080
イメージをビルドして実行する
outyet パッケージのディレクトリからDockerを呼び出し、Dockerfile を使ってイメージをビルドします。
$ docker build -t outyet .
これにより、Docker Hubから golang ベースイメージが取得され、パッケージのソースがその中にコピーされ、
パッケージがその中でビルドされ、出来上がったイメージには outyet というタグが付けられます。
出来上がったイメージからコンテナを実行するには、次のようにします。
$ docker run --publish 6060:8080 --name test --rm outyet
--publish フラグは、コンテナのポート 8080 を外部ポート 6060 として公開するようDockerに指示します。
--name フラグは、コンテナに扱いやすい名前を付けます。
--rm フラグは、outyetサーバーが終了したときにコンテナイメージを削除するようDockerに指示します。
コンテナが起動している状態で、Webブラウザで http://localhost:6060/ を開くと、次のような画面が表示されるはずです。

(Dockerデーモンが別のマシン(あるいは仮想マシン)上で動いている場合は、localhost の部分をそのマシンの
アドレスに置き換えてください。OS XやWindowsでboot2dockerを使っている場合は、
boot2docker ip でそのアドレスを確認できます。)
これでイメージが動作することを確認できたので、別のターミナルウィンドウから実行中のコンテナをシャットダウンしましょう。
$ docker stop test
Docker Hubにリポジトリを作成する
先ほど golang イメージを取得した先であるコンテナレジストリのDocker Hubには、
GitHubやBitBucketのリポジトリからイメージをビルドしてくれるAutomated Buildsという機能があります。
Dockerfileをリポジトリにコミットし、 それに対してautomated buildを作成しておけば、 Dockerがインストールされている環境であれば誰でも、たった1つのコマンドでこのイメージをダウンロードして 実行できるようになります。(この利点は次の節で確認します。)
Automated Buildを設定するには、DockerfileをGitHubやBitBucket上の 自分のリポジトリにコミットし、Docker Hubにアカウントを作成した上で、 Automated Buildの作成手順に従ってください。
設定が完了したら、automated buildの名前を使ってコンテナを実行できます。
$ docker run goexample/outyet
(goexample/outyet の部分は、自分で作成したautomated buildの名前に置き換えてください。)
コンテナをGoogle Compute Engineにデプロイする
Googleは、任意のDockerコンテナを実行する仮想マシンを簡単に立ち上げられる コンテナ最適化されたGoogle Compute Engineイメージを提供しています。 インスタンスの起動時には、そのインスタンス上で動作するプログラムが設定ファイルを読み込み、 実行するコンテナを特定した上でコンテナイメージを取得して実行します。
実行するDockerイメージと公開するポートを指定したcontainers.yaml ファイルを作成します。
version: v1beta2
containers:
- name: outyet
image: goexample/outyet
ports:
- name: http
hostPort: 80
containerPort: 8080
(ここでは、コンテナのポート 8080 を、HTTPトラフィックを扱うデフォルトのポートである外部ポート 80 として
公開している点に注意してください。また、goexample/outyet の部分は自分のAutomated Buildの名前に
置き換える必要があります。)
コンテナを実行するVMインスタンスを作成するには、gcloudツールを使います。
$ gcloud compute instances create outyet \
--image container-vm-v20140925 \
--image-project google-containers \
--metadata-from-file google-container-manifest=containers.yaml \
--tags http-server \
--zone us-central1-a \
--machine-type f1-micro
最初の引数(outyet)はインスタンス名を指定しており、管理上のわかりやすいラベルとして使われます。
--image と --image-project フラグは、使用する特別なコンテナ最適化システムイメージを指定します
(これらのフラグはそのままコピーしてください)。
--metadata-from-file フラグは、作成した containers.yaml ファイルをVMに渡します。
--tags フラグは、VMインスタンスにHTTPサーバーというタグを付け、パブリックなネットワークインターフェースの
ポート80を公開するようファイアウォールを調整します。
--zone と --machine-type フラグは、VMを実行するゾーンとマシンの種類を指定します
(マシンの種類とゾーンの一覧を見るには gcloud compute machine-types list を実行してください)。
コマンドの実行が完了すると、gcloudコマンドはインスタンスに関する情報をいくつか出力します。
その出力の中の networkInterfaces セクションを見つけて、インスタンスの外部IPアドレスを確認してください。
数分もすればそのIPアドレスにWebブラウザからアクセスでき、「Has Go 1.4 been released yet?」というページが
表示されるはずです。
(新しいVMインスタンスで何が起きているかを見るには、gcloud compute ssh outyet でsshログインできます。
そこで sudo docker ps を実行すると、どのDockerコンテナが動作しているかを確認できます。)
もっと知りたい方へ
これはまだほんの入り口にすぎません。Go、Docker、そしてGoogle Compute Engineを使ってできることは、 まだまだたくさんあります。
Dockerについてもっと知りたい方は、詳細なドキュメントを参照してください。
DockerとGoについてもっと知りたい方は、公式の golang Docker Hubリポジトリや、
Kelsey HightowerによるOptimizing Docker Images for Static Go Binariesを参照してください。
DockerとGoogle Compute Engineについてもっと知りたい方は、 Container-optimized VMsのページや google/docker-registry Docker Hubリポジトリを参照してください。
By Andrew Gerrand