Skip to content

Docker イメージを作る

サーバーアプリケーションを作る

コードを書く

naro_serverというディレクトリを作り、その中でコードを書いてください。第 1 部でやったように、 Rust を使って下の条件を満たすサーバーアプリケーションを作ってください。

  • /greetingへの GET リクエストに、環境変数 GREETING_MESSAGEの値を返す。
  • 起動するポートを環境変数PORTで指定できる。

ただし、 listen する IP アドレスとして、必ず 0.0.0.0 を指定してください。

答え
rs
use axum::{http::StatusCode, routing::get, Router};

#[tokio::main]
async fn main() {
    let port = std::env::var("PORT")
        .expect("failed to get env PORT")
        .parse::<u16>()
        .expect("failed to parse PORT");

    let app = Router::new().route("/greeting", get(greeting_handler));

    let addr = std::net::SocketAddr::from(([0, 0, 0, 0], port));

    let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();

    println!("Listening on {}", addr);

    axum::serve(listener, app).await.unwrap();
}

async fn greeting_handler() -> Result<(StatusCode, String), StatusCode> {
    let greeting =
        std::env::var("GREETING_MESSAGE").map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    Ok((StatusCode::OK, greeting))
}

axumtokio の依存関係を追加する必要があります。

ビルドして実行する

今まではcargo runコマンドでプログラムを実行していましたが、Rust ではcargo buildコマンドでコンパイルして実行ファイルを生成し、そのファイルを用いてプログラムを実行できます。

sh
cargo build --release

--releaseオプションをつけることで、最適化されたバイナリが生成されます。

以下のコマンドで実行できます。

sh
GREETING_MESSAGE="こんにちは" PORT="8080" ./target/release/naro-server

実行前に環境変数を設定しています。

localhost:8080/greetingにアクセスすると、メッセージを確認できます。

メッセージとポート番号を「こんにちは」と 8080 から変えてビルド・実行し、ページにアクセスした様子のスクリーンショットを講習会用チャンネルに投稿しましょう。

Dockerfileを書く

Dockerfile を書くと自分で必要な機能がそろったコンテナを立てることができます。

  1. 基本となるベースイメージを探してFROMで指定する。
  2. 必要なパッケージを入れる。
  3. 必要な処理を書く。
  4. 起動設定を書く。

の順番で書いていきます。ベースイメージはできるだけ Docker Hub のオフィシャルイメージを使いましょう。2 から 4 を何度か試しながら修正していきます。

ただ、アプリケーションを動かすだけであれば一度書いた Dockerfile を使いまわすことも可能なので、テンプレートを探してきてそれを使っても構いません。

以下が Rust のプログラムを動かすための最小の Dockerfile です。

Dockerfile
# Rust のベースイメージを指定
FROM rust:latest

# コマンドを実行するコンテナ内のディレクトリをworkに指定
WORKDIR /work

# ローカルのカレントディレクトリをコンテナのカレントディレクトリ(work)にコピー
COPY . .

# Rust のプログラムをビルド
RUN cargo build --release

# ビルドしたものを実行
ENTRYPOINT ["./target/release/naro-server"]

naro_server ディレクトリ内にDockerfileというファイルを作り、上のコードを書きましょう。

VSCode であれば、Docker という拡張機能を入れると Dockerfile を書くのを手助けしてくれます。

詳しい Dockerfile の記法については、このページを読んでください。 https://docs.docker.jp/engine/reference/builder.html

Dockerイメージをビルドする

書いた Dockerfile を使って、イメージを作ることができます。これをイメージのビルドと言います。

sh
docker build -t naro_server .

-tオプションでイメージに名前を付けています。

docker imagesでイメージ一覧を確認しましょう。naro_serverというイメージが作成されているはずです。

docker buildについて https://docs.docker.jp/engine/reference/commandline/build.html

コンテナを起動する

最後に先ほど作った naro_server イメージから Docker コンテナを起動しましょう。

sh
docker run -p "127.0.0.1:3000:8080" -e GREETING_MESSAGE=こんにちは -e PORT=8080 naro_server

このコマンドを実行した後、localhost:3000/greeting にアクセスすると、アプリケーションが動いていることを確認できます。

-pオプション

{ホスト側ポート}:{コンテナ側ポート}と書いて、コンテナ内のどのポートをホスト側のポートに公開するか指定します。127.0.0.1localhostと同じ意味です。ホストとコンテナで指定したポートがパイプでつながれるイメージです。これによって、ホスト側からコンテナ内のアプリケーションへアクセスできるようになります。指定しない場合はアクセスできません。

-eオプション

-e {環境変数名}={値}の形で環境変数を指定できます。今回はアプリケーションの動作に必要なGREETING_MESSAGEPORTを指定しています。

他にも様々なオプションがあります。docker help buildで確認してみましょう。

コンテナ側の側ポートを 8080 以外にして実行し、アクセスした様子をスクリーンショットに撮って講習会用チャンネルに投稿しましょう。

答え

-p-eの両方を変える必要があります。

sh
docker run -p "127.0.0.1:3000:8081" -e GREETING_MESSAGE=こんにちは -e PORT=8081 naro_server

コンテナを止める際にはdocker stop {docker ps で調べたコンテナidか名前}を実行してください。