{"id":581,"date":"2019-12-22T00:49:50","date_gmt":"2019-12-22T06:49:50","guid":{"rendered":"https:\/\/jacobncalvert.com\/?p=581"},"modified":"2019-12-22T09:52:01","modified_gmt":"2019-12-22T15:52:01","slug":"building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support","status":"publish","type":"post","link":"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/","title":{"rendered":"Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support"},"content":{"rendered":"\n<h2>Motivation<\/h2>\n\n\n\n<p>I recently stumbled upon <a href=\"https:\/\/blog.hypriot.com\/\">HypriotOS<\/a> while looking for Docker-ready distributions for my Raspberry Pi 3B+. I flashed this onto and SD card and started playing around with it. It works incredibly well, but I noticed that it was built for <em>armv7l<\/em> which is a 32-bit implementation. Since the Raspberry Pi 3B+ has a 4x core Cortex-A53 which is 64 bit, I wanted to make use of the 64 bit processor! I&#8217;ve worked with Yocto before (in fact,<a href=\"https:\/\/www.windriver.com\/products\/linux\/\"> my day job uses Yocto<\/a>), so I decided I&#8217;d build my own. For more on containers, see my other <a href=\"https:\/\/jacobncalvert.com\/2019\/11\/04\/virtualization-for-embedded-systems-series-types-of-virtualization\/\">blog posts on what it is<\/a>, <a href=\"https:\/\/jacobncalvert.com\/2019\/11\/11\/virtualization-for-embedded-systems-series-applications-in-the-real-world\/\">what it can be used for,<\/a> and <a href=\"https:\/\/jacobncalvert.com\/2019\/11\/18\/virtualization-for-embedded-systems-series-containers-deep-dive\/\">how to use it.<\/a><\/p>\n\n\n\n<h2>Process<\/h2>\n\n\n\n<h3>Prerequisites<\/h3>\n\n\n\n<p>Yocto is a build, not a distribution, so it is quite resource intensive. I would suggest having at least 60GB free disk space, and a quad core machine at a minimum. You&#8217;ll also need a Linux installation, and the build essentials installed (git, gcc, etc.). <\/p>\n\n\n\n<p><strong>EDIT: Checking the disk usage after the builds shows around 55GB used. On a 2C4T Intel Core i5 it took about 2H to build. <\/strong><\/p>\n\n\n\n<h3>Project Setup<\/h3>\n\n\n\n<p>First, create a working directory and clone all the piece-parts we need to build. <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nmkdir rpi3bplus-build-yocto\ncd rpi3bplus-build-yocto\ngit clone git:\/\/git.yoctoproject.org\/poky\ngit clone git:\/\/git.openembedded.org\/meta-openembedded\ngit clone git:\/\/git.yoctoproject.org\/meta-raspberrypi\ngit clone git:\/\/git.yoctoproject.org\/meta-virtualization \n<\/pre><\/div>\n\n\n<p>Next create the project and add the base layers.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\nsource poky\/oe-init-build-env rpi64\nbitbake-layers add-layer ..\/meta-raspberrypi\nbitbake-layers add-layer ..\/meta-openembedded\/meta-oe\nbitbake-layers add-layer ..\/meta-openembedded\/meta-python\nbitbake-layers add-layer ..\/meta-openembedded\/meta-perl\nbitbake-layers add-layer ..\/meta-openembedded\/meta-networking\nbitbake-layers add-layer ..\/meta-openembedded\/meta-filesystems\nbitbake-layers add-layer ..\/meta-virtualization\n<\/pre><\/div>\n\n\n<p>Edit the conf\/local.conf file sections as needed:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nMACHINE ??= &quot;raspberrypi3-64&quot;\nCORE_IMAGE_EXTRA_INSTALL += &quot;kernel-modules htop openssh iperf3 docker-ce bash ntp &quot;\n\nINHERIT += &quot;extrausers&quot;\n\nEXTRA_USERS_PARAMS += &quot; useradd pi; \\\n                       usermod  -p 'raspberry' pi; \\\n                       usermod  -a -G sudo pi; \\\n                       usermod -P root root; &quot;\n\nDISTRO_FEATURES_append = &quot; virtualization&quot;\n\n<\/pre><\/div>\n\n\n<p>Next we will build the image. This will take a while depending on how beefy your build machine is.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nbitbake core-image-minimal\nParsing recipes: 100% |########################################################################################################################################################################################################| Time: 0:02:16\nParsing of 2540 .bb files complete (0 cached, 2540 parsed). 3827 targets, 140 skipped, 0 masked, 0 errors.\nNOTE: Resolving any missing task queue dependencies\n\nBuild Configuration:\nBB_VERSION           = &quot;1.44.0&quot;\nBUILD_SYS            = &quot;x86_64-linux&quot;\nNATIVELSBSTRING      = &quot;universal&quot;\nTARGET_SYS           = &quot;aarch64-poky-linux&quot;\nMACHINE              = &quot;raspberrypi3-64&quot;\nDISTRO               = &quot;poky&quot;\nDISTRO_VERSION       = &quot;3.0&quot;\nTUNE_FEATURES        = &quot;aarch64 cortexa53 crc&quot;\nTARGET_FPU           = &quot;&quot;\nmeta                 \nmeta-poky            \nmeta-yocto-bsp       = &quot;master:6bb4a252199cfd5d44ad7ab6fc4118c80a1aae92&quot;\nmeta-raspberrypi     = &quot;master:a0a5d3848e76b7f90ef8e42c56211da78db1c7ba&quot;\nmeta-oe              \nmeta-python          \nmeta-perl            \nmeta-networking      \nmeta-filesystems     = &quot;master:d9f3e6dbed8e5d96f2069280f0a566af89afb2fa&quot;\nmeta-virtualization  = &quot;master:5fb77ae4c4e1015e40257f9e59e16c497e30c53c&quot;\n\n<\/pre><\/div>\n\n\n<p>After a couple of hours, you will have a completed, ready to flash SD Image at <em>&lt;build&gt;\/rpi3bplus-build-yocto\/rpi64\/tmp\/deploy\/images\/raspberrypi3-64\/core-image-minimal-raspberrypi3-64.rpi-sdimg<\/em> which you can burn to an SD card with:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndd if=.\/core-image-minimal-raspberrypi3-64.rpi-sdimg of=\/dev\/sdX status=progress\n<\/pre><\/div>\n\n\n<p>Your image should boot up and docker will be running! <\/p>\n\n\n\n<p><strong>NOTE: You will manually have to set the date to pull from Docker registries over HTTPS because the certification validation will fail otherwise. We could add and configure NTP to fix the but&#8230; for another day.<\/strong> <strong>Use:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; title: ; notranslate\" title=\"\">\ndate &quot;+%d-%m-%C%y %H:%M:%S&quot; -s &quot;2019-12-22 00:30:01&quot;\n<\/pre><\/div>\n\n\n<p>There is one last thing you&#8217;ll want to do. You&#8217;ll want to use GParted or similar tool to enlarge your filesystem partition to take up the rest of your SD card so you will have some room for container images. You need to do this because the default SD Image builder script only provides enough space for the root filesystem and no more. In my configuration it ended up being ~300MB, so I expanded it take up the remaining ~59GB. See example below:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-21-234142.png\"><img loading=\"lazy\" width=\"777\" height=\"526\" src=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-21-234142.png\" alt=\"\" class=\"wp-image-593\" srcset=\"https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-21-234142.png 777w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-21-234142-300x203.png 300w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-21-234142-768x520.png 768w\" sizes=\"(max-width: 777px) 100vw, 777px\" \/><\/a><\/figure>\n\n\n\n<h2>Results<\/h2>\n\n\n\n<p>As it turns out, I have a system that can build and run 64-bit Docker images and is pretty darn slim. Here&#8217;s a screenshot of <em>htop<\/em> running.. only 12 processes &#8211; not bad!<\/p>\n\n\n\n<figure class=\"wp-block-image foobox\"><a href=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853.png\"><img loading=\"lazy\" width=\"1920\" height=\"1055\" src=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853.png\" alt=\"\" class=\"wp-image-597\" srcset=\"https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853.png 1920w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853-300x165.png 300w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853-1024x563.png 1024w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853-768x422.png 768w, https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/Screenshot-2019-12-22-000853-1536x844.png 1536w\" sizes=\"(max-width: 1920px) 100vw, 1920px\" \/><\/a><\/figure>\n\n\n\n<h3>Some Metrics<\/h3>\n\n\n\n<p>The is the minimal image and it has 12 processes, with an incredibly low footprint. I loaded up an Ubuntu container and installed iperf3, then ran a test to my laptop. I was impressed to find the following result:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#91; ID] Interval           Transfer     Bandwidth       Retr\n&#91;  5]   0.00-10.13  sec   116 MBytes  96.0 Mbits\/sec    9             sender\n&#91;  5]   0.00-10.13  sec   113 MBytes  93.8 Mbits\/sec                  receiver\n\n<\/pre><\/div>\n\n\n<p>Even running that test, the load on the Pi was:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nroot@raspberrypi3-64:~# cat \/proc\/loadavg \n0.05 0.22 0.19 1\/141 2125\nroot@raspberrypi3-64:~# \n\n<\/pre><\/div>\n\n\n<h2>Downloads<\/h2>\n\n\n\n<div class=\"wp-container-1 wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<p><a href=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/sha256sums.txt.asc\">Clear Signed SHA256 Sum of the images below<\/a> (look up my public key 0x2408A81C)<\/p>\n\n\n\n<p><a href=\"https:\/\/drive.google.com\/file\/d\/1aHuCHeF1nHDZC4-hrV2v5yCCy5aqRqz9\/view?usp=sharing\">Minimal Image for RPi3<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/drive.google.com\/file\/d\/1aHuCHeF1nHDZC4-hrV2v5yCCy5aqRqz9\/view?usp=sharing\">Base (more complete) Image for RPi3<\/a><\/p>\n<\/div><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Motivation I recently stumbled upon HypriotOS while looking for Docker-ready distributions for my Raspberry Pi 3B+. I flashed this onto and SD card and started playing around with it. It works incredibly well, but I noticed that it was built for armv7l which is a 32-bit implementation. Since the Raspberry Pi 3B+ has a 4x core Cortex-A53 which is 64 bit, I wanted to make use of the 64 bit processor! I&#8217;ve worked with Yocto before (in fact, my day&hellip;<\/p>\n","protected":false},"author":1,"featured_media":586,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[85,72,5,1,98],"tags":[108,109,39,48,95,110],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v16.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support - Jacob N Calvert<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support - Jacob N Calvert\" \/>\n<meta property=\"og:description\" content=\"Motivation I recently stumbled upon HypriotOS while looking for Docker-ready distributions for my Raspberry Pi 3B+. I flashed this onto and SD card and started playing around with it. It works incredibly well, but I noticed that it was built for armv7l which is a 32-bit implementation. Since the Raspberry Pi 3B+ has a 4x core Cortex-A53 which is 64 bit, I wanted to make use of the 64 bit processor! I&#8217;ve worked with Yocto before (in fact, my day&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/\" \/>\n<meta property=\"og:site_name\" content=\"Jacob N Calvert\" \/>\n<meta property=\"article:published_time\" content=\"2019-12-22T06:49:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-12-22T15:52:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jacobncalvert.com\/wp-content\/uploads\/2019\/12\/coding-computer-data-depth-of-field-577585.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"959\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/#website\",\"url\":\"https:\/\/jacobncalvert.com\/blog-archive\/\",\"name\":\"Jacob N Calvert\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/jacobncalvert.com\/blog-archive\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/coding-computer-data-depth-of-field-577585.jpg\",\"contentUrl\":\"https:\/\/jacobncalvert.com\/blog-archive\/wp-content\/uploads\/2019\/12\/coding-computer-data-depth-of-field-577585.jpg\",\"width\":1280,\"height\":959},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#webpage\",\"url\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/\",\"name\":\"Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support - Jacob N Calvert\",\"isPartOf\":{\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#primaryimage\"},\"datePublished\":\"2019-12-22T06:49:50+00:00\",\"dateModified\":\"2019-12-22T15:52:01+00:00\",\"author\":{\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/#\/schema\/person\/f4b22a996d41bf09ed2bbe22912a8c8a\"},\"breadcrumb\":{\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/\",\"url\":\"https:\/\/jacobncalvert.com\/blog-archive\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/2019\/12\/22\/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support\/#webpage\"}}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/#\/schema\/person\/f4b22a996d41bf09ed2bbe22912a8c8a\",\"name\":\"Jacob\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/jacobncalvert.com\/blog-archive\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/64a2dd1c00cb39dfc19bb1204c87efbc?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/64a2dd1c00cb39dfc19bb1204c87efbc?s=96&d=mm&r=g\",\"caption\":\"Jacob\"},\"sameAs\":[\"https:\/\/jacobncalvert.com\"],\"url\":\"https:\/\/jacobncalvert.com\/blog-archive\/author\/jcalvert\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/posts\/581"}],"collection":[{"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/comments?post=581"}],"version-history":[{"count":27,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/posts\/581\/revisions"}],"predecessor-version":[{"id":612,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/posts\/581\/revisions\/612"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/media\/586"}],"wp:attachment":[{"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/media?parent=581"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/categories?post=581"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jacobncalvert.com\/blog-archive\/wp-json\/wp\/v2\/tags?post=581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}