Docker イメージを作る
サーバーアプリケーションを作る
コードを書く
naro_server
というディレクトリを作り、その中でコードを書いてください。第 1 部でやったように、 Rust を使って下の条件を満たすサーバーアプリケーションを作ってください。
/greeting
への GET リクエストに、環境変数GREETING_MESSAGE
の値を返す。- 起動するポートを環境変数
PORT
で指定できる。
ただし、 listen する IP アドレスとして、必ず 0.0.0.0
を指定してください。
答え
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))
}
※ axum
や tokio
の依存関係を追加する必要があります。
ビルドして実行する
今まではcargo run
コマンドでプログラムを実行していましたが、Rust ではcargo build
コマンドでコンパイルして実行ファイルを生成し、そのファイルを用いてプログラムを実行できます。
cargo build --release
--release
オプションをつけることで、最適化されたバイナリが生成されます。
以下のコマンドで実行できます。
GREETING_MESSAGE="こんにちは" PORT="8080" ./target/release/naro-server
実行前に環境変数を設定しています。
localhost:8080/greetingにアクセスすると、メッセージを確認できます。
メッセージとポート番号を「こんにちは」と 8080 から変えてビルド・実行し、ページにアクセスした様子のスクリーンショットを講習会用チャンネルに投稿しましょう。
Dockerfileを書く
Dockerfile を書くと自分で必要な機能がそろったコンテナを立てることができます。
- 基本となるベースイメージを探して
FROM
で指定する。 - 必要なパッケージを入れる。
- 必要な処理を書く。
- 起動設定を書く。
の順番で書いていきます。ベースイメージはできるだけ Docker Hub のオフィシャルイメージを使いましょう。2 から 4 を何度か試しながら修正していきます。
ただ、アプリケーションを動かすだけであれば一度書いた Dockerfile を使いまわすことも可能なので、テンプレートを探してきてそれを使っても構いません。
以下が Rust のプログラムを動かすための最小の 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 を使って、イメージを作ることができます。これをイメージのビルドと言います。
docker build -t naro_server .
-t
オプションでイメージに名前を付けています。
docker images
でイメージ一覧を確認しましょう。naro_server
というイメージが作成されているはずです。
docker build
について https://docs.docker.jp/engine/reference/commandline/build.html
コンテナを起動する
最後に先ほど作った naro_server
イメージから Docker コンテナを起動しましょう。
docker run -p "127.0.0.1:3000:8080" -e GREETING_MESSAGE=こんにちは -e PORT=8080 naro_server
このコマンドを実行した後、localhost:3000/greeting にアクセスすると、アプリケーションが動いていることを確認できます。
-p
オプション
{ホスト側ポート}:{コンテナ側ポート}
と書いて、コンテナ内のどのポートをホスト側のポートに公開するか指定します。127.0.0.1
はlocalhost
と同じ意味です。ホストとコンテナで指定したポートがパイプでつながれるイメージです。これによって、ホスト側からコンテナ内のアプリケーションへアクセスできるようになります。指定しない場合はアクセスできません。
-e
オプション
-e {環境変数名}={値}
の形で環境変数を指定できます。今回はアプリケーションの動作に必要なGREETING_MESSAGE
とPORT
を指定しています。
他にも様々なオプションがあります。docker help build
で確認してみましょう。
コンテナ側の側ポートを 8080 以外にして実行し、アクセスした様子をスクリーンショットに撮って講習会用チャンネルに投稿しましょう。
答え
-p
と-e
の両方を変える必要があります。
docker run -p "127.0.0.1:3000:8081" -e GREETING_MESSAGE=こんにちは -e PORT=8081 naro_server
コンテナを止める際にはdocker stop {docker ps で調べたコンテナidか名前}
を実行してください。