先日、Go言語のホットリロードツール『Air』でコードの修正を即時反映させるでAirを利用したホットリロード可能なHTTPサーバの紹介をしました。
今回は『Air + Go言語』のDocker環境を構築する手順について紹介します。
目次
今回利用するサンプルコード
localhost:3000
にアクセスするとレスポンスが返ってくるHTTPサーバをサンプルとして利用します。
main.go
package main
import (
"log"
"net/http"
)
func rootHander(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Header().Set("Content-Type", "text/html; charset=utf8")
w.Write([]byte("こんにちは"))
}
func main() {
http.HandleFunc("/", rootHander)
log.Fatal(http.ListenAndServe(":3000", nil))
}
『Air + Go言語』のDocker環境の構築手順
Docker環境の構築手順について紹介します。
下準備: 作業ディレクトリの用意
作業ディレクトリとgo.mod
ファイルの作成をします。
$ mkdir go-docker-example && cd $_
$ go mod init `basename $PWD`
各種ファイルの作成
Dockerfileファイルは以下の通りです。
Dockerfile
FROM golang:1.16.3-buster
# コンテナの作業ディレクトリにローカルのファイルをコピー
WORKDIR /app
COPY . /app
# 必要なパッケージをインストール
RUN go mod tidy
# Airをインストール
RUN go install github.com/cosmtrek/air@v1.27.3
# airコマンドでGoファイルを起動
CMD ["air"]
docker-compose.yml
は以下の通りです。
HTTPサーバがlistenしているポートと、開放するコンテナのポートは一緒にする必要があります。(今回でいうところの3000番)
docker-compose.yml
version: '3'
services:
app:
build: .
ports:
- '3030:3000' # ローカルの3030番ポートでコンテナの3000番ポートに接続
volumes:
- .:/app # ローカルとコンテナのディレクトリをバインドマウント(同期)
- go_path:/go # パッケージやバイナリファイルのインストール先($GOPATH)を永続化
volumes:
go_path:
動作確認
コンテナ起動後、ローカルからcurl
を実行してレスポンスが返ってくればOKです。
### 作業ディレクトリへ移動
$ cd go-example
### バックグラウンドで起動
$ dokcer-compose up -d
### 接続の確認
$ curl localhost:3030
こんにちは
参考: 依存パッケージ不足でコンテナ起動が失敗する問題を解決する
上記で紹介したDocerfile
とdocker-compose.yml
では、go.mod
に不備があるとコンテナ起動に失敗します。
たとえば、以下のようにコードを修正したとします。
package main
import (
"log"
"net/http"
+ "rsc.io/quote"
)
func rootHander(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
w.Header().Set("Content-Type", "text/html; charset=utf8")
- w.Write([]byte("こんにちは"))
+ w.Write([]byte(quote.Hello())
}
func main() {
http.HandleFunc("/", rootHander)
log.Fatal(http.ListenAndServe(":3000", nil))
}
Goファイル修正後go mod tidy
を実行せずにコンテナを起動すると、rsc.io/quote
がgo.mod
に追加されていないため失敗します。
$ docker-compose up
Creating air_app_1 ... done
Attaching to air_app_1
app_1 |
app_1 | __ _ ___
app_1 | / /\ | | | |_)
app_1 | /_/--\ |_| |_| \_ , built with Go
app_1 |
app_1 | watching .
app_1 | !exclude tmp
app_1 | building...
app_1 | main.go:7:2: no required module provides package rsc.io/quote; to add it:
app_1 | go get rsc.io/quote
app_1 | failed to build, error: exit status 1
go mod tidy
をコンテナ起動時、つまりair
コマンドの直前に実行することで、この問題が解決できます。
start.sh
#!/bin/bash -eu
go mod tidy
air
start.sh
を利用してコンテナを起動するようにdocker-compose.yml
を修正します。
docker-compose.yml
version: '3'
services:
app:
build: .
ports:
- '3030:3000'
volumes:
- .:/app
- go_path:/go
+ command: ["./start.sh"]
volumes:
go_path:
air
コマンドの直前にgo mod tidy
が実行されるようになったため、問題なくコンテナが起動できます。
$ docker-compose up
Creating air_app_1 ... done
Attaching to air_app_1
app_1 | go: finding module for package rsc.io/quote
app_1 | go: downloading rsc.io/quote v1.5.2
app_1 | go: found rsc.io/quote in rsc.io/quote v1.5.2
app_1 | go: downloading rsc.io/sampler v1.3.0
app_1 | go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
app_1 |
app_1 | __ _ ___
app_1 | / /\ | | | |_)
app_1 | /_/--\ |_| |_| \_ , built with Go
app_1 |
app_1 | watching .
app_1 | !exclude tmp
app_1 | building...
app_1 | running...
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!