14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rustの開発環境を整えるまでにやったことメモ

Last updated at Posted at 2020-10-13

環境

version 備考
windows10 Pro 1903 (OSビルド) 18362.1082
Docker Desktop 2.4.0.0(48506) wsl2で動作
vscode 1.49.3
コンテナで開発・ビルドできるようにする。
しばらく離れていた&環境が変わったので自分用備忘録
wsl2+Docker Desktopに関してはここここここを参考にした。

hyper-vからの乗り換えの場合、
wsl2を使えるようにしてからhyper-vを無効化したらエラーが出たので、

  1. (Docker Desktopアンインストール)
  2. hyper-v 無効化
  3. wsl2有効化
  4. (Docker Desktop再インストール)

とすると確実かもしれない。

本編

1. コンテナイメージの取得・確認

PowerShellにて

PS:> docker pull rust:latest
     (結果略)

PS:> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
rust                latest              c69fb046b993        3 days ago          1.28GB

2. composeファイルの作成

vscodeで開発用コンテナを立ち上げるために、docker-composeファイルを作成します。
vscodeの機能で作成することもできますが、追加で少しやりたいことがあるため自作します。

{docker-compose.local.yml}
version: '3.7'

services:
  rust-dev:
    image: rust:latest
    container_name: rust_dev
    working_dir: /app
    volumes:
      - ./:/app
      - rust_dev_target:/app/target
    tty: true
    environment:
      USER: xxxxx # cargo で必要になる
      CARGO_BUILD_TARGET_DIR: /app/target

volumes:
  rust_dev_target:
    external: true

基本的な部分の解説はdocker-composeのリファレンスとか、その他の解説記事に任せるとして、
やりたかったことに関わる2点だけ

  1. environmentのCARGO_BUILD_TARGET_DIR
    この環境変数で指定したディレクトリに、targetが吐き出される
  2. volumes
    node_modulesを隔離するための方法から着想を得たやり方。
    CARGO_BUILD_TARGET_DIRでtargetフォルダをプロジェクトの外に出し、1
    そこにrust_dev_targetという外部ボリュームをマウントしなおしている。
    これによってコンテナを削除してもtargetの中身を維持することができる。
小技とか
#### composeファイル内で変数を使う composeファイルと同じ階層に*.env*ファイルを置いておくと、環境変数として**自動で**読み込んでくれる。[^2] これを使って一部置き換えておくことで、例えばマウント先のフォルダ変えたいなーってなったときに少しだけ便利。 composeファイル内での環境変数の参照は${~~}で出来る
{ ..env }
mnt=/app
{docker-compose.local.yml}
version: '3.7'

services:
  rust-dev:
    image: rust:latest
    container_name: rust_dev
    working_dir: ${mnt}
    volumes:
      - ./:${mnt}
      - rust_dev_target:${mnt}/target
    tty: true
    environment:
      USER: xxxxx 
      CARGO_BUILD_TARGET_DIR: ${mnt}/target

volumes:
  rust_dev_target:
    external: true

3. vscodeでコンテナを立ち上げる

  1. 適当なフォルダを作って上記のcomposeファイルを置き、codeで開く

  2. vscodeに拡張機能Remote - Containersを追加する。

  3. 左下に追加される緑のボタンを押し、
    Remote-Containers: Add Development Container Configuration Files...
    を選択する

  4. From 'docker-compose.local.yml'を選択する。
    すると、.devcontainerというフォルダにdevcontainer.jsondocker-compose.yml が作成されるのでそれぞれ編集する

    {docker-compose.yml}

version: '3.7'
services:
rust-dev:
# volumes: # この行コメントアウトした
# Update this to wherever you want VS Code to mount the folder of your project
# - .:/workspace:cached # この行もコメントアウト

  # Overrides default command so things don't shut down after the process ends.
  command: /bin/sh -c "while sleep 1000; do :; done"
```

こちらはvolumesをコメントアウトするだけ。
見やすさのために省略しているが、コメントに説明が書いてあるので、読んで適宜変更。

```{json:devcontainer.json}
{
    "name": "rust😀",
    "dockerComposeFile": [
        "..\\docker-compose.local.yml",
        "docker-compose.yml"
    ],
    "service": "rust-dev",
    "workspaceFolder": "/app",
    "settings": {
        "terminal.integrated.shell.linux": null,
        "editor.formatOnSave": true,
        "rust.target_dir": "/app/target"
    },
    "extensions": [
        "rust-lang.rust",
        "vadimcn.vscode-lldb"
    ]
}

```
<details><summary>分かる範囲で詳細</summary><div>
+ name  
    これだけコメントがない。vscodeでの表示上の名前、だけだと思う。
+ dockerComposeFile  
    composeファイルを読み込む順に書く。composeファイルをさらに分割している場合はここに書けばよい。  
**基本的には変更する必要はない。**
+ service  
composeファイルのservicesに定義した名前。複数定義している場合はメインとなるものを。  
**基本的には変更する必要はない**
+ workspaceFolder  
composeファイルで定義した、*working_dir*と同じ値を設定する。  
コメントアウトすると`/`を開くのでdocker-compose.local.ymlで定義した値が上書きされるっぽい  
じゃあ*working_dir*要らなかったじゃん。ソダネー
+ settings  
vscodeのsetting.jsonに書いている内容をそのまま書ける。  
コンテナ内部にだけ適用されるので、下記extensionsで追加する拡張機能に対する設定はここに書いておけば間違いない。
+ extensions  
コンテナに導入したい拡張機能のIDを書く。IDは拡張機能の名前の横に表示されている。  

image.png
例)図の灰色ががっている部分がID
とりあえずRust拡張機能とCodeLLDB。他にいいものがあれば知りたい。
+ forwardPorts
コンテナのポート開放する際にはアンコメントする。composeファイルにportsで書いても同じ。

</div></details>

**注意点**
settingsのrust.target_dir
これを書かないと、追加したcrateをrlsが見つけられずエラーが出る
  1. volume作成

    PS:> docker volume create rust_dev_target
    
    PS:> docker volume ls
    DRIVER              VOLUME NAME
    local               rust_dev_target
    

    composeファイルでexternal:trueしているので先に作っておかないとエラーになる

  2. 左下の緑のボタンを押し、
    Remote-Containers: Reopen in Container
    を選択する。準備編終わり。

4. プロジェクトの作成

開発はThe Rust Programming Languageを参考にすれば問題ないと思う。
著者とコミュニティに感謝。
Cargoでプロジェクトを作成すればHello worldが出来る。

TERMINAL }
root@02080d70998d:/app# cargo --version
cargo 1.47.0 (f3c7e066a 2020-08-28)
root@02080d70998d:/app# cargo new hello --bin
     Created binary (application) `hello` package
root@02080d70998d:/app# cd hello
root@02080d70998d:/app/hello# cargo run
(略)
Hello, world!

5. オートフォーマット

右下のベルマークのところに
Some Rust components not installed. Install?
と出るのでYesでインストール。
終わると保存したときに整形されるようになる。
コンテナを削除(orリビルド)した場合はもう一度やる必要がある。

6. マルチステージビルド

リリースビルドと同時にコンテナ化したいので専用のDockerfileとcomposeファイルを作る。
ついでにパッケージインストールはキャッシュさせて高速化したいのでそのあたりも対応。 2

Dockerfile}
FROM rust:latest AS builder

WORKDIR /app
ENV USER=root

# RUN rustup target add x86_64-unknown-linux-musl

RUN cargo new my_prj
WORKDIR /app/my_prj

COPY ./hello/Cargo.toml ./hello/Cargo.lock ./
RUN cargo build --release 

COPY ./hello/src ./src
RUN cargo build --release 

FROM debian:stretch-slim AS prod
ENV TZ=Asia/Tokyo
COPY --from=builder /app/my_prj/target/release/ /usr/local/bin
WORKDIR /app
CMD ["hello"]

空プロジェクトを一度ビルドしてからsrcを入れ替えて再ビルドしている。
alpine向けにビルドしようとしてうまくいかなかったので調査中。
続いてcompose

{docker-compose.build.yml}
version: '3.7'

services:
  builder:
    build:
      context: .
      dockerfile: DockerFile
      target: builder
    image: rust-test:builder

  rust_test:
    build:
      context: .
      dockerfile: DockerFile
      target: prod
    image: rust-test:latest

builderサービスをtarget: builder3として定義してあげることで、マルチステージビルドにおけるビルドステージにあたるコンテナにタグをつけておくことができる。
こうすることでdanglingイメージ(<none>:<none>のこと)にならないので、ビルド途中の状態がキャッシュ出来る。

7. 実行用compose作成

rust-test:latestに必要な環境変数とか与えて実行できるようにする。
目新しいことがないので割愛

おわりに

開発用のDBも同時に立ち上がるようにしたり、他にもやったことがあるけど今回はここまで

追記

hot-reload効かない問題への対処

プロジェクトをwindowsのファイルシステム上4に構築すると、
windows-linuxのファイルシステム間の問題でソースコードの変更検知がうまく走らない。
そのため、wslで管理しているディレクトリにコードを置く必要がある。
具体的には、
\\wsl$\Ubuntu-20.04\home\ユーザー名\workspace\プロジェクト名
など。
image.png

  1. targetフォルダは、通常プロジェクトフォルダの内部にできるが、composeファイルにプロジェクトファイルの名称を入れたくなかったため外出ししている

  2. Dockerfile的にはキャッシュしていると思うが、Rustのビルドの仕組みに明るくないので保証はできない。

  3. AS で付けた名前

  4. \cや\d以下の任意のフォルダ

14
17
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
14
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?