Docker-composeを使ってGoの実行環境の作成

# はじめに
Goを使ったプログラムを書きたかったのでコンテナを使い簡単に環境構築を行おうとしました。今回はホットリロード機能も付けた状態となります。備忘録としてまとめます。

# 構成
go
├ app 
│  ├── go.mod
｜  ├── main.go
│    └── .air.toml
├ Dockerfile
└ docker-compose.yaml

# ファイルの作成
## Dockerfile
```sh:Dockerfile
# goバージョン
FROM golang:1.17.9-alpine
# アップデートとgitのインストール
RUN apk add --update &&  apk add git
# appディレクトリの作成
RUN mkdir /go/src/app
# ワーキングディレクトリの設定
WORKDIR /go/src/app
# ホストのファイルをコンテナの作業ディレクトリに移行
ADD . /go/src/app
# ホットリロード用
RUN go install github.com/cosmtrek/air@v1.27.3
CMD ["air","-c",".air.toml"]
```

## docker-compose.yaml
```sh:docker-comopose.yaml
version: "3"
services:
  goapp: # サービス名
    build: . # ビルドに使うDockerファイルのパス
    restart: always
    container_name: "goapp"
    tty: true # コンテナの永続化
    volumes:
      - ./app:/go/src/app # マウントディレクトリ
``` 

## app/go.modの配置
```sh
mkdir app && cd app
```
```sh:go.mod
module go_docker

go 1.14
```

## app/.air.tomlの配置
```sh:app/.air.toml
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format

# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"

[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -o ./tmp/main ."
# Binary file yields from `cmd`.
bin = "tmp/main"
# Customize binary, can setup environment variables when run your app.
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# Exclude specific regular expressions.
exclude_regex = ["_test.go"]
# Exclude unchanged files.
exclude_unchanged = true
# Follow symlink for directories
follow_symlink = true
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms
# Add additional arguments when running binary (bin/full_bin). Will run './tmp/main hello world'.
args_bin = ["hello", "world"]

[log]
# Show log time
time = false

[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"

[misc]
# Delete tmp directory on exit
clean_on_exit = true
```
ただし、この例ではapp/tmp/mainが勝手に作成されてホットリロード機能が動作するが、仕組みがよくわかっていないので、このままにしてある。

https://github.com/cosmtrek/air

## app/main.goの配置
```sh:app/main.go
package main

import "fmt"

func main() {
        fmt.Println("Hello golang from docker!")
}
```

# コンテナの立ち上げとmain.goの実行
```sh
sudo docker-compose build
sudo docker-compose up
vpn@vpn:~/go$ docker-compose up
Creating network "go_default" with the default driver
Creating bot_go ... done
Attaching to bot_go
bot_go   |
bot_go   |   __    _   ___
bot_go   |  / /\  | | | |_)
bot_go   | /_/--\ |_| |_| \_ , built with Go
bot_go   |
bot_go   | mkdir /go/src/app/tmp
bot_go   | watching .
bot_go   | !exclude tmp
bot_go   | building...
bot_go   | running...
bot_go   | Hello golang from docker!
```
ここで別ターミナルを開きapp/main.goの内容を書き換える。
```sh:app/main.go
package main

import "fmt"

func main() {
        fmt.Println("Hello golang from docker air!")
}
```

そして先ほどのターミナルを見てみると
```sh
bot_go   | main.go has changed
bot_go   | building...
bot_go   | running...
bot_go   | Hello golang from docker air!
```
が追記されて正しくホットリロードが行われていることがわかる。


# 特定のgoファイル指定して動作させたい場合
```sh
sudo docker-compose up -d
sudo docker-compose exec goapp go run main.go
```

# 内部で入ってコマンドを実行する場合
```sh
sudo docker-compose exec goapp sh
#任意のコマンド
```

# 参考サイト
https://zenn.dev/ajapa/articles/bc399c7e4c0def

https://zenn.dev/h_sakano/articles/b38336d99f43e4e9e90b

https://zenn.dev/tomi/articles/2020-10-14-go-docker