{"@attributes":{"version":"2.0"},"channel":{"title":"Docker Pirates ARMed with explosive stuff","link":"https:\/\/blog.hypriot.com\/index.xml","description":"Recent content on Docker Pirates ARMed with explosive stuff","generator":"Hugo -- gohugo.io","language":"en-us","lastBuildDate":"Thu, 25 Jul 2019 06:31:00 +0200","item":[{"title":"Releasing HypriotOS 1.11.0: Docker 19.03.0 CE from Raspberry Pi Zero to 4 B","link":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-11\/","pubDate":"Thu, 25 Jul 2019 06:31:00 +0200","guid":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-11\/","description":"<p><strong>We&rsquo;re proud to announce our 1.11.0 release of HypriotOS - the fastest way to get Docker up and running on any Raspberry Pi.<\/strong><\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/release-1-11\/raspberry-pi-4-b.jpg\" alt=\"Raspberry Pi 4 B\" \/><\/p>\n\n<p><\/p>\n\n<h2 id=\"features-of-hypriotos\">Features of HypriotOS<\/h2>\n\n<p><strong>Latest Docker Engine 19.03.0 Community Edition<\/strong> <\/br>\nYou can use the latest features of the freshly-baked Docker Engine 19.03.0 that is still warm. It includes the Swarm Mode, which allows high availability of services in a multi-node cluster within just a few simple commands.<\/p>\n\n<p><strong>Up to date with Raspbian Lite Buster<\/strong> <\/br>\nYou can run HypriotOS with an up-to-date OS and Linux kernel which is in sync with the current Raspbian Lite Buster running a Linux kernel 4.19.58.<\/p>\n\n<p><strong>Support for the complete Raspberry Pi family<\/strong> <\/br>\nYou can run HypriotOS on every model of the Raspberry Pi family - we&rsquo;re supporting Pi 1, 2, 3, the 3 B+, Zero and even the Compute Module and the new Raspberry Pi 4 B.<\/p>\n\n<p><strong>Easy flashing and configuration<\/strong> <\/br>\nWe improved our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a>, which puts HypriotOS onto a SD card that is ready to boot from with a single command. With additional command line options you can customize HypriotOS during the flash operation to have the best out-of-the-box first-boot experience.\nHypriotOS includes <a href=\"https:\/\/cloudinit.readthedocs.io\/en\/18.3\/\">cloud-init<\/a>, which makes the first boot of your Raspberry Pi customizable and you even are able connecting it to your Wi-Fi network during boot.\nAfter booting, you can find the Raspberry Pi at your network with a simple <code>ping black-pearl.local<\/code> \u2013 no more searching for IP addresses required thanks to the integrated Avahi service discovery.<\/p>\n\n<p><strong>Enhanced security out of the box<\/strong> <\/br>\nWe think that security should be shipped out-of-the-box. We make HypriotOS more secure without you even noticing it. For instance, there is no built-in &ldquo;root&rdquo; user. Also, the default user &ldquo;pirate&rdquo; (password &ldquo;hypriot&rdquo;) is can be customized or removed before the first boot. Just look at the file <code>\/boot\/user-data<\/code>. You can add your public SSH key, disable password logins and specify a different user account before you even boot your Raspberry Pi. WiFi can be customized and enabled to have Docker up and running through the air without attaching a keyboard and monitor.<\/p>\n\n<p><strong>Smaller than Raspbian Lite<\/strong> <\/br>\nEven though HypriotOS 1.11.0 is fully packed with the complete and latest Docker tool set, it now comes at a size smaller than the tiniest version of Raspbian (&ldquo;Raspbian Lite&rdquo;).<\/p>\n\n<p>Please see all details in the <a href=\"https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/tag\/v1.11.0\">release notes<\/a>.<\/p>\n\n<h2 id=\"quick-start\">Quick start<\/h2>\n\n<p><strong>Download our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a><\/strong><\/p>\n\n<pre><code>curl -O https:\/\/raw.githubusercontent.com\/hypriot\/flash\/2.3.0\/flash\nchmod +x flash\nsudo mv flash \/usr\/local\/bin\/flash\n<\/code><\/pre>\n\n<p><strong>Now run this command to flash HypriotOS 1.11.0<\/strong><\/p>\n\n<pre><code>flash https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.11.0\/hypriotos-rpi-v1.11.0.img.zip\n<\/code><\/pre>\n\n<p><strong>Afterwards, put the SD card into the Raspberry Pi and power it. That&rsquo;s all to get HypriotOS up and running!<\/strong><\/p>\n\n<h3 id=\"next-steps\">Next steps<\/h3>\n\n<p>If you want to connect to the Raspberry Pi, run<\/p>\n\n<pre><code>ssh pirate@black-pearl.local\n<\/code><\/pre>\n\n<p>with password &ldquo;hypriot&rdquo;.<\/p>\n\n<h3 id=\"flash-with-wi-fi-settings-for-pi-zero-pi-3-pi-4\">Flash with Wi-Fi settings for Pi Zero \/ Pi 3 \/ Pi 4<\/h3>\n\n<p>If you want the Raspberry Pi Zero (or Pi 3 or Pi 4) to connect directly to your Wi-Fi after boot, change the hostname of the Raspberry Pi and more, edit <code>\/boot\/user-data<\/code> of the SD card and have a look at <a href=\"https:\/\/blog.hypriot.com\/faq\/#wifi\">our FAQ<\/a>. Alternatively, checkout the parameters of the <a href=\"https:\/\/github.com\/hypriot\/flash\">Hypriot flash tool<\/a> that also allows you to define your own cloud-init user-data template file which will be copied onto the SD image for you:<\/p>\n\n<pre><code>flash -n myHOSTNAME -u wifi.yml https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.11.0\/hypriotos-rpi-v1.11.0.img.zip\n<\/code><\/pre>\n\n<h2 id=\"feedback-please\">Feedback, please<\/h2>\n\n<p>As always, use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>"},{"title":"NVIDIA Jetson Nano - Docker optimized Linux Kernel","link":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-build-kernel-docker-optimized\/","pubDate":"Sat, 04 May 2019 03:57:21 +0200","guid":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-build-kernel-docker-optimized\/","description":"<p>Despite the fact that the NVIDIA Jetson Nano DevKit comes with Docker Engine preinstalled and you can run containers just out-of-the-box on this great AI and Robotics enabled board, there are still some important kernel settings missing to run Docker Swarm mode, Kubernetes or k3s correctly.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-build-kernel-docker-optimized\/jetson-nano-board-docker-whale.jpg\" alt=\"jetson-nano-board-docker-whale.jpg\" \/><\/p>\n\n<p>So, let&rsquo;s try to fix this&hellip;<\/p>\n\n<p><\/p>\n\n<h3 id=\"analyzing-the-linux-kernel\">Analyzing the Linux Kernel<\/h3>\n\n<p>In my last blogpost <a href=\"https:\/\/blog.hypriot.com\/post\/verify-kernel-container-compatibility\/\">Verify your Linux Kernel for Container Compatibility<\/a>, I already shared all the details how you can easily verify the Linux kernel for all Container related kernel settings. So, this first part of analyzing the capabilities of the stock Linux kernel 4.9.x provided by NVIDIA is already done and documented. And this was an easy task as well, so everyone who&rsquo;s interested in these details can repeat the task at his\/her own device.<\/p>\n\n<p>Let&rsquo;s recap what we did found. Especially there is one important setting which will be used for networking. This feature called &ldquo;IPVLAN&rdquo;, is required for Docker Swarm mode and it&rsquo;s also used for networking in Kubernetes and k3s.<\/p>\n\n<h3 id=\"building-your-own-linux-kernel\">Building your own Linux Kernel<\/h3>\n\n<p>Anyway, even when we&rsquo;d like to include or change only a single kernel setting, we have to customize the kernel configuration and have to compile and build our own Linux kernel. This is typically a common task for a desktop Linux system, but can be pretty ugly and cumbersome if you have to build the kernel for an Embedded Device.<\/p>\n\n<p>When we look back to all the other NVIDIA Jetson boards, like the TK1, TX1 and TX2, this requires a second Linux machine, running Ubuntu 14.04 or 16.04 on an Intel CPU. Then setting up a complete build system for cross-compiling and all these stuff. Honestly, this is a well-known approach for an Embedded Developer, but the good thing now for the Jetson Nano DevKit this is not required any more.<\/p>\n\n<p>Here the good news: you can customize and build your own Linux kernel directly on the Jetson Nano DevKit! You only need an internet connection and some time to perform all steps on your own. BTW, and this is another chance to learn something new.<\/p>\n\n<h3 id=\"preparing-the-build-environment\">Preparing the Build Environment<\/h3>\n\n<p>Before we&rsquo;re able to compile the Linux kernel on the Jetson Nano, we have to make sure we do have all required build tools installed. Here is all it takes, with a fast internet connection this is done within a few minutes only.<\/p>\n\n<pre><code class=\"language-bash\">$ sudo apt-get update\n$ sudo apt-get install -y libncurses5-dev\n<\/code><\/pre>\n\n<h3 id=\"download-linux-kernel-sources-for-jetson-nano\">Download Linux Kernel Sources for Jetson Nano<\/h3>\n\n<p>Next, we&rsquo;ll need to find and download the sources for the Linux kernel for the Jetson Nano DevKit directly from the NVIDIA website. The current version as writing this blogpost is NVIDIA Linux4Tegra Release r32.1 or short L4T 32.1. Just follow this link <a href=\"https:\/\/developer.nvidia.com\/embedded\/linux-tegra\">https:\/\/developer.nvidia.com\/embedded\/linux-tegra<\/a> and select at topic &ldquo;32.1 Driver Details&rdquo; the referenced download link for &ldquo;Jetson Nano&rdquo;, &ldquo;SOURCES&rdquo; and &ldquo;BSP Sources&rdquo;.<\/p>\n\n<p>We can also directly download this package to the Jetson Nano. But please be aware that this download link can change over time, so verify it carefully.<\/p>\n\n<pre><code class=\"language-bash\">$ cd\n$ mkdir -p nano-bsp-sources\n$ cd nano-bsp-sources\n$ wget https:\/\/developer.download.nvidia.com\/embedded\/L4T\/r32_Release_v1.0\/jetson-nano\/BSP\/Jetson-Nano-public_sources.tbz2\n$ ls -alh Jetson-Nano-public_sources.tbz2\n-rw-rw-r-- 1 pirate pirate 133M Mar 16 06:46 Jetson-Nano-public_sources.tbz2\n<\/code><\/pre>\n\n<p>Now extract the kernel source package &ldquo;kernel_src.tbz2&rdquo; from the downloaded file.<\/p>\n\n<pre><code class=\"language-bash\">$ tar xvf Jetson-Nano-public_sources.tbz2 public_sources\/kernel_src.tbz2\n$ mv public_sources\/kernel_src.tbz2 ~\/\n$ cd\n$ ls -alh ~\/kernel_src.tbz2\n-rw-r--r-- 1 pirate pirate 117M Mar 13 08:45 \/home\/pirate\/kernel_src.tbz2\n<\/code><\/pre>\n\n<p>You may now free some disk space and remove all the downloads, as we don&rsquo;t need it any more.<\/p>\n\n<pre><code class=\"language-bash\">$ rm -fr ~\/nano-bsp-sources\/\n<\/code><\/pre>\n\n<p>Last step, please extract the kernel source tree.<\/p>\n\n<pre><code class=\"language-bash\">$ cd\n$ tar xvf .\/kernel_src.tbz2\n<\/code><\/pre>\n\n<h3 id=\"compile-the-default-linux-kernel\">Compile the default Linux Kernel<\/h3>\n\n<p>Cool, we have now all the Linux kernel source tree for the Jetson Nano DevKit downloaded and extracted.<\/p>\n\n<p>As the next step, I&rsquo;d recommend to first compile the default unmodified kernel in order to verify that we do have all the build dependencies installed and this way, we&rsquo;ll also get familiar with the kernel compiling.<\/p>\n\n<p>Before we can start the compile job, we have to make sure to use the correct kernel configuration file. This file &ldquo;.config&rdquo; is missing in the provided kernel source tree, but we can directly get it from our running Linux kernel on the Jetson Nano. This .config file can be found as kernel file at &ldquo;\/proc\/config.gz&rdquo; in a compressed form.<\/p>\n\n<pre><code class=\"language-bash\">$ cd ~\/kernel\/kernel-4.9\n$ zcat \/proc\/config.gz &gt; .config\n<\/code><\/pre>\n\n<p>Now, let&rsquo;s verify the content of the Linux kernel .config file.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~\/kernel\/kernel-4.9$ head -10 .config\n#\n# Automatically generated file; DO NOT EDIT.\n# Linux\/arm64 4.9.140 Kernel Configuration\n#\nCONFIG_ARM64=y\nCONFIG_64BIT=y\nCONFIG_ARCH_PHYS_ADDR_T_64BIT=y\nCONFIG_MMU=y\nCONFIG_DEBUG_RODATA=y\nCONFIG_ARM64_PAGE_SHIFT=12\n...\n<\/code><\/pre>\n\n<p>As you can see, it&rsquo;s a Kernel Configuration for Linux kernel version 4.9.140 and for ARM 64-bit architecture.<\/p>\n\n<p>Start the kernel compile job. As we do have 4x cores available on the Nano, we&rsquo;d like to keep the CPU busy and using 5x parallel compile tasks.<\/p>\n\n<pre><code class=\"language-bash\">$ make prepare\n$ make modules_prepare\n\n# Use 5x parallel compile tasks\n# Compile kernel as an image file\n$ time make -j5 Image\n...\nreal\t28m13,235s\nuser\t91m48,700s\nsys\t7m46,240s\n\n# List newly compiled kernel image\n$ ls -alh arch\/arm64\/boot\/Image\n-rw-rw-r-- 1 pirate pirate 33M May  4 00:14 arch\/arm64\/boot\/Image\n\n# Compile all kernel modules\n$ time make -j5 modules\n...\nreal\t29m15,621s\nuser\t92m41,176s\nsys\t8m18,404s\n<\/code><\/pre>\n\n<p>The Nano CPU&rsquo;s are pretty busy while compiling the kernel and kernel modules.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-build-kernel-docker-optimized\/jetson-nano-board-compile-kernel.jpg\" alt=\"jetson-nano-board-compile-kernel.jpg\" \/><\/p>\n\n<p>The build\/compile job will take around 60 minutes in total, but the good thing is, all happens directly on your Jetson Nano DevKit. No other expensive equipment is required at all, just an internet connection and some of your time.<\/p>\n\n<h3 id=\"install-our-newly-built-linux-kernel-and-modules\">Install our newly built Linux Kernel and Modules<\/h3>\n\n<p>After these pretty long compile jobs for generating our own Linux kernel and kernel modules, we are ready to install the kernel and verify if it&rsquo;s able to boot correctly. Therefore we should make a backup of the old kernel first, then install the new kernel and also install all newly built kernel modules.<\/p>\n\n<p>Before we install the new kernel and boot the Jetson Nano, let&rsquo;s check the default Linux kernel version. Then we can compare it later to our own kernel.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ uname -a\nLinux jetson-nano 4.9.140-tegra #1 SMP PREEMPT Wed Mar 13 00:32:22 PDT 2019 aarch64 aarch64 aarch64 GNU\/Linux\n<\/code><\/pre>\n\n<p>Here is also a ASCIINEMA recording of a <code>check-config.sh<\/code> verification done with the default kernel.\n<a href=\"https:\/\/asciinema.org\/a\/244237?t=0:44\"><img src=\"https:\/\/asciinema.org\/a\/244237.svg\" alt=\"asciicast\" \/><\/a><\/p>\n\n<p>As we can see, we do have a Linux kernel version &ldquo;4.9.140-tegra&rdquo;. This one was compiled at &ldquo;Wed Mar 13 00:32:22 PDT 2019&rdquo; and it&rsquo;s the default kernel provided by NVIDIA for the Jetson Nano.<\/p>\n\n<p>Now, install our new kernel and kernel modules.<\/p>\n\n<pre><code class=\"language-bash\"># Backup the old kernel image file\n$ sudo cp \/boot\/Image \/boot\/Image.original\n\n# Install modules and kernel image\n$ cd ~\/kernel\/kernel-4.9\n$ sudo make modules_install\n$ sudo cp arch\/arm64\/boot\/Image \/boot\/Image\n\n# Verify the kernel images\npirate@jetson-nano:~\/kernel\/kernel-4.9$ ls -alh \/boot\/Image*\n-rw-r--r-- 1 root root 33M May  4 00:55 \/boot\/Image\n-rw-r--r-- 1 root root 33M May  4 00:49 \/boot\/Image.original\n<\/code><\/pre>\n\n<p>Now, reboot the Nano and check the kernel again.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ uname -a\nLinux jetson-nano 4.9.140 #1 SMP PREEMPT Sat May 4 00:12:56 CEST 2019 aarch64 aarch64 aarch64 GNU\/Linux\n<\/code><\/pre>\n\n<p>As you can see, our newly compiled kernel is working. The kernel version has changed to &ldquo;4.9.140&rdquo;, note the missing trailing &ldquo;-tegra&rdquo; which indicates this build is a custom build. And the compile date\/time has also changed to &ldquo;Sat May 4 00:12:56 CEST 2019&rdquo;.<\/p>\n\n<p><strong>Hint:<\/strong> Please remember, every time you do change a kernel setting and compile a new kernel, you have to install the kernel image file AND the kernel modules.<\/p>\n\n<h3 id=\"customizing-the-linux-kernel-configuration\">Customizing the Linux Kernel Configuration<\/h3>\n\n<p>When it comes to the point to modify or customize the Linux kernel configuration, then this can get pretty complicated when you don&rsquo;t know where to start. First of all, it&rsquo;s a very bad idea to edit the .config file directly with an editor. Please, NEVER DO THIS - seriously!<\/p>\n\n<p>The correct way to customize the kernel .config file is, to use the right tooling. One tool which is already built-in and available even in your bash shell (works also via ssh), is the tool <code>menuconfig<\/code>. Therefore we already installed the build dependency &ldquo;libncurses5-dev&rdquo; at the beginning.<\/p>\n\n<p>I don&rsquo;t want to go into all details on how to use <code>menuconfig<\/code>, therefore here are the basic commands to start it and then I did recorded an ASCIINEMA to change the setting for &ldquo;IPVLAN&rdquo;. I think then you&rsquo;ll should get a good idea how this works.<\/p>\n\n<pre><code class=\"language-bash\"># Backup the kernel config\n$ cd ~\/kernel\/kernel-4.9\n$ cp .config kernel.config.original\n\n$ make menuconfig\n<\/code><\/pre>\n\n<p>ASCIINEMA recording on how to include the &ldquo;IPVLAN&rdquo; kernel setting.\n<a href=\"https:\/\/asciinema.org\/a\/244246?t=1:15\"><img src=\"https:\/\/asciinema.org\/a\/244246.svg\" alt=\"asciicast\" \/><\/a><\/p>\n\n<p>Finally let&rsquo;s re-compile the kernel and the kernel modules and install them, like we did before.<\/p>\n\n<pre><code class=\"language-bash\">$ cd ~\/kernel\/kernel-4.9\n\n# Prepare the kernel build\n$ make prepare\n$ make modules_prepare\n\n# Compile kernel image and kernel modules\n$ time make -j5 Image\n$ time make -j5 modules\n\n# Install modules and kernel image\n$ sudo make modules_install\n$ sudo cp arch\/arm64\/boot\/Image \/boot\/Image\n<\/code><\/pre>\n\n<p>Reboot the Nano and check the kernel again.<\/p>\n\n<h3 id=\"fast-forward-fully-container-optimized-kernel-configuration\">Fast Forward - Fully Container Optimized Kernel Configuration<\/h3>\n\n<p>As you have learned here in this tutorial, you&rsquo;re now able to apply more and more settings to your kernel configuration. But this will take some time for sure.<\/p>\n\n<p>In order to save you a lot of time and efforts, I&rsquo;ve already optimized the Linux kernel in all details. Here you can find a public <a href=\"https:\/\/gist.githubusercontent.com\/DieterReuter\/a7d07445c9d62b45d9151c22b446c59b\/\">Gist at Github<\/a> with my resulting kernel .config. You can download it directly to your Nano and compile your own Linux kernel with this configuration.<\/p>\n\n<pre><code class=\"language-bash\"># Download the fully container optimized kernel configuration file\n$ cd ~\/kernel\/kernel-4.9\n$ wget https:\/\/gist.githubusercontent.com\/DieterReuter\/a7d07445c9d62b45d9151c22b446c59b\/raw\/6decc91cc764ec0be8582186a34f60ea83fa89db\/kernel.config.fully-container-optimized \n$ cp kernel.config.fully-container-optimized .config\n\n# Prepare the kernel build\n$ make prepare\n$ make modules_prepare\n\n# Compile kernel image and kernel modules\n$ time make -j5 Image\n$ time make -j5 modules\n\n# Install modules and kernel image\n$ sudo make modules_install\n$ sudo cp arch\/arm64\/boot\/Image \/boot\/Image\n<\/code><\/pre>\n\n<p>Now, reboot the Nano and check the kernel again.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ uname -a\nLinux jetson-nano 4.9.140 #2 SMP PREEMPT Sat May 4 02:17:23 CEST 2019 aarch64 aarch64 aarch64 GNU\/Linux\n\npirate@jetson-nano:~$ ls -al \/boot\/Image*\n-rw-r--r-- 1 root root 34381832 May  4 03:13 \/boot\/Image\n-rw-r--r-- 1 root root 34048008 May  4 00:49 \/boot\/Image.original\n<\/code><\/pre>\n\n<p>ASCIINEMA recording of the final run of <code>check-config.sh<\/code> with the fully optimized kernel for running Containers on the Jetson Nano DevKit.\n<a href=\"https:\/\/asciinema.org\/a\/244250?t=1:13\"><img src=\"https:\/\/asciinema.org\/a\/244250.svg\" alt=\"asciicast\" \/><\/a><\/p>\n\n<p><strong>Result: An almost perfect Linux kernel to run Containers on the NVIDIA Jetson Nano!<\/strong><\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-build-kernel-docker-optimized\/jetson-nano-board-docker-running2.jpg\" alt=\"jetson-nano-board-docker-running2.jpg\" \/><\/p>\n\n<h3 id=\"conclusion\">Conclusion<\/h3>\n\n<p>As you could learn with this short, but highly technical tutorial, you&rsquo;re able to compile your own customized Linux kernel directly on the Jetson Nano DevKit without the need of an additional and maybe expensiv development machine. All can be done within an hour or two, and you have now the ability to change kernel settings whenever you want to. Just customize the kernel .config file, compile a new kernel and kernel modules and install it on your Nano.<\/p>\n\n<p>This way you&rsquo;re now able to optimize the kernel for all your needs. For running Containers on the Nano with the help of Docker, Kubernetes or k3s, you&rsquo;re now well prepared and know how to do this by yourself.<\/p>\n\n<p>Once the Linux kernel is fully optimized with all important Container related kernel settings, you can run Docker Swarm mode, Kubernetes and k3s with all features on that great ARM board from NVIDIA.<\/p>\n\n<p>Finally, May the 4th be with You!\n<img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-build-kernel-docker-optimized\/may-the-4th-be-with-you.jpg\" alt=\"may-the-4th-be-with-you.jpg\" \/><\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"Verify your Linux Kernel for Container Compatibility","link":"https:\/\/blog.hypriot.com\/post\/verify-kernel-container-compatibility\/","pubDate":"Sun, 28 Apr 2019 08:48:50 -0700","guid":"https:\/\/blog.hypriot.com\/post\/verify-kernel-container-compatibility\/","description":"<p>Are you sure whether your Linux kernel is able to run Containers in an optimal way, or if there are still some missing kernel settings which will lead to some strange issues in the future?<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/verify-kernel-container-compatibility\/400px-NewTux.svg.png\" alt=\"400px-NewTux.svg.png\" \/><\/p>\n\n<p>Normally you don&rsquo;t have to bother about this question. When you&rsquo;re using Docker and Containers on a modern Linux system or on a public cloud offering, this has been already optimized by the Linux distribution or your cloud provider. But when you start using Containers on Embedded Devices you should verify this carefully.<\/p>\n\n<p>So, let&rsquo;s learn how easy it is to verify it by yourself&hellip;<\/p>\n\n<p><\/p>\n\n<h3 id=\"how-can-i-verify-the-linux-kernel-for-container-compatibility\">How can I verify the Linux Kernel for Container Compatibility?<\/h3>\n\n<p>Typically this is really an easy task, as soon as you know the right tools.<\/p>\n\n<p>For running Containers you&rsquo;ll need some basic settings applied to your Linux kernel. Some settings are mandatory and some others are optional and only used for specific use cases. But let&rsquo;s see how we can use the right tools.<\/p>\n\n<p>At the Docker open source project you can find a great bash script which does all these tests on your Linux kernel configuration and tells you within a few seconds all the required details. The script is able to read the kernel config live from a running kernel or directly from a kernel .config file as well. Now you can imagine you can verify the container compatibility also from a remote device.<\/p>\n\n<h4 id=\"download-check-config-sh-script\">Download <code>check-config.sh<\/code> script<\/h4>\n\n<p>Let&rsquo;s download the bash script <a href=\"https:\/\/github.com\/moby\/moby\/blob\/master\/contrib\/check-config.sh\">check-config.sh<\/a> directly from the Moby project (yes, this is the new name for the Docker open source project).<\/p>\n\n<pre><code class=\"language-bash\">$ wget https:\/\/github.com\/moby\/moby\/raw\/master\/contrib\/check-config.sh\n$ chmod +x check-config.sh\n<\/code><\/pre>\n\n<h4 id=\"verify-the-linux-kernel-directly\">Verify the Linux Kernel directly<\/h4>\n\n<p>If you have your Linux system available you can download and run the script directly without any parameters.<\/p>\n\n<pre><code class=\"language-bash\">$ .\/check-config.sh\n<\/code><\/pre>\n\n<p>Then you&rsquo;ll get a detailled output with all kernel settings which are important for running containers.<\/p>\n\n<p>If you want to verify a kernel from a remote system, you could also first extract the Linux kernel config on this system and analyse it later.<\/p>\n\n<pre><code class=\"language-bash\"># extract the .config from a running kernel\n$ zcat \/proc\/config.gz &gt; kernel.config\n\n$ ls -al kernel.config\n-rw-rw-r-- 1 pirate pirate 165739 Apr 28 07:26 kernel.config\n<\/code><\/pre>\n\n<p><strong>Hint:<\/strong> On some Linux systems like Raspbian for the Raspberry Pi, the kernel .config is only available as a kernel module. Then you have to load the module first, using the command <code>sudo modprobe configs<\/code>.<\/p>\n\n<h4 id=\"verify-the-linux-kernel-from-a-config-file\">Verify the Linux Kernel from a .config file<\/h4>\n\n<p>The kernel .config is a readable configuration file which is used to compile a new Linux kernel. Typically it will get embedded into your new kernel and therefore you can read it from the running kernel. It&rsquo;s available as a file at <code>\/proc\/config.gz<\/code> in a compressed form, so we have to use <code>zcat<\/code> to extract the .config file in clear text.<\/p>\n\n<pre><code class=\"language-bash\">$ zcat \/proc\/config.gz | head -10\n#\n# Automatically generated file; DO NOT EDIT.\n# Linux\/arm64 4.9.140 Kernel Configuration\n#\nCONFIG_ARM64=y\nCONFIG_64BIT=y\nCONFIG_ARCH_PHYS_ADDR_T_64BIT=y\nCONFIG_MMU=y\nCONFIG_DEBUG_RODATA=y\nCONFIG_ARM64_PAGE_SHIFT=12\n...\n<\/code><\/pre>\n\n<p>Next, let&rsquo;s run the <code>check-config.sh<\/code> script again and read all kernel configs from the file.<\/p>\n\n<pre><code class=\"language-bash\">$ .\/check-config.sh kernel.config\n<\/code><\/pre>\n\n<h3 id=\"verify-the-linux-kernel-on-nvidia-jetson-nano-devkit\">Verify the Linux Kernel on NVIDIA Jetson Nano DevKit<\/h3>\n\n<p>As a real life example let&rsquo;s now verify the Linux kernel of the brand-new Jetson Nano DevKit from NVIDIA. I already wrote a blogpost about how to install Linux for the Nano board, see here <a href=\"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-intro\/\">NVIDIA Jetson Nano Developer Kit - Introduction<\/a>.<\/p>\n\n<p>First we&rsquo;ll check the Linux kernel version and we can see, it&rsquo;s a current LTS kernel 4.9.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ uname -a\nLinux jetson-nano 4.9.140-tegra #1 SMP PREEMPT Wed Mar 13 00:32:22 PDT 2019 aarch64 aarch64 aarch64 GNU\/Linux\n<\/code><\/pre>\n\n<p>Now, let&rsquo;s run the <code>check-config.sh<\/code> script on the Nano and determine all the Container related kernel settings. We&rsquo;ll get the complete output as colored text. From the screenshots here we can clearly see which of the required and optional kernel settings are already applied for the Nano&rsquo;s Linux kernel.<\/p>\n\n<p>In the first section &ldquo;Generally Necessary&rdquo; all the mandatory kernel settings are listed, and for the Nano this is completely green, all is perfect.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/verify-kernel-container-compatibility\/kernel-checkconfig-nano1.jpg\" alt=\"kernel-checkconfig-nano1.jpg\" \/><\/p>\n\n<p>Then in the second section &ldquo;Optional Features&rdquo; we can see that most Container related settings are applied, but a few are missing.<\/p>\n\n<p>Not all of these are really important to have, but when we look into the &ldquo;Network Drivers&rdquo; I would recommend to include all in the kernel to avoid issues. For example, if you want to use Docker Swarm mode you have to know that <code>CONFIG_IPVLAN<\/code> is mandatory - this kernel can&rsquo;t run Swarm mode correctly!<\/p>\n\n<p>For &ldquo;Storage Drivers&rdquo; you can typically ignore the missing settings for <code>aufs<\/code> and <code>zfs<\/code> as long as you don&rsquo;t required to use these, same is true for <code>devicemapper<\/code>.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/verify-kernel-container-compatibility\/kernel-checkconfig-nano2.jpg\" alt=\"kernel-checkconfig-nano2.jpg\" \/><\/p>\n\n<p>Here I&rsquo;d also like to present the output as pure ASCII text so you can easily analyse (search, copy&amp;paste) it later.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ .\/check-config.sh\ninfo: reading kernel config from \/proc\/config.gz ...\n\nGenerally Necessary:\n- cgroup hierarchy: properly mounted [\/sys\/fs\/cgroup]\n- CONFIG_NAMESPACES: enabled\n- CONFIG_NET_NS: enabled\n- CONFIG_PID_NS: enabled\n- CONFIG_IPC_NS: enabled\n- CONFIG_UTS_NS: enabled\n- CONFIG_CGROUPS: enabled\n- CONFIG_CGROUP_CPUACCT: enabled\n- CONFIG_CGROUP_DEVICE: enabled\n- CONFIG_CGROUP_FREEZER: enabled\n- CONFIG_CGROUP_SCHED: enabled\n- CONFIG_CPUSETS: enabled\n- CONFIG_MEMCG: enabled\n- CONFIG_KEYS: enabled\n- CONFIG_VETH: enabled (as module)\n- CONFIG_BRIDGE: enabled\n- CONFIG_BRIDGE_NETFILTER: enabled (as module)\n- CONFIG_NF_NAT_IPV4: enabled (as module)\n- CONFIG_IP_NF_FILTER: enabled (as module)\n- CONFIG_IP_NF_TARGET_MASQUERADE: enabled (as module)\n- CONFIG_NETFILTER_XT_MATCH_ADDRTYPE: enabled (as module)\n- CONFIG_NETFILTER_XT_MATCH_CONNTRACK: enabled (as module)\n- CONFIG_NETFILTER_XT_MATCH_IPVS: enabled (as module)\n- CONFIG_IP_NF_NAT: enabled (as module)\n- CONFIG_NF_NAT: enabled (as module)\n- CONFIG_NF_NAT_NEEDED: enabled\n- CONFIG_POSIX_MQUEUE: enabled\n\nOptional Features:\n- CONFIG_USER_NS: enabled\n- CONFIG_SECCOMP: enabled\n- CONFIG_CGROUP_PIDS: enabled\n- CONFIG_MEMCG_SWAP: enabled\n- CONFIG_MEMCG_SWAP_ENABLED: enabled\n    (cgroup swap accounting is currently enabled)\n- CONFIG_BLK_CGROUP: enabled\n- CONFIG_BLK_DEV_THROTTLING: enabled\n- CONFIG_IOSCHED_CFQ: enabled\n- CONFIG_CFQ_GROUP_IOSCHED: missing\n- CONFIG_CGROUP_PERF: enabled\n- CONFIG_CGROUP_HUGETLB: missing\n- CONFIG_NET_CLS_CGROUP: enabled\n- CONFIG_CGROUP_NET_PRIO: enabled\n- CONFIG_CFS_BANDWIDTH: enabled\n- CONFIG_FAIR_GROUP_SCHED: enabled\n- CONFIG_RT_GROUP_SCHED: enabled\n- CONFIG_IP_NF_TARGET_REDIRECT: missing\n- CONFIG_IP_VS: enabled (as module)\n- CONFIG_IP_VS_NFCT: enabled\n- CONFIG_IP_VS_PROTO_TCP: missing\n- CONFIG_IP_VS_PROTO_UDP: missing\n- CONFIG_IP_VS_RR: enabled (as module)\n- CONFIG_EXT4_FS: enabled\n- CONFIG_EXT4_FS_POSIX_ACL: enabled\n- CONFIG_EXT4_FS_SECURITY: enabled\n- Network Drivers:\n  - &quot;overlay&quot;:\n    - CONFIG_VXLAN: enabled\n      Optional (for encrypted networks):\n      - CONFIG_CRYPTO: enabled\n      - CONFIG_CRYPTO_AEAD: enabled\n      - CONFIG_CRYPTO_GCM: enabled\n      - CONFIG_CRYPTO_SEQIV: enabled\n      - CONFIG_CRYPTO_GHASH: enabled\n      - CONFIG_XFRM: enabled\n      - CONFIG_XFRM_USER: enabled\n      - CONFIG_XFRM_ALGO: enabled\n      - CONFIG_INET_ESP: missing\n      - CONFIG_INET_XFRM_MODE_TRANSPORT: enabled\n  - &quot;ipvlan&quot;:\n    - CONFIG_IPVLAN: missing\n  - &quot;macvlan&quot;:\n    - CONFIG_MACVLAN: enabled (as module)\n    - CONFIG_DUMMY: enabled\n  - &quot;ftp,tftp client in container&quot;:\n    - CONFIG_NF_NAT_FTP: enabled (as module)\n    - CONFIG_NF_CONNTRACK_FTP: enabled (as module)\n    - CONFIG_NF_NAT_TFTP: enabled (as module)\n    - CONFIG_NF_CONNTRACK_TFTP: enabled (as module)\n- Storage Drivers:\n  - &quot;aufs&quot;:\n    - CONFIG_AUFS_FS: missing\n  - &quot;btrfs&quot;:\n    - CONFIG_BTRFS_FS: enabled (as module)\n    - CONFIG_BTRFS_FS_POSIX_ACL: enabled\n  - &quot;devicemapper&quot;:\n    - CONFIG_BLK_DEV_DM: enabled\n    - CONFIG_DM_THIN_PROVISIONING: missing\n  - &quot;overlay&quot;:\n    - CONFIG_OVERLAY_FS: enabled (as module)\n  - &quot;zfs&quot;:\n    - \/dev\/zfs: missing\n    - zfs command: missing\n    - zpool command: missing\n\nLimits:\n- \/proc\/sys\/kernel\/keys\/root_maxkeys: 1000000\n<\/code><\/pre>\n\n<h3 id=\"conclusion\">Conclusion<\/h3>\n\n<p>With these easy steps we&rsquo;ve covered in this short blogpost, you&rsquo;re now able to verify if the Linux kernel you&rsquo;re using is able to run Docker, containerd, Kubernetes or k3s in an optimal way.<\/p>\n\n<p>Just keep this in mind whenever you&rsquo;re discovering some strange errors with your Container Run-Time on a new Linux system. This is especially important when you run Containers on an Embedded Device. We&rsquo;ve discovered a lot of missing kernel settings in the early days with the Raspberry Pi. Even today the Raspberry Pi kernel which comes with the default Raspbian is not fully optimized to run Containers, therefore the image built from HypriotOS is still a better alternative when you wish to run Containers on these devices.<\/p>\n\n<p>And even when Docker runs out-of-the-box on a brandnew device like it does on the Jetson Nano, it&rsquo;s always a good idea to verify the Linux kernel - prior to get into some strange errors.<\/p>\n\n<p>In a later blogpost we&rsquo;ll optimize the stock Linux kernel for the brand-new NVIDIA Jetson Nano DevKit and we&rsquo;ll show you how to build your own customized kernel for this great board.<\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"Docker Engine on Intel Linux runs Arm Containers","link":"https:\/\/blog.hypriot.com\/post\/docker-intel-runs-arm-containers\/","pubDate":"Sat, 27 Apr 2019 10:48:50 -0700","guid":"https:\/\/blog.hypriot.com\/post\/docker-intel-runs-arm-containers\/","description":"<p>Did you read the latest news from Docker about their newly announced technology partnership together with Arm, <a href=\"https:\/\/twitter.com\/Docker\/status\/1121054608795688963\">&ldquo;Docker and Arm Partner to Deliver Frictionless Cloud-Native Software Development and Delivery Model for Cloud, Edge, and IoT&rdquo;<\/a>?<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/docker-intel-runs-arm-containers\/arm-docker-logo.jpg\" alt=\"arm-docker-logo.jpg\" \/><\/p>\n\n<p>This is really a great ground-breaking news, as it will enable an improved development workflow. Build and test all your Arm containers on your Intel-based laptop or workstation. These new Arm capabilities will be available in <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\">Docker Desktop<\/a> products from Docker, both for MacOs and Windows, and for Docker\u2019s commercial enterprise offerings. First technical details and roadmap will be announced next week at <a href=\"https:\/\/www.docker.com\/dockercon\/\">DockerCon 2019<\/a> in San Francisco, so please stay tuned.<\/p>\n\n<p>But wait, what about all the users who are directly working on a pure Linux environment? Well, here is the good news, the basic technology you need is already available and ready-to-use for you.<\/p>\n\n<p>Yes, you could use it right away! Let&rsquo;s start it now&hellip;<\/p>\n\n<p><\/p>\n\n<h3 id=\"run-an-arm-container-with-docker-engine-on-intel\">Run an Arm Container with Docker Engine on Intel<\/h3>\n\n<p>I don&rsquo;t want to hold you back and bore you with a lot of background details, so I&rsquo;m going to show you how easy it is today.<\/p>\n\n<p>First, let&rsquo;s start with a default Docker Engine installed on an Intel-based Linux system. For the sake of simplicity I&rsquo;d like to show it directly on the <a href=\"https:\/\/www.katacoda.com\">Katacoda Training Platform<\/a>, then you are able to replay it without spending too much time. It just takes you a few seconds to spin up a complete Linux Docker environment, just a few click away.<\/p>\n\n<p><strong>Step 1:<\/strong> Start the <a href=\"https:\/\/www.katacoda.com\/contino\/courses\/docker\/basics\">Docker Tutorial<\/a><\/p>\n\n<p>Next you have to click on &ldquo;START SCENARIO&rdquo; and the Linux Docker environment is ready for you.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/docker-intel-runs-arm-containers\/katacoda-docker-tutorial-start.jpg\" alt=\"katacoda-docker-tutorial-start.jpg\" \/><\/p>\n\n<p><strong>Step 2:<\/strong> Run an Arm-based Container<\/p>\n\n<p>In the bottom right box you&rsquo;ll find a Linux Terminal window where you can issue your CLI commands. It&rsquo;s a real Linux bash shell you can control through your browser and Docker is already installed on this machine.<\/p>\n\n<p>As soon as we try to start an Arm-based Docker container,<\/p>\n\n<pre><code class=\"language-bash\">$ docker run -it dieterreuter\/alpine-arm64:3.9\n<\/code><\/pre>\n\n<p>we&rsquo;ll get an cryptic error message <code>exec user process caused &quot;exec format error&quot;<\/code>, which basically tells us that this Docker Image tries to start a binary\/executable which can&rsquo;t be run on the provided Intel processor.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/docker-intel-runs-arm-containers\/katacoda-docker-tutorial-runarm1.jpg\" alt=\"katacoda-docker-tutorial-runarm1.jpg\" \/><\/p>\n\n<p><strong>Step 3:<\/strong> Run the magic command to enable Arm\/Arm64 on Intel<\/p>\n\n<pre><code class=\"language-bash\">$ docker run --rm --privileged hypriot\/qemu-register\n<\/code><\/pre>\n\n<p>This registers a few Qemu emulators inside of our Linux kernel with the help of the <code>binfmt<\/code> tool. This instructs the Linux loader to start the specific Qemu emulator program to run the binary\/executable if it&rsquo;s not based on Intel. Here we register <code>\/qemu-arm<\/code> for Arm 32-bit and <code>\/qemu-aarch64<\/code> for Arm 64-bit.<\/p>\n\n<p>Just to be precise, these emulators will be registered through a privileged Docker container. This is possible for all Linux kernel versions 4.9 and later. The emulators will be uploaded into memory, registered in the kernel and stay there persistent until you reboot your machine. This means you don&rsquo;t have to change anything inside of your Docker Images, all magic will be done by the Linux kernel on the host system!<\/p>\n\n<pre><code class=\"language-bash\">$ docker run --rm --privileged hypriot\/qemu-register\nUnable to find image 'hypriot\/qemu-register:latest' locally\nlatest: Pulling from hypriot\/qemu-register\nfc1a6b909f82: Pull complete\n247c87d40120: Pull complete\n1e300bd4bcdc: Pull complete\n79c54222eda0: Pull complete\n7d0efdace32f: Pull complete\nDigest: sha256:17931ba1f5362c6fbf7f364b32bec7e06e0c376571a9e3b2849dea18ce887c91\nStatus: Downloaded newer image for hypriot\/qemu-register:latest\n---\nInstalled interpreter binaries:\n-rwxr-xr-x    3 root     root       6192520 Apr 27 17:17 \/qemu-aarch64\n-rwxr-xr-x    4 root     root       5606984 Apr 27 17:17 \/qemu-arm\n-rwxr-xr-x    2 root     root       5987464 Apr 27 17:17 \/qemu-ppc64le\n---\nRegistered interpreter=qemu-aarch64\nenabled\ninterpreter \/qemu-aarch64\nflags: OCF\noffset 0\nmagic 7f454c460201010000000000000000000200b700\nmask ffffffffffffff00fffffffffffffffffeffffff\n---\nRegistered interpreter=qemu-arm\nenabled\ninterpreter \/qemu-arm\nflags: OCF\noffset 0\nmagic 7f454c4601010100000000000000000002002800\nmask ffffffffffffff00fffffffffffffffffeffffff\n---\nRegistered interpreter=qemu-ppc64le\nenabled\ninterpreter \/qemu-ppc64le\nflags: OCF\noffset 0\nmagic 7f454c4602010100000000000000000002001500\nmask ffffffffffffff00fffffffffffffffffeffff00\n---\n$\n<\/code><\/pre>\n\n<p><strong>Step 4:<\/strong> Run an Arm-based Container successfully on Intel<\/p>\n\n<p>Now let&rsquo;s start the same Arm-based Docker container again, but this time it actually works successfully.<\/p>\n\n<pre><code class=\"language-bash\">$ docker run -it dieterreuter\/alpine-arm64:3.9\n<\/code><\/pre>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/docker-intel-runs-arm-containers\/katacoda-docker-tutorial-runarm2.jpg\" alt=\"katacoda-docker-tutorial-runarm2.jpg\" \/><\/p>\n\n<p>When we run the command <code>uname -a<\/code> it tell us, we&rsquo;re running a Linux kernel 4.14.29 on Arm 64-bit architecture indicated as <code>aarch64<\/code>.<\/p>\n\n<p>SUCCESS, our Arm 64-bit Docker Container even works on Intel CPU&rsquo;s !!!<\/p>\n\n<p><strong>References:<\/strong> The source code of this magic registration Docker Image is fully open source and can be found at <a href=\"https:\/\/github.com\/hypriot\/qemu-register\">https:\/\/github.com\/hypriot\/qemu-register<\/a>. I also updated it today to the latest available Qemu 4.0.0 release.<\/p>\n\n<h3 id=\"conclusion\">Conclusion<\/h3>\n\n<p>As you could see, it&rsquo;s damn easy to configure your Intel-based Linux Docker Engine to run 32 or 64-bit Arm Containers in an emulation mode seemlessly. As long as you run a recent Linux kernel 4.9 or later it just works.<\/p>\n\n<p>Basically this is the same emulation technology how <a href=\"https:\/\/www.docker.com\/products\/docker-desktop\">Docker Desktop<\/a> is doing this behind the scenes on MacOS and Windows. BTW, this binfmt feature is already built-in in Docker Desktop since about April 2017.<\/p>\n\n<p>In the end it&rsquo;s possible for a user to develop, build and test his\/her Arm-based Docker Containers easily on a Intel-based Linux machine. And with the upcoming new features built-in into the Docker Engine this multi-architecture development workflow will get better and better over time.<\/p>\n\n<p>For Linux users we can use at least all these basic features. And for Mac and Windows users, Docker will present an even better user experience, so stay tuned for <a href=\"https:\/\/www.docker.com\/dockercon\/\">DockerCon 2019<\/a> in San Francisco next week.<\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"NVIDIA Jetson Nano - Upgrade Docker Engine","link":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-upgrade-docker\/","pubDate":"Mon, 22 Apr 2019 08:44:52 +0200","guid":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-upgrade-docker\/","description":"<p>In our last blogposts about the <a href=\"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-intro\/\">NVIDIA Jetson Nano Developer Kit - Introduction<\/a> and <a href=\"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-install-docker-compose\/\">NVIDIA Jetson Nano - Install Docker Compose<\/a> we digged into the brand-new <strong>NVIDIA Jetson Nano Developer Kit<\/strong> and we know, that Docker 18.06.1-CE is already installed, but&hellip;<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-docker-ce\/jetson-desktop-login.jpg\" alt=\"jetson-desktop-login.jpg\" \/><\/p>\n\n<p>But, this isn&rsquo;t the latest available version of the Docker Engine. So, I&rsquo;d like to point you to a few different options on how to upgrade the Docker Engine to the very latest available version for the NVIDIA Jetson Nano.<\/p>\n\n<p><\/p>\n\n<h3 id=\"check-the-current-docker-version\">Check the current Docker Version<\/h3>\n\n<p>For this tutorial I&rsquo;m starting again with a freshly flashed SD card image.<\/p>\n\n<p>Flashing from macOS just takes a few minutes with the Hypriot flash utility, which can be found here <a href=\"https:\/\/github.com\/hypriot\/flash\">https:\/\/github.com\/hypriot\/flash<\/a>.<\/p>\n\n<pre><code class=\"language-bash\">$ time flash --device \/dev\/disk2 jetson-nano-sd-r32.1-2019-03-18.img\n\nIs \/dev\/disk2 correct? y\nUnmounting \/dev\/disk2 ...\nUnmount of all volumes on disk2 was successful\nUnmount of all volumes on disk2 was successful\nFlashing jetson-nano-sd-r32.1-2019-03-18.img to \/dev\/rdisk2 ...\n12.0GiB 0:03:40 [55.8MiB\/s] [=======================================================================================&gt;] 100%\n0+196608 records in\n0+196608 records out\n12884901888 bytes transferred in 220.275160 secs (58494575 bytes\/sec)\nMounting Disk\n\nreal\t3m47.866s\nuser\t0m1.648s\nsys\t0m30.921s\n<\/code><\/pre>\n\n<p>Next we have to attach a computer monitor via HDMI cable, mouse and keyboard and of course an Ethernet cable in order to get an internet connect. Now connecting to a micro-USB power supply and follow the instruction on the screen to perform the initial setup of the NVIDIA Jetson Nano Developer Kit. This will take around 5 to 10 minutes and we do have a new Ubuntu 18.04 desktop running on that nice 64bit ARM Cortex-A57 developer board.<\/p>\n\n<p><strong>Pro-Tip on using Docker client:<\/strong><\/p>\n\n<p>As we have seen in the last blogpost, we have to use sudo when we&rsquo;re calling a docker command in the shell. This can be easily resolved, we only have to issue the following command ones.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo usermod -aG docker pirate\n<\/code><\/pre>\n\n<p>Next, log out and log in again or just start a new shell and we don&rsquo;t have to use sudo any more for our docker commands.<\/p>\n\n<p>Show the current version of the Docker Engine installed on the Nano.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker version\nClient:\n Version:           18.06.1-ce\n API version:       1.38\n Go version:        go1.10.1\n Git commit:        e68fc7a\n Built:             Fri Jan 25 14:35:17 2019\n OS\/Arch:           linux\/arm64\n Experimental:      false\n\nServer:\n Engine:\n  Version:          18.06.1-ce\n  API version:      1.38 (minimum version 1.12)\n  Go version:       go1.10.1\n  Git commit:       e68fc7a\n  Built:            Thu Jan 24 10:49:48 2019\n  OS\/Arch:          linux\/arm64\n  Experimental:     false\n<\/code><\/pre>\n\n<p>And here we see the version <code>18.06.1-ce<\/code> of the Docker Engine, which is installed on the Nano SD card image <code>jetson-nano-sd-r32.1-2019-03-18.img<\/code>. And yes, this is by far not the latest nor the securest available version at all.<\/p>\n\n<h3 id=\"upgrade-docker-engine\">Upgrade Docker Engine<\/h3>\n\n<p>As we&rsquo;ve seen in the previous section, the installed Docker Engine version is 18.06.01-ce. Now let&rsquo;s verify if there is already a newer version available.<\/p>\n\n<p>We can just use the apt utility from the Ubuntu package manager to determine the installed versions of any of the installed software packages. Here on Ubuntu 18.04 the Docker Engine is installed through the <code>docker.io<\/code> package.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ apt list --installed | grep docker.io\n\nWARNING: apt does not have a stable CLI interface. Use with caution in scripts.\n\ndocker.io\/bionic-security,now 18.06.1-0ubuntu1.2~18.04.1 arm64 [installed,upgradable to: 18.09.2-0ubuntu1~18.04.1]\n<\/code><\/pre>\n\n<p>We can see the newer Docker version 18.09.2 is already available in the Ubuntu repository, so we&rsquo;re going to upgrade the software package <code>docker.io<\/code>.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo apt-get --only-upgrade install docker.io\n<\/code><\/pre>\n\n<p>At the end we were able to upgrade the Docker Engine to the very latest version which is provided by the Ubuntu repository.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker version\nClient:\n Version:           18.09.2\n API version:       1.39\n Go version:        go1.10.4\n Git commit:        6247962\n Built:             Tue Feb 26 23:51:35 2019\n OS\/Arch:           linux\/arm64\n Experimental:      false\n\nServer:\n Engine:\n  Version:          18.09.2\n  API version:      1.39 (minimum version 1.12)\n  Go version:       go1.10.4\n  Git commit:       6247962\n  Built:            Wed Feb 13 00:24:14 2019\n  OS\/Arch:          linux\/arm64\n<\/code><\/pre>\n\n<p>Finally we have upgraded the Docker Engine to version 18.09.2. Please keep in mind, this version of the Docker Engine is provided by the Ubuntu repository. Maybe there is even a newer version available directly from the Docker open source project.<\/p>\n\n<h3 id=\"recommendation-install-official-docker-engine-ce\">Recommendation: Install official Docker Engine CE<\/h3>\n\n<p>For this step I can truely recommend to use the official Docker documentation for the Community Edition. For installing Docker Engine CE on Ubuntu you can directly follow the detailled steps at <a href=\"https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/\">https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/<\/a>.<\/p>\n\n<p>As you can see later, Docker Engine CE is also available for ARM 64bit on Ubuntu 18.04 LTS. It&rsquo;s not too complicated to set it up, just follow the installation steps in this documentation and within a few minutes you have installed the official Docker Engine!<\/p>\n\n<p><strong>Step 1:<\/strong> Uninstall old versions<\/p>\n\n<pre><code class=\"language-bash\">$ sudo apt-get remove docker docker-engine docker.io containerd runc\n<\/code><\/pre>\n\n<p><strong>Step 2:<\/strong> Set up the repository<\/p>\n\n<pre><code class=\"language-bash\"># 1. Update the apt package index:\n$ sudo apt-get update\n\n# 2. Install packages to allow apt to use a repository over HTTPS:\n$ sudo apt-get install \\\n    apt-transport-https \\\n    ca-certificates \\\n    curl \\\n    gnupg-agent \\\n    software-properties-common\n\n# 3. Add Docker\u2019s official GPG key:\n$ curl -fsSL https:\/\/download.docker.com\/linux\/ubuntu\/gpg | sudo apt-key add -\n\n$ sudo apt-key fingerprint 0EBFCD88\npub   rsa4096 2017-02-22 [SCEA]\n      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88\nuid           [ unknown] Docker Release (CE deb) &lt;docker@docker.com&gt;\nsub   rsa4096 2017-02-22 [S]\n\n# 4. Use the following command to set up the stable repository:\n#    here select the commands for &quot;arm64&quot;\n$ sudo add-apt-repository \\\n   &quot;deb [arch=arm64] https:\/\/download.docker.com\/linux\/ubuntu \\\n   $(lsb_release -cs) \\\n   stable&quot;\n<\/code><\/pre>\n\n<pre><code class=\"language-bash\"># Alternatively you can also select the &quot;edge&quot; channel for the very latest version\n$ sudo add-apt-repository \\\n   &quot;deb [arch=arm64] https:\/\/download.docker.com\/linux\/ubuntu \\\n   $(lsb_release -cs) \\\n   edge&quot;\n<\/code><\/pre>\n\n<p><strong>Step 3:<\/strong> Install Docker CE<\/p>\n\n<pre><code class=\"language-bash\"># 1. Update the apt package index.\n$ sudo apt-get update\n\n# 2. Install the latest version of Docker CE and containerd\n$ sudo apt-get install docker-ce docker-ce-cli containerd.io\n\n# 3. Add user &quot;pirate&quot; to the group &quot;docker&quot;, so we don't need sudo\n$ sudo usermod -aG docker pirate\n# Now logout and login again\n<\/code><\/pre>\n\n<p><strong>Step 4:<\/strong> Show the installed Docker Engine version<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker version\nClient:\n Version:           18.09.5\n API version:       1.39\n Go version:        go1.10.8\n Git commit:        e8ff056\n Built:             Thu Apr 11 04:48:27 2019\n OS\/Arch:           linux\/arm64\n Experimental:      false\n\nServer: Docker Engine - Community\n Engine:\n  Version:          18.09.5\n  API version:      1.39 (minimum version 1.12)\n  Go version:       go1.10.8\n  Git commit:       e8ff056\n  Built:            Thu Apr 11 04:11:17 2019\n  OS\/Arch:          linux\/arm64\n  Experimental:     false\n<\/code><\/pre>\n\n<p><strong>Step 5:<\/strong> Run the <code>docker info<\/code> command<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker info\nContainers: 0\n Running: 0\n Paused: 0\n Stopped: 0\nImages: 0\nServer Version: 18.09.5\nStorage Driver: overlay2\n Backing Filesystem: extfs\n Supports d_type: true\n Native Overlay Diff: true\nLogging Driver: json-file\nCgroup Driver: cgroupfs\nPlugins:\n Volume: local\n Network: bridge host macvlan null overlay\n Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog\nSwarm: inactive\nRuntimes: runc\nDefault Runtime: runc\nInit Binary: docker-init\ncontainerd version: bb71b10fd8f58240ca47fbb579b9d1028eea7c84\nrunc version: 2b18fe1d885ee5083ef9f0838fee39b62d653e30\ninit version: fec3683\nSecurity Options:\n seccomp\n  Profile: default\nKernel Version: 4.9.140-tegra\nOperating System: Ubuntu 18.04.2 LTS\nOSType: linux\nArchitecture: aarch64\nCPUs: 4\nTotal Memory: 3.868GiB\nName: jetson-nano\nID: 4JER:EIWM:QFNF:6N2C:YUW3:YES2:RSP5:Z4D2:7PKI:YAOT:G5O7:5N25\nDocker Root Dir: \/var\/lib\/docker\nDebug Mode (client): false\nDebug Mode (server): false\nRegistry: https:\/\/index.docker.io\/v1\/\nLabels:\nExperimental: false\nInsecure Registries:\n 127.0.0.0\/8\nLive Restore Enabled: false\nProduct License: Community Engine\n<\/code><\/pre>\n\n<p><strong>Step 6:<\/strong>  Start first Docker container<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker run hello-world\nUnable to find image 'hello-world:latest' locally\nlatest: Pulling from library\/hello-world\n3b4173355427: Pull complete\nDigest: sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e\nStatus: Downloaded newer image for hello-world:latest\n\nHello from Docker!\nThis message shows that your installation appears to be working correctly.\n\nTo generate this message, Docker took the following steps:\n 1. The Docker client contacted the Docker daemon.\n 2. The Docker daemon pulled the &quot;hello-world&quot; image from the Docker Hub.\n    (arm64v8)\n 3. The Docker daemon created a new container from that image which runs the\n    executable that produces the output you are currently reading.\n 4. The Docker daemon streamed that output to the Docker client, which sent it\n    to your terminal.\n\nTo try something more ambitious, you can run an Ubuntu container with:\n $ docker run -it ubuntu bash\n\nShare images, automate workflows, and more with a free Docker ID:\n https:\/\/hub.docker.com\/\n\nFor more examples and ideas, visit:\n https:\/\/docs.docker.com\/get-started\/\n<\/code><\/pre>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-docker-ce\/jetson-desktop-docker-ce.jpg\" alt=\"jetson-desktop-docker-ce.jpg\" \/><\/p>\n\n<h3 id=\"conclusion\">Conclusion<\/h3>\n\n<p>As you could see, on the Jetson Nano DevKit there is already a version of the Docker Engine installed and it&rsquo;s maintained by the Ubuntu project. But this is not the latest version available and it will not get updated fast enough to include all important security fixes in time.<\/p>\n\n<p>Therefore I&rsquo;d like to strongly recommend to use the Docker Engine CE from the official Docker project. It&rsquo;s well maintained and updated in time. All installation steps and options are also extremely well documented at <a href=\"https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/\">https:\/\/docs.docker.com\/install\/linux\/docker-ce\/ubuntu\/<\/a>.<\/p>\n\n<p>And in case you need more help or having some technical questions about running Docker on an ARM 64bit system like the NVIDIA Jetson Nano, there is an <code>arm<\/code> Slack channel available for you at the <a href=\"https:\/\/dockercommunity.slack.com\/messages\/C2293P89Y\">DockerCommunity Slack<\/a>.<\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"NVIDIA Jetson Nano - Install Docker Compose","link":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-install-docker-compose\/","pubDate":"Sat, 20 Apr 2019 09:51:52 +0200","guid":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-install-docker-compose\/","description":"<p>In our last blogpost <a href=\"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-intro\/\">NVIDIA Jetson Nano Developer Kit - Introduction<\/a> we digged into the brand-new <strong>NVIDIA Jetson Nano Developer Kit<\/strong> and we did found out, that Docker 18.06.1-CE is already pre-installed on this great ARM board.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/Jetson-Nano-Upacked.jpg\" alt=\"Jetson-Nano-Upacked.jpg\" \/><\/p>\n\n<p>Today, I want to share some more details on how you can easily install Docker Compose on the Jetson Nano.<\/p>\n\n<p><\/p>\n\n<h3 id=\"install-docker-compose\">Install Docker Compose<\/h3>\n\n<p>Sadly, there is no binary of <a href=\"https:\/\/docs.docker.com\/compose\/\">Docker Compose<\/a> available we could install directly on an ARM 64bit board like the NVIDIA Jetson Nano. If we are looking at the official GitHub release page for Docker Compose <a href=\"https:\/\/github.com\/docker\/compose\/releases\/tag\/1.24.0\">https:\/\/github.com\/docker\/compose\/releases\/tag\/1.24.0<\/a> there are only binaries provided for Intel x86-64 based operating systems like Linux, macOS and Windows - but nothing for ARM 32bit or 64bit systems.<\/p>\n\n<p>This isn&rsquo;t too bad, because Docker Compose is based upon Python and maybe it&rsquo;s easier to install if Python is already available on our board. So, let&rsquo;s check this out the easy way.<\/p>\n\n<h3 id=\"docker-compose-is-based-upon-python\">Docker Compose is based upon Python<\/h3>\n\n<p>First, check out if Python is already available on the Jetson Nano. As we have a complete Ubuntu 18.04 LTS desktop operation system this is very likely. But let&rsquo;s verify it directly on a shell running on the Nano. This can be done from the desktop terminal app or via a SSH shell.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ python --version\nPython 2.7.15rc1\n<\/code><\/pre>\n\n<p>OK, this looks pretty promising. We do have the Python version 2.7.15rc1 already installed on the Nano.<\/p>\n\n<p>Let&rsquo;s try to install Docker Compose via Python PIP. So, first we need to install Python PIP itself.<\/p>\n\n<pre><code class=\"language-bash\"># first, we have to install Python PIP\n$ sudo apt-get update -y\n$ sudo apt-get install -y curl\n$ curl -sSL https:\/\/bootstrap.pypa.io\/get-pip.py | sudo python\n\n# verify the installed Python PIP version\npirate@jetson-nano:~$ pip --version\npip 19.0.3 from \/usr\/local\/lib\/python2.7\/dist-packages\/pip (python 2.7)\n<\/code><\/pre>\n\n<p>Now, let&rsquo;s try to install Docker Compose via Python PIP. Here we&rsquo;re going to pin the latest version of Docker Compose, which is 1.24.0 of the time of writing this blogpost.<\/p>\n\n<pre><code class=\"language-bash\"># install Docker Compose via pip\nexport DOCKER_COMPOSE_VERSION=1.24.0\nsudo pip install docker-compose==&quot;${DOCKER_COMPOSE_VERSION}&quot;\n<\/code><\/pre>\n\n<p>But this will throw a lot of error messages because it seems we do miss some required build dependencies. If you&rsquo;re interested here are the full details.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ curl -sSL https:\/\/bootstrap.pypa.io\/get-pip.py | sudo python\nDEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.\nThe directory '\/home\/pirate\/.cache\/pip\/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\nThe directory '\/home\/pirate\/.cache\/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\nCollecting pip\n  Downloading https:\/\/files.pythonhosted.org\/packages\/d8\/f3\/413bab4ff08e1fc4828dfc59996d721917df8e8583ea85385d51125dceff\/pip-19.0.3-py2.py3-none-any.whl (1.4MB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1.4MB 843kB\/s\nCollecting setuptools\n  Downloading https:\/\/files.pythonhosted.org\/packages\/c8\/b0\/cc6b7ba28d5fb790cf0d5946df849233e32b8872b6baca10c9e002ff5b41\/setuptools-41.0.0-py2.py3-none-any.whl (575kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 583kB 761kB\/s\nCollecting wheel\n  Downloading https:\/\/files.pythonhosted.org\/packages\/96\/ba\/a4702cbb6a3a485239fbe9525443446203f00771af9ac000fa3ef2788201\/wheel-0.33.1-py2.py3-none-any.whl\nInstalling collected packages: pip, setuptools, wheel\nSuccessfully installed pip-19.0.3 setuptools-41.0.0 wheel-0.33.1\npirate@jetson-nano:~$ pip --version\npip 19.0.3 from \/usr\/local\/lib\/python2.7\/dist-packages\/pip (python 2.7)\n\npirate@jetson-nano:~$ export DOCKER_COMPOSE_VERSION=1.24.0\npirate@jetson-nano:~$ sudo pip install docker-compose==&quot;${DOCKER_COMPOSE_VERSION}&quot;\nDEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.\nThe directory '\/home\/pirate\/.cache\/pip\/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\nThe directory '\/home\/pirate\/.cache\/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\nCollecting docker-compose==1.24.0\n  Downloading https:\/\/files.pythonhosted.org\/packages\/51\/56\/5745e66b33846e92a8814466c163f165a26fadad8b33afe381e8b6c3f652\/docker_compose-1.24.0-py2.py3-none-any.whl (134kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 143kB 2.3MB\/s\nCollecting cached-property&lt;2,&gt;=1.2.0 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/3b\/86\/85c1be2e8db9e13ef9a350aecd6dea292bd612fa288c2f40d035bb750ded\/cached_property-1.5.1-py2.py3-none-any.whl\nCollecting docopt&lt;0.7,&gt;=0.6.1 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/a2\/55\/8f8cab2afd404cf578136ef2cc5dfb50baa1761b68c9da1fb1e4eed343c9\/docopt-0.6.2.tar.gz\nCollecting jsonschema&lt;3,&gt;=2.5.1 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/77\/de\/47e35a97b2b05c2fadbec67d44cfcdcd09b8086951b331d82de90d2912da\/jsonschema-2.6.0-py2.py3-none-any.whl\nCollecting backports.ssl-match-hostname&gt;=3.5; python_version &lt; &quot;3.5&quot; (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/ff\/2b\/8265224812912bc5b7a607c44bf7b027554e1b9775e9ee0de8032e3de4b2\/backports.ssl_match_hostname-3.7.0.1.tar.gz\nRequirement already satisfied: six&lt;2,&gt;=1.3.0 in \/usr\/lib\/python2.7\/dist-packages (from docker-compose==1.24.0) (1.11.0)\nCollecting ipaddress&gt;=1.0.16; python_version &lt; &quot;3.3&quot; (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/fc\/d0\/7fc3a811e011d4b388be48a0e381db8d990042df54aa4ef4599a31d39853\/ipaddress-1.0.22-py2.py3-none-any.whl\nCollecting requests!=2.11.0,!=2.12.2,!=2.18.0,&lt;2.21,&gt;=2.6.1 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/ff\/17\/5cbb026005115301a8fb2f9b0e3e8d32313142fe8b617070e7baad20554f\/requests-2.20.1-py2.py3-none-any.whl (57kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 61kB 2.8MB\/s\nCollecting texttable&lt;0.10,&gt;=0.9.0 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/02\/e1\/2565e6b842de7945af0555167d33acfc8a615584ef7abd30d1eae00a4d80\/texttable-0.9.1.tar.gz\nCollecting dockerpty&lt;0.5,&gt;=0.4.1 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/8d\/ee\/e9ecce4c32204a6738e0a5d5883d3413794d7498fe8b06f44becc028d3ba\/dockerpty-0.4.1.tar.gz\nCollecting enum34&lt;2,&gt;=1.0.4; python_version &lt; &quot;3.4&quot; (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/c5\/db\/e56e6b4bbac7c4a06de1c50de6fe1ef3810018ae11732a50f15f62c7d050\/enum34-1.1.6-py2-none-any.whl\nCollecting PyYAML&lt;4.3,&gt;=3.10 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/9e\/a3\/1d13970c3f36777c583f136c136f804d70f500168edc1edea6daa7200769\/PyYAML-3.13.tar.gz (270kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 276kB 2.9MB\/s\nCollecting websocket-client&lt;1.0,&gt;=0.32.0 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/29\/19\/44753eab1fdb50770ac69605527e8859468f3c0fd7dc5a76dd9c4dbd7906\/websocket_client-0.56.0-py2.py3-none-any.whl (200kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 204kB 3.2MB\/s\nCollecting docker[ssh]&lt;4.0,&gt;=3.7.0 (from docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/48\/68\/c3afca1a5aa8d2997ec3b8ee822a4d752cf85907b321f07ea86888545152\/docker-3.7.2-py2.py3-none-any.whl (134kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 143kB 3.5MB\/s\nCollecting functools32; python_version == &quot;2.7&quot; (from jsonschema&lt;3,&gt;=2.5.1-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/c5\/60\/6ac26ad05857c601308d8fb9e87fa36d0ebf889423f47c3502ef034365db\/functools32-3.2.3-2.tar.gz\nCollecting urllib3&lt;1.25,&gt;=1.21.1 (from requests!=2.11.0,!=2.12.2,!=2.18.0,&lt;2.21,&gt;=2.6.1-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/df\/1c\/59cca3abf96f991f2ec3131a4ffe72ae3d9ea1f5894abe8a9c5e3c77cfee\/urllib3-1.24.2-py2.py3-none-any.whl (131kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 133kB 3.2MB\/s\nCollecting chardet&lt;3.1.0,&gt;=3.0.2 (from requests!=2.11.0,!=2.12.2,!=2.18.0,&lt;2.21,&gt;=2.6.1-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/bc\/a9\/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8\/chardet-3.0.4-py2.py3-none-any.whl (133kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 143kB 3.5MB\/s\nCollecting idna&lt;2.8,&gt;=2.5 (from requests!=2.11.0,!=2.12.2,!=2.18.0,&lt;2.21,&gt;=2.6.1-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/4b\/2a\/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165\/idna-2.7-py2.py3-none-any.whl (58kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 61kB 5.8MB\/s\nCollecting certifi&gt;=2017.4.17 (from requests!=2.11.0,!=2.12.2,!=2.18.0,&lt;2.21,&gt;=2.6.1-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/60\/75\/f692a584e85b7eaba0e03827b3d51f45f571c2e793dd731e598828d380aa\/certifi-2019.3.9-py2.py3-none-any.whl (158kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 163kB 353kB\/s\nCollecting docker-pycreds&gt;=0.4.0 (from docker[ssh]&lt;4.0,&gt;=3.7.0-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/f5\/e8\/f6bd1eee09314e7e6dee49cbe2c5e22314ccdb38db16c9fc72d2fa80d054\/docker_pycreds-0.4.0-py2.py3-none-any.whl\nCollecting paramiko&gt;=2.4.2; extra == &quot;ssh&quot; (from docker[ssh]&lt;4.0,&gt;=3.7.0-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/cf\/ae\/94e70d49044ccc234bfdba20114fa947d7ba6eb68a2e452d89b920e62227\/paramiko-2.4.2-py2.py3-none-any.whl (193kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 194kB 3.2MB\/s\nCollecting pyasn1&gt;=0.1.7 (from paramiko&gt;=2.4.2; extra == &quot;ssh&quot;-&gt;docker[ssh]&lt;4.0,&gt;=3.7.0-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/7b\/7c\/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c\/pyasn1-0.4.5-py2.py3-none-any.whl (73kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 81kB 3.2MB\/s\nCollecting bcrypt&gt;=3.1.3 (from paramiko&gt;=2.4.2; extra == &quot;ssh&quot;-&gt;docker[ssh]&lt;4.0,&gt;=3.7.0-&gt;docker-compose==1.24.0)\n  Downloading https:\/\/files.pythonhosted.org\/packages\/ce\/3a\/3d540b9f5ee8d92ce757eebacf167b9deedb8e30aedec69a2a072b2399bb\/bcrypt-3.1.6.tar.gz (42kB)\n    100% |\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 51kB 8.4MB\/s\n  Installing build dependencies ... error\n  Complete output from command \/usr\/bin\/python \/usr\/local\/lib\/python2.7\/dist-packages\/pip install --ignore-installed --no-user --prefix \/tmp\/pip-build-env-qwOdIW\/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https:\/\/pypi.org\/simple -- setuptools wheel &quot;cffi&gt;=1.1; python_implementation != 'PyPy'&quot;:\n  DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.\n  The directory '\/home\/pirate\/.cache\/pip\/http' or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\n  The directory '\/home\/pirate\/.cache\/pip' or its parent directory is not owned by the current user and caching wheels has been disabled. check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.\n  Collecting setuptools\n    Downloading https:\/\/files.pythonhosted.org\/packages\/c8\/b0\/cc6b7ba28d5fb790cf0d5946df849233e32b8872b6baca10c9e002ff5b41\/setuptools-41.0.0-py2.py3-none-any.whl (575kB)\n  Collecting wheel\n    Downloading https:\/\/files.pythonhosted.org\/packages\/96\/ba\/a4702cbb6a3a485239fbe9525443446203f00771af9ac000fa3ef2788201\/wheel-0.33.1-py2.py3-none-any.whl\n  Collecting cffi&gt;=1.1\n    Downloading https:\/\/files.pythonhosted.org\/packages\/93\/1a\/ab8c62b5838722f29f3daffcc8d4bd61844aa9b5f437341cc890ceee483b\/cffi-1.12.3.tar.gz (456kB)\n  Collecting pycparser (from cffi&gt;=1.1)\n    Downloading https:\/\/files.pythonhosted.org\/packages\/68\/9e\/49196946aee219aead1290e00d1e7fdeab8567783e83e1b9ab5585e6206a\/pycparser-2.19.tar.gz (158kB)\n  Installing collected packages: setuptools, wheel, pycparser, cffi\n    Running setup.py install for pycparser: started\n      Running setup.py install for pycparser: finished with status 'done'\n    Running setup.py install for cffi: started\n      Running setup.py install for cffi: finished with status 'error'\n      Complete output from command \/usr\/bin\/python -u -c &quot;import setuptools, tokenize;__file__='\/tmp\/pip-install-XfNg4G\/cffi\/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\\r\\n', '\\n');f.close();exec(compile(code, __file__, 'exec'))&quot; install --record \/tmp\/pip-record-lpvT6b\/install-record.txt --single-version-externally-managed --prefix \/tmp\/pip-build-env-qwOdIW\/overlay --compile:\n      Package libffi was not found in the pkg-config search path.\n      Perhaps you should add the directory containing `libffi.pc'\n      to the PKG_CONFIG_PATH environment variable\n      No package 'libffi' found\n      Package libffi was not found in the pkg-config search path.\n      Perhaps you should add the directory containing `libffi.pc'\n      to the PKG_CONFIG_PATH environment variable\n      No package 'libffi' found\n      Package libffi was not found in the pkg-config search path.\n      Perhaps you should add the directory containing `libffi.pc'\n      to the PKG_CONFIG_PATH environment variable\n      No package 'libffi' found\n      Package libffi was not found in the pkg-config search path.\n      Perhaps you should add the directory containing `libffi.pc'\n      to the PKG_CONFIG_PATH environment variable\n      No package 'libffi' found\n      Package libffi was not found in the pkg-config search path.\n      Perhaps you should add the directory containing `libffi.pc'\n      to the PKG_CONFIG_PATH environment variable\n      No package 'libffi' found\n      running install\n      running build\n      running build_py\n      creating build\n      creating build\/lib.linux-aarch64-2.7\n      creating build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/ffiplatform.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/vengine_gen.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/setuptools_ext.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/verifier.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/backend_ctypes.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/vengine_cpy.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/pkgconfig.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/recompiler.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/api.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/cparser.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/__init__.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/cffi_opcode.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/error.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/lock.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/model.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/commontypes.py -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/_cffi_include.h -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/parse_c_type.h -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/_embedding.h -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      copying cffi\/_cffi_errors.h -&gt; build\/lib.linux-aarch64-2.7\/cffi\n      running build_ext\n      building '_cffi_backend' extension\n      creating build\/temp.linux-aarch64-2.7\n      creating build\/temp.linux-aarch64-2.7\/c\n      aarch64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=\/build\/python2.7-ytvI67\/python2.7-2.7.15~rc1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I\/usr\/include\/ffi -I\/usr\/include\/libffi -I\/usr\/include\/python2.7 -c c\/_cffi_backend.c -o build\/temp.linux-aarch64-2.7\/c\/_cffi_backend.o\n      c\/_cffi_backend.c:15:10: fatal error: ffi.h: No such file or directory\n       #include &lt;ffi.h&gt;\n                ^~~~~~~\n      compilation terminated.\n      error: command 'aarch64-linux-gnu-gcc' failed with exit status 1\n\n      ----------------------------------------\n  Command &quot;\/usr\/bin\/python -u -c &quot;import setuptools, tokenize;__file__='\/tmp\/pip-install-XfNg4G\/cffi\/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\\r\\n', '\\n');f.close();exec(compile(code, __file__, 'exec'))&quot; install --record \/tmp\/pip-record-lpvT6b\/install-record.txt --single-version-externally-managed --prefix \/tmp\/pip-build-env-qwOdIW\/overlay --compile&quot; failed with error code 1 in \/tmp\/pip-install-XfNg4G\/cffi\/\n\n  ----------------------------------------\nCommand &quot;\/usr\/bin\/python \/usr\/local\/lib\/python2.7\/dist-packages\/pip install --ignore-installed --no-user --prefix \/tmp\/pip-build-env-qwOdIW\/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https:\/\/pypi.org\/simple -- setuptools wheel &quot;cffi&gt;=1.1; python_implementation != 'PyPy'&quot;&quot; failed with error code 1 in None\n<\/code><\/pre>\n\n<p>After some investigation we&rsquo;re able to identify the missing build dependencies and here are the required commands to install it.<\/p>\n\n<pre><code class=\"language-bash\"># install Docker Compose build dependencies for Ubuntu 18.04 on aarch64\n$ sudo apt-get install -y libffi-dev\n$ sudo apt-get install -y python-openssl\n<\/code><\/pre>\n\n<h3 id=\"install-docker-compose-via-python-pip\">Install Docker Compose via Python PIP<\/h3>\n\n<p>TL;DR These are all commands you need to install Docker Compose on a freshly installed NVIDIA Jetson Nano.<\/p>\n\n<pre><code class=\"language-bash\"># step 1, install Python PIP\n$ sudo apt-get update -y\n$ sudo apt-get install -y curl\n$ curl -sSL https:\/\/bootstrap.pypa.io\/get-pip.py | sudo python\n\n# step 2, install Docker Compose build dependencies for Ubuntu 18.04 on aarch64\n$ sudo apt-get install -y libffi-dev\n$ sudo apt-get install -y python-openssl\n\n# step 3, install latest Docker Compose via pip\n$ export DOCKER_COMPOSE_VERSION=1.24.0\n$ sudo pip install docker-compose==&quot;${DOCKER_COMPOSE_VERSION}&quot;\n<\/code><\/pre>\n\n<h3 id=\"conclusion\">Conclusion<\/h3>\n\n<p>Finally we have the latest available Docker Compose version 1.24.0 installed on the NVIDIA Jetson Nano. It just takes a few minutes.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker-compose version\ndocker-compose version 1.24.0, build 0aa5906\ndocker-py version: 3.7.2\nCPython version: 2.7.15rc1\nOpenSSL version: OpenSSL 1.1.0g  2 Nov 2017\n\npirate@jetson-nano:~$ docker-compose --version\ndocker-compose version 1.24.0, build 0aa5906\n<\/code><\/pre>\n\n<h3 id=\"another-pro-tip-on-using-docker-command-line-interface\">Another Pro-Tip on using Docker command line interface<\/h3>\n\n<p>As we have seen in the last blogpost, we have to use sudo when we&rsquo;re calling a docker command in the shell. This can be easy resolved, we only have to issue the following command ones.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo usermod -aG docker pirate\n<\/code><\/pre>\n\n<p>Next, log out and log in again or just start a new shell and we don&rsquo;t have to use sudo any more for our docker commands.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ docker version\nClient:\n Version:           18.06.1-ce\n API version:       1.38\n Go version:        go1.10.1\n Git commit:        e68fc7a\n Built:             Fri Jan 25 14:35:17 2019\n OS\/Arch:           linux\/arm64\n Experimental:      false\n\nServer:\n Engine:\n  Version:          18.06.1-ce\n  API version:      1.38 (minimum version 1.12)\n  Go version:       go1.10.1\n  Git commit:       e68fc7a\n  Built:            Thu Jan 24 10:49:48 2019\n  OS\/Arch:          linux\/arm64\n  Experimental:     false\n<\/code><\/pre>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"NVIDIA Jetson Nano Developer Kit - Introduction","link":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-intro\/","pubDate":"Fri, 19 Apr 2019 14:16:25 +0200","guid":"https:\/\/blog.hypriot.com\/post\/nvidia-jetson-nano-intro\/","description":"<p>Let me introduce the brand new <strong>NVIDIA Jetson Nano Developer Kit<\/strong>, which is basically a quad-core 64bit ARM Cortex-A57 CPU with 128 GPU cores - suitable for all kinds of maker ideas: AI, Robotics, and of course for running Docker Containers&hellip;<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/Jetson-Nano-Box.jpg\" alt=\"Jetson-Nano-Box.jpg\" \/><\/p>\n\n<h3 id=\"unboxing\">Unboxing<\/h3>\n\n<p>Let&rsquo;s unbox the board and do the initial configuration&hellip;<\/p>\n\n<p><\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/Jetson-Nano-Upacked.jpg\" alt=\"Jetson-Nano-Upacked.jpg\" \/><\/p>\n\n<p>When opening the box we&rsquo;ll find the board itself and a short getting started flyer which heads us to the NVIDIA website <a href=\"https:\/\/NVIDIA.com\/JetsonNano-Start\">https:\/\/NVIDIA.com\/JetsonNano-Start<\/a> where we can find all basic information about the new DevKit.<\/p>\n\n<p>Please note, there are no other parts included in the DevKit. So, in order to use the DevKit you&rsquo;ll need some additional accessories:<\/p>\n\n<ul>\n<li>MicroSD card (at least 16GByte)<\/li>\n<li>Monitor with HDMI or DisplayPort connector<\/li>\n<li>HDMI or DisplayPort cable to connect to the monitor<\/li>\n<li>USB Keyboard and Mouse<\/li>\n<li>Micro-USB power supply (5V, 2Amps for 10 watts)<\/li>\n<\/ul>\n\n<h3 id=\"getting-started\">Getting Started<\/h3>\n\n<p>Following the official documentation <a href=\"https:\/\/developer.nvidia.com\/embedded\/learn\/get-started-jetson-nano-devkit\">Getting Started With Jetson Nano Developer Kit<\/a> we have to download and flash the SD card. I don&rsquo;t want to repeat these basic steps here, because it&rsquo;s covered in great detail directy in the official NVIDIA tutorial <a href=\"https:\/\/developer.nvidia.com\/embedded\/learn\/get-started-jetson-nano-devkit#write\">Write Image to the microSD Card<\/a>.<\/p>\n\n<p>When downloading the SD card image, please be aware this one isn&rsquo;t small at all. The download is a zipped image file of 5 GByte of compressed data.<\/p>\n\n<pre><code class=\"language-bash\">$ ls -alh jetson-nano-sd-r32.1-2019-03-18.zip\n-rw-r--r--@ 1 dieter  staff   5.3G Mar 15 22:49 jetson-nano-sd-r32.1-2019-03-18.zip \n<\/code><\/pre>\n\n<p>The SD card image is a huge 12 GByte data blob. I would strongly recommend to use a SD card size with at least 32 GByte, with the recommended 16 GByte minimum you won&rsquo;t get really happy. So, please do yourself a favour and get a 32 or 64 GByte SD card.<\/p>\n\n<pre><code class=\"language-bash\">$ ls -alh jetson-nano-sd-r32.1-2019-03-18.img\n-rwxr-xr-x  1 dieter  staff    12G Mar 15 19:19 jetson-nano-sd-r32.1-2019-03-18.img\n<\/code><\/pre>\n\n<p>For flashing the SD card image you could also use the Hypriot <code>flash<\/code> tool, which can be found here <a href=\"https:\/\/github.com\/hypriot\/flash\">https:\/\/github.com\/hypriot\/flash<\/a>. That&rsquo;s exactly what I did from macOS.<\/p>\n\n<pre><code class=\"language-bash\">$ flash --device \/dev\/disk2 jetson-nano-sd-r32.1-2019-03-18.img\n\nIs \/dev\/disk2 correct? y\nUnmounting \/dev\/disk2 ...\nUnmount of all volumes on disk2 was successful\nUnmount of all volumes on disk2 was successful\nFlashing jetson-nano-sd-r32.1-2019-03-18.img to \/dev\/rdisk2 ...\nPassword:\n12.0GiB 0:03:58 [51.6MiB\/s] [=======================================================================================&gt;] 100%\n0+196608 records in\n0+196608 records out\n12884901888 bytes transferred in 234.213296 secs (55013537 bytes\/sec)\nMounting Disk\n<\/code><\/pre>\n\n<p>Now our SD card is flashed with the latest image version, which is from March 18th 2019 as of time of this writing. But before using the SD card to boot up the NVIDIA Jetson Nano device, let&rsquo;s have a short look at what&rsquo;s on the SD card. Please, re-insert the SD card and list the current partitions. On macOS it looks like:<\/p>\n\n<pre><code class=\"language-bash\">$ diskutil list \/dev\/disk2\n\/dev\/disk2 (external, physical):\n   #:                       TYPE NAME                    SIZE       IDENTIFIER\n   0:      GUID_partition_scheme                        *64.0 GB    disk2\n   1:           Linux Filesystem                         12.9 GB    disk2s1\n   2:           Linux Filesystem                         131.1 KB   disk2s2\n   3:           Linux Filesystem                         458.8 KB   disk2s3\n   4:           Linux Filesystem                         589.8 KB   disk2s4\n   5:           Linux Filesystem                         65.5 KB    disk2s5\n   6:           Linux Filesystem                         196.6 KB   disk2s6\n   7:           Linux Filesystem                         589.8 KB   disk2s7\n   8:           Linux Filesystem                         65.5 KB    disk2s8\n   9:           Linux Filesystem                         655.4 KB   disk2s9\n  10:           Linux Filesystem                         458.8 KB   disk2s10\n  11:           Linux Filesystem                         131.1 KB   disk2s11\n  12:           Linux Filesystem                         81.9 KB    disk2s12\n<\/code><\/pre>\n\n<p>OK, we&rsquo;ll find at least 12 different partitions from NVIDIA. Currently we don&rsquo;t look into all the details, maybe we can do this as part of a future blog post. For now we just know, 12 partitions are here and therefore flashing should be successful.<\/p>\n\n<h3 id=\"initial-configuration\">Initial Configuration<\/h3>\n\n<p>For <a href=\"https:\/\/developer.nvidia.com\/embedded\/learn\/get-started-jetson-nano-devkit#setup\">Setup and First Boot<\/a> of the NVIDIA Jetson Nano DevKit you need to attach a computer display, mouse and keyboard. All these steps are well documented at the NVIDIA web site, just following the prior hyperlink.<\/p>\n\n<p>Then power up the board with the Micro-USB power supply and follow the tutorial. This procedure will take a few minutes and then you&rsquo;ll have a fully configured desktop system up and running which is based upon Ubuntu 18.04 LTS.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/Jetson-Nano-Board-Closeup.jpg\" alt=\"Jetson-Nano-Board-Closeup.jpg\" \/><\/p>\n\n<p>As I already said, the initial configuration of the Nano board has to be done interactively with the help of a computer monitor, mouse and keyboard. It&rsquo;s really straight forward and consists of the following steps and settings. I also did a short video of this initial setup, so it&rsquo;s maybe a little bit easier for you to follow.<\/p>\n\n<p><strong>Settings:<\/strong><\/p>\n\n<ol>\n<li><p>Accept NVIDIA End User License Agreements: YES<\/p><\/li>\n\n<li><p>Select system language: ENGLISH<\/p><\/li>\n\n<li><p>Select keyboard layout: ENGLISH (US)<\/p><\/li>\n\n<li><p>Select location\/timezone: BERLIN<\/p><\/li>\n\n<li><p>Set username: pirate<\/p><\/li>\n\n<li><p>Set computer name: jetson-nano<\/p><\/li>\n\n<li><p>Set password: hypriot<\/p><\/li>\n<\/ol>\n\n<p>[Here is the video link: NVIDIA-Jetson-Nano&ndash;Initial-Setup <strong>Coming soon!<\/strong>]<\/p>\n\n<p>At the end we login with the defined username &ldquo;pirate&rdquo; and get this nice Ubuntu desktop on our computer monitor. Yes, it&rsquo;s really a fully Linux desktop system running on a 64bit ARM Cortex A57 board with 4 GByte of memory!<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/jetson-desktop.jpg\" alt=\"jetson-desktop.jpg\" \/><\/p>\n\n<h3 id=\"running-docker\">Running Docker<\/h3>\n\n<p>TL;DR <strong>Docker is running out-of-the-box on the NVIDIA Jetson Nano board!<\/strong><\/p>\n\n<p>[Here is the video link: NVIDIA-Jetson-Nano&ndash;Running-Docker <strong>Coming soon!<\/strong>]<\/p>\n\n<p>As soon as the Jetson Nano board is configured and attached with an ethernet network cable, we can also discover it on the network with ping. Just use the computer name you defined. Here I used <code>jetson-nano<\/code>, or you have to add <code>.local<\/code>, this depends on your router setup. But just trying both it&rsquo;s easy to do.<\/p>\n\n<pre><code class=\"language-bash\">$ ping -c 3 jetson-nano\nPING jetson-nano.lan (192.168.7.158): 56 data bytes\n64 bytes from 192.168.7.158: icmp_seq=0 ttl=64 time=1.786 ms\n64 bytes from 192.168.7.158: icmp_seq=1 ttl=64 time=1.954 ms\n64 bytes from 192.168.7.158: icmp_seq=2 ttl=64 time=2.227 ms\n\n--- jetson-nano.lan ping statistics ---\n3 packets transmitted, 3 packets received, 0.0% packet loss\nround-trip min\/avg\/max\/stddev = 1.786\/1.989\/2.227\/0.182 ms\n<\/code><\/pre>\n\n<pre><code class=\"language-bash\">$ ping -c 3 jetson-nano.local\nPING jetson-nano.local (192.168.7.158): 56 data bytes\n64 bytes from 192.168.7.158: icmp_seq=0 ttl=64 time=1.338 ms\n64 bytes from 192.168.7.158: icmp_seq=1 ttl=64 time=2.198 ms\n64 bytes from 192.168.7.158: icmp_seq=2 ttl=64 time=1.964 ms\n\n--- jetson-nano.local ping statistics ---\n3 packets transmitted, 3 packets received, 0.0% packet loss\nround-trip min\/avg\/max\/stddev = 1.338\/1.833\/2.198\/0.363 ms\n<\/code><\/pre>\n\n<p>First, I&rsquo;m going to check the kernel version.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ uname -a\nLinux jetson-nano 4.9.140-tegra #1 SMP PREEMPT Wed Mar 13 00:32:22 PDT 2019 aarch64 aarch64 aarch64 GNU\/Linux\n<\/code><\/pre>\n\n<p>We do have a LTS 4.9 kernel available on the Jetson Nano, which is pretty OK for running Docker and Containers.<\/p>\n\n<p>Now, let&rsquo;s check if there is already a Docker Engine preinstalled.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo docker version\n[sudo] password for pirate:\nClient:\n Version:           18.06.1-ce\n API version:       1.38\n Go version:        go1.10.1\n Git commit:        e68fc7a\n Built:             Fri Jan 25 14:35:17 2019\n OS\/Arch:           linux\/arm64\n Experimental:      false\n\nServer:\n Engine:\n  Version:          18.06.1-ce\n  API version:      1.38 (minimum version 1.12)\n  Go version:       go1.10.1\n  Git commit:       e68fc7a\n  Built:            Thu Jan 24 10:49:48 2019\n  OS\/Arch:          linux\/arm64\n  Experimental:     false\n<\/code><\/pre>\n\n<p>And show what details we&rsquo;ll get from a <code>docker info<\/code> command:<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo docker info\nContainers: 2\n Running: 2\n Paused: 0\n Stopped: 0\nImages: 1\nServer Version: 18.06.1-ce\nStorage Driver: overlay2\n Backing Filesystem: extfs\n Supports d_type: true\n Native Overlay Diff: true\nLogging Driver: json-file\nCgroup Driver: cgroupfs\nPlugins:\n Volume: local\n Network: bridge host macvlan null overlay\n Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog\nSwarm: inactive\nRuntimes: runc\nDefault Runtime: runc\nInit Binary: docker-init\ncontainerd version:  (expected: 468a545b9edcd5932818eb9de8e72413e616e86e)\nrunc version: N\/A (expected: 69663f0bd4b60df09991c08812a60108003fa340)\ninit version: v0.18.0 (expected: fec3683b971d9c3ef73f284f176672c44b448662)\nSecurity Options:\n seccomp\n  Profile: default\nKernel Version: 4.9.140-tegra\nOperating System: Ubuntu 18.04.2 LTS\nOSType: linux\nArchitecture: aarch64\nCPUs: 4\nTotal Memory: 3.868GiB\nName: jetson-nano\nID: CR66:D4BV:6TQC:GI4I:CXLP:EQMK:NK2P:FUFM:OATD:5F6M:J657:LU5T\nDocker Root Dir: \/var\/lib\/docker\nDebug Mode (client): false\nDebug Mode (server): false\nRegistry: https:\/\/index.docker.io\/v1\/\nLabels:\nExperimental: false\nInsecure Registries:\n 127.0.0.0\/8\nLive Restore Enabled: false\n<\/code><\/pre>\n\n<p>Here is another screenshot directly from the Jetson Nano desktop with running the <code>docker version<\/code> command.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/jetson-desktop-docker.jpg\" alt=\"jetson-desktop-docker.jpg\" \/><\/p>\n\n<h3 id=\"starting-a-docker-container-for-arm\">Starting a Docker Container for ARM<\/h3>\n\n<p>Pull a first Docker Image which should run on ARM, here I&rsquo;m going to use a Docker Image I did created almost four years ago for the Raspberry Pi and showcased live on stage at DockerCon 2015 in San Francisco, see <a href=\"https:\/\/blog.hypriot.com\/post\/dockercon2015\/\">Hypriot-Demo and challenge at DockerCon 2015<\/a>. As this is an 32bit ARM image, let&rsquo;s see if it works out-of-the-box on this brandnew Jetson Nano board.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo docker pull hypriot\/rpi-busybox-httpd\nUsing default tag: latest\nlatest: Pulling from hypriot\/rpi-busybox-httpd\nc74a9c6a645f: Already exists\n6f1938f6d8ae: Already exists\ne1347d4747a6: Already exists\na3ed95caeb02: Already exists\nDigest: sha256:c00342f952d97628bf5dda457d3b409c37df687c859df82b9424f61264f54cd1\nStatus: Image is up to date for hypriot\/rpi-busybox-httpd:latest\n<\/code><\/pre>\n\n<p>The Docker Image is pulled directly from Docker Hub and we can have a closer look, it&rsquo;s pretty small in size with 2.16MByte only and it is already 3 years old.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo docker images\nREPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE\nhypriot\/rpi-busybox-httpd   latest              fbd9685c5ffc        3 years ago         2.16MB\n<\/code><\/pre>\n\n<p>Now, let&rsquo;s see how it runs on the Jetson Nano.<\/p>\n\n<pre><code class=\"language-bash\">pirate@jetson-nano:~$ sudo docker run -d -p 8000:80 hypriot\/rpi-busybox-httpd\ned6e7838c9af3f73e6f7129e7c38bf369bb9a33aa67a3b160b1f1c6c7251b2b2\n\npirate@jetson-nano:~$ sudo docker ps\nCONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                  NAMES\ned6e7838c9af        hypriot\/rpi-busybox-httpd   &quot;\/bin\/busybox httpd \u2026&quot;   8 seconds ago       Up 7 seconds        0.0.0.0:8000-&gt;80\/tcp   laughing_lalande\n<\/code><\/pre>\n\n<p>Opening up a web browser with the URL <code>http:\/\/192.168.7.158:8000<\/code> and we should see the web page served by our Docker container running on the NVIDIA Jetson Nano.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/docker-container-webpage.jpg\" alt=\"docker-container-webpage.jpg\" \/><\/p>\n\n<p>Here is another screenshot directly from the Jetson Nano desktop and a Chromium browser window which is showing our webpage served from the Docker container.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/nvidia-jetson-nano-intro\/jetson-desktop-container-webpage.jpg\" alt=\"jetson-desktop-container-webpage.jpg\" \/><\/p>\n\n<p><strong>SUCCESS:<\/strong> Docker Engine 18.06.1-CE is preinstalled on the brandnew NVIDIA Jetson Nano board and even old 32bit ARM Docker Images are running easily!<\/p>\n\n<h3 id=\"recap\">Recap<\/h3>\n\n<p>As you can see, there is already a fully running version of the Docker Engine preinstalled on the official SD card image for the NVIDIA Jetson Nano board. The Linux kernel 4.9.x has all the basic features enabled to run containers locally.<\/p>\n\n<p>So, Docker just works out-of-the-box and you are able to use Docker Images right away. Even 32bit Docker images are able to run on this board because it&rsquo;s based upon an ARM Cortex A57 CPU and this one is capable to run 64bit and 32bit ARM instructions.<\/p>\n\n<p>If you want to learn more general details about the NVIDIA Jetson Nano Developer Kit, please visit the JetsonHacks website at <a href=\"https:\/\/www.jetsonhacks.com\/2019\/03\/25\/nvidia-jetson-nano-developer-kit\/\">https:\/\/www.jetsonhacks.com\/2019\/03\/25\/nvidia-jetson-nano-developer-kit\/<\/a>.<\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"Releasing HypriotOS 1.10.0: Docker 18.06.3 CE from Raspberry Pi Zero to 3 B+","link":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-10\/","pubDate":"Sun, 24 Feb 2019 16:01:00 +0200","guid":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-10\/","description":"<p><strong>We&rsquo;re proud to announce our 1.10.0 release of HypriotOS - the fastest way to get Docker up and running on any Raspberry Pi.<\/strong><\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/release-1-10\/hypriotos-1.10.0-docker-18.06.3.png\" alt=\"Raspberry Pi Zero with Docker 18.06.3\" \/><\/p>\n\n<p><\/p>\n\n<h2 id=\"features-of-hypriotos\">Features of HypriotOS<\/h2>\n\n<p><strong>Latest Docker Engine 18.06.3-ce<\/strong> <\/br>\nYou can use the latest features of the freshly-baked Docker Engine 18.06.3-ce that is still warm. It includes the Swarm Mode, which allows high availability of services in a multi-node cluster within just a few simple commands.\nThis version contains a fix for the <a href=\"https:\/\/blog.docker.com\/2019\/02\/docker-security-update-cve-2018-5736-and-container-security-best-practices\/\">CVE-2019-5736<\/a> in runC.<\/p>\n\n<p><strong>Up to date with Raspbian Lite<\/strong> <\/br>\nYou can run HypriotOS with an up-to-date OS and Linux kernel which is in sync with the current Raspbian Lite running a Linux kernel 4.14.98.<\/p>\n\n<p><strong>Support for the complete Raspberry Pi family<\/strong> <\/br>\nYou can run HypriotOS on every model of the Raspberry Pi family - we&rsquo;re supporting Pi 1, 2, 3, the 3 B+, Zero and even the Compute Module.<\/p>\n\n<p><strong>Easy flashing and configuration<\/strong> <\/br>\nWe improved our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a>, which puts HypriotOS onto a SD card that is ready to boot from with a single command. With additional command line options you can customize HypriotOS during the flash operation to have the best out-of-the-box first-boot experience.\nHypriotOS includes <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/0.7.9\/\">cloud-init<\/a>, which makes the first boot of your Raspberry Pi customizable and you even are able connecting it to your Wi-Fi network during boot.\nAfter booting, you can find the Raspberry Pi at your network with a simple <code>ping black-pearl.local<\/code> \u2013 no more searching for IP addresses required thanks to the integrated Avahi service discovery.<\/p>\n\n<p><strong>Enhanced security out of the box<\/strong> <\/br>\nWe think that security should be shipped out-of-the-box. We make HypriotOS more secure without you even noticing it. For instance, there is no built-in &ldquo;root&rdquo; user. Also, the default user &ldquo;pirate&rdquo; (password &ldquo;hypriot&rdquo;) is can be customized or removed before the first boot. Just look at the file <code>\/boot\/user-data<\/code>. You can add your public SSH key, disable password logins and specify a different user account before you even boot your Raspberry Pi. WiFi can be customized and enabled to have Docker up and running through the air without attaching a keyboard and monitor.<\/p>\n\n<p><strong>Smaller than Raspbian Lite<\/strong> <\/br>\nEven though HypriotOS 1.10.0 is fully packed with the complete and latest Docker tool set, it now comes at a size smaller than the tiniest version of Raspbian (&ldquo;Raspbian Lite&rdquo;).<\/p>\n\n<p>Please see all details in the <a href=\"https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/tag\/v1.10.0\">release notes<\/a>.<\/p>\n\n<h2 id=\"quick-start\">Quick start<\/h2>\n\n<p><strong>Download our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a><\/strong><\/p>\n\n<pre><code>curl -O https:\/\/raw.githubusercontent.com\/hypriot\/flash\/2.2.0\/flash\nchmod +x flash\nsudo mv flash \/usr\/local\/bin\/flash\n<\/code><\/pre>\n\n<p><strong>Now run this command to flash HypriotOS 1.10.0<\/strong><\/p>\n\n<pre><code>flash https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.10.0\/hypriotos-rpi-v1.10.0.img.zip\n<\/code><\/pre>\n\n<p><strong>Afterwards, put the SD card into the Raspberry Pi and power it. That&rsquo;s all to get HypriotOS up and running!<\/strong><\/p>\n\n<h3 id=\"next-steps\">Next steps<\/h3>\n\n<p>If you want to connect to the Raspberry Pi, run<\/p>\n\n<pre><code>ssh pirate@black-pearl.local\n<\/code><\/pre>\n\n<p>with password &ldquo;hypriot&rdquo;.<\/p>\n\n<h3 id=\"flash-with-wi-fi-settings-for-pi-zero\">Flash with Wi-Fi settings for Pi Zero<\/h3>\n\n<p>If you want the Raspberry Pi Zero (or Pi 3) to connect directly to your Wi-Fi after boot, change the hostname of the Raspberry Pi and more, edit <code>\/boot\/user-data<\/code> of the SD card and have a look at <a href=\"https:\/\/blog.hypriot.com\/faq\/#wifi\">our FAQ<\/a>. Alternatively, checkout the parameters of the <a href=\"https:\/\/github.com\/hypriot\/flash\">Hypriot flash tool<\/a> that also allows you to define your own cloud-init user-data template file which will be copied onto the SD image for you:<\/p>\n\n<pre><code>flash -n myHOSTNAME -u wifi.yml https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.10.0\/hypriotos-rpi-v1.10.0.img.zip\n<\/code><\/pre>\n\n<h2 id=\"feedback-please\">Feedback, please<\/h2>\n\n<p>As always, use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<ul>\n<li>Stefan <a href=\"https:\/\/twitter.com\/stefscherer\">@stefscherer<\/a><\/li>\n<\/ul>"},{"title":"We now accept donations. Buy us a beer!","link":"https:\/\/blog.hypriot.com\/post\/donation-liberapay-support-contribute\/","pubDate":"Tue, 29 May 2018 16:30:00 +0200","guid":"https:\/\/blog.hypriot.com\/post\/donation-liberapay-support-contribute\/","description":"<p><strong>Many of our users have asked for it for quite a long time. Now, we finally took the time to setup a donation option.<\/strong><\/p>\n\n<p>Since we started Hypriot in 2015, we received great attention from a growing community around Docker on ARMed devices. We received numerous &ldquo;kudos&rdquo; and nice words. Even though we greatly appreciate this until today, words do not enable us to pay our infrastructure bills. Now you have the option to support us materialistically.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/donations\/liberapay-hypriot.png\" alt=\"Donations Screenshot Liberpay\" \/><\/p>\n\n<p><\/p>\n\n<h2 id=\"what-we-do-with-your-donation\">What we do with your donation<\/h2>\n\n<p>Open source software might seem to be &ldquo;free&rdquo; (as in free beer) at first sight - that&rsquo;s a fallacy. Its development, testing, and deployment require a huuuge amount of scarce time, ARMed hardware for testing, costs for service providers that help us throughout the software lifecycle, and costs for software licenses.<\/p>\n\n<p>Today, everything at Hypriot we do in our leisure time and pay for related bills with our private wallet. It would be great if we could at least cover our basic costs for infrastructure. Many parts of our infrastructure are free of charge for us because many service providers for e.g. build pipelines or Github support open source projects (our software is 100% open source). However, some providers do not offer free subscriptions for open source projects. We&rsquo;ll use your donation to cover the bills from them.<\/p>\n\n<p>If the infrastructure costs are completely funded, we&rsquo;ll use the surplus to enjoy a good beer during our hacking sessions :-)<\/p>\n\n<h2 id=\"why-liberapay\">Why Liberapay?<\/h2>\n\n<p>Liberapay is a relatively new and trendy donation platform for free software projects. The unique thing about this platform: <strong>it pays its bills for development by receiving donations on its own platform<\/strong>! As transaction fees for payments, this platform only invoices for the fees they are charged by their financial provider. In addition, Liberapay is fully open source and based within the European Union. Using software stemming from within the EU got more important with the advent of the new data protection regulation.<\/p>\n\n<p>Thus Liberapay offers several advantages over other popular platforms like Patreon (closed source, high transaction fees, not EU based).<\/p>\n\n<h2 id=\"buy-us-at-least-a-little-beer\">Buy us at least a little beer!<\/h2>\n\n<p>If many of our community only provide little portions, the sum can be high. So please click on the following button, create an account and charge the account with some euros or dollars. Finally, specify a little amount you&rsquo;d like to donate to us.<\/p>\n\n<p><a href=\"https:\/\/liberapay.com\/Hypriot\/donate\"><img alt=\"Donate using Liberapay\" src=\"https:\/\/liberapay.com\/assets\/widgets\/donate.svg\"><\/a><\/p>\n\n<p>Thank you very much in advance!<\/p>\n\n<p>@MathiasRenner at <a href=\"https:\/\/twitter.com\/MathiasRenner\">Twitter<\/a> or <a href=\"https:\/\/mastodon.social\/@mathiasrenner\">Mastodon<\/a><\/p>"},{"title":"Releasing HypriotOS 1.8.0: Raspberry Pi 3 B+, Stretch and more","link":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-8\/","pubDate":"Tue, 27 Mar 2018 16:30:00 +0200","guid":"https:\/\/blog.hypriot.com\/post\/releasing-HypriotOS-1-8\/","description":"<p><strong>We&rsquo;re proud to announce our 1.8.0 release of HypriotOS - the fastest way to get Docker up and running on any Raspberry Pi including the new Pi 3 B+.<\/strong><\/p>\n\n<p>At this years Pi day the Raspberry Pi foundation <a href=\"https:\/\/www.raspberrypi.org\/blog\/raspberry-pi-3-model-bplus-sale-now-35\/\">has announced a new model<\/a> - the Raspberry Pi 3 B+ with improved networking and a faster CPU. A good reason for us to update our HypriotOS to support this new device. And while we were at it we also updated the OS to Raspbian Stretch and Linux Kernel version 4.9.80 - and of course the latest Docker 18.03.0-ce release.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/release-1-8\/pi3-b-plus.jpg\" alt=\"Raspberry Pi 3 B+\" \/><\/p>\n\n<p><\/p>\n\n<h2 id=\"features-of-hypriotos\">Features of HypriotOS<\/h2>\n\n<p><strong>Latest Docker Engine 18.03.0-ce with Swarm Mode<\/strong> <\/br>\nYou can use the latest features of the freshly-baked Engine Docker 18.03.0-ce that is still warm. It includes the Swarm Mode, which allows high availability of services in a multi-node cluster within just a few simple commands.\n<a href=\"https:\/\/blog.docker.com\/2016\/07\/swarm-mode-on-a-raspberry-pi-cluster\/\">See this short video how it works.<\/a><\/p>\n\n<p><strong>Up to date with Raspbian Lite<\/strong> <\/br>\nYou can run HypriotOS with an up-to-date OS and Linux kernel which is in sync with Raspbian Lite. We have updated to Raspbian Stretch and also prepared a new Docker optimized kernel 4.9.80.<\/p>\n\n<p><strong>Support for the complete Raspberry Pi family<\/strong> <\/br>\nYou can run HypriotOS on every model of the Raspberry Pi family - we&rsquo;re supporting Pi 1, 2, 3, the 3 B+, Zero and even the Compute Module.<\/p>\n\n<p><strong>Easy flashing and configuration<\/strong> <\/br>\nWe improved our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a>, which puts HypriotOS onto a SD card that is ready to boot from with a single command. With additional command line options you can customize HypriotOS during the flash operation to have the best out-of-the-box first-boot experience.\nHypriotOS includes <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/0.7.9\/\">cloud-init<\/a>, which makes the first boot of your Raspberry Pi customizable and you even are able connecting it to your Wi-Fi network during boot.\nAfter booting, you can find the Raspberry Pi at your network with a simple <code>ping black-pearl.local<\/code> \u2013 no more searching for IP addresses required thanks to the integrated Avahi service discovery.<\/p>\n\n<p><strong>Enhanced security out of the box<\/strong> <\/br>\nWe think that security should be shipped out-of-the-box. We make HypriotOS more secure without you even noticing it. For instance, there is no built-in &ldquo;root&rdquo; user. Also, the default user &ldquo;pirate&rdquo; (password &ldquo;hypriot&rdquo;) is can be customized or removed before the first boot. Just look at the file <code>\/boot\/user-data<\/code>. You can add your public SSH key, disable password logins and specify a different user account before you even boot your Raspberry Pi. WiFi can be customized and enabled to have Docker up and running through the air without attaching a keyboard and monitor.<\/p>\n\n<p><strong>Smaller than Raspbian Lite<\/strong> <\/br>\nEven though HypriotOS 1.8.0 is fully packed with the complete and latest Docker tool set, it now comes at a size smaller than the tiniest version of Raspbian (&ldquo;Raspbian Lite&rdquo;).<\/p>\n\n<p>Please see all details in the <a href=\"https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/tag\/v1.8.0\">release notes<\/a>.<\/p>\n\n<h2 id=\"quick-start\">Quick start<\/h2>\n\n<p><strong>Download our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a><\/strong><\/p>\n\n<pre><code>curl -O https:\/\/raw.githubusercontent.com\/hypriot\/flash\/2.0.0\/flash\nchmod +x flash\nsudo mv flash \/usr\/local\/bin\/flash\n<\/code><\/pre>\n\n<p><strong>Now run this command to flash HypriotOS 1.8.0<\/strong><\/p>\n\n<pre><code>flash https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.8.0\/hypriotos-rpi-v1.8.0.img.zip\n<\/code><\/pre>\n\n<p><strong>Afterwards, put the SD card into the Raspberry Pi and power it. That&rsquo;s all to get HypriotOS up and running!<\/strong><\/p>\n\n<h3 id=\"next-steps\">Next steps<\/h3>\n\n<p>If you want to connect to the Raspberry Pi, run<\/p>\n\n<pre><code>ssh pirate@black-pearl.local\n<\/code><\/pre>\n\n<p>with password &ldquo;hypriot&rdquo;.<\/p>\n\n<p>If you want the Raspberry Pi to connect directly to your Wi-Fi after boot, change the hostname of the Raspberry Pi and more, edit <code>\/boot\/user-data<\/code> of the SD card and have a look at <a href=\"https:\/\/blog.hypriot.com\/faq\/#wifi\">our FAQ<\/a>. Alternatively, checkout the parameters of the <a href=\"https:\/\/github.com\/hypriot\/flash\">Hypriot flash tool<\/a> that also allows you to define your own cloud-init user-data template file which will be copied onto the SD image for you:<\/p>\n\n<pre><code>flash -n myHOSTNAME -u wifi.yml https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.8.0\/hypriotos-rpi-v1.8.0.img.zip\n<\/code><\/pre>\n\n<p>We will improve the flash tool to bring back support of the <code>-s<\/code> and <code>-p<\/code> options so you can add WiFi support without creating your own user-data template file.<\/p>\n\n<h2 id=\"hands-free-projects\">Hands-free projects<\/h2>\n\n<p>We have put together a small sample YAML that shows what you can do with HypriotOS, cloud-init and Docker. You can prepare a wireless Raspberry Pi with an SD card image that creates a Docker Swarm and starts a service to drive some LED&rsquo;s automatically. You don&rsquo;t have to login to this device. It will also start the service again after a power outage.<\/p>\n\n<p>The sample <a href=\"https:\/\/github.com\/hypriot\/flash\/blob\/master\/sample\/rainbow.yml\">rainbow.yml<\/a> shows how to setup a user with SSH public key authentication, activate WiFi and run a rainbow service.\nYou only have to customize the YAML file at<\/p>\n\n<ul>\n<li>line 16: insert your SSH public key for authentication<\/li>\n<li>line 32 and 33: insert your WiFi settings<\/li>\n<\/ul>\n\n<p>Then flash an SD image with this command<\/p>\n\n<pre><code>flash -u rainbow.yml https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.8.0\/hypriotos-rpi-v1.8.0.img.zip\n<\/code><\/pre>\n\n<p>And after booting a Raspberry Pi Zero or Pi 3\/Pi 3 B+ you will see some blinking LED&rsquo;s once everything has been set up after the first boot.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/release-1-8\/rainbow.jpg\" alt=\"Raspberry Pi 3 B+ with rainbow service\" \/><\/p>\n\n<h2 id=\"feedback-please\">Feedback, please<\/h2>\n\n<p>As always, use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<ul>\n<li>Stefan <a href=\"https:\/\/twitter.com\/stefscherer\">@stefscherer<\/a><\/li>\n<\/ul>"},{"title":"Bootstrapping a Cloud with Cloud-Init and HypriotOS","link":"https:\/\/blog.hypriot.com\/post\/cloud-init-cloud-on-hypriot-x64\/","pubDate":"Sun, 29 Oct 2017 00:14:00 -0700","guid":"https:\/\/blog.hypriot.com\/post\/cloud-init-cloud-on-hypriot-x64\/","description":"<blockquote>\n<p>Things may come to those who wait, but only the things left by those who hustle.<\/p>\n<\/blockquote>\n\n<p>Over the last year, a lot has happened in the Raspberry Pi and Docker communities, there are Docker Captains helping lead the charge, one of those, <a href=\"https:\/\/twitter.com\/Quintus23M\">Dieter Reuter<\/a> really has been pushing the cause for ARM64 support with both Raspberry Pi 3 and LinuxKit. He isn&rsquo;t a single man army, the rest of the <a href=\"http:\/\/blog.hypriot.com\/crew\/\">Docker Pirates<\/a> over at <a href=\"http:\/\/blog.hypriot.com\/\">Hypriot<\/a> have been doing some awesome things as well!<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/cloud-init\/brown-airplanes.jpg\" alt=\"airplanes\" \/>\n<div style=\"text-align:right; font-size: smaller\">Image courtesy of <a href=\"https:\/\/www.flickr.com\/photos\/horiavarlan\/5019447085\/in\/photolist-8DxYK8-6RFbEf-6RFfrw-6RLCGd-6RAH6n-6RF9gf-6RATnx-6RGCKM-6RB7L2-6REXqA-6T4VEQ-6RBeKg-brFbp6-6RAZU8-6RGwNk-6RAiLD-6RBgp6-6RLAvm-6RBbwM-6RAE5e-6RLJVj-6RLFdN-6RBsmr-6RFxxw-6RLJrY-6RFvGJ-6RFtZS-6REvrf-6RENUY-6RFwCC-6RGBEn-6RGz9n-6RFpb3-6RFzo1-if9tn-9NF66y-84UZy9-6RFew9-6RFq2m-6RLHWJ-6T4Wd9-9NChKc-6RAZ5V-9NCiK8-6T5Lbf-6RAUfp-6RBhb6-9NF3UW-9NF979-9NFaFW\">Horia Varlan<\/a><\/div><\/p>\n\n<p>Building on the backs of these outstanding community members, I was finally able to spin up a Raspberry Pi, exactly like I do in the &ldquo;real world&rdquo;, just turn it on, let it self-configure, then software just runs.<\/p>\n\n<p><\/p>\n\n<p>A lot of this is really about having <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/latest\/index.html\">cloud-init <\/a> available in the HypriotOS 64bit images thanks to another Pirate <a href=\"https:\/\/twitter.com\/stefscherer\">Stefan Scherer<\/a>. In the &ldquo;cloud world&rdquo;, you spin up instances, give it some user-data, then when it boots, the machines self-configures based on the instance meta-data and the user-data provided.<\/p>\n\n<h2 id=\"before\">Before<\/h2>\n\n<p>Before we talk about the &ldquo;new&rdquo; pirate way, let&rsquo;t talk about the &ldquo;old&rdquo; non-pirate way.<\/p>\n\n<ul>\n<li>Download Raspbian Lite (the easiest for nubbies like me)<\/li>\n<li>Flash said image to an SD Card<\/li>\n<li>Optionally re-mount SD Card and monkey some stuff around<\/li>\n<li>Put the card in your RPi<\/li>\n<li>Power up the RPi<\/li>\n<li>If you don&rsquo;t have avahi\/bonjour, go find the IP in your router<\/li>\n<li>SSH into the server<\/li>\n<li>Update Packages<\/li>\n<li>Run <code>raspi-config<\/code> and modify some junk<\/li>\n<li>Reboot<\/li>\n<li>Install Docker<\/li>\n<li>Initialize Docker Swarm<\/li>\n<li>Configure <a href=\"http:\/\/portainer.io\">Portainer<\/a> service (if not, are you broken?)<\/li>\n<li>&ldquo;try&rdquo; and find some images you can run on arm<\/li>\n<li>Cheer at your glory based nginx hello world page!<\/li>\n<li>Figure out how to use automation tools like Ansible to make your life easier when you need a cluster<\/li>\n<li>Bang head on desk learning so much&hellip;<\/li>\n<li>Do victory dances when you created a bunch of automation around setting up servers<\/li>\n<li>Go find out what the community is doing<\/li>\n<\/ul>\n\n<p>It is at that point, when the community really is an awesome place. Given the latest <a href=\"https:\/\/github.com\/DieterReuter\/image-builder-rpi64\/releases\/tag\/v20171013-172949\">HypriotOS-rpi64<\/a>, the <a href=\"https:\/\/github.com\/hypriot\/flash\">flash<\/a> utility (also from Hypriot), Docker images now being multi-architecture supported through the <a href=\"https:\/\/github.com\/docker\/distribution\/blob\/master\/docs\/spec\/manifest-v2-2.md\">manifest v2 API<\/a> and Docker pushing to get all the <a href=\"https:\/\/github.com\/docker-library\/official-images#architectures-other-than-amd64\">supported images covering a lot of architectures<\/a>, life begins to get much <strong>much<\/strong> easier.<\/p>\n\n<hr \/>\n\n<p><strong>DISCLAIMER<\/strong>: Before we continue, we need to talk about ARM 64 naming issues.<\/p>\n\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/ARM_architecture#64.2F32-bit_architecture\">ARM is complicated<\/a> when it comes to the latest version of the architecture (v8). A lot of the distros still haven&rsquo;t settled on what to call it, and you will find a lot of differences: <code>AArch64<\/code> and <code>ARM64v8<\/code> being the two most popular. When in doubt, do what <a href=\"https:\/\/github.com\/docker-library\/official-images#architectures-other-than-amd64\">Docker does<\/a>.<\/p>\n\n<hr \/>\n\n<h2 id=\"after\">After<\/h2>\n\n<p>Now that we got that out of the way, let&rsquo;s get into some code. Given the list of <code>arm64v8<\/code> images in the <a href=\"https:\/\/hub.docker.com\/u\/arm64v8\/\">Docker registry<\/a> I wanted to find something that would be interesting. Luckily, I was able to find <a href=\"https:\/\/nextcloud.com\/\">NextCloud<\/a>. I have no idea if this software is worth keeping around, but it was something I could play with, try to break, reboot to see if it lives, and have something to play with when I succeed!<\/p>\n\n<h3 id=\"user-data\">User Data<\/h3>\n\n<p>The first thing we need to do, is create our <code>user-data<\/code> file. This will be placed inside of our SD card when we flash it and instruct <code>cloud-init<\/code> what to do when the system boots for the first time.<\/p>\n\n<p>It should be noted, that at this time, the cloud-init version available for Debian distribution is <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/0.7.9\/\">0.7.9<\/a>, not the 17.1 you would have thought (as latest). Currently only Ubuntu is the only distribution I know of that is using 17.1.<\/p>\n\n<p>The next important fact to know is that the Data Source we are utilizing is the <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/0.7.9\/topics\/datasources\/nocloud.html\">NoCloud<\/a> data source. This basically means (in the 0.7.9 and below version) that the <code>user-data<\/code> and <code>meta-data<\/code> are on the local file system, not pulled from a remote resource or other means.<\/p>\n\n<p>The <code>user-data<\/code> file is simply a YAML file, you can get a lot more complicated, but for the sake of simplicity, let&rsquo;s just call it a YAML file.<\/p>\n\n<p>The <code>user-data<\/code> for this project:<\/p>\n\n<pre><code class=\"language-yaml\">#cloud-config\n# vim: syntax=yaml\n#\n\nhostname: nextcloud-pi64\nmanage_etc_hosts: true\n\nresize_rootfs: true\ngrowpart:\n    mode: auto\n    devices: [&quot;\/&quot;]\n    ignore_growroot_disabled: false\n\nusers:\n  - name: pirate\n    gecos: &quot;Hypriot Pirate&quot;\n    sudo: ALL=(ALL) NOPASSWD:ALL\n    shell: \/bin\/bash\n    groups: users,docker,video\n    plain_text_passwd: hypriot\n    lock_passwd: false\n    ssh_pwauth: true\n    chpasswd: { expire: false }\n\npackage_update: true\npackage_upgrade: true\npackage_reboot_if_required: true\npackages:\n  - ntp\n\nlocale: &quot;en_US.UTF-8&quot;\ntimezone: &quot;America\/Los_Angeles&quot;\n\nwrite_files:\n    - path: &quot;\/etc\/docker\/daemon.json&quot;\n      owner: &quot;root:root&quot;\n      content: |\n        {\n          &quot;labels&quot;: [ &quot;os=linux&quot;, &quot;arch=arm64&quot; ],\n          &quot;experimental&quot;: true\n        }\n\nruncmd:\n  - [ systemctl, restart, avahi-daemon ]\n  - [ systemctl, restart, docker ]\n  - [docker, swarm, init ]\n  - [\n      docker, service, create,\n      &quot;--detach=false&quot;,\n      &quot;--name&quot;, &quot;portainer&quot;,\n      &quot;--publish&quot;, &quot;9000:9000&quot;,\n      &quot;--mount&quot;, &quot;type=volume,src=portainer_data,dst=\/data&quot;,\n      &quot;--mount&quot;, &quot;type=bind,src=\/\/var\/run\/docker.sock,dst=\/var\/run\/docker.sock&quot;,\n      &quot;portainer\/portainer&quot;, &quot;-H&quot;, &quot;unix:\/\/\/var\/run\/docker.sock&quot;, &quot;--no-auth&quot;\n    ]\n  - [mkdir, &quot;-p&quot;, &quot;\/var\/cloud\/data&quot; ]\n  - [setfacl, &quot;-m&quot;, &quot;u:www-data:rwx&quot;, &quot;\/var\/cloud\/data&quot; ]\n  - [\n      docker, service, create,\n      &quot;--detach=false&quot;,\n      &quot;--name&quot;, &quot;nextcloud&quot;,\n      &quot;--publish&quot;, &quot;80:80&quot;,\n      &quot;--mount&quot;, &quot;type=volume,src=nextcloud,dst=\/var\/www\/html&quot;,\n      &quot;--mount&quot;, &quot;type=bind,src=\/\/var\/cloud\/data,dst=\/var\/www\/html\/data&quot;,\n      &quot;--env&quot;, &quot;SQLITE_DATABASE=nextcloud&quot;,\n      &quot;--env&quot;, &quot;NEXTCLOUD_ADMIN_USER=pirate&quot;,\n      &quot;--env&quot;, &quot;NEXTCLOUD_ADMIN_PASSWORD=hypriot&quot;,\n      &quot;nextcloud:latest&quot;\n    ]\n<\/code><\/pre>\n\n<p>It is extremely important that before you flash this to a disk and attempt to boot, that you run this file through a YAML linter. There are some good ones <a href=\"http:\/\/www.yamllint.com\/\">available online<\/a>, but you should never use an online linter if your <code>user-data<\/code> contains real passwords or SSH keys, you can&rsquo;t trust if they store the YAML or not on the server side.<\/p>\n\n<p>Now, let&rsquo;s break this down into somewhat readable chunks&hellip;<\/p>\n\n<h4 id=\"configure-host-name\">Configure Host Name<\/h4>\n\n<p>This will simply configure your hostname of the machine as well as make sure that <code>\/etc\/hosts<\/code> is appropriately updated. You can specify an <code>fqdn<\/code> here, as you will see below. However, the hostname in this file isn&rsquo;t super important, as we will use the <code>--hostname<\/code> option with the flash utility later to change this when we write the image.<\/p>\n\n<pre><code class=\"language-yaml\">hostname: nextcloud-pi64\nmanage_etc_hosts: true\n<\/code><\/pre>\n\n<h4 id=\"resize-file-system\">Resize File System<\/h4>\n\n<p>This is something that had plagued RPi users for years, finally at some point the foundation images included this on first boot, but the wonderful thing about <code>cloud-init<\/code> is it already had this built in. You &ldquo;really&rdquo; don&rsquo;t need these settings in the file, I put these here to show that this is just built in functionality for <code>cloud-init<\/code>.<\/p>\n\n<pre><code class=\"language-yaml\">resize_rootfs: true\ngrowpart:\n    mode: auto\n    devices: [&quot;\/&quot;]\n    ignore_growroot_disabled: false\n<\/code><\/pre>\n\n<h4 id=\"create-users\">Create Users<\/h4>\n\n<p>Creating users is pretty simple, plop in an array element, give it some information, and your off to the races. The below is actually what is in the default <code>cloud-init<\/code> for the HypriotOS image if you don&rsquo;t overwrite it.  You can actually do a lot more with this, including adding SSH keys. Check out the <a href=\"http:\/\/cloudinit.readthedocs.io\/en\/0.7.9\/topics\/modules.html#users-and-groups\">users documentation<\/a><\/p>\n\n<pre><code class=\"language-yaml\">users:\n  - name: pirate\n    gecos: &quot;Hypriot Pirate&quot;\n    sudo: ALL=(ALL) NOPASSWD:ALL\n    shell: \/bin\/bash\n    groups: users,docker,video\n    plain_text_passwd: hypriot\n    lock_passwd: false\n    ssh_pwauth: true\n    chpasswd: { expire: false }\n<\/code><\/pre>\n\n<h4 id=\"update-and-add-packages\">Update and Add Packages<\/h4>\n\n<p>Because we live in a world of ever updating software, you really don&rsquo;t know what is out of date in your image. This ensures that on first boot, all packages are updated. Additionally, you can install additional packages you might need. In this case I am installing NTP (there is a better way to do this, but there is an outstanding issue with it atm). Additionally, we instruct <code>cloud-init<\/code> to reboot the server if the updates require one.<\/p>\n\n<pre><code class=\"language-yaml\">package_update: true\npackage_upgrade: true\npackage_reboot_if_required: true\npackages:\n  - ntp\n<\/code><\/pre>\n\n<p>NTP missing from the HypriotOS image is something I will be bringing up with the team to get fixed in the future!<\/p>\n\n<h4 id=\"set-localized-settings\">Set Localized Settings<\/h4>\n\n<p>These will setup your server in your correct part of the world. The Raspbian comes with UK as default, at least HypriotOS came with a sane UTC default, but sometimes you just want your local time. This is definitely one of those time savers where most people used <code>raspi-config<\/code> to set these (horrible horrible menus).<\/p>\n\n<pre><code class=\"language-yaml\">locale: &quot;en_US.UTF-8&quot;\ntimezone: &quot;America\/Los_Angeles&quot;\n<\/code><\/pre>\n\n<p>This is something I feel like you should also be able to configure in the flash utility, and will be bringing it up as well with the Pirates.<\/p>\n\n<h4 id=\"write-some-arbitrary-files\">Write some arbitrary files<\/h4>\n\n<p>The power to create files on boot&hellip; This simple file output below is configuring docker labels as well as doing the (currently required) experimental features flag. This will require a Docker daemon restart, but we will cover that soon enough!<\/p>\n\n<pre><code class=\"language-yaml\">write_files:\n    - path: &quot;\/etc\/docker\/daemon.json&quot;\n      owner: &quot;root:root&quot;\n      content: |\n        {\n          &quot;labels&quot;: [ &quot;os=linux&quot;, &quot;arch=arm64&quot; ],\n          &quot;experimental&quot;: true\n        }\n<\/code><\/pre>\n\n<h4 id=\"run-a-bunch-of-commands\">Run a bunch of commands<\/h4>\n\n<p>There are actually a few ways to run commands in <code>cloud-init<\/code>, this is the most used, because it is the last thing that is done during initialization.<\/p>\n\n<p>In this, we are essentially restarting Docker and avahi to pickup our configuration changes, initializing Docker Swarm, running good ol Portainer (so we can see what is going on without SSH).<\/p>\n\n<p>The last steps are all specific to NextCloud. I create a new directory to store the files and SQL Lite database, set permissions for the <code>www-data<\/code> user since NextCloud is using Apache, and running as a known user, we need to give that specific user permissions, and finally bootstrap NextCloud to self-configure and initialize.<\/p>\n\n<pre><code class=\"language-yaml\">runcmd:\n  # Pickup the hostname changes\n  - [ systemctl, restart, avahi-daemon ]\n\n  # Pickup the daemon.json changes\n  - [ systemctl, restart, docker ]\n\n  # Init a swarm, because why not\n  - [docker, swarm, init ]\n\n  # Run portainer, so we can see our logs and control stuff from a UI\n  - [\n      docker, service, create,\n      &quot;--detach=false&quot;,\n      &quot;--name&quot;, &quot;portainer&quot;,\n      &quot;--publish&quot;, &quot;9000:9000&quot;,\n      &quot;--mount&quot;, &quot;type=volume,src=portainer_data,dst=\/data&quot;,\n      &quot;--mount&quot;, &quot;type=bind,src=\/\/var\/run\/docker.sock,dst=\/var\/run\/docker.sock&quot;,\n      &quot;portainer\/portainer&quot;, &quot;-H&quot;, &quot;unix:\/\/\/var\/run\/docker.sock&quot;, &quot;--no-auth&quot;\n    ]\n\n  # Create a specific directory to store all the data,\n  # this way you could mount an external drive later (coming soon!)\n  - [mkdir, &quot;-p&quot;, &quot;\/var\/cloud\/data&quot; ]\n\n  # This gives the nextcloud permissions to write to this directory\n  # since it runs as www-data\n  - [setfacl, &quot;-m&quot;, &quot;u:www-data:rwx&quot;, &quot;\/var\/cloud\/data&quot; ]\n\n  # Create the nextcloud instance configuring it on startup\n  # - you should change the user\/password below to something less obvious\n  # or use the config UI\n  - [\n      docker, service, create,\n      &quot;--detach=false&quot;,\n      &quot;--name&quot;, &quot;nextcloud&quot;,\n      &quot;--publish&quot;, &quot;80:80&quot;,\n      &quot;--mount&quot;, &quot;type=volume,src=nextcloud,dst=\/var\/www\/html&quot;,\n      &quot;--mount&quot;, &quot;type=bind,src=\/\/var\/cloud\/data,dst=\/var\/www\/html\/data&quot;,\n      &quot;--env&quot;, &quot;SQLITE_DATABASE=nextcloud&quot;,\n      &quot;--env&quot;, &quot;NEXTCLOUD_ADMIN_USER=pirate&quot;,\n      &quot;--env&quot;, &quot;NEXTCLOUD_ADMIN_PASSWORD=hypriot&quot;,\n      &quot;nextcloud:latest&quot;\n    ]\n<\/code><\/pre>\n\n<p>There are some important bits here, the <code>SQLITE_DATABASE=&lt;name&gt;<\/code> is actually what triggers the &ldquo;auto-configure&rdquo; option, without that, the <code>NEXTCLOUD_*<\/code> variables are ignored, despite what the documentation says.<\/p>\n\n<h3 id=\"flash\">FLASH<\/h3>\n\n<p>If you don&rsquo;t know about this utility yet, please head over to the <a href=\"https:\/\/github.com\/hypriot\/flash\">github repo<\/a> and check it out.<\/p>\n\n<p>Good, your back, now lets see my command line I use to run this on my Ubuntu 16.x Server.<\/p>\n\n<p>The following statements will install the prerequisites for flash, download the script, download this blog posts <code>user-data.yml<\/code> file, then attempt to flash the image to an SD card.<\/p>\n\n<p>I highly recommend using a 32 or 64 GB flash card for this project, because if you decide to keep this cloud around, you might want to store one or two things in it.<\/p>\n\n<p>When prompted, insert your SD flash card into an available USB slot, then choose the right one, and verify the right one. You really don&rsquo;t want DD to mount\/flash\/unmount your main drive.<\/p>\n\n<pre><code class=\"language-bash\">sudo apt-get install pv unzip hdparm\ncurl -O https:\/\/raw.githubusercontent.com\/hypriot\/flash\/master\/$(uname -s)\/flash\nchmod +x flash\nsudo mv flash \/usr\/local\/bin\/flash\n\n# Just make sure the existing is gone\nrm .\/user-data.yml\n\n# Download this yaml from this repo\ncurl -O https:\/\/gist.githubusercontent.com\/RenEvo\/6a9e244b670df334c42578b8fe95400b\/raw\/user-data.yml\n\n\/\/ flash it\nflash \\\n  --hostname mycloud.home.renevo.com \\\n  --userdata .\/user-data.yml \\\n  https:\/\/github.com\/DieterReuter\/image-builder-rpi64\/releases\/download\/v20171013-172949\/hypriotos-rpi64-v20171013-172949.img.zip\n<\/code><\/pre>\n\n<p>When finished, pull out that sweet SD card, and let&rsquo;s get ready to plug in.<\/p>\n\n<h3 id=\"boot-and-forget\">Boot and Forget<\/h3>\n\n<p>For this, I simply put the SD card into a random RPi3 I had laying around, plugged in a network cable to my switch and the RPi, and then applied power to it.<\/p>\n\n<p>This is really where the waiting game begins, the RPi is going to boot up, self-name, self-update, possible reboot, pull down some Docker images, bootstrap a Docker Swarm, run Portainer, then finally&hellip; start a personal cloud.<\/p>\n\n<p>At the time of writing this, you are still going to have to go fish out your IP from DNS unless you are on Mac or Linux with avahi, at that case, you can just navigate to <code>http:\/\/&lt;hostname&gt;.local<\/code> or <code>http:\/\/&lt;hostname&gt;<\/code> if you used an fqdn like I did. There are actually ways to get the RPi to phone home when it is finished bootstrapping, but I am going to save that for another post!<\/p>\n\n<p>So, after you get some coffee, you can try navigating to your RPi on port 9000 with your browser, that should get you into the Portainer instance without any type of authentication (don&rsquo;t do this in a real environment please, go read the docs on securing it).<\/p>\n\n<p>After you go get a snack and take a short walk, you can try navigating to your RPi on port 80 with your browser, once you get prompted, login with user: <code>pirate<\/code> and password: <code>hypriot<\/code> to get access to your cloud. Click close on the annoying modal about downloading sync programs, and there you have it&hellip; Your own personal cloud, bootstrapped from a simple YAML file, without you ever having to SSH into your PI.<\/p>\n\n<p>Here is the fun part, you can reflash that anytime you want to recreate the exact same baseline SD card image.<\/p>\n\n<h2 id=\"summary\">Summary<\/h2>\n\n<p>This was a lot of fun for me, and without having to actually figure out some nitty gritty details, not over documenting things, and getting prepared to write this post, it realistically took me about 10 minutes to go from downloading the OS image to running NextCloud on my RPi. And that is all due to the hard work of the community, and especially the Docker Pirates at Hypriot, and to them, I thank you.<\/p>\n\n<p>I plan to continue playing with this, potentially updating the server to use an external USB drive for data and auto-mounting it on boot, possible setup a GlusterFS and run them in a small 2 or 3 node cluster, and call it my PiCloud.<\/p>\n\n<p>Who knows, it&rsquo;s all about having fun and experimenting right?<\/p>\n\n<p>All the samples can be <a href=\"https:\/\/gist.github.com\/RenEvo\/6a9e244b670df334c42578b8fe95400b\">found on on GitHub<\/a>.<\/p>\n\n<h2 id=\"about-me\">About Me<\/h2>\n\n<blockquote>\n<p>Who is this guy, and why is he posting on this blog?<\/p>\n<\/blockquote>\n\n<p>My name is <a href=\"https:\/\/twitter.com\/TribalTom\">Tom Anderson<\/a>, I am a Senior II Cloud Software Engineer by day at a killer gaming company, and by night I am a father, musician, tinkerer, and still&hellip; a hobbiest programmer of all the things. Dieter Reuter was nice enough to ask me to guest post this topic, and I just felt it had to be done! The Pirates have given so much to the community, I felt I needed to give a little something back.<\/p>\n\n<p>Additionally, I build and talk about some things I think are cool on my own blog <a href=\"http:\/\/tomanderson.me\">tomanderson.me<\/a>, feel free to stop by and say hi!<\/p>\n\n<p>Finally, because legaleeze and stuff&hellip; All opinions here are my own, and do not reflect the opinions of Blizzard Entertainment.<\/p>"},{"title":"DockerCon 2017 Demo: Monitoring Docker Swarm with LED's","link":"https:\/\/blog.hypriot.com\/post\/dockerconaustin2017\/","pubDate":"Thu, 20 Apr 2017 14:30:34 -0600","guid":"https:\/\/blog.hypriot.com\/post\/dockerconaustin2017\/","description":"<p>At DockerCon 2017 in Austin I gave a presentation of a Raspberry Pi cluster mixed with some UP boards. The audience really liked the visual effects of the Docker Swarm scaling a service up and down. So I show you some background details what you need to run that demo on your Raspberry Pi cluster as well.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/dockercon2017\/stage2.jpg\" alt=\"PiCloud at DockerCon Austin\" \/><\/p>\n\n<p><\/p>\n\n<p>All the effort played off to build that cluster, to find out how to drive LED&rsquo;s in swarm mode, to put it into my bag and go through customs on my flight from Germany to Austin, Texas. It really was fun to show this the audience and everybody liked it.<\/p>\n\n<p>To enable you to replay the demo with some Pimoroni Blinkt! LED&rsquo;s and Raspberry Pi - regardless if you only have Pi Zeros I want to show you the Docker images I used and the commands to show the scaling demo.<\/p>\n\n<p>The Docker image <a href=\"https:\/\/hub.docker.com\/r\/stefanscherer\/monitor\/\">stefanscherer\/monitor<\/a> is available on the Docker Hub. It is a multi-architecture image that can be used on Linux with Intel or ARM CPU&rsquo;s.<\/p>\n\n<p>So just create a Docker swarm with the usual commands <code>docker swarm init<\/code> and then join some other workers with the swarm token shown in your terminal.<\/p>\n\n<h2 id=\"start-the-led-monitor\">Start the LED monitor<\/h2>\n\n<p>First we have to start the LED monitor as a service so that it is running on each node of the Docker swarm. The option <code>--mode global<\/code> will do this and start one instance on each node. We have to bind mount both the Docker socket and a part of the file system into the container so it can access the <code>\/sys\/class\/fs<\/code> file system.<\/p>\n\n<pre><code class=\"language-bash\">docker service create --name monitor --mode global \\\n  --restart-condition any --mount type=bind,src=\/sys,dst=\/sys \\\n  --mount type=bind,src=\/var\/run\/docker.sock,dst=\/var\/run\/docker.sock \\\n  stefanscherer\/monitor:1.1.0\n<\/code><\/pre>\n\n<p>Now we are all set to play with scaling an example service.<\/p>\n\n<h2 id=\"scale-up\">Scale up<\/h2>\n\n<p>There is another multi-arch image that I used for the scaling demo. It is the &ldquo;whoami&rdquo; web service that responds the container&rsquo;s hostname.<\/p>\n\n<p>First we create the service with<\/p>\n\n<pre><code class=\"language-bash\">docker service create --name whoami stefanscherer\/whoami:1.1.0\n<\/code><\/pre>\n\n<p>As said this works with any Raspberry Pi or the UP board that has an Intel Atom CPU.\nAfter the image has been downloaded the LED monitor should show one yellow LED lighting up.<\/p>\n\n<p>Now scale the service a little more eg. to the number of nodes you have to have one LED lighting up per node.<\/p>\n\n<pre><code class=\"language-bash\">docker service scale whoami=4\n<\/code><\/pre>\n\n<p>Then scale it up a little more<\/p>\n\n<pre><code class=\"language-bash\">docker service scale whoami=16\n<\/code><\/pre>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/dockercon2017\/scale-up.gif\" alt=\"Scale up\" \/><\/p>\n\n<p>And then light up all the LED&rsquo;s by scaling up to the number of LED&rsquo;s you have.<\/p>\n\n<pre><code class=\"language-bash\">docker service scale whoami=32\n<\/code><\/pre>\n\n<h2 id=\"rolling-update\">Rolling update<\/h2>\n\n<p>Another thing that can be visualized is a rolling update. The LED monitor shows each container with a yellow color for version 1.1.0 of the service and blue for version 1.2.0.<\/p>\n\n<p>So start the rolling update by specifing <code>--update-parallelism<\/code> with the number of containers that should be replaced in one step. So Docker Swarm kills that number of containers and starts the new version of it before stopping the next bulk of containers. Use the <code>--image<\/code> option to specifiy the new version that should be used by the whoami service.<\/p>\n\n<pre><code class=\"language-bash\">docker service update --update-parallelism 5 \\\n  --image stefanscherer\/whoami:1.2.0 whoami\n<\/code><\/pre>\n\n<p>Now watch what happens. Each destroyed container lights up red and then dims. After a while Docker swarm manager starts the new version and so new LED&rsquo;s with blue light up. After a while all LED&rsquo;s have changed from yellow (version 1.1.0) to blue (version 1.2.0). And while this rolling update is going on you still can use this &ldquo;whoami&rdquo; service by curl&rsquo;ing it.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/dockercon2017\/rolling-update.gif\" alt=\"Rolling update\" \/><\/p>\n\n<h2 id=\"scale-down-to-one\">Scale down to one<\/h2>\n\n<p>Another nice effect is to scale down the service back to one as all LED&rsquo;s will flash up in red and only one LED remains blue.<\/p>\n\n<pre><code class=\"language-bash\">docker service scale whoami=1\n<\/code><\/pre>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/dockercon2017\/scale-down-to-one.gif\" alt=\"Scale down to one\" \/><\/p>\n\n<p>Hope I did make you curious to try it out on your own cluster. Happy hacking and have fun! If you want to improve the visual effects have a look at the Node.js sources in the <a href=\"https:\/\/github.com\/StefanScherer\/swarm-monitor\">GitHub repo<\/a>. Rewrite it in Golang or anything else and suprise me with other nice visual effects.<\/p>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Stefan <a href=\"https:\/\/twitter.com\/stefscherer\">@stefscherer<\/a><\/p>"},{"title":"Building a 64bit Docker OS for the Raspberry Pi 3","link":"https:\/\/blog.hypriot.com\/post\/building-a-64bit-docker-os-for-rpi3\/","pubDate":"Thu, 02 Mar 2017 11:28:42 +0100","guid":"https:\/\/blog.hypriot.com\/post\/building-a-64bit-docker-os-for-rpi3\/","description":"<p>I&rsquo;m happy to announce the start of a &ldquo;short&rdquo; workshop were I&rsquo;m going through all the steps to build a complete 64bit operating system for the Raspberry Pi 3. This 64bit HypriotOS is mainly focused on running Docker containers easily on this popular DIY and IoT device.<\/p>\n\n<p><img src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/e\/e6\/Raspberry-Pi-3-Flat-Top.jpg\" alt=\"Raspi3-Image\" \/><\/p>\n\n<p>You&rsquo;ll see that I&rsquo;m using Docker heavily for each and every build step, because it really helps us a lot to run a local build with <a href=\"https:\/\/docs.docker.com\/docker-for-mac\/\">Docker-for-Mac<\/a> or later on the cloud build servers at <a href=\"https:\/\/travis-ci.org\">Travis CI<\/a>.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/building-a-64bit-docker-os-for-rpi3\/bee42-workshop.jpg\" alt=\"bee42-workshop.jpg\" \/><\/p>\n\n<p>This workshop is sponsored by <a href=\"http:\/\/bee42.com\">bee42 solutions<\/a> <a href=\"https:\/\/twitter.com\/bee42solutions\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @bee42solutions<\/a><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n\n<p><\/p>\n\n<h3 id=\"background-and-contents\">Background and Contents<\/h3>\n\n<p>As you may already know, a complete Linux operating system consists of several important building blocks and I&rsquo;d like to show you how to build all of these step by step.<\/p>\n\n<p>For this purpose I&rsquo;m not going to reinvent the wheel and so I&rsquo;ll reuse all of the existing parts which are already published by the Raspberry Pi Organisation, by the Debian Linux project and will add some more glue code.<\/p>\n\n<p>At the end you should have learned how to build all the necessary parts and how to automatically create a finished SD card image which could be flashed on an empty SD card. Then boot your Raspberry Pi 3 with and in less than a minute you have a fully running Docker Engine on a Debian-based 64bit Linux OS.<\/p>\n\n<p>Here is a short overview of the contents of the workshop:<\/p>\n\n<ul>\n<li><p><strong>Part 1: Bootloader<\/strong><\/p><\/li>\n\n<li><p><strong>Part 2: Kernel<\/strong><\/p><\/li>\n\n<li><p><strong>Part 3: Root filesystem<\/strong><\/p><\/li>\n\n<li><p><strong>Part 4: SD Card Image<\/strong><\/p><\/li>\n<\/ul>\n\n<p>So, that&rsquo;s enough for explaining the background of this workshop. For more informations please follow along the details I&rsquo;ll publish on the coming tweets at Twitter and in the GitHub repos until all the parts of this workshop are finished and available as OpenSource.<\/p>\n\n<p>Please be aware that this OS is in a development phase and far from being perfect. So you are encouraged to help me with reporting issues and filing pull-requests to add features and fix bugs.<\/p>\n\n<h3 id=\"further-links\">Further Links<\/h3>\n\n<p>I&rsquo;m going to publish all the details and steps to build the new operating system in a public GitHub repo. All other details and necessary GitHub repos will be linked here in this section as a future reference.<\/p>\n\n<ul>\n<li><strong>Workshop Repo<\/strong> <a href=\"https:\/\/github.com\/dieterreuter\/workshop-raspberrypi-64bit-os\">https:\/\/github.com\/dieterreuter\/workshop-raspberrypi-64bit-os<\/a><\/li>\n<\/ul>\n\n<p>So please stay tuned, this link list will be extended over the next few days.<\/p>\n\n<h3 id=\"acknowledgments\">Acknowledgments<\/h3>\n\n<p>Please follow along the detailed tweets about this workshop via<\/p>\n\n<ul>\n<li><a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a> <a href=\"https:\/\/twitter.com\/Quintus23M\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @Quintus23M<\/a><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/li>\n<li><a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a> <a href=\"https:\/\/twitter.com\/HypriotTweets\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @HypriotTweets<\/a><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/li>\n<li><a href=\"https:\/\/twitter.com\/bee42solutions\">@bee42solutions<\/a> <a href=\"https:\/\/twitter.com\/bee42solutions\" class=\"twitter-follow-button\" data-show-count=\"false\">Follow @bee42solutions<\/a><script async src=\"\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/li>\n<\/ul>\n\n<p>Special thanks goes to <a href=\"http:\/\/bee42.com\">bee42 solutions<\/a> for giving me the time to work on this awesome topic to build a complete Docker-enabled 64bit OS for the Raspberry Pi 3.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/building-a-64bit-docker-os-for-rpi3\/bee42-logo.jpg\" alt=\"bee42-logo.jpg\" \/><\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"Let's build the smallest possible Docker image","link":"https:\/\/blog.hypriot.com\/post\/build-smallest-possible-docker-image\/","pubDate":"Wed, 22 Feb 2017 09:18:35 +0100","guid":"https:\/\/blog.hypriot.com\/post\/build-smallest-possible-docker-image\/","description":"<p>Imagine what happens if we&rsquo;re starting to use Docker containers on IoT devices. On small and slow devices with limited system resources and connected via a damn slow network connection we do have to care differently on how to build and ship our apps. In these circumstances it pays off and it&rsquo;s absolutely essential to optimize our applications and the resulting Docker images for size.<\/p>\n\n<p>SIZE DOES MATTER<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/build-smallest-possible-docker-image\/docker-image-minimal.png\" alt=\"docker-image-minimal.png\" \/><\/p>\n\n<p>If we&rsquo;re doing it right we&rsquo;ll get a lot of benefits such as blasting fast download speed for updating to a new or more secured version. On wireless networks we are also reducing the costs for data transfers as well.<\/p>\n\n<p>According to my <a href=\"https:\/\/twitter.com\/quintus23m\/status\/834132186211180544\">tweet<\/a> I&rsquo;d like to start a new Docker challenge:<\/p>\n\n<p><strong>How small is the smallest Docker image we could build, which prints a &ldquo;Hello Docker World!&rdquo;?<\/strong><\/p>\n\n<p><\/p>\n\n<h3 id=\"background\">Background<\/h3>\n\n<p>Sometimes developing directly on an IoT device can be pretty hard or nearly impossible due to the lack of enough system resources. These resources can be the amount of memory, disk space or CPU capacity - or it can be just a limited network connectivity over a low-bandwith 64kbit\/sec wireless network.<\/p>\n\n<p>So, let&rsquo;s assume we do have a Raspberry Pi already deployed in the field and this IoT device has such a low-bandwidth network connection. We&rsquo;re preparing our developing system to run on a bare-metal cloud server and we are transfering our build artefacts as ready-to-run Docker images regularly with each and every new release in a DevOps driven manner. For this reason we&rsquo;d like to speed up the deployment with minimized Docker image sizes.<\/p>\n\n<p>Wait, I thought a Docker image can be pretty heavy with up to 1 GByte or even larger? Well, that could happen if we&rsquo;re packing a whole Operating System like Ubuntu or Debian into our Docker images. But as we&rsquo;re building an IoT application we should take care about that situation. A Docker image can instead be build with an app consisting of a statically linked binary and when we start it as a Docker container it will run a single Linux process only.<\/p>\n\n<h3 id=\"creating-our-app-in-arm-assembly\">Creating our App in ARM assembly<\/h3>\n\n<p>TL;DR all the source code and build instructions can be found in this public <a href=\"https:\/\/github.com\/DieterReuter\/dockerchallenge-smallest-image\">GitHub repo<\/a>.<\/p>\n\n<p>Here is my starting example of an assembly program which just prints a single static text string. It is written in ARM assembly language and should be compiled into a really small binary we can run on any ARMv7 device.<\/p>\n\n<pre><code>$ cat hello.S\n.data\nmsg:\n    .ascii      &quot;Hello Docker World!\\n&quot;\nlen = . - msg\n\n.text\n\n.globl _start\n_start:\n    \/* syscall write(int fd, const void *buf, size_t count) *\/\n    mov     %r0, $1     \/* fd -&gt; stdout *\/\n    ldr     %r1, =msg   \/* buf -&gt; msg *\/\n    ldr     %r2, =len   \/* count -&gt; len(msg) *\/\n    mov     %r7, $4     \/* write is syscall #4 *\/\n    swi     $0          \/* invoke syscall *\/\n\n    \/* syscall exit(int status) *\/\n    mov     %r0, $0     \/* status -&gt; 0 *\/\n    mov     %r7, $1     \/* exit is syscall #1 *\/\n    swi     $0          \/* invoke syscall *\/\n<\/code><\/pre>\n\n<p>Let&rsquo;s compile and link it as a static program<\/p>\n\n<pre><code>$ as -o hello.o hello.S\n$ ld -s -o hello hello.o\n<\/code><\/pre>\n\n<p>Show details about the binary<\/p>\n\n<pre><code>$ file hello\nhello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, stripped\n<\/code><\/pre>\n\n<p>Now as we do have our app as a single binary program, we can build our smallest Docker image easily from scratch. This new Docker image consists only our binary and nothing else of other components at all. But you have to know this only works if the binary is statically linked and has all necessary tools baked in.<\/p>\n\n<pre><code>$ cat Dockerfile.armhf\nFROM scratch\nADD hello \/hello\nCMD [&quot;\/hello&quot;]\n<\/code><\/pre>\n\n<p>Building the Docker image<\/p>\n\n<pre><code>$ docker build -t dieterreuter\/hello -f Dockerfile.armhf .\n<\/code><\/pre>\n\n<h3 id=\"starting-point\">Starting point<\/h3>\n\n<p>With all the details I&rsquo;ve shown above in this blog post I finally built a first super-small Docker image with an indicated size of 452 Bytes only.<\/p>\n\n<pre><code>$ docker images\nREPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE\ndieterreuter\/hello           latest              b961df9c849e        27 hours ago        452 B\n<\/code><\/pre>\n\n<p>Starting this Docker container on a Raspberry Pi (or another ARMv7 machine) will print the requested text string.<\/p>\n\n<pre><code>$ docker run dieterreuter\/hello\nHello Docker World!\n<\/code><\/pre>\n\n<p>Well, if you&rsquo;re working with <a href=\"https:\/\/docs.docker.com\/docker-for-mac\/\">Docker-for-Mac<\/a> or <a href=\"https:\/\/docs.docker.com\/docker-for-windows\/\">Docker-for-Windows<\/a> you should try to run this command, too. I guess you&rsquo;ll be surprised what happens on your Intel based system when you start this Docker container which is containing an ARM binary. But this is a topic for another future blog post.<\/p>\n\n<h3 id=\"challenge-details\">Challenge details<\/h3>\n\n<p>There are not many rules for this challenge, but let&rsquo;s give you some hints:<\/p>\n\n<ol>\n<li>the Docker image should output the text &ldquo;Hello Docker World!&rdquo; on the console<\/li>\n<li>we measure the size of the Docker image with <code>docker images<\/code> or <code>docker image ls<\/code><\/li>\n<li>feel free to use a CPU architecture of your choice: Intel, ARMv7, ARMv8\/AARCH64, &hellip;<\/li>\n<\/ol>\n\n<p>Please publish your results on DockerHub, source codes on GitHub and tweet about it on Twitter with the hashtag #DockerChallenge. The goal of this challenge is to get familiar with the techniques to build minimal sized Docker images not only for IoT use cases, to understand the fact that a Docker container can be just a single process, and that this process can be really extremely small itself. On the way we&rsquo;ll learn to take care about all the necessary steps to reduce the size and how we can optimize our development workflow as well.<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/build-smallest-possible-docker-image\/docker-image-minimal2.png\" alt=\"docker-image-minimal2.png\" \/><\/p>\n\n<p>So, let&rsquo;s start the journey&hellip;<\/p>\n\n<h3 id=\"feedback-please\">Feedback, please<\/h3>\n\n<p>As always use the comments below to give us feedback and share it on Twitter or Facebook.<\/p>\n\n<p>Please send us your feedback on our <a href=\"https:\/\/gitter.im\/hypriot\/talk\">Gitter channel<\/a> or tweet your thoughts and ideas on this project at <a href=\"https:\/\/twitter.com\/HypriotTweets\">@HypriotTweets<\/a>.<\/p>\n\n<p>Dieter <a href=\"https:\/\/twitter.com\/Quintus23M\">@Quintus23M<\/a><\/p>"},{"title":"Setup Kubernetes on a Raspberry Pi Cluster easily the official way!","link":"https:\/\/blog.hypriot.com\/post\/setup-kubernetes-raspberry-pi-cluster\/","pubDate":"Wed, 11 Jan 2017 14:03:34 +0100","guid":"https:\/\/blog.hypriot.com\/post\/setup-kubernetes-raspberry-pi-cluster\/","description":"<p><a href=\"kubernetes.io\">Kubernetes<\/a> shares the pole position with Docker in the category &ldquo;orchestration solutions for Raspberry Pi cluster&rdquo;.\nHowever it&rsquo;s setup process has been elaborate \u2013 until <a href=\"http:\/\/blog.kubernetes.io\/2016\/09\/how-we-made-kubernetes-easy-to-install.html\">v1.4 with the kubeadm announcement<\/a>.\nWith that effort, Kubernetes changed this game completely and can be up and running officially within no time.<\/p>\n\n<p>I am very happy to announce that this blog post has been written in collaboration with <a href=\"https:\/\/github.com\/luxas\">Lucas K\u00e4ldstr\u00f6m<\/a>, an independent maintainer of Kubernetes (his story is very interesting,  you can read it in a <a href=\"https:\/\/www.cncf.io\/blog\/2016\/11\/29\/diversity-scholarship-series-programming-journey-becoming-kubernetes-maintainer\">CNCF blogpost<\/a>).<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/raspberry-pi-cluster.png\" alt=\"SwarmClusterHA\" \/><\/p>\n\n<p><\/p>\n\n<h2 id=\"why-kubernetes\">Why Kubernetes?<\/h2>\n\n<p>As shown in my recent <a href=\"http:\/\/www.slideshare.net\/MathiasRenner\/high-availability-performance-of-kubernetes-and-docker-swarm-on-a-raspberry-pi-cluster\/\">talk<\/a>, there are many software suites available to manage a cluster of computers. There is Kubernetes, Docker Swarm, Mesos, OpenStack, Hadoop YARN, Nomad&hellip; just to name a few.<\/p>\n\n<p>However, at Hypriot we have always been in love with tiny devices. So when working with an orchestrator, the maximum power we wanna use is what&rsquo;s provided by a Raspberry Pi. Why? We have IoT networks in mind that will hold a large share in tomorrow&rsquo;s IT infrastructure. At their edges, the power required for large orchestrators simply is not available.<\/p>\n\n<p>This boundary of resources leads to several requirements that need to be checked before we start getting our hands dirty with an orchestrator:<\/p>\n\n<ul>\n<li><strong>Lightweight:<\/strong> Software should be fit on a Raspberry Pi or smaller. As proofed in my talk mentioned above, Kubernetes painlessly runs on a Raspberry Pi.<\/li>\n<li><strong>ARM compatible:<\/strong> Since the ARM CPU architecture is designed for low energy consumption but still able to deliver a decent portion of power, the Raspberry Pi runs an ARM CPU. Thanks to Lucas, Kubernetes is ARM compatible.<\/li>\n<li><strong>General purpose:<\/strong> Hadoop or Apache Spark are great for data analysis. But what if your use case changes? We prefer general purpose software that allows to run <strong>anything<\/strong>. Kubernetes uses a container runtime (with Docker as the 100% supported runtime for the time being) that allows to run whatever you want.<\/li>\n<li><strong>Production ready:<\/strong> Since we compare Kubernetes against a production ready Docker suite, let&rsquo;s be fair and only choose equivalents. Kubernetes itself is production ready, and while the ARM port has some small issues, it&rsquo;s working exactly as expected when going the official kubeadm route, which also will mature with time.<\/li>\n<\/ul>\n\n<p>So, Kubernetes seems to be a compelling competitor to Docker Swarm. Let&rsquo;s get our hands on it!<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"wait-what-about-kubernetes-on-arm\">Wait \u2013 what about <em>Kubernetes-on-ARM<\/em>?<\/h2>\n\n<p>If you followed the discussion of Kubernetes on ARM for some time, you probably know about Lucas&rsquo; project <a href=\"https:\/\/github.com\/luxas\/kubernetes-on-arm\">kubernetes-on-ARM<\/a>. Since the beginning of the movement to bring Kubernetes on ARM in 2015, this project has always been the most stable and updated.<\/p>\n\n<p>However, during 2016, Lucas&rsquo; contributions have successfully been merged into official Kubernetes repositories, such that there is no point any more for using the kubernetes-on-ARM project.\nIn fact, the features of that project are far behind of what&rsquo;s now implemented in the official repos, <strong>and that has been Lucas&rsquo; goal from the beginning.<\/strong><\/p>\n\n<p>So if you&rsquo;re up to using Kubernetes, please stick to the official repos now. And as of the kubeadm documentation, <strong>the following setup is considered official for Kubernetes on ARM.<\/strong><\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"at-first-flash-hypriotos-on-your-sd-cards\">At first: Flash HypriotOS on your SD cards<\/h2>\n\n<p>As hardware, take at least two Raspberry Pis and make sure they are connected to each other and to the Internet.<\/p>\n\n<p>First, we need an operating system. Download and flash <a href=\"https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\">HypriotOS<\/a>. The fastest way to download and flash HypriotOS on your SD cards is by using our <a href=\"https:\/\/github.com\/hypriot\/flash\">flash tool<\/a> like so:<\/p>\n\n<pre><code>flash --hostname node01 https:\/\/github.com\/hypriot\/image-builder-rpi\/releases\/download\/v1.4.0\/hypriotos-rpi-v1.4.0.img.zip\n<\/code><\/pre>\n\n<p>Provision all Raspberry Pis you have like this and boot them up.<\/p>\n\n<p>Afterwards, SSH into the Raspberry Pis with<\/p>\n\n<pre><code>ssh pirate@node01.local\n<\/code><\/pre>\n\n<p>The password <code>hypriot<\/code> will grant you access.<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"install-kubernetes\">Install Kubernetes<\/h2>\n\n<p>The installation requires root privileges. Retrieve them by<\/p>\n\n<pre><code>sudo su -\n<\/code><\/pre>\n\n<p>To install Kubernetes and its dependencies, only some commands are required.\nFirst, trust the kubernetes APT key and add the official APT Kubernetes repository on every node:<\/p>\n\n<pre><code>$ curl -s https:\/\/packages.cloud.google.com\/apt\/doc\/apt-key.gpg | apt-key add -\n$ echo &quot;deb http:\/\/apt.kubernetes.io\/ kubernetes-xenial main&quot; &gt; \/etc\/apt\/sources.list.d\/kubernetes.list\n<\/code><\/pre>\n\n<p>&hellip; and then just install <code>kubeadm<\/code> on every node:<\/p>\n\n<pre><code>$ apt-get update &amp;&amp; apt-get install -y kubeadm\n<\/code><\/pre>\n\n<p>After the previous command has been finished, initialize Kubernetes on the <strong>master node<\/strong> with<\/p>\n\n<pre><code>$ kubeadm init --pod-network-cidr 10.244.0.0\/16\n<\/code><\/pre>\n\n<p>It is important that you add the <code>--pod-network-cidr<\/code> command as given here, because we will use <a href=\"https:\/\/coreos.com\/flannel\/docs\/latest\/\">flannel<\/a>. Read the next notes about flannel if you wanna know why.<\/p>\n\n<blockquote>\n<p><strong>Some notes about flannel<\/strong>: We picked flannel here because that\u2019s the only available solution for ARM at the moment (this is subject to change in the future though).<\/p>\n\n<p>flannel can use and is using in this example the Kubernetes API to store metadata about the Pod CIDR allocations, and therefore we need to tell <em>Kubernetes<\/em> first which subnet we want to use. The subnet we chose here is somehow fixed, because the <a href=\"https:\/\/github.com\/coreos\/flannel\/blob\/master\/Documentation\/kube-flannel.yml#L25\">flannel configuration file<\/a> that we&rsquo;ll use later in this guide predefines the equivalent subnet. Of course, you can adapt both.<\/p>\n<\/blockquote>\n\n<p>If you are connected via WIFI instead of Ethernet, add <code>--apiserver-advertise-address=&lt;wifi-ip-address&gt;<\/code> as parameter to <code>kubeadm init<\/code> in order to publish Kubernetes&rsquo; API via WiFi. Feel free to explore the other options that exist for <code>kubeadm init<\/code>.<\/p>\n\n<p>After Kubernetes has been initialized, the last lines of your terminal should look like this:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/init.png\" alt=\"init\" \/><\/p>\n\n<p>To start using your cluster, you need to run (as a regular user):<\/p>\n\n<pre><code>$ sudo cp \/etc\/kubernetes\/admin.conf $HOME\/\n$ sudo chown $(id -u):$(id -g) $HOME\/admin.conf\n$ export KUBECONFIG=$HOME\/admin.conf\n<\/code><\/pre>\n\n<p>Next, as told by that output, let all other nodes join the cluster via the given <code>kubeadm join<\/code> command. It will look something like:<\/p>\n\n<pre><code>$ kubeadm join --token=bb14ca.e8bbbedf40c58788 192.168.0.34\n<\/code><\/pre>\n\n<p>After some seconds, you should see all nodes in your cluster when executing the following <strong>on the master node<\/strong>:<\/p>\n\n<pre><code>$ kubectl get nodes\n<\/code><\/pre>\n\n<p>Your terminal should look like this:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/get-nodes.png\" alt=\"k8S\" \/><\/p>\n\n<p>Finally, <strong>we need to setup flannel v0.9.1 as the Pod network driver<\/strong>. Do not use <a href=\"https:\/\/github.com\/coreos\/flannel\/releases\/tag\/v0.8.0\">v0.8.0<\/a> due to a known <a href=\"https:\/\/github.com\/coreos\/flannel\/issues\/773\">bug<\/a> that can cause a <code>CrashLoopBackOff<\/code> error. Run this <strong>on the master node<\/strong>:<\/p>\n\n<pre><code>$ curl -sSL https:\/\/rawgit.com\/coreos\/flannel\/v0.9.1\/Documentation\/kube-flannel.yml | sed &quot;s\/amd64\/arm\/g&quot; | kubectl create -f -\n<\/code><\/pre>\n\n<p>Your terminal should look like this:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/flannel.png\" alt=\"k8S\" \/><\/p>\n\n<p>Then wait until all flannel and all other cluster-internal Pods are <code>Running<\/code> before you continue:<\/p>\n\n<pre><code>$ kubectl get po --all-namespaces\n<\/code><\/pre>\n\n<p>Nice, it seems like they are all <code>Running<\/code>:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/show-namespaces.png\" alt=\"show-namespaces\" \/><\/p>\n\n<p>That&rsquo;s all for the setup of Kubernetes! Next, let&rsquo;s actually spin up a service on the cluster!<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"test-your-setup-with-a-tiny-service\">Test your setup with a tiny service<\/h2>\n\n<p>Let&rsquo;s start a simple service so see if the cluster actually can publish a service:<\/p>\n\n<pre><code>$ kubectl run hypriot --image=hypriot\/rpi-busybox-httpd --replicas=3 --port=80\n<\/code><\/pre>\n\n<p>This command starts set of containers called <strong>hypriot<\/strong> from the image <strong>hypriot\/rpi-busybox-httpd<\/strong> and defines the port the container listens on at <strong>80<\/strong>. The service will be <strong>replicated with 3 containers<\/strong>.<\/p>\n\n<p>Next, expose the Pods in the above created Deployment in a Service with a stable name and IP:<\/p>\n\n<pre><code>$ kubectl expose deployment hypriot --port 80\n<\/code><\/pre>\n\n<p>Great! Now, let&rsquo;s check if all three desired containers are up and running:<\/p>\n\n<pre><code>$ kubectl get endpoints hypriot\n<\/code><\/pre>\n\n<p>You should see three endpoints (= containers) like this:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/show-endpoints.png\" alt=\"show-endpoints\" \/><\/p>\n\n<p>Let&rsquo;s curl one of them to see if the service is up:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/curl-service.png\" alt=\"curl-service\" \/><\/p>\n\n<p>The HTML is the response of the service. Good, it&rsquo;s up and running! Next, let&rsquo;s see how we can access it from outside the cluster!<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"finally-access-your-service-from-outside-the-cluster\">Finally access your service from outside the cluster<\/h2>\n\n<p>We will now deploy an example Ingress Controller to manage incoming requests from the outside world onto our tiny service. Also, in this example we we&rsquo;ll use <a href=\"https:\/\/traefik.io\">Traefik<\/a> as load balancer. Read the following notes if you wanna know more about Ingress and Traefik.<\/p>\n\n<blockquote>\n<p><strong>In contrast to Docker Swarm, Kubernetes itself does not provide an option to define a specific port that you can use to access a service<\/strong>. According to Lucas this is an important design decision; routing of incoming requests should be handled by a third party, such as a load balancer or a webserver, but not by the core product. The core Kubernetes should be lean and extensible, and encourage others to build tools on top of it for their specific needs.<\/p>\n\n<p>Regarding load balancers in front of a cluster, there is <a href=\"http:\/\/kubernetes.io\/docs\/user-guide\/ingress\/\">the Ingress API object<\/a> and some sample <a href=\"https:\/\/github.com\/kubernetes\/ingress\">Ingress Controllers<\/a>. Ingress is a built-in way of exposing Services to the outside world via an Ingress Controller that anyone can build. An <em>Ingress rule<\/em> defines how traffic should flow from the node the Ingress controller runs on to services inside of the cluster.<\/p>\n<\/blockquote>\n\n<p>First, let&rsquo;s deploy traefik as load balancer:<\/p>\n\n<pre><code>$ kubectl apply -f https:\/\/raw.githubusercontent.com\/hypriot\/rpi-traefik\/master\/traefik-k8s-example.yaml\n<\/code><\/pre>\n\n<p>Label the node you want to be the load balancer. Then the Traefik Ingress Controller will land on the node you specified. Run:<\/p>\n\n<pre><code>$ kubectl label node &lt;load balancer-node&gt; nginx-controller=traefik\n<\/code><\/pre>\n\n<p>Lastly, create an Ingress object that makes Traefik load balance traffic on port <code>80<\/code> to the <code>hypriot<\/code> service:<\/p>\n\n<pre><code>$ cat &gt; hypriot-ingress.yaml &lt;&lt;EOF\napiVersion: extensions\/v1beta1\nkind: Ingress\nmetadata:\n  name: hypriot\nspec:\n  rules:\n  - http:\n      paths:\n      - path: \/\n        backend:\n          serviceName: hypriot\n          servicePort: 80\nEOF\n$ kubectl apply -f hypriot-ingress.yaml\n<\/code><\/pre>\n\n<p>Visit the loadbalancing node&rsquo;s IP address in your browser and you should see a nice web page:<\/p>\n\n<p><img src=\"https:\/\/blog.hypriot.com\/images\/kubernetes-setup-cluster\/hypriot-website.png\" alt=\"curl-service\" \/><\/p>\n\n<p>If you don&rsquo;t see a website there yet, run:<\/p>\n\n<pre><code>$ kubectl get pods\n<\/code><\/pre>\n\n<p>&hellip; and make sure all hypriot Pods are in the <code>Running<\/code> state.<\/p>\n\n<p>Wait until you see that all Pods are running, and a nice Hypriot website should appear!<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"tear-down-the-cluster\">Tear down the cluster<\/h2>\n\n<p>If you wanna reset the whole cluster to the state after a fresh install, just run this on each node:<\/p>\n\n<pre><code>$ kubeadm reset\n<\/code><\/pre>\n\n<p>In addition, it is recommended to delete some additional files <a href=\"http:\/\/stackoverflow.com\/questions\/41359224\/kubernetes-failed-to-setup-network-for-pod-after-executed-kubeadm-reset\/41372829#41372829\">as it is mentioned here<\/a>.<\/p>\n\n<p><\/br><\/p>\n\n<h2 id=\"optional-deploy-the-kubernetes-dashboard\">Optional: Deploy the Kubernetes dashboard<\/h2>\n\n<p>The dashboard is a wonderful interface to visualize the state of the cluster. Start it with:<\/p>\n\n<pre><code>$ kubectl apply -f https:\/\/raw.githubusercontent.com\/kubernetes\/dashboard\/master\/src\/deploy\/recommended\/kubernetes-dashboard-arm.yaml\n<\/code><\/pre>\n\n<p>Edit the kubernetes-dashboard service to use <code>type: ClusterIP<\/code> to <code>type: NodePort<\/code>, see <a href=\"https:\/\/github.com\/kubernetes\/dashboard\/wiki\/Accessing-Dashboard---1.7.X-and-above\">Accessing Kubernetes Dashboard<\/a> for more details.<\/p>\n\n<pre><code>$ kubectl -n kube-system edit service kubernetes-dashboard\n<\/code><\/pre>\n\n<p>The following command provides the port that the dashboard is exposed at on every node with the NodePort function of Services, which is another way to expose your Services to the outside of your cluster:<\/p>\n\n<pre><code>$ kubectl -n kube-system get service kubernetes-dashboard -o template --template=&quot;{{ (index .spec.ports 0).nodePort }}&quot; | xargs echo\n<\/code><\/pre>\n\n<p>Then you can checkout the dashboard on any node&rsquo;s IP address on that port! Make sure to use <code>https<\/code> when accessing the dashboard, for example if running on port <code>31657<\/code> access it at <code>https:\/\/node:31657<\/code>.<\/p>\n\n<p>Newer versions of the Kubernetes Dashboard require either a <code>Kubeconfig<\/code> or <code>Token<\/code> to view information on the dashboard. <a href=\"https:\/\/github.com\/kubernetes\/dashboard\/wiki\/Access-control#introduction\">Bearer tokens<\/a> are recommended to setup proper permissions for a user, but to test the <code>replicaset-controller-token<\/code> Token may be used to test.<\/p>\n\n<pre><code>kubectl -n kube-system describe secret `kubectl -n kube-system get secret | grep replicaset-controller-token | awk '{print $1}'` | grep token: | awk '{print $2}'\n<\/code><\/pre>\n\n<p><\/br><\/p>\n\n<h2 id=\"you-like-a-follow-up\">You like a follow-up?<\/h2>\n\n<p>It was our goal to show that Kubernetes indeed works well on ARM (and ARM 64-bit!). For more examples including the AMD64 platform, check out the <a href=\"http:\/\/kubernetes.io\/docs\/getting-started-guides\/kubeadm\/\">official kubeadm documentation<\/a>.<\/p>\n\n<p>We might follow-up this blog post with a more in-depth post about the current and planned state of Kubernetes officially on ARM and more, so stay tuned and tell Lucas if that&rsquo;s something you&rsquo;re interested in reading.<\/p>\n\n<p>As always, use the comments below to give us feedback and share this post on Twitter, Google or Facebook.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/MathiasRenner\">Mathias Renner<\/a> and <a href=\"https:\/\/twitter.com\/kubernetesonarm\">Lucas K\u00e4ldstr\u00f6m<\/a><\/p>"}]}}