Rustの公式イメージを使用して展開を簡素化する

以前 、Caddy 2 公式イメージを使用して Web アプリケーションをより迅速にデプロイする方法に取り組みました。 今回は、Rustアプリケーションに注目します。

Rust Foundationは、2010年に開発者に Rust プログラミング言語を紹介しました。 それ以来、開発者はCLIプログラム、ネットワークサービス、組み込みアプリケーション、およびWebAssemblyアプリを構築する際にそれに依存してきました。

Rustは、 Stack Overflowの2021年の開発者調査によると最も愛されているプログラミング言語であり、 Git Towerの2022年の調査によるとMac開発者が最も求めている言語でもあります。 85,000以上の専用ライブラリがあり、 Rust公式画像 のダウンロード数は1,000万を超えています。Rustには情熱的なユーザーベースがあります。 その人気は、 2018年の生産性の更新2021年の言語一貫性の強化に続いてのみ成長しました。

とはいえ、Rustアプリケーションの展開は必ずしも簡単ではありません。 これはなぜですか?

導入の課題

開発者には、Rustアプリケーションをデプロイするための多くの手段があります。 柔軟性は優れていますが、さまざまなオプションが圧倒される可能性があります。 したがって、展開戦略は、アプリケーションの種類とそのユーザーによって異なります。

フル マネージドの IaaS ソリューション、PaaS ソリューション、またはもっとシンプルなものが必要ですか? スケーラビリティはどの程度重要ですか? このアプリケーションは、個人用プロジェクトとしてですか、それともエンタープライズ展開の一部としてですか。 これらに対する答えは、特にそのアプリケーションを長期間サポートする場合に、展開アプローチに影響を与えます。

Herokuのようなものを考えてみましょう。 このプラットフォームは、PHP、Python、囲碁、ノード.jsなどの主要言語の公式サポートを提供します。 Java、Ruby、その他。 ただし、これらの言語のみが、Heroku が「ファーストクラス」サポートと呼ぶものを受け取ります。

したがって、Rust の場合、Heroku のチームは Rust フレームワーク、言語機能、または更新されたバージョン管理を積極的に維持していません。 あなたはこれらのタスクに取り組む責任があります。 Heroku を効果的に拡張するには、コミュニティで作成されたさまざまな非公式のビルドパックをくまなく調べる必要があります。 興味深いことに、一部のパックにはDockerを使用したテストに関するメモが含まれていますが、仲介者を切り取ってみませんか?

レンダリングやVercelなどのオプションもあり、さまざまなレベルの生産準備を備えています。

そのため、Rustの公式画像はとても便利です。 プロセスを簡素化することで展開を加速します。 次のRustプロジェクトに取り組んでいますか? 一般的なユースケースについて説明し、Rust公式イメージを介してデプロイを合理化し、いくつかの重要なヒントを共有します。

なぜ錆びるのですか?

Rustのメンテナとコミュニティは、システムプログラミング、ネットワーキング、コマンドラインアプリケーション、およびWebAssembly(別名「Wasm」)を中心としています。 多くの場合、Rustは複数のユースケースを共有しているため、C ++の代替として提示されます。 したがって、Rustはメモリの安全性、強力なタイプの安全性、およびモジュール性も誇っています。

また、Rustのアプリケーションバイナリインターフェイス(ABI)とCの互換性を利用して、RustアプリがCライブラリ内の低レベルのバイナリデータにアクセスするのに役立てることもできます。 さらに、wasm-packwasm-bindgen 、 Neon 、 Helix 、 rust-cpython 、 cbindge n などのヘルパーを使用すると、他の言語で記述されたコードベースを Rust コンポーネントで拡張できます。これにより、アプリケーションのすべての部分がシームレスに連携できます。

最後に、32ビットまたは64ビットの静的x86バイナリ(またはArmなどの非x86バイナリ)に簡単にクロスコンパイルできます。 Rustはプラットフォームに依存しません。 その組み込みメカニズムは、より信頼性の高い長時間実行されるサービスもサポートします。

とは言うものの、Rustは通常「エントリーレベル」の言語とは見なされません。 経験豊富な開発者(特にCまたはC ++に精通している開発者)は、Rustを少し簡単に習得する傾向があります。 幸いなことに、一般的なビルドの複雑さを軽減することで、アクセシビリティを向上させることができます。 これは、コンテナー イメージが輝く場所です。 次に、Rustイメージの活用の背後にある基本について簡単に説明します。

Rustの利点の詳細については、 この有益な内訳をお読みください

前提条件と技術的基礎

Rust公式イメージは、展開を加速し、すべての依存関係を1つのパッケージにグループ化するのに役立ちます。

開始するために必要なものは次のとおりです。

  1. あなたのRustアプリケーションコード
  2. Docker Desktopの最新バージョン
  3. 選択したIDE(VSCode をお勧めしますが、必須ではありません)

このガイドでは、完成したアプリケーション コードを持ち込むことを前提としています。 これが適切な場所にあることを確認して、今後のビルド内で検出および使用できるようにします。

Rustビルドは、既存のRustクレートを利用することもできます(パッケージとク レート の詳細については、 こちらをご覧ください)。 パッケージには、アプリケーションのコア機能を提供する 1 つ以上のクレート (またはコンパイルされた実行可能ファイルとバイナリプログラムのグループ) が含まれています。 また、依存関係を共有するアプリケーションにライブラリ クレートを利用することもできます。

一部のクレートには、通常はスタンドアロンツールの形式で重要な実行可能ファイルが含まれています。 次に、考慮すべき構成があります。 という感じで .yaml ファイル、ファイル (パッケージ マニフェスト とも呼ばれます) は、Cargo.toml アプリの基盤を形成します。各マニフェストにはセクションが含まれています。 たとえば、セクションは次のようになります [package]

[テキスト]
[パッケージ]
name = "hello_world" # パッケージの名前
version = "0.1.0" #現在のバージョン、semverに従う
authors = ["アリス 「, "ボブ "]
[/テキスト]

マニフェスト内で多くの構成を定義できます。 Rustは、パッケージの作成時に、次の $ cargo new スクリプトを使用してこれらのセクション化されたファイルを生成します。

[シェル]
$ cargo new my-project (貨物ニューマイプロジェクト)
作成されたバイナリ(アプリケーション)「my-project」パッケージ
$ ls マイプロジェクト
Cargo.toml(カーゴトムル)
src (ソース)
$ ls マイプロジェクト/src
main.rs
[/シェル]

Rustは自動的にバイナリクレートルートディレクトリとして使用します src/main.rssrc/lib.rs 、ライブラリクレートを持つパッケージを参照します。 Rustの公式ドキュメントの上記の例では、ビルド内に単純なバイナリクレートが組み込まれています。

先に進む前に、コンテナーとイメージの管理がはるかに簡単になる Docker Desktop をインストールすることをお勧めします。 コンテナを表示、実行、停止、および構成するには、CLI の代わりにダッシュボードを使用します。 ただし、CLIはVSCode内で引き続き使用でき、Dockerデスクトップのコンテナインターフェイスを介してコンテナに直接SSHで接続できます。

それでは、画像を調べて、いくつかのベストプラクティスについて説明しましょう。 作業を少し簡単にするには、続行する前にDockerデスクトップを起動します。

錆の公式画像を使用する

Rustイメージを使用する最も簡単な方法は、Rustコンテナとして実行することです。 まず、イメージ バージョンを自動的に取得 latest するコマンドを入力します docker pull rust 。これには、VSCode内で約45秒かかります。

スクリーンレコーディング 2022 06 07 で 2.36. 32午後

Docker Desktop がイメージを正常にプルしたことを確認するには、サイドバーの [イメージ] タブにアクセスし、リストで イメージ を見つけます rust

スクリーンショット 2022 06 07 で 2.35. 29午後

この画像をコンテナとして実行するには、その上にカーソルを置き、表示される青い[実行]ボタンをクリックします。 ポップアップモーダル内でもう一度[実行]をクリックして確認します。 [オプション設定] フォームを展開してコンテナーをカスタマイズできますが、現在は必要ありません。

コンテナーが実行されていること rust を確認するには、[ コンテナー] タブにアクセスし、一覧内でコンテナーを見つけます。 オプション設定をバイパスしたため、Dockerデスクトップはコンテナにランダムな名前を付けます。 各コンテナー名の横にある青いラベルに注意してください。 Docker デスクトップには name:tag 、各コンテナーの基本イメージの情報が表示されます。

スクリーンショット 2022 06 07 で 3.19.31午後

手記: または、タグ :<version>を使用して特定のバージョンのRustをプルすることもできます。 これは、予測可能性と展開前のテストが重要な運用環境では望ましい場合があります。 イメージは新しい修正や機能をもたらす可能性がありますが :latest 、アプリケーションに未知の脆弱性をもたらす可能性もあります。

コンテナにカーソルを合わせて四角い「停止」ボタンをクリックすると、コンテナを停止できます。 このプロセスは完了するまでに10秒かかります。 停止すると、Docker デスクトップはコンテナーに終了済みというラベルを付けます。 この手順は、構成を変更する前に重要です。

同様に、先に進む前にコンテナを削除することができます(そして削除する必要があります)。

ドッカーファイルのカスタマイズ

上記の例は、画像とコンテナがデスクトップ内でどのように存在するかを示しています。 ただし、Rustアプリケーションコードを使用していなかったため、「ベア」コンテナを使用していたことに気付いたかもしれません。

プロジェクト コードによってアプリケーションに命が吹き込まれ、イメージ ビルドに追加する必要があります。 これ Dockerfile を達成します。 これは、シーケンシャル命令を使用してレイヤー化されたイメージを構築するのに役立ちます。

基本的なRust Dockerfile は次のようになります。

[テキスト]
錆から:1。61.0
WORKDIR /usr/src/myapp (英語)
写し。 .
cargo install –path を実行します。
CMD ["myapp"]
[/テキスト]

Docker がプロジェクト コードにアクセスできることがわかります。 さらに、 cargo install RUN コマンドはパッケージを取得します。

パッケージ化された Rust ツールの完全なセットを使用してイメージをビルドして実行するには、次のコマンドを入力します。

[シェル]
$ docker build -t my-rust-app を実行します。
$ docker run -it –rm –name my-running-app my-rust-app
[/シェル]

この画像は1.8GBで、かなり大きいです。 代わりに、可能な限りスリムなイメージビルドが必要になる場合があります。 いくつかのヒントとベストプラクティスについて説明しましょう。

画像のヒントとベストプラクティス

ツールなしでコンパイルすることでスペースを節約

Rustツールは便利ですが、アプリケーションにとって必ずしも必須ではありません。 コンパイルされたアプリケーションだけが必要なシナリオがあります。 拡張が Dockerfile これを説明する方法は次のとおりです。

[テキスト]
錆から:1。61.ビルダーとしての0
WORKDIR /usr/src/myapp (英語)
写し。 .
cargo install –path を実行します。
から debian:buster-slim
apt-get update & apt-get install -y extra-runtime-dependencies & rm -rf /var/lib/apt/lists/* を実行します。
コピー –from=builder /usr/local/cargo/bin/myapp /usr/local/bin/myapp
CMD ["myapp"]
[/テキスト]

Rustプロジェクトの開発者によると、このイメージはわずか200MBです。 これは、前の画像と比較して小さいです。 これにより、ディスク領域が節約され、アプリケーションの肥大化が軽減され、レイヤーごとの変更の追跡が容易になります。 ビルドは 多段階 (レイヤーの追加)ですが、大幅に縮小するため、結果は逆説的に見えます。

さらに、ステージに名前を付け、それぞれ COPY でそれらの名前を使用すると、指示を並べ替えてもステージ COPY が壊れないようにします。

このソリューションを使用すると、ステージ間で主要なアーティファクトをコピーし、不要なアーティファクトを破棄できます。 不要なコンポーネントを最終的なイメージに持ち込むことはありません。 ボーナスとして、Rustアプリケーションを単一の Dockerfile.

手記: 上記で使用されている && 演算子を参照してください。 これは複数の RUN コマンドをまとめて圧縮するのに役立ちますが、必ずしもこれがベストプラクティスであるとは考えていません。 これらの統合コマンドは、長期にわたって維持するのが難しい場合があります。 これらの文字列が大きくなるにつれて、行継続構文(\)を追加するのを忘れがちです。

最後に、Rustは静的にコンパイルされます。 命令を使用して FROM scratch 作成 Dockerfile し、バイナリのみをイメージに追加できます。Dockerは scratch ノーオペレーションとして扱い、余分なレイヤーを作成しません。 したがって、 Scratch は、わずか数MBのごくわずかなビルドを作成するのに役立ちます。

Dockerfile 手順をよりよく理解するには、 リファレンスドキュメントを確認してください

タグを活用する

さらに多くのスペースを節約する必要がありますか? Rust alpine イメージを使用すると、さらに60MB節約できます。 代わりに、次のような FROM rust:1.61.0-alpine as builder命令を指定します。 ただし、これには警告がないわけではありません。 アルパインイメージは の代わりに glibc and friends 利用 musl libcされるため、重要な依存関係が除外されると、ソフトウェアで問題が発生する可能性があります。ここで 各ライブラリを 比較して安全を確保できます。

より小さなRustイメージを構築する方法は他にもいくつかあります。

  • タグは rust:<version>-slim 、Rustを実行するために必要な最小限のパッケージのみを含むイメージをプルします。 これにより、多くのスペースを節約できますが、イメージ以外の rust 展開が必要な環境では失敗します
  • このタグは rust:<version>-slim-bullseye 、現在の安定したディストリビューションであるDebian11ブランチ上に構築されたイメージをプルします
  • この rust:<version>slim-buster タグは、後継者よりも bullseye わずかに小さいDebian10ブランチ上に構築されたイメージもプルします

Docker Hub には、Rust 公式イメージの多数のイメージタグがリストされています 。各バージョンのサイズは、各 OS アーキテクチャに従って一覧表示されます。

可能な限りスリムなアプリケーションを作成することは、立派な目標です。 ただし、このプロセスには目標または利点を念頭に置く必要があります。 たとえば、(依存関係を取り除くことによって) イメージ サイズを縮小しても、アプリケーションで必要ない場合は問題ありません。 数メガバイトを節約するためにコア機能を犠牲にしないでください。

最後に、サブコマンドに cargo-chef 頼って、RustDockerビルドを劇的に高速化できます。 このソリューションは、Dockerのネイティブキャッシュを完全に活用し、有望なパフォーマンスの向上を提供します。 詳細については、 こちらをご覧ください

結論

クロスプラットフォームのRust開発は複雑である必要はありません。 いくつかの簡単な手順に従い、いくつかの親しみやすい最適化を行って、ビルドを改善できます。 これにより、複雑さ、アプリケーションのサイズ、およびビルド時間が大幅に短縮されます。 さらに、ベストプラクティスを採用することで、生活を楽にすることができます。

次のRustプロジェクトをすぐに始めたいですか? 私たちの awesome-compose ライブラリには、Rustバックエンドを使い始めるためのショートカットがあります。 この例に従って 、PostgresデータベースでRustバックエンドを活用するReactアプリケーションを構築します。 また、 Docker Compose がプロセスの合理化にどのように役立つかについても説明します。