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@d343da456c14:/workspaces/nerves-devcontainer# ls LICENSE.txt README.md root@d343da456c14:/workspaces/nerves-devcontainer# ls ~/.mix/* /root/.mix/archives: hex-2.3.1 nerves_bootstrap-1.14.0 /root/.mix/elixir: 1-18 root@d343da456c14:/workspaces/nerves-devcontainer# elixir --version Erlang/OTP 27 [erts-15.2.7] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns] Elixir 1.18.3 (compiled with Erlang/OTP 27) root@d343da456c14:/workspaces/nerves-devcontainer# iex Erlang/OTP 27 [erts-15.2.7] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns] Interactive Elixir (1.18.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@d343da456c14:/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-devcontainerYou can set your own environment variables with remoteEnv option in
./devcontainer/devcontainer.json.
By default, ${MIX_TARGET} is set to rpi5 when running the dev-container.
Please change the value accordingly if your target of Nerves
is already determined by something other than rpi5.
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>.fwIf 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-nervesPlease 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