Go ブログ

Docker を使用した Go サーバーのデプロイ

Andrew Gerrand
2014年9月26日

はじめに

今週、Docker は 公式のベースイメージ を Go とその他の主要な言語向けに発表し、プログラマーは Go プログラムのコンテナを信頼性が高く簡単に構築できるようになりました。

この記事では、単純な Go Web アプリケーションの Docker コンテナを作成し、そのコンテナを Google Compute Engine にデプロイするための手順を説明します。Docker に慣れていない場合は、先に進む前に Docker の概要 をお読みください。

デモアプリ

デモでは、outyet プログラム(Go examples リポジトリ から取得)を使用します。これは、次のバージョンの Go がリリースされたかどうかを報告する単純な Web サーバーです(isgo1point4.outyet.org などのサイトを動かすために設計されています)。標準ライブラリ以外の依存関係はなく、実行時に追加のデータファイルは必要ありません。Web サーバーとしては、これ以上シンプルになることはありません。

「go get」を使用して、ワークスペース に outyet を取得してインストールします。

$ go get golang.org/x/example/outyet

Dockerfile を記述する

outyet ディレクトリにある Dockerfile という名前のファイルを次の内容に置き換えます。

# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang

# Copy the local package files to the container's workspace.
ADD . /go/src/golang.org/x/example/outyet

# Build the outyet command inside the container.
# (You may fetch or manage dependencies here,
# either manually or with a tool like "godep".)
RUN go install golang.org/x/example/outyet

# Run the outyet command by default when the container starts.
ENTRYPOINT /go/bin/outyet

# Document that the service listens on port 8080.
EXPOSE 8080

この Dockerfile は、outyet を実行するコンテナの構築方法を指定します。基本的な依存関係(Go がインストールされた Debian システム、公式の golang Docker イメージ)から開始し、outyet パッケージソースを追加してビルドし、最後に実行します。

ADDRUNENTRYPOINT の各ステップは、あらゆる 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 をそのマシンのアドレスに置き換える必要があります。boot2docker を OS X または Windows で使用している場合は、boot2docker ip でそのアドレスを見つけることができます。)

イメージが機能することを確認したので、別のターミナルウィンドウから実行中のコンテナをシャットダウンします。

$ docker stop test

Docker Hub にリポジトリを作成する

Docker Hub (先に golang イメージを取得したコンテナレジストリ)は、自動ビルド と呼ばれる機能を提供しており、GitHub または BitBucket リポジトリからイメージをビルドします。

Dockerfile をリポジトリにコミットし、自動ビルド を作成することにより、Docker をインストールしたユーザーは、単一の command でイメージをダウンロードして実行できます。(次のセクションで、このユーティリティを確認します。)

自動ビルドを設定するには、GitHub または BitBucket のリポジトリに Dockerfile をコミットし、Docker Hub でアカウントを作成し、自動ビルドの作成 に関する手順に従います。

完了したら、自動ビルドの名前を使用してコンテナを実行できます。

$ docker run goexample/outyet

(goexample/outyet を作成した自動ビルドの名前に置き換えます。)

コンテナを 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 を外部ポート 80(HTTP トラフィックを提供するためのデフォルトポート)として公開していることに注意してください。そして、再び、goexample/outyet を自動ビルドの名前に置き換える必要があります。)

gcloud ツール を使用して、コンテナを実行する VM インスタンスを作成します。

$ 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アドレスを見つけます。数分以内に、WebブラウザでそのIPアドレスにアクセスして、「Go 1.4 はまだリリースされていますか?」というページが表示されるはずです。

(新しい VM インスタンスで何が起こっているかを確認するには、gcloud compute ssh outyet を使用して SSH で接続します。そこから、sudo docker ps を試して、実行中の Docker コンテナを確認します。)

詳細情報

これはほんの始まりにすぎません。Go、Docker、Google Compute Engine でできることは他にもたくさんあります。

Docker の詳細については、充実したドキュメント を参照してください。

Docker と Go の詳細については、公式の golang Docker Hub リポジトリ と、Kelsey Hightower の 静的 Go バイナリ用の Docker イメージの最適化 を参照してください。

Docker と Google Compute Engine の詳細については、コンテナ最適化された VM ページgoogle/docker-registry Docker Hub リポジトリ を参照してください。

次の記事:Google I/O と Gopher SummerFest での Go
前の記事:定数
ブログインデックス