【Nginx & Golang & MySql】在Docker上搭建开发环境
首先
这是MYJLab Advent Calendar 2023的第七天文章。
昨天我们开发了一个将片平的Minecraft转换成Van Saber风格的插件。虽然我从未尝试过Van Saber,但我很想尝试在Minecraft中做些有趣的事情。
2. 要做的事情 zuò de
我們將使用Docker建立Go和MySQL的API服務器開發環境。Nginx將僅以反向代理的方式將請求流向Go容器。這只是建立環境,所以內部沒有任何內容。
因为这是我第一次从头开始进行环境配置,所以可能会有我不明白的部分或错误的地方。
3. 目录结构
整体形状如下。我尽量将其构成设计得很小。view 下面的 HTML 文件是为了进行操作验证而非必需的。.air.toml 文件是为了热重载。
├── Dockerfile
├── backend
│ ├── .air.toml
│ ├── go.mod
│ ├── go.sum
│ ├── main.go
│ └── view
│ └── index.html
├── docker-compose.yml
├── mysql
│ ├── Dockerfile
│ ├── docker-entrypoint-initdb.d
│ │ └── init.sql
│ └── my.cnf
└── nginx
├── Dockerfile
└── default.conf
4. Docker Compose (Docker组合)
数据库容器
-
- environment:でルートユーザーのパスワードと、ルートユーザー以外のユーザーとパスワードを設定しています。
- volumes:ではmysql/~にあるinit.sqlを指定しています。ファイルの中は何もないです。
后端容器
-
- tty: trueでコンテナ起動後すぐに閉じないようにしています。
- environment:の部分はよくわからないですが参考にしたサイトの通り書いています。
version: "3"
services:
db:
container_name: "db"
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: myuser
MYSQL_PASSWORD: mypass
TZ: Asia/Tokyo
volumes:
- ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
ports:
- "3306:3306"
backend:
container_name: "backend"
build: .
tty: true
environment:
APP_MODE: local
DB_USER: localuser
DB_PASSWORD: localpass
DB_HOST: db
DB_PORT: 3300
DB_NAME: go_sample
DB_NAME_TEST: go_sample_test
DB_LOC: Asia/Tokyo
volumes:
- ./backend:/go/src/backend
ports:
- "3000:3000"
nginx:
container_name: "nginx"
build: ./nginx
ports:
- "8080:80"
depends_on:
- backend
5. MySQL是一个流行的关系型数据库管理系统。
FROM mysql:latest
ENV TZ Asia/Tokyo
#タイムゾーンの設定と/var/lib/mysql/ディレクトリ以下の所有者を変更しています。
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && chown -R mysql:root /var/lib/mysql/
COPY my.cnf /etc/mysql/conf.d/my.cnf
COPY docker-entrypoint-initdb.d/init.sql /docker-entrypoint-initdb.d/
CMD ["mysqld"]
[mysqld]
character-set-server=utf8mb4
explicit_defaults_for_timestamp=1
collation-server=utf8mb4_general_ci
[client]
default-character-set=utf8mb4
- 余談ですが自分はmy.cnfの名前をmy.confとしていて何度もエラーが起きていました。
6. 后端(Go)
- backendのDockerfileです
FROM golang:latest
# timezoneの設定
ENV TZ Asia/Tokyo
## 作業ディレクトリをbackendディレクトリに指定
WORKDIR /backend
#ホットリロードのためのairをダウンロード
RUN go install github.com/cosmtrek/air@latest
# ローカルのgoディレクトリ全てをimage内の/go/src/
COPY . /go/src/backend
WORKDIR /go/src/backend
# ホットリロードのairを実行
CMD ["air", "-c", ".air.toml"]
-
- ホットリロードのためのairファイルです
-
- 公式のgithubです
- https://github.com/cosmtrek/air
# 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
[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
- 9000版ポートをリッスンしてview/いかにあるindex.htmlを返してます。
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.LoadHTMLGlob("view/*.html")
router.GET("/", func(ctx *gin.Context){
ctx.HTML(200, "index.html", gin.H{})
})
router.Run(":3000")
}
6. nginx = Nginx
FROM nginx:1.25.3-alpine
COPY default.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]
FROM nginx:1.25.3-alpine
COPY default.conf /etc/nginx/conf.d/default.conf
CMD ["nginx", "-g", "daemon off;"]
- ローカル8080で受け取ったリクエストを3000番(backend)に流す
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://backend/cmd:3000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
6. 执行结果

我希望将后端容器改造成只返回数据的形式,作为API服务器。
7. 参考资料:
-
- Go + MySQL + nginxの開発環境をDocker(docker-compose)で作る
-
- とりあえずgolang+nginx+mysql+docker-composeの環境構築
- GolangでAPIを開発する方法まとめ【Docker・Gin・Nginx・MySQL・Postman・Actions】