Docker 19.03 comes to NVIDIA Jetson Nano

Estimated Reading Time: 9 minutes

Did you know? In the latest Docker 19.03 Release, a new flag –gpus have been added for docker run which allows to specify GPU resources to be passed through to the Docker Image(NVIDIA GPUs). The latest nvidia-docker has already adopted this feature (see github), but deprecated --runtime=nvidia.

Last Dockercon, I met with a four-wheeled knee-high tiny cute food delivery robot called Kiwibot. Built by KiwiCampus Inc., Kiwibot is the robot counterpart of the pizza delivery person. Thanks to Dockercon for bringing this amazing piece of technology in-house for distributing swags, stickers, chocolates and goodies.

What’s so cool about Kiwibots?

Just open up your Wiki app and place an order for food. When you place an order online(facility to choose a participating restaurant), you get the option of delivery via Kiwi. Once you choose, one of the company’s fleet of super cool robots with insulated, locking storage compartments will swing by the place, your order is put within, and it brings it to your location. You can even watch the last bit live from the robot’s perspective as it rolls up to your place. Amazing, isn’t it?

Well, the super cute make and structure of these kiwibots looked interesting to me BUT what fascinated me really is the technology behind these small robots. A Kiwibot is equipped with six cameras and GPS to deliver the order at the right place. Nice ! Now here comes the best part. Only the person who has ordered will be able to open the Kiwibot and retrieve the order through the app which means it is intelligent enough to do object detection and analytics too. Interesting !!

Tell me more…


I went through the technology stack and was really amazed to learn that it uses NVIDIA Jetson TX2 system for  all of the AI processing, imaging, and related computing tasks(see picture below). Jetson TX2 is a credit card-sized platform that puts AI computing to work in the world all around us. Obviously, GPU-based deep learning has given computers the ability to understand — and react to — the data streaming in from all these devices in uncanny new ways. Both through training — which creates smart systems — and through inference — which creates systems that are able to react intelligently to the world around them in real time.

Before I loose my patience any further, the day finally arrived when I was lucky enough to hold the most powerful AI platform in my hand.

The NVIDIA® Jetson Nano™ Developer Kit is purely an AI computer. It is a small, powerful computer that lets you run multiple neural networks in parallel for applications like image classification, object detection, segmentation, and speech processing. All in an easy-to-use platform that runs in as little as 5 watts. It is perfect for makers, learners, and developers that brings the power of modern artificial intelligence to a low-power, easy-to-use platform.

Some Really Useful Facts around NVIDIA Jetson Nano..

  • There are 2 ways to power a Jetson Nano – either using Micro USB power supplies Or by using Barrel Jack 5V 4A(20W) power supplies. I don’t recommend using the normal micro-USB adapter which you use for mobile. Buy here if you are in India
  • Jetson Nano works in 2 model – MAXN and 5 Watt. By default the Nano works at MAXN(10 Watt mode). If using a Micro USB adapter you should change that immediately to 5W mode. When using the barrel jack to connect a 5V 4A (20W) power supply, you should set the Nano into 10 Watt mode to allow maximum power usage. Learn more
  • No WiFi module is shipped with this board. A user can easily get a wifi dongle or module that’s already been certified and plug it in for the usage
  • Jetson Nano is supported by the comprehensive NVIDIA® JetPack™ SDK, and has the performance and capabilities needed to run modern AI workloads. JetPack includes:
  • Jetson Nano comes with Full desktop Linux with NVIDIA driver, AI and Computer Vision libraries and APIs. developer tools & documentation and sample code.

Installing Docker 19.03 on NVIDIA Jetson Nano

Early this May 2019, I wrote a blog post around Docker 19.03 which comes with a new –gpus CLI plugin capability. With the recent 19.03 GA Release, now you don’t need to spend time in downloading the NVIDIA-DOCKER plugin and rely on nvidia-wrapper to launch GPU containers. All you can now use –gpus option with docker run CLI to allow containers to use GPU devices seamlessly.

As I wanted to try running CUDA containers on Jetson Nano, I couldn’t wait to update it to 19.03 release so as to see how containers can leverage the existing GPU device. Under this blog post, I will showcase how to get started with Docker 19.03 on Jetson Nano.

Preparing Jetson Nano

  • Unboxing Jetson Nano Pack
  • Preparing your microSD card

To prepare your microSD card, you’ll need a computer with Internet connection and the ability to read and write SD cards, either via a built-in SD card slot or adapter.

  1. Download the Jetson Nano Developer Kit SD Card Image, and note where it was saved on the computer.
  2. Write the image to your microSD card( atleast 16GB size) by following the instructions below according to the type of computer you are using: Windows, Mac, or Linux. If you are using Windows laptop, you can use SDFormatter software for formatting your microSD card and Win32DiskImager to flash Jetson Nano Image. In case you are using Mac, you will need Etcher software.
  1. To prepare your microSD card, you’ll need a computer with Internet connection and the ability to read and write SD cards, either via a built-in SD card slot or adapter

The Jetson Nano SD card image is of 12GB(uncompressed size).

Next, It’s time to remove this tiny SD card from SD card reader and plugin it to Jetson Board to let it boot.

Wow ! Jetson Nano comes with 18.09 by default

Yes, you read it correct. Let us try it once. First we will verify OS version running on Jetson Nano.

Verifying OS running on Jetson Nano

jetson@jetson-desktop:~$ sudo cat /etc/os-release
VERSION="18.04.2 LTS (Bionic Beaver)"
PRETTY_NAME="Ubuntu 18.04.2 LTS"

Verifying Docker

jetson@jetson-desktop:~$ sudo docker version
 Version:           18.09.2
 API version:       1.39
 Go version:        go1.10.4
 Git commit:        6247962
 Built:             Tue Feb 26 23:51:35 2019
 OS/Arch:           linux/arm64
 Experimental:      false

  Version:          18.09.2
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.4
  Git commit:       6247962
  Built:            Wed Feb 13 00:24:14 2019
  OS/Arch:          linux/arm64
  Experimental:     false

Updating OS Repository

sudo apt update

Installing Docker 19.03 Binaries

You will need curl command to update Docker 18.09 to 19.03 flawlessly.

sudo apt install curl
curl -sSL | sh
jetson@jetson-desktop:~$ sudo docker version
Client: Docker Engine - Community
 Version:           19.03.2
 API version:       1.40
 Go version:        go1.12.8
 Git commit:        6a30dfc
 Built:             Thu Aug 29 05:32:21 2019
 OS/Arch:           linux/arm64
 Experimental:      false

Server: Docker Engine - Community
  Version:          19.03.2
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.8
  Git commit:       6a30dfc
  Built:            Thu Aug 29 05:30:53 2019
  OS/Arch:          linux/arm64
  Experimental:     false
  Version:          1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
  Version:          0.18.0
  GitCommit:        fec3683

Installing Docker Compose

root@jetson-desktop:/home/jetson# /usr/bin/docker-compose version
docker-compose version 1.17.1, build unknown
docker-py version: 2.5.1
CPython version: 2.7.15+
OpenSSL version: OpenSSL 1.1.1  11 Sep 2018

Turn Your Jetson Nano into CCTV Camera

You can connect USB camera module directly into Jetson Nano camera slot and it should work flawlessly.

All you need to do is clone the below GITHUB repository and run the script.

git clone
cd docker-cctv-raspbian

The script will pull the Docker Image from DockerHub and run the container to turn your Jetson Nano into CCTV camera.

root@jetson-desktop:~/docker-cctv-raspbian# docker ps
CONTAINER ID        IMAGE                             COMMAND             CREATED             STATUS              PORTS                    NAMES
b6ff860d4f2a        ajeetraina/docker-cctv-raspbian   "motion"            6 seconds ago       Up 2 seconds>8081/tcp   hopeful_newton

Just one liner CLI and I was able to see my logitech webcam in action.(see below)

Figure: This image is captured by Logitech webcam mounted on Jetson Nano board

Running Hello World Example with Jetson Nano

jetson@jetson-desktop:~$ docker run arm64v8/hello-world
Unable to find image 'arm64v8/hello-world:latest' locally
latest: Pulling from arm64v8/hello-world
3b4173355427: Pull complete
Digest: sha256:5970f71561c8ff01d1d97782f37b0142315c53f31ad23c22883488e36a6dcbcb
Status: Downloaded newer image for arm64v8/hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:

For more examples and ideas, visit:


Verifying NVIDIA Container Runtime

NVIDIA Container Runtime with Docker integration (via the nvidia-docker2 packages) is included as part of NVIDIA JetPack. It is available for install via the NVIDIA SDK Manager along with other JetPack components as shown below:

jetson@jetson-desktop:~$ sudo docker info | grep nvidia
 Runtimes: nvidia runc
jetson@jetson-desktop:~$ sudo dpkg --get-selections | grep nvidia
libnvidia-container-tools                       install
libnvidia-container0:arm64                      install
nvidia-container-runtime                        install
nvidia-container-runtime-hook                   install
nvidia-docker2                                  deinstall
nvidia-l4t-3d-core                              install
nvidia-l4t-apt-source                           install
nvidia-l4t-bootloader                           install
nvidia-l4t-camera                               install
nvidia-l4t-ccp-t210ref                          install
nvidia-l4t-configs                              install
nvidia-l4t-core                                 install
nvidia-l4t-cuda                                 install
nvidia-l4t-firmware                             install
nvidia-l4t-graphics-demos                       install
nvidia-l4t-gstreamer                            install
nvidia-l4t-init                                 install
nvidia-l4t-kernel                               install
nvidia-l4t-kernel-dtbs                          install
nvidia-l4t-kernel-headers                       install
nvidia-l4t-multimedia                           install
nvidia-l4t-multimedia-utils                     install
nvidia-l4t-oem-config                           install
nvidia-l4t-tools                                install
nvidia-l4t-wayland                              install
nvidia-l4t-weston                               install
nvidia-l4t-x11                                  install
nvidia-l4t-xusb-firmware                        install

Running CUDA on Containers on Jetson Nano

jetson@jetson-desktop:~$ sudo docker run -it --runtime nvidia devicequery
./deviceQuery Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "NVIDIA Tegra X1"
  CUDA Driver Version / Runtime Version          10.0 / 10.0
  CUDA Capability Major/Minor version number:    5.3
  Total amount of global memory:                 3956 MBytes 
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       49152 bytes

What’s Next?

Integrating Pico – A Deep Learning Platform with Jetson & Docker is an exciting project I am working on. If you’re completely new, do check out for further details.

Installing Docker Engine 19.03 on Raspberry Pi 3 in 2 Minutes

Estimated Reading Time: 6 minutes

Docker is officially supported both on Raspberry Pi 3 and 4. Installing Docker is just a matter of single-liner command. All you need to do is a simple curl command:

curl -sSL | sh

to get Docker binaries installed flawlessly. Isn’t it damn simple?

Raspbian is a free operating system based on Debian optimized for the Raspberry Pi hardware. An operating system is the set of basic programs and utilities that make your Raspberry Pi run. However, Raspbian provides more than a pure OS: it comes with over 35,000 packages, pre-compiled software bundled in a nice format for easy installation on your Raspberry Pi.

Docker today support the latest Raspbian Buster release. If you really want to play around with stable release of Docker for Raspbian Buster, then head over to this link.

Under this blog post, I will showcase how to install latest Docker Engine 19.03.1 on Raspbian OS Buster release flawlessly.

Tested Infrastructure

PlatformNumber of InstanceReading Time
Raspberry Pi 3 Model B15 min

Preparing Your Environment

Raspberry Pi 3 Model BBuy

Waveshare-LCD 5-inch TFT Resistive
Touch Screen Display Module

Geauxrobot Raspberry Pi 3 Model B 7-Layer
Dog Bone Stack Clear Case Box 


  • Flash Raspbian OS on SD card

If you are in Mac, you might need to install Etcher tool. If on Windows, install SDFormatter to format SD card as well as Win32installer to flash Raspbian ISO image onto the SD card. You will need SD card reader to achieve this.

Booting up Raspbian OS

Just use the same charger which you use for your mobile to power on Raspberry Pi box. Connect HDMI port to your TV or display. Let it boot up.

The default username is pi and password is raspberry.

Enable SSH to perform remote login

To login via your laptop, you need to allow SSH service running. You can verify IP address command via ifconfig command.

[Captains-Bay]🚩 >  ssh pi@
pi@'s password:
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 26 12:30:00 2019 from
pi@raspberrypi:~ $ sudo su
root@raspberrypi:/home/pi# cd

Verifying Raspbian OS Version

root@raspberrypi:~# cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION="9 (stretch)"

Installing Docker 19.03.1

Its a single liner command. -L means location, -s means silent and -S means show error.

root@raspberrypi:~# curl -sSL | sh

Deploying Nginx App

root@raspberrypi:~# docker run -d -p 80:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
9c38b5a8a4d5: Pull complete
1c9b1b3e1e0d: Pull complete
258951b5612f: Pull complete
Digest: sha256:dd2d0ac3fff2f007d99e033b64854be0941e19a2ad51f174d9240dda20d9f534
Status: Downloaded newer image for nginx:latest
root@raspberrypi:~# curl localhost:80
<!DOCTYPE html>
<title>Welcome to nginx!</title>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href=""></a>.<br/>
Commercial support is available at
<a href=""></a>.</p>

<p><em>Thank you for using nginx.</em></p>
root@raspberrypi:~# docker info
Containers: 1
 Running: 1
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 19.03.1
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 9754871865f7fe2f4e74d43e2fc7ccd237edcbce
runc version: 09c8266bf2fcf9519a651b04ae54c967b9ab86ec
init version: fec3683
Security Options:
  Profile: default
Kernel Version: 4.14.98-v7+
Operating System: Raspbian GNU/Linux 9 (stretch)
OSType: linux
Architecture: armv7l
CPUs: 4
Total Memory: 927.2MiB
Name: raspberrypi
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Experimental: false
Insecure Registries:
Live Restore Enabled: false
Product License: Community Engine

WARNING: No memory limit support
WARNING: No swap limit support
WARNING: No kernel memory limit support
WARNING: No oom kill disable support
WARNING: No cpu cfs quota support
WARNING: No cpu cfs period support

BuildKit on Raspberry Pi

root@raspberrypi:~# export DOCKER_BUILDKIT=1
root@raspberrypi:~# git clone
Cloning into 'hellowhale'...
remote: Enumerating objects: 28, done.
remote: Total 28 (delta 0), reused 0 (delta 0), pack-reused 28
Unpacking objects: 100% (28/28), done.
root@raspberrypi:~# cd hellowhale/
root@raspberrypi:~/hellowhale# ls
Dockerfile  html
root@raspberrypi:~/hellowhale# docker build -t ajeetraina/hellowhalecom .
[+] Building 7.9s (5/8)                                                         
 => [internal] load build definition from Dockerfile                       0.1s
 => => transferring dockerfile: 129B                                       0.0s
 => [internal] load .dockerignore                                          0.2s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for            0.0s
 => [1/3] FROM                              0.0s
 => => resolve                              0.0s
 => [internal] helper image for file operations                            0.1s
 => => resolve  7.5s
 => => sha256:b13ecc473b58ad8d80fba73ae6de690f6fcbe341bdaca42 736B / 736B  0.0s
 => => sha256:fabe16b757ee155dfd7210795199962d1b35e22b3437d06 767B / 767B  0.0s
 => [internal] load build context                                          0.1s
 => => transferring context: 34.39kB                                       0.0s

root@raspberrypi:~/hellowhale# time docker build -t ajeetraina/hellowhale .
[+] Building 0.4s (9/9) FINISHED                                                
 => [internal] load build definition from Dockerfile                       0.1s
 => => transferring dockerfile: 31B                                        0.0s
 => [internal] load .dockerignore                                          0.1s
 => => transferring context: 2B                                            0.0s
 => [internal] load metadata for            0.0s
 => [internal] helper image for file operations                            0.0s
 => [1/3] FROM                              0.0s
 => [internal] load build context                                          0.0s
 => => transferring context: 317B                                          0.0s
 => CACHED [2/3] COPY /                                         0.0s
 => CACHED [3/3] COPY html /usr/share/nginx/html                           0.0s
 => exporting to image                                                     0.1s
 => => exporting layers                                                    0.0s
 => => writing image sha256:5aee990f7e24e7c0f486ed01b4c1f8696ff307f836af1  0.0s
 => => naming to                           0.0s

real	0m0.615s
user	0m0.204s
sys	0m0.082s

Verifying Dockerd

root@raspberrypi:~/hellowhale# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: e
   Active: active (running) since Tue 2019-02-26 13:01:04 IST; 38min ago
 Main PID: 2437 (dockerd)
      CPU: 1min 46.174s
   CGroup: /system.slice/docker.service
           ├─2437 /usr/bin/dockerd -H unix://
           ├─2705 /usr/bin/docker-proxy -proto tcp -host-ip -host-port 8
           └─4186 /usr/bin/docker-proxy -proto tcp -host-ip -host-port 8

Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.400368104+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.402012958+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.402634316+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.403005881+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.408358205+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.810154786+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.810334839+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.811462659+0
Feb 26 13:37:06 raspberrypi dockerd[2437]: time="2019-02-26T13:37:06.811768546+0
Feb 26 13:37:07 raspberrypi dockerd[2437]: time="2019-02-26T13:37:07.402282796+0

Verifying if armv7 hello-world image is available or not

docker run --rm mplatform/mquery hello-world
Unable to find image 'mplatform/mquery:latest' locally
latest: Pulling from mplatform/mquery
db6020507de3: Pull complete
5107afd39b7f: Pull complete
Digest: sha256:e15189e3d6fbcee8a6ad2ef04c1ec80420ab0fdcf0d70408c0e914af80dfb107
Status: Downloaded newer image for mplatform/mquery:latest
Image: hello-world
 * Manifest List: Yes
 * Supported platforms:
   - linux/amd64
   - linux/arm/v5
   - linux/arm/v7
   - linux/arm64
   - linux/386
   - linux/ppc64le
   - linux/s390x
   - windows/amd64:10.0.14393.2551
   - windows/amd64:10.0.16299.846
   - windows/amd64:10.0.17134.469
   - windows/amd64:10.0.17763.194

Verifying Hellowhale Image

root@raspberrypi:~# docker run --rm mplatform/mquery ajeetraina/hellowhale
Image: ajeetraina/hellowhale
 * Manifest List: No
 * Supports: amd64/linux

Verifying Random Images

root@raspberrypi:~# docker run --rm mplatform/mquery rycus86/prometheus
Image: rycus86/prometheus
 * Manifest List: Yes
 * Supported platforms:
   - linux/amd64
   - linux/arm/v7
   - linux/arm64

In my next blog post, I will showcase how to setup Docker Swarm on bunch of Raspberry Pi 3 nodes.

Unboxing 3.5” Touch Screen RPi LCD for Raspberry Pi 3 in 2 Minutes

Estimated Reading Time: 3 minutes
A 3.5” LCD mounted directly into Raspberry Pi showing Docker Installables

If you have ever conducted Docker on Raspberry Pi workshop during the Meetup event, you surely understand the pain in bringing up working infrastructure. Especially when you are dependent upon WiFi network of the hosting company, it becomes difficult as in every new Meetup venue, you need to plug your HDMI-equipped monitor into the Raspberry Pi using a standard HDMI cable and then configuring IP address so as to get it discovered over findPi Mobile application.

The HDMI cable is one of the most important piece of equipment that you can use with your Raspberry Pi, which means that in theory you can connect it to a wide selection of televisions and even modern desktop computer monitors. But in case HDMI cable is not available, then you might have to rely on alternative way of getting display device to configure Pi systems.

RPi LCD comes to the rescue..

Raspberry Pi Touchscreen LCD provides you with the ability to create a standalone device that can be utilized as a custom tablet or an all-in-one interactive interface for a future project using your Raspberry Pi 3. This small 3.5-inch touch screen module is designed especially for Raspberry Pi, using the latest Linux Core system. This is ideal for DIY anywhere, anytime and does not require any separate power source or case to hold it. The module sits right on top of Pi and an ideal alternative solution for HDMI monitors. The screen also comes with a stylus to interact with the small screen.


  1. Designed for Raspberry Pi, an ideal alternative solution for HDMI monitor
  2. Supports all revision of Raspberry Pi (directly-pluggable models)
  3. Works with Raspbian/Ubuntu directly
  4. Comes with full set of screws and nuts for assembly
  5. 320×480 resolution, better display
  6. Lightweight and easy to install

Preparing Your Setup


To configure RPi LCD for Raspberry Pi, first login to your Pi system:

Visit and search for “RPi LCD” for your specific model which you have purchased. In my case, it was 3.5” LCD monitor, hence I went ahead and selected it to open the below link:

Run the below command:

sudo raspi-config

Select Boot Options > Desktop Autologin

As soon as you select Desktop Autologin, it will ask to select “Finish” and the system will go for reboot.

Clone the Repository

git clone

Execute the script


After system rebooting, the RPi LCD is ready to use.

In my next blog post, I will showcase how I used 3.5” LCD screen directly mounted over Celestron Telescope to view moon’s surface flawlessly.