前書き
本記事では、表題の技術を組み合わせて、Webアプリケーション開発における基本的な開発環境の構築方法を順を追って説明します。自身の学習やプロジェクトの雛形としても活用できる内容になっています。構成ファイルやセットアップ手順も含め、初学者でも再現できる様、丁寧にまとめています。
Go言語の概要
[Go言語(Golang)は、Googleが開発した静的型付きコンパイル言語である。シンプルで高速なコンパイルとガベージコレクションを備え、並行処理(Goroutine)が軽量で強力である。C言語に似た構文を持ちつつも、安全性と開発生産性を両立している。バイナリ単体で動作するため、DevOpsやクラウド環境での運用に適している。標準パッケージが充実しており、Web開発やCLI、ネットワークアプリケーションまで幅広く対応できる。
Ginの概要
GinはGo言語で書かれた高速なWebフレームワークである。ルーティング、ミドルウェア、JSON
バインディング、バリデーションなどWeb API開発に必要な機能を備えつつ、驚くほど軽量である。net/http
をラップし、直感的なルーティングとミドルウェアのチェーン処理が可能。大量のリクエストを効率良く処理できるため、マイクロサービスやREST API構築に最適。開発・テスト・運用を効率化する設計が特徴である。
前提条件
- Homebrewがインストールされている
- Docker Desktopがインストールされている
- Go言語(Golang)がインストールされている
ディレクトリ構成
- 最終的に、下記のディレクトリー構成になる
.
├── backend/
│ └── web1/
│ ├── tmp/ # ⇦ 自動生成
│ │ ├── build-errors.log # ⇦ 自動生成
│ │ └── main # ⇦ 自動生成
│ ├── Dockerfile
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── nginx/
│ ├── conf/
│ │ └── web1.conf
│ └── Dockerfile
├── db/
│ ├── conf/
│ │ └── .env
│ └── mysql_volume # ⇦ 自動生成
├── phpmyadmin/
│ └── conf/
│ └── .env
├── compose.yml
├── .gitignore
└── README.md
構築準備
.gitignore
-
.gitignore
に、git
へ含めたくないファイルの情報を記載する
# DB関連
mysql_volume
/db/conf/*
/phpmyadmin/conf/*
!/db/conf/.keep
!/phpmyadmin/conf/.keep
# Go関連
backend/web1/tmp/
!backend/web1/tmp/.keep
# すべてのログファイルと一時ファイルを無視する
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# macOS Finderが生成するファイルを無視
.DS_Store
Docker-compose
- ルートディレクトリに
compose.yml
を作成し、下記の内容を記述する
services:
nginx:
container_name: nginx
build: ./nginx
image: nginx:latest
ports:
- "80:80"
depends_on:
- web1
web1:
container_name: web1
build: ./backend/web1
image: web1:latest
working_dir: /web1
depends_on:
- db
ports:
- "8080:8080"
- "2345:2345"
volumes:
- ./backend/web1:/web1
command: sh -c "go mod tidy && air"
tty: true
stdin_open: true
db:
container_name: mysql
image: mysql:latest
env_file: ./db/conf/.env
volumes:
- ./db/mysql_volume:/var/lib/mysql
ports:
- "3306:3306"
restart: always
phpmyadmin:
container_name: phpmyadmin
image: phpmyadmin:latest
restart: always
depends_on:
- db
env_file:
- ./phpmyadmin/conf/.env
ports:
- "3001:80"
Go環境
Dockerfile
-
backend/web1
にDockerfile
を作成し、下記の内容を記述する
FROM golang:latest
ENV LANG=C.UTF-8 \
TZ=Asia/Tokyo \
WEB1_ROOT=/web1 \
APP_ENV=development
WORKDIR ${WEB1_ROOT}
# 開発支援ツールをインストール(AirとDelve)
RUN go install github.com/air-verse/air@latest && \
go install github.com/go-delve/delve/cmd/dlv@latest
# 依存関係のみ先にコピーしてダウンロード
COPY go.mod go.sum ./
RUN go mod download
# アプリケーションソースをコピー
COPY . .
# go.mod と go.sumを整理して、不要な依存を削除・不足を追加する
RUN go mod tidy
# ホットリロードをデフォルトコマンドに設定
CMD ["air", "-c", ".air.toml"]
Nginx環境
- nginのディレクトリーに、
conf
ディレクトリーとDockerfile
を作成する -
Dockerfile
には、下記の内容を記述する
FROM nginx:latest
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y \
curl && \
rm -rf /var/lib/apt/lists/*
# default.confを削除
RUN rm -f /etc/nginx/conf.d/default.conf
# Nginxの設定ファイルをコピー
COPY ./conf/web1.conf /etc/nginx/conf.d/web1.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
-
conf
ディレクトリーに、web1.conf
を作成し下記の内容を記述する
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
メソッド(ディレクティブ)内容の説明
メソッド(ディレクティブ) | 説明 |
---|---|
listen 80; |
このサーバーは、ポート80 (HTTP) で接続を受け付ける |
server_name localhost; |
このサーバーは、localhost というドメイン名に対して反応するよう指定している |
location / { ... } |
すべてのアクセス(http://ドメイン/ 以下のURL)に対して、この中の設定内容を適用する場所(ルール)を定義する |
proxy_pass http://web1:8080; |
ブラウザから届いたリクエストを、Go アプリ(web1コンテナ)の 8080 番ポートにそのまま渡す設定(リバースプロキシ) |
proxy_set_header Host $host; |
元のHost ヘッダー(例: localhost )をバックエンドにそのまま渡す |
proxy_set_header X-Real-IP $remote_addr; |
クライアントの 実際のIPアドレスをヘッダーに含めて渡す |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
ユーザーがアクセスしてきた時に、どの経路(IPアドレス)を通ってきたかの一覧をヘッダーに追加する設定。例えば、プロキシやロードバランサーを経由してきた場合でも、元のクライアントのIPアドレスまで把握できるようにする。追加されるヘッダー名は、 X-Forwarded-For 。複数のIPがカンマ区切りで並ぶ |
proxy_set_header X-Forwarded-Proto $scheme; |
リクエストが「http 」か「https 」かの情報を、Goアプリ側に伝えるための設定。 例えば、ユーザーが https://example.com にアクセスした場合、「これはHTTPS で来たよ(スキーム = https )」という情報がバックエンド(Goアプリ)に届くようになる |
補足
リバースプロキシ
- ユーザー(ブラウザなど)からのリクエストを一度Nginxが受け取り、裏側で動いているアプリケーションサーバー(ここではGoアプリ)に転送する仕組み。これにより、セキュリティの強化、負荷分散、ログの集中管理などが可能になる
DB
- dbのディレクトリーに、
conf
ディレクトリーを作成し、その中に.env
ファイルを作成する -
.env
には下記を記述をする
MYSQL_DATABASE=example_db
MYSQL_ROOT_PASSWORD=password
TZ=Asia/Tokyo
設定内容の説明
項目名 | 説明 |
---|---|
MYSQL_DATABASE | コンテナ起動時に作成されるデフォルトのMySQLデータベース名を指定する |
MYSQL_ROOT_PASSWORD | MySQLのrootユーザーのパスワードを設定する |
TZ | コンテナ内で使用するタイムゾーンを指定する(例:Asia/Tokyoは日本時間) |
phpMyAdmi
- phpmyadminのディレクトリーに、
conf
ディレクトリーを作成し、その中に.env
を作成する -
.env
には下記を記述をする
PMA_ARBITRARY=1
PMA_HOSTS=db
PMA_USER=root
PMA_PASSWORD=password
設定内容の説明
項目名 | 説明 |
---|---|
PMA_ARBITRARY | 任意のサーバーへの接続を許可する(1で有効)。複数のDB管理が可能になる |
PMA_HOSTS | 接続先のMySQLホスト名を指定(例:サービス名が db のコンテナを指す) |
PMA_USER | 初期ログイン時に使用されるMySQLのユーザー名(例:root) |
PMA_PASSWORD | 上記ユーザーのパスワード(例:root に対応するパスワード password) |
構築手順
-
/backend/web1
に移動して、下記コマンドを実行する
# go.modの作成
go mod init web1
# ginのインストールとgo.sumの作成
go get github.com/gin-gonic/gin
-
.air.toml
を作成する
docker compose run --rm web1 air init
# compose.ymlにworking_dirの設定がない場合、下記のコマンドを実行する
docker compose run --rm -w /web1 web1 air init
-
.air.toml
を下記の内容に修正する - 修正する部分は、矢印にて記載
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main" # ⇦ 修正箇所
cmd = "go build -gcflags='all=-N -l' -o ./tmp/main ./" # ⇦ 修正箇所
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = "dlv exec --accept-multiclient --log --headless --continue --listen :2345 --api-version 2 ./tmp/main" # ⇦ 修正箇所
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
silent = false
time = false
[misc]
clean_on_exit = false
[proxy]
app_port = 0
enabled = false
proxy_port = 0
[screen]
clear_on_rebuild = false
keep_scroll = true
-
path/backend/web1
に移動して、main.go
を作成する
touch main.go
-
main.go
に下記の内容を記述する
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// ブラウザで http://localhost/ にアクセスしたとき "Hello, World!" を返す
r.GET("/", func(c *gin.Context) {
c.String(200, "Hello, World!")
})
// ここでWebサーバーを立ち上げる
r.Run(":8080")
}
-
go.mod
の更新が必要である為、コンテナーの再起動する
# コンテナーの立ち下げ
docker compose down
# コンテナーの起動
docker compose up -d
GitHub
参考資料
公式
非公式
- とりあえずgolang+nginx+mysql+docker-composeの環境構築
- go + nginx でリバースプロキシを体験する
- go_debug_test2
- VSCodeでGO+air+delveのDocker環境をリモートデバッグしよう!
- 2024年版 Go + Docker + VSCode + air + delveの環境でサクサクローカル開発
感想
今回は、Goの環境を構築しました。最近はGoの開発を本格的に行っている為、学んだ事は積極的にアウトプットしていきたいと考えています。