LoginSignup
23
8

More than 3 years have passed since last update.

ElixirでIoT#4.1.2:[使い方篇] Docker(とVS Code)だけ!でNerves開発環境を整備する

Last updated at Posted at 2020-12-04

この記事は fukuoka.ex Elixir/Phoenix Advent Calendar 2020 の4日目です.
3日目は,@torifukukaiouさんの「ElixirでAtCoderのABC123を解いてみる!」でした.awesome!!:tada::tada::tada:

はじめに

どうも最近は開発環境厨みが増してきている気がします.
ElixirでIoT!の連載記事も久々な気がするんですが,今回も開発環境な記事です^^;

これまでの実績はこんな感じです.

なんか新しいものを導入するたびにホスト環境はいろいろ汚れるわけですが,それを解消するために最近はDockerにハマりつつあります.
@matsujirushi さんがこんな記事を公開していました!

こんなcoolなsolution,もうちょい綺麗にできそう!ってことで, @matsujirushi さんにリポジトリの権限をいただきつつ,Docker(とVS Code)だけで素敵な開発環境を整えてみました!!

この記事では整備した環境について,ユーザ目線での使い方を主に紹介します.
中身の解説はまた機会を改めて^^;

つくったもの

なにが嬉しいの?いつ使うの?

  • Dockerを使えば,数ステップだけでNervesの開発環境が整います.ElixirでIoT#4.1で紹介したみたいに,Nervesの開発環境の準備って,いろいろライブラリを入れたり,いろいろErlangインストールにハマったり,いろいろ大変なんですよね,,, そんなシチュエーションが気楽に回避できます.
  • 特に入門者にとっては嬉しいですし,知り合いにすぐ試してもらいたい!場合にも紹介しやくなるかと思います.
  • ハンズオンの開催を計画する時にすごく頭を悩ませるのが,参加者の環境を揃えることです.DockerfileとかVS Codeの各種設定ファイルを調整すれば,これもお手軽に解消できます!!
  • すでにNervesを導入済みの方でも,最新のバージョンや機能を味見で試してみたいことは多いです.そんなときにDockerを使えば,ホストの環境は汚さずにお手軽に最新版を試すことができます.asdfでErlang/Elixirのバージョンを切り替えて mix archive.install hex nerves_bootstrap のバージョンも,,, って煩わしさも無くなります.
  • Docker Hubにビルド済みのイメージを公開しています.これを使えば,さらに効率よくNerves開発環境が手に入ります(ただし最新版じゃないことがありますので,ご注意ください.全てはメンテナの @takasehideki の頑張り次第です^^;

ツラいことは??

  • Dockerを動かすので,CPU/メモリの負荷がそれなりに掛かります.あとイメージ展開のためのディスク容量も必要です.
  • mix burn でNervesファームウェアをmicroSDカードに書き込む作業ができません,,, ホスト上で fwup を実行する必要があります:fire::fire::fire:

導入手順

インストールが必要なものは下記です.

DockerとVS Codeの詳しい導入方法は「ALGYAN x Seeed x NervesJPハンズオン!に向けた開発環境の準備方法」の記事を参照してください.

Docker単体で動かす

Docker Hubリポジトリから

ビルド済みのDockerイメージを使用します.pullしてrunするだけです.

$ docker pull nervesjp/nerves
$ docker run -it -w /workspace nervesjp/nerves
root@6e304327bd2e:/workspace# 

GitHubリポジトリから

GitHubで公開しているDockerfileを使ってローカルでビルドします.自分好みにDockerfileをカスタマイズすることもできます.

$ git clone https://github.com/NervesJP/docker-nerves
$ cd docker-nerves

$ docker build -t docker-nerves .
$ docker run -it -w /workspace docker-nerves 
root@9bc88d0fc7b8:/workspace# pwd
/workspace
root@9bc88d0fc7b8:/workspace# echo ${HOME}
/root
root@9bc88d0fc7b8:/workspace# ls ~/.mix/*
/root/.mix/rebar  /root/.mix/rebar3

/root/.mix/archives:
hex-0.20.6  nerves_bootstrap-1.10.0

Docker単体動作でのTips

ファイルシステムのマウント

Dockerはイメージの再構築時/実行時に,そのファイルシステムが消えてしまいます.このため,Nervesプロジェクトのファイルを保持するためにホストにボリュームをマウントしておくのが便利です.
-v $ {PWD}:/ workspace によって,ホスト上の現在のディレクトリをDockerイメージにマウントできます.

$ docker run -it -w /workspace -v ${PWD}:/workspace docker-nerves 

Elixir/Nervesに関連する設定ファイルをマウントしておくのも効率的です. ~/.hex~/.nerves.ssh/ があります.
以下は,ホストとイメージ間で設定ファイルを共有する例です.

$ docker run -it -w /workspace -v ${PWD}:/workspace \\
  -v ~/.hex:/root/.hex -v ~/.nerves:/root/.nerves -v ~/.ssh:/root/.ssh \\
  docker-nerves 

環境変数の設定

Dockerコンテナの立ち上げ時にシェルの環境変数を設定することができます.

Nerves開発時に必須の環境変数として ${MIX_TARGET} があります.
開発対象とするNervesのtargetがすでに決まっていて固定されているなら,この変数を設定したほうが楽になります.
次の例ではrpi3に設定してます.

$ docker run -it -w /workspace -e MIX_TARGET=rpi3 docker-nerves 
root@deda9932d7e3:/workspace# echo $MIX_TARGET
rpi3

複数の環境変数を同時に設定したい場合は --env-file を使うと良いでしょう.
例えば,vintage_net_wifiのWiFi接続設定を環境変数で与える方法があります.
下記のように env.list を作成してオプションで与えるだけです.

$ cat env.list 
MIX_TARGET=rpi3
WIFI_SSID=xxxxxxxx
WIFI_PSK=yyyyyyyy
$ docker run -it -w /workspace --env-file env.list docker-nerves 
root@cf815278594a:/workspace# echo $MIX_TARGET
rpi3
root@cf815278594a:/workspace# echo $WIFI_SSID
xxxxxxxx
root@cf815278594a:/workspace# echo $WIFI_PSK
yyyyyyyy

環境変数を用いたVintageNetのWiFiの設定方法は,次の記事をご参照ください(どちらも両記事!!:tada:

VS Codeでより便利に!

みんな大好きVisual Studio Codeを使うと,さらに快適な開発環境が手に入ります.
通称dev-containerという拡張機能 Remote - Containers を利用します.
詳しくは下記の記事などをご参照ください〜

使用方法

1. リポジトリをclone

git clone https://github.com/NervesJP/nerves-devcontainer

Gitに慣れていなければ,下記から直接ダウンロードもできます.
https://github.com/NervesJP/nerves-devcontainer/archive/main.zip

2. VS Codeをdev-container機能で開く

VS Codeを起動して,クイックアクションのステータスバー項目(左下の緑の >< となっているところ)かF1をクリックします.
コマンドパレットが開きますので,Remote-Containers: Open Folder in Container...を選択し,手順1でcloneしてきたディレクトリを選択します.

image.png

image.png

3. コーヒーを淹れる:coffee:

Dockerイメージのダウンロードと展開がよしなに始まります.PCスペックとネットワーク環境によっては10分くらい掛かるかもしれません.コーヒーでも呑みながら,落ち着いてお待ちください

うまくいかない?場合は,Docker Desktopのアプリが起動していないことが考えられます.
Windowsだと,デスクトップ右下のタスクトレイにこんな感じのクジラのアイコンが表示されているか確認してください(Macだとメニューバーにいてます)

image.png

ちゃんと進んでいるか気になる方は, 右下の青字の "Starting Dev Container (show log)" をクリックすると,進捗のログが表示できます.

ということで,こんな感じに出来上がりっ♪
左下の緑色なところが
>< Dev Container: Nerves
な表示になっていることを確認してください.
(画像は途中で "Starting Dev Container (show log)" をクリックして進捗を表示した場合のものです)

image.png

メニューの [ターミナル] > [新しいターミナル](ショートカットキーは Ctrl+Shift+`)でターミナルを開くと, Dockerイメージ内でNerves開発環境の整ったターミナルを良い感じに利用できます.
(起動直後は[新しいターミナル]が選択できないことがあるようです.その場合は左側[エクスプローラー]で右クリックして[統合ターミナルで開く]を選択してみてください)

root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# ls 
LICENSE.txt  README.md
root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# ls ~/.mix/*
/root/.mix/rebar  /root/.mix/rebar3

/root/.mix/archives:
hex-0.20.6  nerves_bootstrap-1.10.0
root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# elixir --version 
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Elixir 1.11.2 (compiled with Erlang/OTP 23)
root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# iex 
Erlang/OTP 23 [erts-11.1.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 

4. SSH鍵を作成する

Nervesのファームウェア開発とネットワーク接続には,SSH鍵交換方式が使われます.
下記のように,いちばん代表的であるRSA鍵を作成しておきます.

ssh-keygen -t rsa -N "" -f .ssh/id_rsa

Tips a.k.a コダワリどころ

ローカルでのイメージの手動ビルド

GitHubで公開しているVS Codeのディレクトリは,Docker Hubでビルド済みのイメージのを使用しています.
手元でカスタマイズしてビルドしたい場合は,もともとのDockerfile./.devcontainer に配置して, ./.devcontainer/devcontainer.json//"dockerFile": "Dockerfile", の行のコメントを解除してください.

.devcontainer/devcontainer.json
{
    "name": "Nerves",
    // Pull Docker image from DockerHub  https://hub.docker.com/r/nervesjp/nerves
    //"image": "nervesjp/nerves:0.1.1",
    // NOTE: original Dockerfile is maintained at https://github.com/NervesJP/docker-nerves/blob/main/Dockerfile
    // You can also build Docker image locally by locating above file to here and uncomment next line 
    "dockerFile": "Dockerfile",

〜〜(省略)〜〜

Nerves設定に関するファイルのマウント

先ほどのTIPSと同じく,イメージの再構築時/実行時に,そのファイルシステムが消えてしまいます.
VS Code/GitHubでは docker run 時のオプションも統一できるので,これらのファイルが含まれるディレクトリをカレントに保持するようにしました.
(これらはどこにマウントするのがいいのか,割りと悩ましかったです.${HOME} のほうがええんちゃうかという気もします.ご意見いただけたら嬉しいです)

1つめは,Dockerコンテナ内の ~/.hex にマウントされる ${PWD}/.hex です.ElixirのHexパッケージが保持されます.

2つめは,Dockerコンテナ内の ~/.nerves にマウントされる ${PWD}/.nerves です.このディレクトリでは,Nervesのツールチェーンとnerves_system_brのアーカイブが保持されます.

Dockerコンテナの再起動のたびに mix deps.get でこのアーカイブのダウンロード/展開は面倒ですし時間が掛かります.なので,このディレクトリをマウントするようにしています.
ホストとコンテナのファイルシステム間のバインディングはパフォーマンスが悪いため,最初の mixdeps.get の実行時には多少の時間が掛かります.ですが,Docker起動のたびにダウンロード/展開に待たされるよりはマシじゃね?と判断しました.

最後に ${PWD}/.ssh です.
ステップ4で作成した id_rsaid_rsa.pub のSSHキーペアが含まれます.これらは,Nervesファームウェアの構築とNervesデバイスへのSSH接続のために使用されます.

さらに,VS Code拡張機能の自動設定で,Nervesのプロジェクトファイルも現在のディレクトリに保持されます.

環境変数の設定

これまたVS Code拡張機能の便利なところで, ./.devcontainer/devcontainer.json にてコンテナ内のシェル環境変数を設定することができます.

今回はこんな感じで設定してあります.お好みに合わせて編集してからご利用ください.

.devcontainer/devcontainer.json
(省略)
    // This section sets environment variables for Nerves development
    "remoteEnv": {
        "MIX_TARGET": "rpi3",
        "WIFI_SSID": "xxxxxxxx",
        "WIFI_PSK": "yyyyyyyy"
    }
(省略)

制約事項,,, mix burnできないorz

すっげー便利やん!と思うのですが,冒頭にも挙げている欠点がひとつだけあります.
Docker環境からはmicroSDカードへのアクセスができません,,, このため,せっかくDocker内でビルドしたNervesファームウェアを,mix burnでそのままmicroSDカードに書き込めません.

代案として,Nervesファームウェアの書込みのためのユーティリティである fwup をホストにインストールして実行します.
https://github.com/fhunleth/fwup

fwupのインストール

Windowsの場合

Chocolateryを使われている方は,下記でインストールできます.

choco install fwup

そうでない方は,下記からバイナリを直接ダウンロードして,ダウンロード先にPath環境変数を設定してください.
https://github.com/fhunleth/fwup/releases/download/v1.8.3/fwup.exe

上記URLのv1.8.3のバージョン番号は,最新リリースに合わせて変更してください.

macOSの場合

brewでインストールできます.

brew install fwup

Linuxの場合

プラットフォームに合わせて,パッケージのダウンロードとインストールを行ってください.
https://github.com/fhunleth/fwup#installing

例えばDebian/Ubuntuならこんな感じです.

$ wget https://github.com/fhunleth/fwup/releases/download/v1.8.3/fwup_1.8.3_amd64.deb
$ sudo dpkg -i fwup_1.8.3_amd64.deb

上記URLのv1.8.3のバージョン番号は,最新リリースに合わせて変更してください.

fwupによるファームウェアの書込み

インストールが完了したら,ターミナルを開いてNervesのプロジェクトのディレクトリに移動して,下記のとおり実行してください.
Windowsの方は,PowerShellを「管理者として実行する」で開く必要があります.

$ cd <your_nerves_project_dir>
$ fwup _build/${MIX_TARGET}_dev/nerves/images/<project_name>.fw

Dockerだから仕方ない話しではあるのですが,なんかうまいことできたら嬉しいところです.
例えばmicroSDの /dev/diskX を書き込み可能でアクセスできたり,ホストにシェルプロセスの立ち上げをそこで実行したり,,, (WSL 2ではそんな機能があるらしい??

良い方法をご存じの方がいましたら,ここのissue#1かコメント欄で教えてください〜

おわりに

この記事の初稿は,実は英語で書きました.
よっしゃElixir Forumに投稿してやんぜ!世界のみんなを楽にしてやんぜ!Advent Calendarも英語記事を登録やっ!!
って息巻いていたんですが,どうもElixir ForumはModeratorsの審査承認作業があるらしく,,,
敢えなく日本語で書き直す,そんな不毛な作業の果てでした^^;

↓ この1時間後,,, 無事にapprovedされて公開されました!! :grin:


fukuoka.ex Elixir/Phoenix Advent Calendar 2020 の5日目は @hisaway さんによる「[Elixir]匿名関数をパターンマッチする」です.ASTの世界をチラ見しましょっ:eyes:

23
8
2

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
23
8