🚄

Go × Clean Architecture × Railway でSaaS風アプリを1人でデプロイしてみた話

に公開

はじめに

普段はPHPメインで開発していますが、Go言語でも案件を取りたくて、ポートフォリオ兼練習用のアプリをAI使って作ってみました。
基本的なDBの処理とGoの処理を理解するためClean Architectureで簡単な会員管理機能(会員登録/ログイン)を実装/デプロイしたのでその方法を書いていきたいと思います
Railwayのデプロイ方法を書きます。

🎯 作ったもの

アプリ名:GoFlow
ソース
https://github.com/nishun0419/goflow/tree/develop
※現在も開発中のため、develop ブランチで動かしています。
公開してるもの(見た目だけでGoogle OAuthでのみログインできます)
https://goflow-delta.vercel.app/login

  • 会員登録 / ログイン(JWT & Google OAuth 対応)
  • Clean Architecture + Testify / Mock によるテスト設計(usecase)
  • フルスタック構成を Docker + GitHub で CI/CD

⚙️ 技術構成

レイヤー 技術
フロントエンド Next.js (App Router, NextAuth)
バックエンド Go (Gin, Clean Architecture)
DB MySQL (Railwayでホスティング)
認証 JWT / Google OAuth
インフラ Vercel(フロント)+ Railway(バック)
CI/CD GitHub → 自動デプロイ

🗂️ 構成図

goflow構成図.jpg

🛠️ Goデプロイ手順

  • Railwayの公式サイトにアクセス
  • 右上のsign inをクリックしてgitアカウントでログインする
    スクリーンショット 2025-05-03 15.00.33.png
  • ログイン後ダッシュボードが出るので右上の「NEW」で新しいプロジェクトを作る
    スクリーンショット 2025-05-03 15.02.45.png
  • 「Deploy from GitHub repo」を選んでimportしたいリポジトリを選択する(最初は何も出ないと思うので、Configure GitHub Appを選択してリポジトリをimportする)
    スクリーンショット 2025-05-03 15.04.50.png
    スクリーンショット 2025-05-03 15.06.32.png
  • importするとこのような画面になりデプロイが走る
    スクリーンショット 2025-05-03 15.09.57.png

🛠️ MySQLデプロイ手順

次にデータベースのデプロイをする

  • 右上のCreateをクリックしてDatabaseを選択する
    スクリーンショット 2025-05-03 15.10.25.png
  • 使いたいDBの選択(今回はMySQL)
    スクリーンショット 2025-05-03 15.10.40.png
  • 選択するとすぐにデプロイが走り、起動する
    スクリーンショット 2025-05-03 15.11.06.png
  • DBの環境変数はVariables、ホストはSettingsに書いてるのでApp側でDB接続するためにメモしとく(Raw Editorをクリックするとenvファイルの形で編集できる)
    スクリーンショット 2025-05-03 15.12.19.png

🛠️ 再デプロイ

  • メモした環境変数やホスト情報をApp側の環境変数に入れる(本番用のenvファイルがあればそれをコピーして貼り付けた方が早いかも)
    スクリーンショット 2025-05-03 15.13.49.png
  • 設定後再デプロイすると環境変数を読み込んだ状態でサービスが立ち上がる
    スクリーンショット 2025-05-03 15.19.29.png

⛔️ 開発の流れとハマりポイント

起動したいDockerfileのパスが指定できない

  • docker composeだとbackend/Dockerfileを読み込むようにしてたがRailwayはパス指定できない

✅解決した方法

  • Railwayは Dockerfile をプロジェクト直下でしか認識しないため、backend/ にあったDockerfileとは別に、Railway用のDockerfileをプロジェクト直下に新たに作成しました
#Railway用のDockerfile
# Golang 1.23の公式イメージを使用
FROM golang:1.23-alpine

# 作業ディレクトリを設定
WORKDIR /app

# キャッシュ利用で効率化するために別でコピー
COPY backend/go.mod backend/go.sum ./
RUN go mod download

# アプリケーションのソースコードをコピー
COPY backend/ .

# アプリケーションをビルド
RUN go build -o main ./cmd/main.go

# エントリポイントスクリプトをコピーして実行権限を付与
COPY backend/railway_start.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/railway_start.sh

# エントリポイントを設定
ENTRYPOINT ["railway_start.sh"]

# ポートを公開
EXPOSE 8080

起動後のDBマイグレーションが走らずkillエラーが出る

  • 起動時gooseを使ってマイグレーションが走るようにエントリポイントのシェルスクリプトを書いてたがKilled エラー発生してマイグレーションが失敗した(メモリ制限 or 起動時間オーバー)
GOOSE_DBSTRING="user:pass@tcp(host:port)/dbname" \
  goose -dir db/migrations mysql up

✅解決した方法

  • シェルスクリプトからマイグレーションの処理を削除して、ローカルからマイグレーションを実施することで対応(テストなので一時的に対応したが本番運用時は起動時にマイグレーションが走るようにする)

📝 学び & 今後やりたいこと

学び

  • Clean Architecture は責務を分けやすく、テストも書きやすい
  • Next.js App Router + Go API の構成は意外とハマらず動いた
  • Vercel × Railway の組み合わせは無料でもここまでできる

今後やりたいこと

  • リフレッシュトークンによるJWT認可強化
  • メール通知 / Slack通知 連携
  • CIパイプラインの自動テスト連携
  • 実務でGoの経験を積みたい

✍️ 最後に

Go + Next.js を使って、短期間で会員管理SaaS風アプリをデプロイできました。
副業や案件獲得にもつながれば嬉しいし、今後はより実用性の高いプロダクトにもチャレンジしたいと思っています。

Discussion