Nerves development workspace with Visual Studio Code dev-container (Remote - Containers extension)
- Docker Desktop
- Visual Studio Code
- Remote - Containers extensions
-
Clone this repository
$ git clone https://github.com/NervesJP/nerves-devcontainer
-
Start VS Code, run the Remote-Containers: Open Folder in Container... command from the Command Palette (F1) or quick actions Status bar item, and select the project folder you cloned at Step 1.
-
After a while, you can enjoy Nerves/Elixir development with Bash on Docker image and VS Code like as follows.
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.21.1 nerves_bootstrap-1.10.1 root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# elixir --version Erlang/OTP 23 [erts-11.1.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] Elixir 1.11.3 (compiled with Erlang/OTP 23) root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# iex Erlang/OTP 23 [erts-11.1.7] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] Interactive Elixir (1.11.3) - press Ctrl+C to exit (type h() ENTER for help) iex(1)>
-
Note that you need to generate your SSH keys, only for the first time to login Docker image.
root@ebc5e1a19ae3:/workspaces/nerves-devcontainer# ssh-keygen -t rsa -N "" -f .ssh/id_rsa
This repository will clone pre-built image on Docker Hub.
Original Dockerfile is maintained at https://github.com/NervesJP/docker-nerves/blob/main/Dockerfile.
The number of Docker Tag and the Release number of this repository are associated with the Release of GitHub repository for Dockerfile.
You can also build Docker image locally by locating above Dockerfile to
./devcontainer
and uncommenting //"dockerFile": "Dockerfile",
on
./devcontainer/devcontainer.json
.
It means you can customize your own Nerves development environment as you want.
Each time an image is execute, a filesystem into Docker image will disappear. So Elixir/Nerves related setting directories are mounted in the current (this) directory on the host.
First directory is ${PWD}./hex
that will be mounted to ~/.hex
. It keeps Hex archives.
Second, ${PWD}./nerves
will be mounted to ~/.nerves
. It keeps archives of
Nerves toolchains and nerves_system_br
.
If they disappeared when Docker container was restarted, you need to download
archives every time you operate mix deps.get
.
So we decided to mount it on this directory.
Although mix deps.get
at first will take a while to unzip archives to
./nerves/artifacts
due to poor performance about bindings between host and
container filesystems, we think it is acceptable compared that we always have
to wait when running mix deps.get
for a long time.
The last one is ${PWD}/.ssh
that is expected to contain id_rsa
and
id_rsa.pub
SSH key pairs.
They are used for the construction of Nerves firmware and secure connection to Nerves devices.
It is mounted to ~/.ssh/
on Docker image.
To generate your SSH keys, you need to operate ssh-keygen -t rsa -N "" -f /workspaces/nerves-devcontainer/.ssh/id_rsa
after logging into Docker image
for the first time.
In addition, your Nerves project can be kept on the current directory by the VS Code automatic feature.
By default, the Remote-Container extension automatically mounts
/works/nerves-devcontainer
on the container at the current location on
the host. Working here is efficient because you can edit the files in the
Nerves project with the VS Code GUI, and you can also access them from
the host. However, you may feel building the Nerves application becomes
slow due to the performance of bindings between their filesystems.
One way to establish both speed up the performance for building and keep the development efficiency is to create a symbolic link in the working directory inside the container from the location.
root@25168de60a54:/workspaces/nerves-devcontainer# pwd
/workspaces/nerves-devcontainer
root@25168de60a54:/workspaces/nerves-devcontainer# pushd ~
~ /workspaces/nerves-devcontainer
root@25168de60a54:~# pwd
/root
root@25168de60a54:~# mix nerves.new hello_nerves
...
root@25168de60a54:~# ln -s /root/hello_nerves /workspaces/nerves-devcontainer/hello_nerves
root@25168de60a54:~# popd
/workspaces/nerves-devcontainer
root@25168de60a54:/workspaces/nerves-devcontainer# cd hello_nerves
root@25168de60a54:/workspaces/nerves-devcontainer/hello_nerves# mix do deps.get, firmware
...
Again, note that a filesystem into the Docker image will disappear when it is regenerated. When development is settled, we recommend copying to the file system bound to the host (or pushing to your GitHub :D
root@25168de60a54:/workspaces/nerves-devcontainer# rm hello_nerves
root@25168de60a54:/workspaces/nerves-devcontainer# cp -r /root/hello_nerves /workspaces/nerves-devcontainer
You can set your own environment variables with remoteEnv
option in
./devcontainer/devcontainer.json
.
By default, ${MIX_TARGET}
is set to rpi3
when running the dev-container.
Please change the value accordingly if your target of Nerves
is already determined by something other than rpi3
.
In addition to this, here we define environment variables for WiFi settings.
You may set these values of ${WIFI_SSID}
and ${WIFI_PSK}
according to the
WiFi access point. See "Connect to a target device" on this
article
for details.
Docker has restrict policies to avoid effecting host environment. And also, it is not possible to pass through a USB device (or a serial port) to a container as it requires support at the hypervisor level both in Windows and macOS as the host.
Therefore, mix burn
cannot be operated from Docker image because there is no
right to access /dev
to on host as a root user.
One way to burn Nerves firmware is just operating fwup
on the host. fwup
is
an utility for constructing/burning Nerves firmware. See https://github.com/fhunleth/fwup.
After installing fwup
on the host according to this step,
please do following command on the host terminal (e.g., PowerShell as
Administrator, Terminal.app).
$ cd <your_nerves_project_dir>
$ fwup _build/${MIX_TARGET}_dev/nerves/images/<project_name>.fw
If you are using Linux as the host, you may be able to access microSD from the
Docker environment along with the privileged
option.
You may need to use a different /dev/
address for your purposes.
$ docker run -it -w /workspace -v ${PWD}:/workspace \\
-v /dev/sdb:/dev/sdb --privileged docker-nerves
Please let us know if you have a cool solution! (issue#1)
- Elixir Forum Topic: Nerves development environment with Docker (and VS Code) - Nerves Forum / Chat / Discussions - Elixir Programming Language Forum
- Qiita article (in Japanese)
- @matsujirushi : original (awesome!) contributor
- @takasehideki : main maintainer