前回の記事で作成した Rust で実装した API サーバーをローカルで動作確認できる環境を整えます。また Heroku にもスムーズにデプロイできるように設定します。いずれも、Docker を利用します。
GitHub のリポジトリは
こちら。
ローカル開発環境を整える#
基本的には以前の記事: docker-compose で DB とアプリサーバを立ち上げ、接続する で行ったことと同じです。
DB 設定のための Dockerfile#
/db/Dockerfile
に DB のための設定を書きます:
/db/docker-entrypoint-initdb.d
のディレクトリの下に DB 立ち上げ直後に実行する SQL を置いておきます。
- 今回は、DB 立ち上げ時にロール
root
とデータベースroot
がないよ、というエラーメッセージが出るのに対応するための SQL を置いてます。- なぜこのエラーが出るのかはよく分かってません。
##Q# API サーバのための Dockerfile
/server/Dockerfile
に API サーバを立ち上げるための設定を書きます:
- マルチステージビルドを利用します。
- 開発環境(develop-stage)ではローカル環境でサーバーを稼働させるためのコマンド cargo-watch 、Diesel で PostgreSQL を扱う際に必要な libpg-dev 、Diesel でマイグレーションなどを行うのに必要なコマンド
diesel_cli
をインストールします。また、本番環境のために成果物をコピーしておきます。 - ビルド環境(build-stage)では、開発環境を用いて本番環境向けのビルドを実行します。
- 本番環境(production-stage) では、ビルド環境の成果物をコピーしてきて実行します。
1# 開発環境
2FROM rust:1.57.0 as develop-stage
3WORKDIR /app
4RUN cargo install cargo-watch
5RUN apt install -y libpq-dev
6RUN cargo install diesel_cli
7COPY . .
8
9# ビルド環境
10FROM develop-stage as build-stage
11RUN update-ca-certificates
12RUN cargo build --release
13
14# 本番環境
15FROM rust:1.57.0-slim-buster as production-stage
16RUN apt-get update
17RUN apt-get install libpq-dev -y
18COPY --from=build-stage /app/target/release/actix_web_sample .
19CMD ["./actix_web_sample"]
docker-compose.yml
の記述#
DB とサーバーの両方をローカル環境で立ち上げるために、 docker-composed.yml
を用意します。
- DB は
pg_isready
コマンドでヘルスチェックを行い、正常に起動していることを確認します。 - DB の環境変数は後に紹介する
.env
ファイルの内容に合わせて設定します。 - サーバーは DB が正常に起動したことを確認してから起動します。
- 起動の際、diesel によるマイグレーション(テーブル作成)と
cargo watch
によるアプリ起動を行います。 cargo watch
により、ソースの保存を自動で検知して再ビルドしてくれるため、開発が楽になります。
- 起動の際、diesel によるマイグレーション(テーブル作成)と
1version: '3.7'
2services:
3 server:
4 build:
5 context: ./server
6 target: 'develop-stage'
7 ports:
8 - "8080:8080"
9 depends_on:
10 db:
11 condition: service_healthy
12 volumes:
13 - ./server:/app
14 - cargo-cache:/usr/local/cargo/registry
15 - target-cache:/app/target
16 command: /bin/sh -c "diesel setup && cargo watch -x run"
17 tty: true
18
19 db:
20 build:
21 context: ./db
22 ports:
23 - '5432:5432'
24 environment:
25 POSTGRES_USER: admin
26 POSTGRES_PASSWORD: password
27 POSTGRES_DB: postgres
28 volumes:
29 - ./db/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
30 healthcheck:
31 test: ["CMD-SHELL", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "postgres"]
32 interval: 10s
33 timeout: 5s
34 retries: 5
35
36 volumes:
37 cargo-cache:
38 target-cache:
.env
の用意#
ローカルで立ち上げる際に利用する環境変数の設定を記述します。
- Rust の dotenv で環境変数を設定するようにしています。
ローカル開発環境でのサーバ&DB立ち上げ#
docker-compose を用いてローカル環境を立ち上げます。
前述の通り、開発中は立ち上げっぱなしにしておけば、Rust のコードを変更した場合でも自動的にビルドして反映してくれます。
1docker-compose up -d
Heroku の設定#
コマンドラインから設定します。アプリの追加と、 PostgreSQL のアドオンを追加します。
- PostgreSQL のアドオンを追加すると自動的にアプリの環境変数
DATABASE_URL
が追加されます。
1# Heroku に CLI でログイン(ブラウザが立ち上がるのでログインを行う)
2$ heroku login
3heroku: Press any key to open up the browser to login or q to exit:
4Opening browser to https://cli-auth.heroku.com/auth/cli/browser/XXXXX
5Logging in... done
6Logged in as hoge@mail.com
7heroku create rust-web-api-server-sample
8
9# アプリの作成
10$ heroku create rust-web-api-sample
11Creating ⬢ rust-web-api-sample... done
12https://rust-web-api-sample.herokuapp.com/ | https://git.heroku.com/rust-web-api-sample.git
13
14# アプリに PostgreSQL のアドオン(Hobby プラン)を追加
15$ heroku addons:create heroku-postgresql:hobby-dev --app rust-web-api-sample
16Creating heroku-postgresql:hobby-dev on ⬢ rust-web-api-sample... free
17Database has been created and is available
18 ! This database is empty. If upgrading, you can transfer
19 ! data from another database with pg:copy
20Created postgresql-contoured-25420 as DATABASE_URL
21Use heroku addons:docs heroku-postgresql to view documentation
GitHub Actions の設定#
ここから、手でコマンドをポチポチ打ってデプロイをしても良いのですが、せっかくなので、 GitHub Action でデプロイを自動化します。
以下のように .github/workflows/deploy-to-heroku.yml
を作成します:
- AkhileshNS/heroku-deploy を利用してデプロイします。
- Heroku へのデプロイは Docker を利用する設定にしています。
- あらかじめ、リポジトリのシークレットに以下を設定しておきます:
HEROKU_API_KEY
: Heroku の Account Settings 画面 -> API Key で取得できる API キーを指定HEROKU_EMAIL
: Heroku のアカウントで使用しているメールアドレスを指定
- 起動したサーバーの IP アドレスは環境変数で設定します。
- 環境変数の設定は
heroku config:set
コマンドで行います。 - Github Actions 内で
heroku
コマンドを利用するためには Heroku へのログイン処理を行う必要があるのですが、AkhileshNS/heroku-deploy を一度でも使うことで Heroku へのログインを行なってくれます。- このツールを使ってログイン処理だけ行うということもできます(
justlogin
オプション)
- このツールを使ってログイン処理だけ行うということもできます(
- 環境変数の設定は
- ヘルスチェックも入れています。
1name: Deploy to heroku
2
3on:
4 push:
5 branches:
6 - main
7 workflow_dispatch:
8
9jobs:
10 build:
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/checkout@v2
14 - uses: akhileshns/heroku-deploy@v3.12.12
15 with:
16 heroku_api_key: ${{secrets.HEROKU_API_KEY}}
17 heroku_app_name: "rust-web-api-server-sample"
18 heroku_email: ${{secrets.HEROKU_EMAIL}}
19 buildpack: "https://github.com/emk/heroku-buildpack-rust.git"
20 usedocker: true
21 appdir: server
22 healthcheck: "https://rust-web-api-server-sample.herokuapp.com/health"
23 checkstring: "Ok"
24 rollbackonhealthcheckfailed: true
25 - run: |
26 heroku config:set SERVER_ADDRESS=0.0.0.0
Heroku へのデプロイにあたっての補足:環境変数について#
Heroku でのサーバー起動の際のポートの指定は、環境変数 PORT
の値を使用するようにすればOKですので、以下のように書けばOKです。
1 let port = std::env::var("PORT")
2 .ok()
3 .and_then(|val| val.parse::<u16>().ok())
4 .unwrap_or(CONFIG.server_port)
今回は、ローカルでの起動も考慮に入れているので、環境変数 PORT
の指定がなければ、 .env
ファイルの SERVER_PORT
の値を利用するという設定にしています。
まとめ#
- Docker を用いて、ローカルでの開発と Heroku へのデプロイを簡単にすることができました。
- 今回の成果物をテンプレとすると、 Heroku に載せる Rust で実装した API サーバーを簡単に構築できる気がします。
- 他のサーバー環境へのデプロイ方法も試してみたいです。
- GitHub Actions のワークフローをもう少し工夫して、テストなどを走らせるようにもしておきたいです。