0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RustをDockerで動かしてホットリロードしてみる

Posted at

対象読者

Dockerコンテナ上でRustのコードをデプロイしたいけど、コードを変更するたびにDockerコンテナを立ち上げ直さなければいけない、や一回プロセス終了させて

docker compose exec hoge cargo run 

とかやるの面倒だ、と思っている方が対象です!

ある程度、Dockerのコマンドや概念、RustやCargoについて知っている前提で進めていきます。

要約

  • Docker Compose Watch を利用してコードの変更を認識する
  • cargo-watchをコンテナでインストールする
  • compose.ymlにこれを追記する
compose.yml
services:
  back:
    develop:
      watch:
        - action: sync
          path: ./backend
          target: /work/backend
          ignore:
            - ./backend/target
    command: /bin/sh -c "cargo watch -x run"

Rustでホットリロード

皆さん!Rustでサーバーサイド処理書いていますか?
サーバーサイドでなくても、常に動かしておくプログラムっていっぱい書くと思います。
そのようなプログラムを書いているとき、プログラムを書き替えたら再ビルドを自動でしてくれると便利ですよね。

そこでホットリロードの登場です!

ホットリロードは、プログラムを書き替えると再ビルドを自動で行ってくれる機能ですが、それをRustで行う方法として cargo-watch があります。
やり方としては、

cargo install cargo-watch --locked

と、cargo-watchをインストールして、プロジェクトのディレクトリで

cargo watch -x run

とするだけでホットリロードが実現できます。

しかし、Dockerコンテナ上ではそううまくはいきません。

起こったこと

まず、前提としてこのようなディレクトリ構成で作業しています。

/project
├─/backend
│ ├─Cargo.toml
│ ├─Cargo.lock
│ ├─.gitignore
│ ├─Dockerfile
│ ├─/target
│ └─/src
│   └─main.rs
├─/frontend
├─/database
│ ├─init.sql
│ └─Dockerfile
├─.env
└─compose.yml

また、compose.ymlやDockerfileにはこのようなことを記述しています。

compose.yml
services:
  back:
    build:
      context: ./backend
    tty: true
    hostname: "${APP_HOST}"
    ports:
      - "${APP_PORT}:${APP_PORT}"
    env_file:
      - .env
    volumes:
      - "./cargo-cache:/usr/local/cargo/registry"
      - "./rust-target-cache:/work/backend/target"
      - "./backend:/work/backend"
    command: /bin/sh -c "cargo watch -x run"

volumes:
  cargo-cache:
  rust-target-cache:
./backend/Dockerfile
FROM rust:latest

WORKDIR /work/backend

# 必要なツールをインストール
RUN apt-get update && apt-get install -y \
	inotify-tools

# cargo-watchをインストール
RUN cargo install cargo-watch

このcompose.ymlとDockerfileを書いて

docker compose up -d

としたところ、

ホットリロードが行われていませんでした😭

いったいなぜ?と思い、私たちはアマゾンのジャングルの中へ・・・

なんとマウントされたファイルは認識しないとのこと!?[1]

となると、どうしたらいいんだ・・・と思い、調査を続けると、どうやら Docker Compose Watch なるものがあるじゃないですか!

Docker Compose Watch

Docker Compose Watchは、compose.ymlファイルに記述したディレクトリ以下で変更があった場合に、コンテナの再スタートや再ビルド、同期等を行ってくれる機能です。

この様にcompose.ymlに記述すると、Docker側でホットリロードを行ってくれます。([3]からの引用)

compose.yml
services:
  web:
    build: .
    command: npm start
    develop:
      watch:
        - action: sync
          path: ./web
          target: /src/web
          ignore:
            - node_modules/
        - action: rebuild
          path: package.json

この設定の場合は、./web以下のファイルに変更があれば/src/webと./webを同期し、package.jsonに変更があればコンテナをビルドし直す設定になっています。

これを利用して早速Rustでホットリロードしていきましょう!

Dockerコンテナ上でのRustのホットリロード

では、まず./backend/Dockerfileを変更していきましょう。
このやり方では、マウントではなくCOPYして同期させる方法でWindows上の変更をDockerコンテナに適用させます。
そのため、COPYを追記し、backendディレクトリ以下のファイルをコンテナにコピーさせています。

FROM rust:latest

WORKDIR /work/backend

# 必要なツールをインストール
RUN apt-get update && apt-get install -y \
	inotify-tools

# cargo-watchをインストール
RUN cargo install cargo-watch

COPY . .

次に、変更したファイルをDocker上のファイルに適用させるため、compose.ymlを変更しましょう!
backend以下に変更があれば、コンテナ上のファイルにも適用させてほしいので、./backend以下に変更があれば、/work/backendに対してsyncを行うよう設定します。
また、targetディレクトリ以下が変更されても無視をする設定を行っています。

compose.yml
services:
  back:
    build:
      context: ./backend
    tty: true
    hostname: "${APP_HOST}"
    ports:
      - "${APP_PORT}:${APP_PORT}"
    env_file:
      - .env
    volumes:
      - "./cargo-cache:/usr/local/cargo/registry"
      - "./rust-target-cache:/work/backend/target"
    depends_on:
      - db
    develop:
      watch:
        - action: sync
          path: ./backend
          target: /work/backend
          ignore:
            - ./backend/target
    command: /bin/sh -c "cargo watch -x run"

volumes:
  cargo-cache:

これで、動かしてみます。
動かす方法は、

docker compose up --watch

で、composeで立ち上げたものをwatchしています。
さて、まずは動作確認・・・

image.png

キタ━━━━(゚∀゚)━━━━!!(DBコンテナが動いているのは気にしないでね)

では、ホットリロードが機能するのか・・・

println!("Hello, World!");

を追記してみてみたいと思います!

動くか・・・

image.png

キタ━━━━(゚∀゚)━━━━!!

ついにやってやりました!
これでわずらわしさを少し減らして開発ができる・・・

めちゃくちゃ調べるのに時間がかかったので是非参考にしていただければと思います。
また、至らぬ点や気になる点があればぜひコメントお願いします!

参考文献

[1] "WSL+DockerでHot reload が動作しない", https://banatech.net/blog/view/54 (2024/12/27)
[2] "Docker Compose Watchを触ってみる", https://zenn.dev/maybe_dog/articles/bfeeee3b6650a1 (2024/12/27)
[3] "Use Compose Watch", https://docs.docker.com/compose/how-tos/file-watch/ (2024/12/27)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?