Actix-Webでwebアプリケーションを作る – Part 1 環境構築編

rust

環境

  • Ubuntu 22.04
  • Docker 20.10.17
  • Visual Studio Code 1.69.1

はじめに

Actix-Webは非常に高速に動作するRust製のWebフレームワークとして知られており、TechEmpower社によるWebフレームワークのベンチマーク調査「web framework benchmarks Round 20」でも上位にランクインしています。

主なRust製のWebフレームワークを以下の表にまとめました。この表ではRocketが意外とgithubのスター数が多いですが、githubスター数、Crates.ioのダウンロード数の両方ともに多いのはActix-Webということがわかります。また、githubのスター数、Crates.io DL数は少ないですがweb framework benchmarks Round 20 でも上位にランクインしてるntexというフレームワークもありました。

フレームワーク名githubスター数Crates.io DL数初回リリース
Actix-Web14.6K6.9M2017年10月
Rocket17.8K1.9M2016年12月
axum5.4K1.9M2021年7月
warp6.7K5.6M2018年8月
ntex1.0K71K2020年3月
Rust製Webフレームワーク(2022年7月17日調査)

各種Webフレームワークの速度を比較できるWeb Frameworks Benchmarkというサイトがあります。上表のntexは無かったためそれ以外の速度を比較した結果を参考としてリンクを張っておきます。

ソースコード

この記事ではgithubスター数、Crates.io DL数が両方ともに多く、速度も早いと評価されているActix-Webを使っていきます。

最終的にファイル構成は以下のようなものになります。

.
├── .env
├── Dockerfile
├── docker-compose.yml
├── entrypoint.sh
└── web

.env

まず、.envファイルですが、このファイルはコンテナに渡す環境変数を定義しています。LOCAL_UIDとLOCAL_GIDの値を定義しています。この値は、ホストのユーザのuidとgidの値と同じにしておくとvolumeのオーナー問題が起こらなくなります。

LOCAL_UID=1000
LOCAL_GID=1000

uidとgidを調べるにはidコマンドを使用します。

$ id
uid=1000(higmasan) gid=1000(higmasan) groups=1000(higmasan)

Dockerfile

次にDockerfileについてです。rust:1.62.0-slimを元にイメージをビルドします。entrypoint.shをホストからイメージにコピーして実行権を付与しています。rustuserと言う名前のユーザの作成を行いrustuserに切り替えています。最後にコンテナにログインした時にentrypoint.shを実行するようにしています。

FROM rust:1.62.0-slim

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh \
    && adduser -q --gecos "" --disabled-login rustuser

USER rustuser

ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]

entrypoint.sh

このファイルでは、rustuserのuidとgidの値をそれぞれ.envで定義されたLOCAL_UIDとLOCAL_GIDの値に変更しています。LOCAL_UIDとLOCAL_GIDはデフォルトでは両方とも1000を使います。このスクリプトを実行するとホストのユーザとコンテナ内のユーザのuidとgidを一致させることが出来ます。

#!/bin/sh

UID=${LOCAL_UID:-1000}
GID=${LOCAL_GID:-1000}

echo "Starting with UID: $UID, GID: $GID"

groupmod -g $GID rustuser
usermod -u $UID -g $GID rustuser

/bin/sh

ホストのユーザとコンテナ内のユーザのuidとgidを一致するとvolumesでマウントされたディレクトリ下のオーナー問題がなくなり。パーミッションエラーが起こらなくなります。

docker-compose.yml

このファイルでは、起動させるサービスの定義をしています。Dockerfileというファイル名のdockerfileを使用してrust-wabappという名前のイメージを作成するように設定しています。コンテナの起動時にはホストの./webディレクトリとコンテナ内の/webディレクトリをマウントします。ホストの8080番ポートとコンテナの8080番ポートを対応させています。

version: '3'
services:

  web:
    build:
      context: .
      dockerfile: Dockerfile
    image: rust-webapp
    container_name: rust-webapp
    volumes:
      - ./web:/web
    working_dir: /web
    env_file:
      - .env
    tty: true
    command: /bin/sh
    ports:
      - 8080:8080
属性説明
build.contextbuildコマンドを実行した時のワーキングディレクトリ
build.dockerfilebuildコマンドを実行した時に使用するdockerfile
image作成するdockerイメージ名
container_nameコンテナを起動した時のコンテナ名
volumes– {ホストのディレクトリパス}:{コンテナのディレクトリパス}という記述でマウントする
working_dirコンテナを起動した時のワーキングディレクトリ
env_file使用する環境変数を定義したファイル名
tty疑似端末の有効/無効の設定
commandコンテナを起動した時に実行するコマンド
ports– {ホストのポート番号}:{コンテナのポート番号}という記述でホストとコンテナのポート番号を対応付ける

ビルド

次にイメージのビルドを行います。docker-compose.ymlのあるディレクトリでdocker compose build --no-cacheを実行します。このコマンドでイメージのビルドを行います。Successfully builtが表示されていればOKです。

$ docker compose build --no-cache
Sending build context to Docker daemon  223.8MB
Step 1/5 : FROM rust:1.62.0-slim
 ---> 278f9d1dd2ba
Step 2/5 : COPY entrypoint.sh /usr/local/bin/entrypoint.sh
 ---> c7d8baafa250
Step 3/5 : RUN chmod +x /usr/local/bin/entrypoint.sh     && adduser -q --gecos "" --disabled-login rustuser
 ---> Running in 540818029c67
 ---> 4eb1599cbd08
Step 4/5 : USER rustuser
 ---> Running in 0cd8ca7d28e7
 ---> 6fd7d39ff466
Step 5/5 : ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ]
 ---> Running in 2c0472d74edb
 ---> 5bc56bacf9d0
Successfully built 5bc56bacf9d0
Successfully tagged rust-webapp:latest

docker compose imagesコマンドでイメージを確認してrust-webappの行が表示されていればOKです。

$ docker images
REPOSITORY       TAG        IMAGE ID       CREATED         SIZE
rust-webapp      latest     5bc56bacf9d0   6 minutes ago   714MB

コンテナの起動

docker compose up -dコマンドでコンテナを起動します。

$ docker compose up -d
[+] Running 2/2
 ⠿ Network rust-webapp_default  Created                                                                                                                                                                       0.0s
 ⠿ Container rust-webapp        Started 

docker compose psコマンドで起動したコンテナを確認してSTATUSがrunningになっていればOKです。

$ docker compose ps
NAME             COMMAND                  SERVICE        STATUS         PORTS
rust-webapp      "/usr/local/bin/entr…"   web            running        0.0.0.0:8080->8080/tcp, :::8080->8080/tcp

コンテナに接続する

この記事ではvscodeのRemote – Containersという拡張機能を使ってコンテナに接続します。まず、vscode画面左の拡張機能のボタンを押すかCtrl + Shift + xを押すと拡張機能のメニューが開きます。検索画面にremote containersと入力するとRemote – Containersと言う名前の拡張機能が表示されるのでインストールします。

では、vscodeのremote containersでコンテナに接続していきます。まず、vscode画面の左下のオレンジ色の部分をクリックします。

すると、メニューが開くのでAttach to Running Container…を選択します。

上のバーに起動しているコンテナが表示されます。docker-compose.ymlのcontainer_nameで指定したrust-webappをクリックします。

これでコンテナに接続できているはずです。左下のオレンジ色の部分がContainer ~~~と表示されていればOKです。では、フォルダーを開いてみましょう。

/webディレクトリを選択もしくは入力してOKを押します。

/webディレクトリはdocker-compose.ymlのvolumesで指定したコンテナ側のディレクトリです。

ターミナルのディレクトリが/webになっていればOKです。

最後に

次回はRustのプロジェクトを作成してサーバを立ち上げてみたいと思います。

コメント