Zephyr – getting started using Docker


Setting up a build environment for a new toolchain can be a tedious task, so is the case with Zephyr Project – there are lots of dependencies that need to be fulfiled before we can even start developing the simplest applications. Can we speed up this process?

This is where Docker come in handy – it allow us to ship whole toolchain with all dependencies in a single contained image, which can noticeably speed up the developement process. This way each member of a firmware development team is certainly using the same version of building tools, which leaves no room for misunderstandings.

Since our the primary goal is to build and run a simple Zephyr Project application, LPN Plant have prepared a Docker image specifically for this task.

Test platform

  • Operaring System: Ubuntu 18.04
  • Board: Nordic Semiconductor nRF52840 Development Kit

Setting up the Docker

To use the Docker, we have to install its engine. As an example we will install it on Ubuntu 18.04 using the apt package manager.

Note: For the most recent instructions, or instructions for other operating systems please refer to the Docker’s official installation guide

# Update the apt package index and install packages to allow `apt`
# to use a repository over HTTPS:
$ sudo apt-get update
$ sudo apt-get install 

# Add Docker's official GPG key:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# Verify that you now have the key with the fingerprint
# 9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88,
# by searching for the last 8 characters of the fingerprint:
$ sudo apt-key fingerprint 0EBFCD88

# Use the following command to set up the stable repository.
$ sudo add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu 
   $(lsb_release -cs) 

# Install the Docker Engine
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

# Verify the installation by running the `hello-world` container.
# It is a prebuilt image which will get pulled from the hub.docker.com:
$ sudo docker run hello-world

# (OPTIONAL) Create `docker` usergroup and add yourself to it,
# so that you can run Docker commands as a non-root user:
$ sudo groupadd docker
$ sudo usermod -aG docker $USER

# Log out and log back in to apply new usergroup.

# Now you can run `docker` commands without `sudo`:
$ docker run hello-world

Using the Docker

Now that we have confirmed installation of the Docker Engine we can finally set up our Zephyr OS build environment container. To get started quickly with Zephyr OS we recommend pulling our prebuilt image from the Docker Hub.

$ docker pull lpnplant/zephyr-builder:latest

When the download completes run it over zephyrproject-rtos/zephyr
(git clone https://github.com/zephyrproject-rtos/zephyr) repository:

$ docker run --rm -it --privileged 
    -v /dev/bus/usb:/dev/bus/usb 
    -v $PWD/zephyr:/home/build/zephyr 


  • rundocker subcommand for running the containers
  • --rm – clean-up the storage after stopping the container
  • -it – create an interactive terminal session and bind STDIN to the container
  • --privileged – grant extended privileges to this container, needed for
    managing USB devices (flashing etc.)
  • -v – bind host volume with containers volume: <host>:<container>
  • lpnplant/zephyr-builder:latest – tag of the container to be run

The Docker container will start, with entry point set to /home/build/zephyr. The container will automatically update the project submodules to newest versions. When the init process ends we are finally ready to go.

Building own Docker image

If you prefer to build own Docker image you have to get to know Dockerfiles.

The Dockerfile is essentially a recipe for building the Docker container. In other words it specifies all the necessary software packages to install and all the commands to prepare the environment for our use. Using this approach we can offload developers from the tedious task of preparing own machine, setting up the toolchain and getting frustrated about typos. Instead, the Docker can doit all for us in one easy to remember command:

$ docker build -t <tag> .


  • build – subcommand of docker engine used for building containers
  • . – use Dockerfile from the current directory
  • -t <tag> – flag used to tag the container for ease of identification

It will take a while to complete, but in the meantime feel free to sit back, as the whole process is fully automatic. The image build process is a one-time job, so although it might be time consuming, the subsequent runs of the container are much faster.

Building Zephyr Project example

west is Zephyr Project meta-tool for building, flashing and managing projects.

Being inside the docker container, you can check how many examples are available:

$ ls samples/

Perhaps the most classic example, the “Hello, World!” of hardware, is blinky – the blinking LED. It is placed under samples/basic/blinky/, so to build it using west:

$ west build 
    -b nrf52840dk_nrf52840 

[... truncated output ...]

[126/131] Linking C executable zephyr/zephyr_prebuilt.elf
Memory region         Used Size  Region Size  %age Used
           FLASH:       14948 B         1 MB      1.43%
            SRAM:        5296 B       256 KB      2.02%
        IDT_LIST:          56 B         2 KB      2.73%
[131/131] Linking C executable zephyr/zephyr.elf


  • buildwest subcommand for building projects
  • -b <board_name> – used to specify board model, in our case nRF52840 dev kit
  • samples/basic/blinky/ – path to a project to be build

Flash zephyr binary

If the build have finished successfully, connect your board to PC (in the case of nRF52840-DK you need to connect micro-USB cable to the port placed on the shorter side of the board) and flash the binary containing blinky project:

$ west flash
-- west flash: rebuilding
[0/1] cd /home/build/zephyr/build/zephyr/cmake/fl...cmake/cmake-3.18.0-Linux-x86_64/bin/cmake -E echo

-- west flash: using runner nrfjprog
-- runners.nrfjprog: Flashing file: /home/build/zephyr/build/zephyr/zephyr.hex
Parsing hex file.
Erasing page at address 0x0.
Erasing page at address 0x1000.
Erasing page at address 0x2000.
Erasing page at address 0x3000.
Applying system reset.
Checking that the area to write is not protected.
Programming device.
Enabling pin reset.
Applying pin reset.
-- runners.nrfjprog: Board with serial number 1234567890 flashed successfully.

Now you should see, that LED1 on your board blinks: 1s [ON], 1s [OFF].


Building ZephyrOS using Docker image doesn’t need more effort than without it, but it allows to build the same application on different machines, without worries, that output will differ.

In LPN Plant we connect consulting, technical expertise and financial effectiveness to design and implement low power wireless solutions for industry. If you are looking for product developers or just need support in a piece of your system feel free to contact us. If you enjoying this type of content feel free to share content on social media.

Leave a Reply

Your email address will not be published. Required fields are marked *