RustとDockerでWEBサーバーを立ててみた
2021/09/12 2021/09/13 #Docker #RustRustとDockerでWEBサーバーを立ててみた
こんにちは。のんです。
今回は前回からやっている
RustでHello Worldやってみたを見る
RustでHello Worldやってみた
の続編になります。
Rustを使うにしても、結局私はWEB屋なので組み込みとかにはあまり使わずWEBアプリの開発に利用するでしょう。
ということで、WEBアプリとして実行できる開発環境の構築をしつつ、WEBアプリとして基礎的な動作をするところまで進めたいと思います。
勉強用リポジトリ
バージョンの管理とか面倒。Dockerを使いたい。
こちらは前回触れていなかった内容です。
公式の推奨はRustup
を利用することです。
しかし、正直複数人でプロダクトを管理するときにバージョン管理とか面倒。絶対Node.jsとかと同じ道を歩みそう。
ということでDockerを利用しています。
app:
container_name: app
ports:
- 8080:8080
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./app:/app:cache
- rust-target:/app/target
- cargo-cache:/usr/local/cargo/registry
working_dir: /app
depends_on:
- mysql
command: /bin/sh -c "cargo watch -x run"
WEBアプリとしてポートを開放するときには8080番ポートを利用するようにしています。80番はよく使うし、他のアプリとも競合しそう。セキュリティ的にどうなんだというところも。
ports:
- 8080:8080
と記載することで、http://localhost:8080 でアクセスすると出てくるようにします。
volumes:
- ./app:/app:cache
- rust-target:/app/target
- cargo-cache:/usr/local/cargo/registry
rust-target:/app/target
でtarget
内のものをボリュームに保存できるようにします。target
内にはコンパイルした成果物が保存されます。
cargo-cache:/usr/local/cargo/registry
でcargo
コマンドのキャッシュを保存しておきます。一応cargo run
時に時間がかからないようにするために追加していますが、あまり...効果は無さそう。この辺は後で勉強し直しましょう。
command: /bin/sh -c "cargo watch -x run"
これはホットリロードのためにしています。詳細は後で。
actix-webを利用してWEBアプリとして起動する
Cargo.toml
[package]
name = "sample"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = "3.3.2"
[[bin]]
name = "sample"
path = "main.rs"
に変更。
変更箇所は以下。
[dependencies]
actix-web = "3.3.2"
actix-web
のライブラリをインストールするようにしています。今の所、このファイルの設定はPHPでいうcomposer
という認識。多分合っているでしょう。
この状態でcargo run
すると、ライブラリをインストールしてコンパイルしてくれます。
肝心のソースコードはこちら
use actix_web::{get, App, HttpResponse, HttpServer, Responder};
#[get("/")]
async fn index() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(index)
})
.bind("app:8080")?
.run()
.await
}
ほとんどはactix-web
のサンプルの通り。
一点、他と違うのはこちら。
.bind("app:8080")?
127.0.0.1:8080
としてはいけません。
頭がRustでいっぱいになっていて忘れがちです。私はここで1時間ハマりました。
ここではDockerを利用しているので、コンテナ間で共有されている仮想ホスト名である、コンテナ名を指定します。
ソースコードが書き終えたらコンテナを起動します。
docker compose run --rm app cargo run
このとき、コンパイルのためのモジュールが足りないとエラーが発生する場合があります。
FROM rust:1.53.0-alpine3.13
RUN apk update
RUN apk add alpine-sdk
COPY ./app /app
alpine-sdk
が足りないので、Dockerfileに追記しておきます。
RUN apk update
RUN apk add alpine-sdk
実行結果:
ここで気づいたのですが、WEBサーバーがありません。
調べてみると、どうやらactix-web
がその辺もしてくれているようです。もちろんnginx
を前に立ててプロキシ機能を利用すれば、Appサーバーのように振る舞うこともできます。
ホットリロードに対応する
ソースコードを変更するたびにコンテナを起動し直すのは面倒ですし、時間がかかります。
そこで、ReactやVueのようにホットリロードできるようにします。npm run watch
ですね。
このあたりの機能も用意されています。
今回利用するのはcargo-watch
です。
https://crates.io/crates/cargo-watchを見る
https://crates.io/crates/cargo-watch
Dockerfile
FROM rust:1.53.0-alpine3.13
RUN apk update
RUN apk add alpine-sdk
RUN cargo install cargo-watch
COPY ./app /app
RUN cargo install cargo-watch
を追記します。
docker compose run --rm app cargo run
を毎回打つのが面倒くさいです。
docker compose up -d
で全てを終わらせたいので、
docker-compose.yml
に下記を追記します。
command: /bin/sh -c "cargo watch -x run"
cargo watch -x run
でホットリロードできるようになります。この辺のコマンドは公式ページを見て変更しても良いかもしれません。
最後に
今回はRustの勉強の続きを記事にしてみました。
このブログはレスポンス遅いですし、処理も昔のコードのまま。
現在はPHPなのですぐに書き直してもいいのですが、せっかくなので高速と言われているRustで書き直そうかなと思っています。
フロントはNuxtかReactですかね。NextはReactの本格的な勉強をしてからにしたいので、候補外。
それかWebAssemblyでもいいかもと思っていますが、これだといつになるやら...という感じなので、、多分Nuxtかなと思います。
次回はHttpRequestやResponseを捌く箇所を勉強したいです。
また記事にしたいと思います。
その時はよしなに。
.
のん
所属 : 株式会社スマレジ 開発部
YouTube : のんラボ
Twitter : @nonz250
Github : nonz250
Qiita : @nonz250
主にPHPを使用し、サーバーサイドを担当。最近はフロントにも興味津々。
なにかを作ったりいじったりするのが好きで、個人開発なども行っている。
趣味はバイクアイコン画像は大抵愛車の「Z250」である。友達にアイコン描いてもらえて嬉しい。
PHP / Laravel / CakePHP2 / CakePHP3 / Vue / Nuxt / C# / etc...
Tweet
Tweets by nonz250Past articles
2022/05/15 S3みたいなストレージサーバーっぽいものを自前で用意する⑤【DI / Repogitory実装】2022/04/24 S3みたいなストレージサーバーっぽいものを自前で用意する④【RFC 7807 エラーレスポンス実装】
2022/04/10 S3みたいなストレージサーバーっぽいものを自前で用意する③【Digest認証実装】
2022/03/26 S3みたいなストレージサーバーっぽいものを自前で用意する②【ミドルウェア実装】
2022/03/13 S3みたいなストレージサーバーっぽいものを自前で用意する①【ルーティング初期設定】
2022/02/11 Next.jsのGetServerSidePropsの挙動について
2022/01/29 RustでMVC・クリーンアーキテクチャっぽく書いてみた
2022/01/07 2022年の抱負