何もわかってない初心者がGolang+Nuxt3+Nginxなdocker環境を構築する奮闘記
次の現場が「Golang」+「Nuxt3」な環境での開発を行っているらしいので、勉強がてら自分でローカル環境を作成してみようと思い立った。
◎簡単なプロフィール◎
- エンジニア2年生
- 未経験からの転職組
- これまでは
PHP7+CodeIgniter
のレガシースタックを使ってきた - Apacheしか使ったことがない
次への一歩として新たな環境にチャレンジ中。
奮闘記としてスクラップ程度で調べたことや理解したこと・整理したことを残しておく。
■今回作成するもの
- 簡単な管理ツール(なにかの。作りながら決める。)
- LINEのAPIにちょっと興味があるので、LINEアプリとの連携を目指す。
■今回のシステム構造
- あくまでも願望
- できるかどうかは調べてない
- 実装段階なので後から追記する
▼2024年9月20日時点(最終更新:2024年9月22日)
- APIサーバー
- Go + echo
- バージョン
- GO:1.23.1
- echo:
- フロント
- Vue3 + Nuxt3
- バージョン
- Node.js:20.17.0
- Vue3:3.5.6
- Nuxt3:3.13.0
- pnpm:
- Proxyサーバー
- Nginx
- バージョン:latest
- データベース
- MySQL
- バージョン:9.0.1
①各コンテナのディレクトリ・ファイルを整備
最終的には添付画像のような形になった。
▼ディレクトリ・ファイルについての詳細
【apiディレクトリ】
APIサーバー用コンテナを作成。
-
.air.toml
- Golangで形成するAPIサーバーで、ホットリロードを有効化するために必要なモジュール(
Air
)の設定ファイル(?) - 基本的にはモジュール公式GitHubの
air_example.toml
をそのまま引用- 後で一部環境用に書き換えるかも?
- 色々参考にした記事の中ではそのままでも使えるというのはよく見かけた
- Golangで形成するAPIサーバーで、ホットリロードを有効化するために必要なモジュール(
Dockerfile
api/Dockerfile
# Install Golang @2024-09-18
FROM golang:1.23.1-alpine
ENV ROOT=/app/src/GolangNuxt/backend
ENV TZ=Asia/Tokyo
WORKDIR ${ROOT}
## Enable Go modules.
ENV GO111MODULE=on
## Enable hot reload.
RUN go install github.com/air-verse/air@latest
COPY ./.air.toml ${ROOT}/.air.toml
RUN apk update && \
apk upgrade && \
apk add --no-cache \
git gcc bash vim \
make which less musl-dev
EXPOSE 8080 5173
CMD air
【clientディレクトリ】
Nuxt3用コンテナを作成
Dockerfile
client/Dockerfile
FROM amazonlinux:2023.5.20240903.0
RUN ln -snf /usr/share/zoneinfo/Japan /etc/localtime
## Install basic tools.
RUN dnf -y install \
git gcc bash vim tar \
which less
# Install Node.js LTS version. @2024-09-19
ENV NODE_VERSION 20.17.0
## Install nvm.
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
RUN . $HOME/.nvm/nvm.sh && \
nvm install ${NODE_VERSION} && \
nvm use ${NODE_VERSION} && \
npm install -g pnpm && \
node -v && npm -v
### nvmの初期化するように.bashrcに書き込む.
RUN echo -e "\
export NVM_DIR=\"\$HOME/.nvm\"\n\
[ -s \"\$NVM_DIR/nvm.sh\" ] && \. \"\$NVM_DIR/nvm.sh\"\n\
" >> ~/.bashrc
EXPOSE 3000
【databaseディレクトリ】
MySQL用コンテナを作成
-
data
- データ永続化用のディレクトリ
- デフォルトでは
.gitkeep
のみがある状態
Dockerfile
database/Dockerfile
# Install MySQL @2024-09-20
FROM mysql:9.0.0
## timezone.
RUN ln -snf /usr/share/zoneinfo/Japan /etc/localtime
COPY ./my.cnf /etc/my.cnf
-
my.cnf
- MySQL設定用ファイル
- (ファイル名は違うかもだけど)探したら割と落ちてるので参考にした
【serverディレクトリ】
Nginx用コンテナを作成
-
log
- ログファイルsync用
- デフォルトでは
.gitkeep
のみがある状態 -
access_log
・error_log
をバインド
Dockerfile
server/Dockerfile
FROM nginx:alpine
# Remove the default configuration file.
RUN rm -f /etc/nginx/conf.d/*
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
# TimeZone.
RUN apk add --no-cache tzdata
ENV TZ Asia/Tokyo
# Enable the Nginx service After build.
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
nginx.conf
nginx.confの中身
server_tokens off;
server {
# Listen on port 80
listen 80;
# server_name is the domain name of the server
server_name www.nuxt-golang.jp;
# Proxy / requests to the client server
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_pass http://client:3000/app/src/public/;
}
# Proxy /api requests to the API server
location /api/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_pass http://api:8080/;
}
}
②コンテナのビルド
コンテナをビルドする前に、app/src
配下にプロジェクトのソースコードをクローン
# app/srcは、デフォルトで.gitignoreでignoreされており、.gitkeepのみが存在する状態
cd app/src
git clone -b develop 「GitHubプロジェクトのURL」
cd ../../docker
docker compose up -d --build
エラーが出た箇所については適宜修正
※ほぼエラーは出なかったので恐らく大丈夫
コンテナが永続化できない場合
個人的に悩まされたのはmysqlのコンテナがExit(1)
になってしまう現象。
これは現職でも一回悩まされたのを後日思い出したので無事解決。
以下解決方法。
①volumesに指定しているdatabase/dataディレクトリ配下のデータを一度全て削除
②削除が完了したら再度ビルド
③エラーが出てビルドが失敗するたびにdatabase/dataディレクトリ配下のデータを全て削除して再ビルドする。
※エラーはDocker Desktopの各コンテナからログを参照できる。
③ビルドしたコンテナで各ソースの準備
3-1. Nuxt3の準備
ビルドしたコンテナにログインし、Nuxt3プロジェクトを作成
cd docker
docker compose exec -it client bash
cd app/src/クローンしたプロジェクト名
# 今回はfrontendというプロジェクト名でプロジェクトを作成(ディレクトリ名がfrontendになってくれるので)
# @see https://nuxt.com/docs/getting-started/installation
# pnpm dlx nuxi@latest init <project-name>
pnpm dlx nuxi@latest init frontend
# 質問は「pnpm」「git initialize NO」で回答
cd frontend
# lsしてプロジェクトが生成されていたら🙆♂️
ls -la
3-2. Golang側の調整
cd docker
docker exec -it api ash
# Echoをインストール
go install github.com/labstack/echo/v4
# モジュールエントリーを作成し、go.modを生成
go mod init
# lsしてgo.modが生成されていることを確認
ls
VScodeでbackend
配下にmain.go
を作成する。
(もちろんtouch
で作ってもOK)
main.go
を以下のように編集
main.go
の内容については、以下記事より引用。
▼参考
Go(Echo)+MySQLでCRUDを行えるAPIサーバをDocker上で構築する(2)APIサーバを構築する
package main
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
// Echoインスタンスを作成
e := echo.New()
// httpリクエストの情報をログに表示
e.Use(middleware.Logger())
// パニックを回復し、スタックトレースを表示
e.Use(middleware.Recover())
// ルートを設定(第一引数にエンドポイント、第二引数にハンドラーを指定)
e.GET("/api", hello)
// サーバーをポート番号8080で起動
e.Logger.Fatal(e.Start(":8080"))
}
// ハンドラーを定義(どういう処理を実行するか)
func hello(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
}
backend
配下にdatabase/database.go
を作成し、以下のように編集。
内容については、上記同様以下記事より引用
▼参考
Go(Echo)+MySQLでCRUDを行えるAPIサーバをDocker上で構築する(1)APIサーバを構築する
package database
import (
"fmt"
"errors"
"os"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// MySQLに作成するUserテーブルの定義
type User struct {
// gorm.Modelをつけると、idとCreatedAtとUpdatedAtとDeletedAtが作られる
gorm.Model
Name string
Age int
}
// DBを起動させる
func dbInit() *gorm.DB {
// [ユーザ名]:[パスワード]@tcp([ホスト名]:[ポート番号])/[データベース名]?charset=[文字コード]
dsn := fmt.Sprintf(
`%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True`,
os.Getenv("MYSQL_USER"),
os.Getenv("MYSQL_PASSWORD"),
os.Getenv("MYSQL_HOST"),
os.Getenv("MYSQL_DATABASE")
)
// DBへの接続を行う
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// エラーが発生した場合、エラー内容を表示
if err != nil {
log.Fatal(err)
}
// 接続に成功した場合、「db connected!!」と表示する
fmt.Println("db connected!!")
return db
}
func main() {
// DB起動
db := dbInit()
// Userテーブル作成
db.AutoMigrate(&User{})
}