とりあえずgolang+nginx+mysql+docker-composeの環境構築

Ginを使ったAPIサーバーをnginx, mysql,そしてdockerで構築します。
ファイルをただ並べていくだけの記事です。

## やっていること

mysql, nginx, goの最低限のファイルをメモがわりに並べています。
（DBへの接続、マイグレーションなどはここでは割愛してます）

## 全体像

全体像としては以下のようになっています。

```
├── backend
│   ├── Dockerfile
│   ├── Dockerfile.local
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
├── docker-compose.yml
├── mysql
│   ├── Dockerfile
│   └── my.cnf
└── nginx
    ├── Dockerfile
    └── nginx.conf
```

## docker-compose

go, mysql, nginxの3つのサーバーを立てます。nginxは80にアクセスがくると、8080のほうに流すように設定していきます。

```docker-compose.yml
version: '3'
services:
    go:
        build:
            context: ./backend
            dockerfile: Dockerfile.local
        volumes:
            - ./backend:/go/src/backend
        working_dir: /go/src/backend
        environment:
            TZ: Asia/Tokyo
        ports:
            - 8080:8080
            - 2345:2345
        security_opt: 
            - apparmor:unconfined
        cap_add: 
            - SYS_PTRACE

    mysql:
        build: ./mysql
        environment:
            TZ: Asia/Tokyo
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: backend
        ports:
            - 13306:3306
        volumes:
            - mysql_volume:/var/lib/mysql

    nginx:
        container_name: "nginx"
        build: ./nginx
        ports:
            - "80:80"
        depends_on:
            - "go"

volumes:
    mysql_volume:
```

## go

delveでデバッグできるようにしたいので、ローカル用のDockerfileを作成しています。
.air.tomlは[Githubのページ](https://github.com/cosmtrek/air)からコピペできます。

```Dockerfile.local
FROM golang:1.15.2
COPY . /go/src/sample
WORKDIR /go/src/sample
RUN go get -u github.com/cosmtrek/air
RUN go get -u github.com/go-delve/delve/cmd/dlv
CMD ["air", "-c", ".air.toml"]**
```

Herokuにデプロイするときのことも考えて `USE_HEROKU`という環境変数が入っています。ですがこれはなくてもデフォルトで8080を選ぶようになっているので設定する必要はありません。今のところAPIのパスは何も用意していないのですが、、、

```main.go
package main

import (
	"os"

	"github.com/joho/godotenv"
	"github.com/zeroboard-dev/zeroboard-toC/backend/lib"
	"github.com/zeroboard-dev/zeroboard-toC/backend/router"
)

func main() {
	if os.Getenv("USE_HEROKU") != "1" {
		err := godotenv.Load()
		if err != nil {
			panic(err)
		}
	}

	r := gin.Default()

	if os.Getenv("USE_HEROKU") != "1" {
		// local
		r.Run(os.Getenv("HTTP_HOST") + ":" + os.Getenv("HTTP_PORT")) // listen and serve on 0.0.0.0:8080
	} else {
		// heroku
		deployPort := os.Getenv("PORT")
		if deployPort == "" {
			deployPort = "8080"
		}
		r.Run(":" + deployPort)
	}
}

```

## mysql

mysqlはいつも通りという感じです。

```Dockerfile
FROM mysql:8.0.21
# FROM mysql@sha256:77b7e09c906615c1bb59b2e9d7703f728b1186a5a70e547ce2f1079ef4c1c5ca

RUN echo "USE mysql;" > /docker-entrypoint-initdb.d/timezones.sql &&  mysql_tzinfo_to_sql /usr/share/zoneinfo >> /docker-entrypoint-initdb.d/timezones.sql

COPY ./my.cnf /etc/mysql/conf.d/my.cnf
```

```my.cnf
# MySQLサーバーへの設定
[mysqld]
# 文字コード/照合順序の設定
character_set_server=utf8mb4
collation_server=utf8mb4_bin

# タイムゾーンの設定
default_time_zone=SYSTEM
log_timestamps=SYSTEM

# デフォルト認証プラグインの設定
default_authentication_plugin=mysql_native_password

# mysqlオプションの設定
[mysql]
# 文字コードの設定
default_character_set=utf8mb4

# mysqlクライアントツールの設定
[client]
# 文字コードの設定
default_character_set=utf8mb4
```

## nginx

Dockerfileは以下です。もっと新しくしたほうがいいのでしょうか、、

```Dockerfile
FROM nginx:1.17.4-alpine
ADD ./nginx.conf /etc/nginx/conf.d/default.conf
```

こちら `http://go:8080`としているのは、docker-composeにてserviceの名前がgoとなっているからです。サービスの名前（コンテナの名前）にする必要があります。

```nginx.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    include /etc/nginx/default.d/*.conf;

    location / {
        proxy_pass http://go:8080;
    }
}
```

## アクセスしたときの挙動

ページを何も用意していないので404が帰ってきていますが、nginxがちゃんと仕事をしているのはわかります。

```
go_1     | [GIN] 2021/06/28 - 01:42:25 | 404 |        22.6µs |      172.28.0.4 | GET      "/"
nginx    | 172.28.0.1 - - [27/Jun/2021:16:42:25 +0000] "GET / HTTP/1.1" 404 18 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36" "-"
go_1     | [GIN] 2021/06/28 - 01:42:25 | 404 |        15.5µs |      172.28.0.4 | GET      "/favicon.ico"
nginx    | 172.28.0.1 - - [27/Jun/2021:16:42:25 +0000] "GET /favicon.ico HTTP/1.1" 404 18 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36" "-"
nginx    | 172.28.0.1 - - [27/Jun/2021:16:47:26 +0000] " " 400 157 "-" "-" "-"
nginx    | 172.28.0.1 - - [27/Jun/2021:16:53:18 +0000] " " 400 157 "-" "-" "-"
nginx    | 172.28.0.1 - - [27/Jun/2021:16:59:10 +0000] " " 400 157 "-" "-" "-"
```