概要
最近、Rustの勉強を始めました。
基本的な文法や言語機能を簡単に読んでみて、そろそろ自分で色々試してみようと、DockerでのYew(RustのWebAssemblyフレームワーク)環境を構築をしました。
公式イメージで簡単にできるかと思いきや、こちらのページにあるようにDockerなしで環境構築するのと同じ方法では妙なところで詰まるので、そのあたりを備忘録として残しておきます
目次
-
- 前提
-
- 成果物(Dockerfileとcompose.yaml)
-
- Rust?
-
- Yew?
-
- Dockerを用いたYew環境構築 準備
-
- Dockerなしで環境構築準備する場合(参考)
- Yew環境構築
前提
この記事作成時の開発環境
OS:macOS Venture 13.1
CPU:Apple Silicon M1
(chromebook上のcrostini(bullseye)でも動作確認済み)
ツール群
インストール済み
-
- Docker
- (ファイルシステムはgRPC FUSEを推奨)
Dockerfileに記述してコンテナ内にグローバルインストールするもの
-
- Rust(イメージは 1-slimを使用)
-
- libssl-dev
-
- pkf-config
-
- trunk
-
- wasm-bindgen-cli
- wasm32-unknown-unknown
プロジェクトにローカルインストールするもの
- yew
成果物
まずは出来上がったDockerfileとcompose.yamlを記載
Dockerの運用がわかるけど妙なところで詰まった、という方はこれだけ見てサクッと構築してください。
ファイル構成
以下の構成でDockerfileとcompose.yamlを作成
.
├── Dockerfile
└── compose.yaml
Dockerfile
FROM rust:1-slim
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
libssl-dev pkg-config \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& cargo install trunk wasm-bindgen-cli \
&& rustup target add wasm32-unknown-unknown
compose.yaml
services:
front:
build: ./front
tty: true
volumes:
- ./front:/app
working_dir: /app
ports:
- "8080:8080"
Rust?
概要
オープンソースのコミュニティベースで開発が進められている、性能・メモリ安全性・安全な並行性を目指して設計されたマルチパラダイムのプログラミング言語
パフォーマンス・信頼性・生産性に優れていることが公式サイトに明記されています
パフォーマンス
Rustは非常に高速でメモリ効率が高くランタイムやガベージコレクタがないため、パフォーマンス重視のサービスを実装できますし、組込み機器上で実行したり他の言語との調和も簡単にできます。
信頼性
Rustの豊かな型システムと所有権モデルによりメモリ安全性とスレッド安全性が保証されます。さらに様々な種類のバグをコンパイル時に排除することが可能です。
生産性
Rustには優れたドキュメント、有用なエラーメッセージを備えた使いやすいコンパイラ、および統合されたパッケージマネージャとビルドツール、多数のエディタに対応するスマートな自動補完と型検査機能、自動フォーマッタといった一流のツール群が数多く揃っています。
Rustの現状
直近、以下のような理由でOS開発等に採用されてきている
CやC++の独壇場であるOS開発等のシステムプログラミングであるが、Microsoftによると同社製品のセキュリティ脆弱性の約70%がメモリ管理に起因したものであり
the root cause of approximately 70% of security vulnerabilities that Microsoft fixes and assigns a CVE (Common Vulnerabilities and Exposures) are due to memory safety issues. This is despite mitigations including intense code review, training, static analysis, and more.
C/C++では「大規模な開発においてメモリー安全なコードを記述することがほぼ不可能」
it’s clear that no matter the amount of mitigations put in place, it is near impossible to write memory-safe code using traditional systems-level programming languages at scale .
(We need a safer systems programming languageより引用)
一方で、今日のアプリケーション開発によく使われている言語はガベージコレクションを採用しておりメモリー安全が保証されてはいるが、処理のオーバーヘッドが発生するためシステムプログラミングには不向きという事情もある
Rustはガベージコレクションを使っていないがコンパイラーがメモリー安全を保証してくれており、C/C++と同等のパフォーマンスを得られるという特徴があるため、GoogleやMicrosoft、AmazonもOS開発等に採用したことを発表しています
なぜRustでwebアプリケーションなのか
前述した高速処理と安全性が両立しているRustという言語はシステムプログラミングだけでなくWebサービス開発でも注目されている。
WebアプリのフロントエンドではJavaScriptが活用されているが、プログラムが肥大化すると動作速度が遅くなるという課題がある。これを解決するために登場した仕組みが「WebAssembly」
色々な言語からコンパイルして生成されるWebAssemblyですが、高速な処理が可能でサンドボックスを利用するためセキュリティが強固、そして主要なwebブラウザにはほぼ実装されています。そして、もともと安全かつ高速な処理を特徴とするRustは安全で高速なWebアプリを開発できるというメリットがあり、現在WebAssemblyをターゲットにしたプログラミング言語で最も利用されています。
また、バックエンドのフレームワークとして高速に動作するActix Web等のクレートも多数存在し、コミュニティの活動が活発であるためドキュメントも豊富に揃っています。
Rustを用いれば、高速でセキュアなwebアプリ開発を比較的容易に可能となっています
Yew?
Yewは、WebAssemblyでマルチスレッドのフロントエンドアプリを作成するためのElmとReactにインスパイアされたモダンなRustフレームワーク (引用: https://github.com/jetli/awesome-yew)
Component Based
コンポーネントベースのフレームワークを採用し、インタラクティブなUIを簡単に作成することができます。ReactやElmのようなフレームワークの経験がある開発者なら、Yewを使うことに違和感はないはずです。
HTML macro
Rust 式でインタラクティブな HTML を宣言するためのマクロを備えています。ReactでJSXを使用した経験のある開発者は、Yewを使用する際に非常に快適に感じるはずです。
Server Side Rendering
サーバーサイドレンダリングを採用し、SPAの操作性を維持しながら、サーバーレンダリングアプリのSEO対策や機能拡張が可能
Dockerを使ったYewの環境構築 準備
それでは、Dockerを使ったYew環境の構築を始めていきます
Dockerfile, compose.yamlの準備
任意のフォルダにDockerfileとcompose.yamlという2つのファイルを作成してください
内容はそれぞれ以下の通りです
- Dockerfile
敢えてslimのイメージを使っている点、Macで通常構築する場合基本的には必要ないlibssl-devやpkg-config、wasm-bindgen-cliを入れている点以外は、公式ドキュメントのtutorial記載の通りで特に特別なことはしていません(2023-03-12時点)
curlやvim等欲しいものがあれば追加して使用ください
FROM rust:1-slim
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
libssl-dev pkg-config \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& cargo install trunk wasm-bindgen-cli \
&& rustup target add wasm32-unknown-unknown
- compose.yaml(docker-compose.yamlとかでもok)
詳しい説明は省きますが、Dockerfileの指定やコンテナ内外で同期するフォルダの設定、コンテナ内での作業フォルダ、ポートフォワーディング(コンテナに届いた信号の転送)設定を書いてます
services:
front:
build: .
tty: true
volumes:
- ./front:/app
working_dir: /app
ports:
- "8080:8080"
注意点
当方の環境では、Dockerのfile sharing implementationをVirtioFSにしていると、ファイル更新時に低確率でコンパイルエラーになることがありました。gRPC FUSEにしておくと今のところ問題が起きていないため、そちらを推奨としておきます。(デフォルトでgRPC FUSEのはずなので、何言ってるかわからない人はスルーして大丈夫です)
Dockerなしで環境構築(参考)
Dockerfileに記述してある内容なので、Dockerを使って環境構築する方はYewの環境構築に進んでOKです
Rustをインストール
公式ページの通りにやりましょうhttps://www.rust-lang.org/ja/tools/install
Mac, Linuxの場合
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
trunkをインストール
wasmに必要なツールであるtrunkiを以下のコマンドでインストール
$ cargo install trunk
WebAssemblyのターゲットアーキテクチャを追加
$ rustup target add wasm32-unknown-unknown
これでDockerを使わない場合の準備は完了です。Yewの環境構築に進んでください
Yewの環境構築
Dockerコンテナを起動して中に入る
以下のコマンドでDockerコンテナを起動し、コンテナ内で作業できるようにしてください
$ docker compose up -d
$ docker compose exec front bash
Yew用のプロジェクトを作成
cargoを用いて、プロジェクトを作成してディレクトリの中に入る
プロジェクト名はyew-appとしていますが、任意の名前に設定してください
$ cargo new yew-app
$ cd yew-app
(参考)この時点でcargo runを実行すると、ターミナルに”Hello world !”が表示されます
Yewをインストール
cargoでプロジェクトにyewの依存関係を追加します。Cargo.tomlに直接追加しても構いません
cargoを使う場合はこちら(yewのversionが0.20でないと動かない可能性があります)
$ cargo add yew -F csr
Cargo.tomlに直接追加する場合は、ファイル内の[dependencies]に以下の内容を追記してください
[dependencies]
yew = { version = "0.20", features = ["csr"] }
Index.htmlを追加
下のコマンドでyew-appディレクトリ直下にindex.htmlを作成
$ touch index.html
できたファイルの中身を以下のように変更
<!DOCTYPE html>
<html lang="en">
<head> </head>
<body></body>
</html>
Yewの記述を追加
src/main.rsの中身を以下のように変更
use yew::prelude::*;
#[function_component(App)]
fn app() -> Html {
html! {
<h1>{ "Hello World" }</h1>
}
}
fn main() {
yew::Renderer::<App>::new().render();
}
開発サーバーを起動
以下のコマンドでサーバーを起動することで、localhostで開発中のページを確認できます
Dockerで実行する場合は–address 0.0.0.0オプションを忘れないよう注意
$ trunk serve --address 0.0.0.0
参考
Qiita既存のyewコンテナ構築記事
以下のページは公式提供のDockerイメージが使えない方向けにdebianのimageをベースに環境を構築したもののようです。
DockerでYew(Rust+WebAssembly)環境を構築 – Qiita
Docker + WasmでWasmコンテナ実行
公式からテクニカルプレビューが発表されたDocker + Wasmを用いるというものもあり
Docker+Wasm で WASM をコンテナとして実行する | 豆蔵デベロッパーサイト