フリーランス 技術調査ブログ

フリーランス/エンジニア Ruby Python Nodejs Vuejs React Dockerなどの調査技術調査の備忘録

DockerでRustのRocketフレームワークが利用できる環境を構築する

はじめに

  • Rustでわざわざ公式のイメージを使わないで環境を構築してみる。
  • Dockerが必ず使える環境とは限らない。あとどのようなライブラリが必要か勉強になる
  • いろいろとトライアンドエラーで3~4日構築に時間がかかった。
  • alpineを選択している理由は自分が動かしているサーバーが600円ぐらいのLinuxサーバーのため、重たいOSは厳しいため。 hub.docker.com

Dockerfile

  • rustのインストールが対話形式のため、rust_install.shを利用してexpectを利用している。
  • developerユーザーを作成しているのはRustのプロジェクトを作成するときにrootユーザーでは作成できないため、作成している。 ※ユーザー名は何でもよい。
FROM alpine:latest

RUN apk update
RUN apk add --no-cache curl openssl ncurses-libs libgcc gcc expect sudo musl-dev make g++

WORKDIR /srv

RUN echo 'root:root' |chpasswd
RUN adduser -S developer \
    && echo "developer ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
    && echo 'developer:developer' | chpasswd

RUN su -s /bin/ash developer

RUN curl -f -L https://static.rust-lang.org/rustup.sh -O

USER developer

ADD rust_install.sh ./

RUN sh rust_install.sh

ENV PATH="/home/developer/.cargo/bin:$PATH"

Rustインストール用シェルスクリプト

  • Rustの対話式のインストールを自動化するためのシェルスクリプト
  • sleepはインストールする環境のスペック次第で短くできるはず、
  • sendの1は対話で聞かれるインストール形式の指定のため、自分はdefaultの1を指定している
1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

シェルスクリプトのコード

#!/bin/sh

expect -c "
  spawn sh /srv/rustup.sh
  expect \">\"
  send \"1\n\"
  sleep 10
expect"

Docker build

  • Rustフォルダを作成して、Dockerfileとrust_install.shを同じディレクトに格納して、そのフォルダ内で下記のコマンドを実行する
docker build -t rust-rocket-api .
  • 実行後下記のようにイメージが作成されている
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rust-rocket-api     latest              b00d1cebd60c        15 minutes ago      521MB
alpine              latest              a24bb4013296        4 weeks ago         5.57MB

Dockerコンテナ起動

# docker run -e USER=developer -p 80:8000 -it rust-rocket-api /bin/ash

Rocketをインストールする

/srv $ cd 
~ $ pwd
/home/developer

リリースチャンネルを選択

  • stable / beta / nightly の3 つのリリースチャンネルがあり。nightly は最新の開発版、stable がリリース版。beta では nightly でのテストが終わりリリースに向けた機能。
$ rustup install nightly
 $ rustup default nightly
info: using existing install for 'nightly-x86_64-unknown-linux-musl'
info: default toolchain set to 'nightly-x86_64-unknown-linux-musl'

  nightly-x86_64-unknown-linux-musl unchanged - rustc 1.46.0-nightly (394e1b40d 2020-06-27)

プロジェクトの作成

~ $ cargo new hello-rocket --bin
     Created binary (application) `hello-rocket` package
~ $  cd hello-rocket
~/hello-rocket $

Cargo.tomlファイル

  • Cargo.tomlファイルにrocketを追加する。RubyでいうGemfile、nodejsでいうpackage.jsonのようなもの
vi Cargo.toml

[package]
name = "hello-rocket"
version = "0.1.0"
authors = ["developer"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rocket = "0.4.5"       <- こちらを記述する

RocketでHello,word!

vi src/main.rs

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

Rustサーバーを起動する

  • 作成したプロジェクトのルートディレクトリで実行する
cargo run

? Configured for development.
    => address: localhost
    => port: 8000
    => log: normal
    => workers: 2
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => tls: disabled
?  Mounting /:
    => GET / (index)
? Rocket has launched from http://localhost:8000

リクエストを投げる

  • Hello,World!と表示されていることを確認する
$ curl localhost:8000
Hello, world!
GET /:
    => Matched: GET / (index)
    => Outcome: Success
    => Response succeeded.

まとめ

  • 現時点のファイルはコマンド一発ですべて動く環境が整っていないので、近いうちにdokcer-compose化を目指します。
  • サーバーはメモリは最低1GBはほしい。500MBだとしんどかった。
  • curlでリクエストが通りましたがブラウザからのアクセスができなかったので調査をする

環境構築時にやくにたった情報

https://github.com/SergioBenitez/Rocket/issues/735 https://github.com/rust-lang/rust/issues/60149