docker環境を構築し、
Go言語のフレームワークのechoフレームワークに、
JWT Token認証 ホットリロード、リモートデバッグ、マイグレーション、
GormのORMと色々入ったフルスタックフレームワークチックな環境の構築をしてみました。
今回の記事は、この記事の作成の為に公開しました、gihubのソースの動かし方の説明になります。
※githubのソースは記事の一番下になります。
記事の評判がよければ、ライブラリーの比較や説明、ソースコードの説明等記事を更新するかもしれません。
※ validation、テストは入っておりません。
あと、errorハンドリングやlog出力等できていないです。
この記事は、golang初心者やechoフレームワークをこれから学ぶ人向けとなります。
自分は、golangの学習を初めて時間があまり経っていないので、少し説明やソースコードに粗がありますが、ご容赦ください
あと、元々echo v4で作っていたのを、echo v5-alphaに書き換えているので、
v5-alphaの作法に書き変わっていない部分があります。
今回詰まった点は下記の記事に載せております。
Golangを始めた理由は、phpに飽きてきたのと
LaravelやRailsといった動的型付け言語のフルスタックフレームワークは、
すこぶる実行速度が遅いという理由です。
laravelでいうとEloquentが機能の中で一番遅い為、build queryやPDOといった物で代用したりするケースもありますが、
個人的にそこまでするのであれば、そもそも使わない方が良いのではと思います。
そもそも便利なModelや認証自体自作しないといけなくなり苦行です。
また、そこまでしてもベースが遅いのでそこまでする意味がありません
あと、動的型付け言語はDDDといった設計との相性も良くないといわれており
設計をこだわるなら初めからScalaといった言語を選定すれば良いと思ってしまいます。
echoフレームワーク選定理由なのですが、
Go言語のフレームワーク中で軽量かつ一番高速に動く為です。
小規模〜中規模までのシステムや
マイクロサービス化のbackendに使用するならechoが良さそうです。
他のフレームワークもかなり悩んだのですが、やはり、高速で動くという点に
心動かされました。
何故、この記事とgithubのリポジトリーを公開したのか?
なのですが、自分も含め、ehcoをインストールすると下記のキャプチャーのように
2ファイル、go.mod、go.sumしかインストールされず、初学者には実装イメージも掴めずハードルが高いと思ったからです。
あと、Laravelみたいに、マイグレーションやEloquentみたいにSQLを書かなくてもDB操作ができたりし
少しでも、簡単に開発できるようにしたかったからです。
あと、echoは、Apiサーバー用に使われすのが普通なので、JWT token必須なので導入しました。
ちなみgo.mod、go.sumの説明なのですが、
phpのcomposerでいうと、go.modがcomposer.json、go.sumがcomposer.lockにあたり、
nodeでいうと、go.modがpackage.json、go.sumがyarn.lockやpackage-lock.jsonになります。
余談になりますが、Go言語のパッケージ管理なのですが、
色々短期間に変更されているみたいで、
現在は、Go Modulesが一般的です。
モジュールのインストール方法は、go get
だったのですが、
Go1.18 からは、go install
に完全に切り替わります。
goのDockerfileもgo get
からgo install
に書き換えております。
go get
RUN go get github.com/pilu/fresh
go install
RUN go install github.com/pilu/fresh@latest
違いは、go get
はバージョンを指定できなかったのに対し、
go install
はバージョンを指定する必要があります。
go install github.com/ライブラリー@バージョン
となります。
ではどういう風に学習していったかというと
echoで既に組まれたサンプルを落とし、自分で肉付けしてイメージをつけていきました。
参考にさせて頂きました記事はこちらになります。
オニオンアーキテクチャーかクリーンアキテクチャーで迷ったのですが、
設計に詳しくないですが、あまり変わらないということなので、
オニオンアーキテクチャーを選択しました。
こちらは、goのライブラリー管理が「Gopkg.toml」と「Gopkg.lock」で古かったり
一部のライブラリーの開発が終了していたりしていた為、
再度ライブラリー選定し入れ直したりしております。
利用ライブラリー
go-sql-driver
golang-jwt
golang-migrate
jinzhu/gorm
上記を使っていますが、
下記が公式のgormになります。恐らく下記を使った方が良いかもしれません。
※ jinzhu/gormは、公式gormをforkして作られています。
※ go-gorm/gorm
spf13/viper
公開リポジトリーの動かし方
一番最後のリポジトリをgit cloneした後、docker-compose.ymlのtargetを任意のものに
変更してください、target prodとdevはコメントアウトしている為、
そのままdockerを立ち上げるとホットリロード + リモートデバッグ環境になります。
必ずどれかひとつのみ設定してください。
docker-compose.yml
services:
back:
build:
context: .
dockerfile: app/Dockerfile #Dockerfileの場所
# target: prod # 本番用
# target: dev # 開発用(ホットリロード)
target: dev-debug # 開発用(ホットリロード + リモートデバッグ)
volumes:
上記を編集後、
docker-compose up -d
を行いdockerを立ち上げてください。
※ docker ps で起動中コンテナ確認
docker exec -i -t echo-backend-v5-alpha_back_1 sh
でechoの置いてあるコンテナに移動し、
その後、dbフォルダに移動し
cd /go/src/app/db
下記のコマンドでマイグレーションの実行を行なってください、
テーブルが自動で生成されます。
go run migrate.go -exec up
マイグレーションなのですが、下記の方の記事の方法を参考に動かない部分は直しほぼそのまま使っております。
※ /go/src/appにgo.sumが生成されていなければ、
下記を実施しgo moduleをインストールしてください
恐らくdockerを立ち上げると生成されていると思います。
go mod tidy
もしくは
go get
デバッグ設定
Goland
下記の用に、Debug Configurationsの設定をこなってください
Visual Studio Code
下記を参考に拡張機能をインストール後、リポジトリーをcloneしたら
.vscode/launch.jsonを用意していますので、こちらを読み込んでください。
起動確認
上記手順まで行い下記の、URLにアクセスすると
起動しません。
docker-compose.yml の下記のtargetをdev-debugで立ち上げると
そのままアクセスしても、うまく動きません、
target: devや、target: prodで立ち上げるとそのまま開きます。
こちらは、マルチステージングビルドになり、
Dockerfileのどのコンテナを使うか指定しています。
マルチステジーングビルドとは、
デプロイするなら、軽量なOSでビルドされた物だけを、
開発で使うのであれば、リモートデバッグやリアルタイムでコンパイルできるホットリロード環境が入った物など
用途によってどのコンテナを使うか選ぶことができます。
マルチステジーングビルドを使わないと環境ごとに、Dockerfileを用意しないといけないので、
大変便利です。
services:
back:
build:
context: .
dockerfile: app/Dockerfile #Dockerfileの場所
# target: prod # 本番用
# target: dev # 開発用(ホットリロード)
target: dev-debug # 開発用(ホットリロード + リモートデバッグ)
volumes:
で、ホットリロード + リモートデバッグで立ち上げた場合は、
必ず、エディター上で一度、デバックしてください、
で、立ち上げたら、ステップ実行やり切るか、リモートデバッグを中断してください、
Golandの場合は、下記のように、Yesを押して中断すると、Debugできなくなるので
注意してください、Visual Studio Codeは大丈夫です。
デバッグできなくなったら、コンテナに入り、
docker exec -i -t echo-backend-v5-alpha_back_1 sh
/go/src/app
パスで、
air -c ./air.toml
を実行してください。
その後、再度、上記の手順通りに、デバッグ開始してください
しかし、何故、ホットローデイングとホットリロード + リモートデバッグの環境を分けているかというと、
ホットリロード + リモートデバッグは、go-delve + air
というライブラリーを使っており、この環境では、開発中にエラーが発生すると
コンパイルエラーが発生し完全にサーバー自体が止まってしまい為です。
ホットリロードは、freshというライブラリーを使っており、
こちらでは、コンパイルエラーが発生したとしても止まらず動いてくれる為
残しております。
go-delveとfreshを組み合わせて環境構築しようとしましたが、
うまくいかず断念しております。
fresh
go-delve + airの設定は下記を参考にさせて頂きました。
動作確認
サインアップ
curl -X POST \
-H 'Content-Type: application/json' \
-d '{"name":"Golang man", "email":"test@gmail.com", "password":"test5555"}' \
localhost:5566/api/signup
レスポンス
{"id":1,"name":"Golang man","email":"test@gmail.com","password":"$2a$10$/Yt3rqgEDNXf3Ot/Wf8qfempj/GJcGgv.f4cjioNvJXDR7kPgO2CS","created_at":"2022-06-15T15:30:03.1773644Z","updated_at":"2022-06-15T15:30:03.1773644Z"}
ログイン
curl -X POST \
-H 'Content-Type: application/json' \
-d '{"email":"test@gmail.com", "password":"test5555"}' \
localhost:5566/api/login
レスポンス
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiYWRtaW4iOnRydWUsImV4cCI6MTY1NTU2NjgyNn0.c1x7Eml70EkuvTT1DcfLlr9ECC7OuTUcQNDdbU74ot4"}
token認証確認
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiYWRtaW4iOnRydWUsImV4cCI6MTY1NTU2NjgyNn0.c1x7Eml70EkuvTT1DcfLlr9ECC7OuTUcQNDdbU74ot4" localhost:5566/api/auth/refresh
レスポンス
{"id":1,"name":"Golang man","email":"test@gmail.com","password":"$2a$10$/Yt3rqgEDNXf3Ot/Wf8qfempj/GJcGgv.f4cjioNvJXDR7kPgO2CS","created_at":"2022-06-16T00:30:03+09:00","updated_at":"2022-06-16T00:30:03+09:00"}
こちらリポジトリーになります。
反応が良ければこちらの記事やリポジトリー内容を更新しようと思いますので
記事が参考になりましたら、LGTMお願いします。
あと、別記事で、echoとNext.js(redux、redux-toolkit、react-hook)、ISR(incremental static regeneration)や
また、Nuxt.jsの3系が出たら、ISR(incremental static regeneration)も使えるので
backendとフロントを組み合わせたサンプル載せようと思っております。