LoginSignup
2
3

More than 3 years have passed since last update.

Goで書いたサーバーアプリケーションをdockerで動かす

Last updated at Posted at 2019-12-28

来年1月からアサイン予定のプロジェクトにて、dockerを用いた開発を行なうので、ここ最近勉強したdockerに関する知識をまとめたいと思います。

課題

この記事ではgo言語を用いて簡単なサーバーアプリケーションを作成し、dockerで動かします。後半はさらにmulti-stage-bulidという機能を用いてより軽量なdocker imageを作成するまでを目標にします。

dockerのインストールは各自でやっておいてねw

サーバーアプリケーション

ここでは静的なHTMLを返してくれるアプリケーションを作成します。
/にアクセスすると、Hello!!を返してくれるものとし、のちほどherokuにデプロイする事を想定してポートは実行時に指定できるようにしましょう。(デフォルトでは:8080ポートを使用します。)

$GOPATH/src以下にパッケージ名docker_demoとし以下のコードを配置してください。

main.go

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
)

func main() {
    port := flag.String("port", "8080", "port number")
    flag.Parse()
    http.HandleFunc("/", indexHandler)
    fmt.Println("server start!")
    if err := http.ListenAndServe(fmt.Sprintf(":%s", *port), nil); err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "<h1>Hello!!</h1>")
}

コンパイル&実行

$ go install
$ $GOPATH/bin/docker_demo -9000 #9000ポートを使用
server start!

$ curl http://localhost:9000
<h1>Hello!!</h1>

goで本格的なwebアプリケーションを書いてみたいと思った方はこちらが大変参考になります。

dockerを用いて起動する

下準備これくらいにしてdockerコンテナ内で先ほど作成したアプリケーションを起動してみましょう。

docker imageの作成

Dockerfileを下記のように定義してbulidします。

Dockerfile
FROM golang:1.13-alpine
WORKDIR /go/src/docker_demo
COPY . .
CMD go run .

$ docker image build -t docker_demo:latest .
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker_demo         latest              126666514643        1 minutes ago       359MB

コンテナ内でアプリケーションを立ち上げる

それでは今回のメインディッシュdocker container内で先ほど作成したサーバーアプリを動かしてみましょう。

ポートフォワードを使用する事で、ホスト側のポートとコンテナ側のポートを繋ぐ事ができます。今回動かすプログラムはデフォルトで8080ポートを使用します。ホスト側9000ポートと接続してみましょう。

# -d バックグラウンドで起動、-p ポートフォワードを使用(ホスト:コンテナ)
$ docker container run -d -p 9000:8080 docker_demo

バックグラウンドでコンテナが起動しました。
http requestを送って確認してみましょう。

$ curl http://localhost:9000
<h1>Hello!!</h1>

より軽量なdocker imageを作成する

先ほど作成したdocker imageは問題なくコンテナを作成し、動かす事ができました。
しかしこのimageにはプログラムを実行するのに余分なものが含まれています。
goはコンパイラ言語なので実行にはコンパイルした実行ファイルと、最低限のosの機能さえあれば十分です。
したがってこの余分なものを削ぎ落とす事でイメージのサイズを小さくする事ができます。

multi-stage-build

$ docker image lsで先ほどビルドしたイメージのサイズを確認してみると359MBもあります... 余計なお肉は削ぎ落としてスリムな体型にしてあげたいものです。
こんな時に便利なmulti-stage-buildという機能が存在します。

その名の通りイメージのbuildを複数段階に分けてbuildできる機能ですが、これを使用する事でアプリケーションをビルドする環境と、実行環境を分離できるというわけです。

では早速Dockerfileを下記のように変更します。

Dockerfile

FROM golang:1.13-alpine AS build
WORKDIR /go/src/docker_demo
COPY . .
RUN go build
RUN GOOS=linux GOARCH=amd64 go install  

FROM alpine AS docker_demo
RUN apk add ca-certificates 
COPY --from=build /go/bin/docker_demo /bin/docker_demo
CMD ./bin/docker_demo -port=9000

ビルド環境イメージにASを用いてエイリアスを貼ることで、実行環境イメージをビルドする際に参照できるようになっています。

実行環境のベースイメージには必要最低限の機能をもつAlpine Linuxを使用し、ビルド環境で出来上がった実行ファイルのみを渡してあげる事で、最終的なイメージを最小にする事ができます。

docker imageをビルドしてサイズを確認してみましょう。


$ docker image build -t docker_demo
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker_demo         latest              947f14bfd6ad        1 minutes ago      15.2MB

なんという事でしょう!15MBまで小さくする事ができました!

まとめ

今回はgoアプリケーションをコンテナで動かしてみるという簡単な内容でした。multi-stage-buildを使用してビルドと実行の環境を分けるという手法は、docker初心者の僕としては感動ものです。

今回作成したアプリケーションをherokuにデプロイする工程も記事にする予定なので、参考にしていただけると幸いです。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3