Go(Echo) Go Modules × Dockerで開発環境構築

# はじめに

フレームワークに`Echo`
ライブラリ管理に`go mod`
ホットリロードに`fresh`
を使用したGoの開発環境をDockerを使って構築したいと思います。
Goのバージョンは`Go 1.15`です。

この記事ではDockerのインストール方法や細かい解説等はしません。

# 最終的なディレクトリ構成
```
.
├── app
│   ├── Dockerfile
│   ├── go.mod
│   ├── go.sum
│   └── main.go
└── docker-compose.yml
```
[GitHub](https://github.com/suganuma3510/go-docker)
# 急いでいる人向け
 [ここ](https://github.com/suganuma3510/go-docker)からコードをダウンロードして`docker-compose up`すればできます。

# Dockerfile作成

まず最初に適当なディレクトリを作成（私の場合go-dockerというディレクトリを作成）
上記のディレクトリ構成を参考にappというディレクトリを作成し、
そしてappディレクトリに`Dockerfile`という名前でファイルを作成します。

```dockerfile:Dockerfile

FROM golang:1.15-alpine

WORKDIR /go/src/app
COPY ./app .

RUN apk update && \
    apk add --no-cache git && \
    go get github.com/pilu/fresh

EXPOSE 8080

CMD ["fresh"]
```

# main.go作成
次はappディレクトリに`main.go`というファイルを作成します。

```go:main.go
package main

import (
    "net/http"
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello world")
    })
    e.Logger.Fatal(e.Start(":8080"))
}
```

# docker-compose.yml作成

次に`docker-compose.yml`という名前でファイルを作成します。
フォルダ構成を参考にファイルを作成する場所に気をつけてください。

```yml:docker-compose.yml

version: "3"

services:
  app:
    build:
      context: .
      dockerfile: app/Dockerfile #Dockerfileの場所
    volumes:
      - ./app:/go/src/app
    ports:
      - "8080:8080"
    tty: true #コンテナ永続化
```

# build
次にymlファイルがある場所と同じ階層で`docker-compose build`コマンドを実行します。

```
$ docker-compose build
Building app
Step 1/6 : FROM golang:1.15-alpine
 ---> b3bc898ad092
Step 2/6 : WORKDIR /go/src/app
 ---> Running in 55f4bfc0b0e5
Removing intermediate container 55f4bfc0b0e5
 ---> bb957624bc5e
Step 3/6 : ADD ./app /go/src/app
 ---> 94a4c0aeb52e
Step 4/6 : RUN apk update &&     apk add --no-cache git &&     go get github.com/labstack/echo/... &&     go get github.com/pilu/fresh
 ---> Running in 2e16203c8eac
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz     
v3.12.3-65-g746e0b7bc7 [http://dl-cdn.alpinelinux.org/alpine/v3.12/main]
v3.12.3-62-gebf75fec7d [http://dl-cdn.alpinelinux.org/alpine/v3.12/community]
OK: 12756 distinct packages available
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz     
(1/5) Installing nghttp2-libs (1.41.0-r0)
(2/5) Installing libcurl (7.69.1-r3)
(3/5) Installing expat (2.2.9-r1)
(4/5) Installing pcre2 (10.35-r0)
(5/5) Installing git (2.26.2-r0)
Executing busybox-1.31.1-r16.trigger
OK: 22 MiB in 20 packages
Removing intermediate container 2e16203c8eac
 ---> dfceb18e2ebd
Step 5/6 : EXPOSE 8080
 ---> Running in 8353095ba65e
Removing intermediate container 8353095ba65e
 ---> fa4b48a798c4
Step 6/6 : CMD ["fresh"]
 ---> Running in a8c85cdb33ba
Removing intermediate container a8c85cdb33ba
 ---> e121e6032342

Successfully built e121e6032342
Successfully tagged go-docker_app:latest
```

# go mod init

次に`docker-compose run --rm app go mod init`というコマンドを実行します。
するとappディレクトリに`go.mod`が作成されます。

```
$ docker-compose run --rm app go mod init
Creating network "go-docker_default" with the default driver
Creating go-docker_app_run ... done
go: creating new go.mod: module app
```


# docker-compose up

最後に`ddocker-compose up`というコマンドを実行します。
そして`go.sum`も作られコンテナが立ち上がります。

```
$ docker-compose up
Creating go-docker_app_1 ... done
Attaching to go-docker_app_1
app_1  | 9:27:18 runner      | InitFolders
app_1  | 9:27:18 runner      | mkdir ./tmp
app_1  | 9:27:18 watcher     | Watching .
app_1  | 9:27:18 main        | Waiting (loop 1)...
app_1  | 9:27:18 main        | receiving first event /
app_1  | 9:27:18 main        | sleeping for 600 milliseconds
app_1  | 9:27:18 main        | flushing events
app_1  | 9:27:18 main        | Started! (5 Goroutines)
app_1  | 9:27:18 main        | remove tmp/runner-build-errors.log: no such file or directory
app_1  | 9:27:18 build       | Building...
app_1  | 9:27:34 runner      | Running...
app_1  | 9:27:34 main        | --------------------
app_1  | 9:27:34 main        | Waiting (loop 2)...
app_1  | 9:27:34 app         | 
app_1  |    ____    __
app_1  |   / __/___/ /  ___
app_1  |  / _// __/ _ \/ _ \
app_1  | /___/\__/_//_/\___/ v3.3.10-dev
app_1  | High performance, minimalist Go web framework
app_1  | https://echo.labstack.com
app_1  | ____________________________________O/_______
app_1  |                                     O\
app_1  | 9:27:34 app         | ⇨ http server started on [::]:8080
```
この状態になったら下記にアクセスして`Hello world`と表示されていたら成功です。
http://localhost:8080/

# さいごに
このDockerfileには開発に最低限なものしか入れていないので、必要に合わせて追加してください。