<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Phil Wilson</title>
    <description>The latest articles on DEV Community by Phil Wilson (@phildwilson).</description>
    <link>https://dev.to/phildwilson</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F509284%2Fc5dfddb4-527d-48be-8297-0f083ad25808.jpeg</url>
      <title>DEV Community: Phil Wilson</title>
      <link>https://dev.to/phildwilson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phildwilson"/>
    <language>en</language>
    <item>
      <title>Learning: First principles and patterns</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Wed, 16 Feb 2022 11:46:23 +0000</pubDate>
      <link>https://dev.to/phildwilson/learning-first-principles-and-patterns-3d7m</link>
      <guid>https://dev.to/phildwilson/learning-first-principles-and-patterns-3d7m</guid>
      <description>&lt;p&gt;Oscar, 5, finished his breakfast this morning, jumped down from his seat with a bottle of water in his hand, and washed down the last mouthful. All in one fluid motion. Then he stood there for several seconds, motionless, his face frozen in deep thought. I watched him from the other side of the room as I sipped the first coffee of the day, trying to guess what was happening in his young mind. Eventually his eyes began to move again, and he turned his head to me, his expression changing to one of confusion. "Dad" he began "I've always wondered why when we drink, we can just swallow, but with food we need to chew.".&lt;/p&gt;

&lt;h2&gt;
  
  
  Perception vs Conception
&lt;/h2&gt;

&lt;p&gt;I've observed in some friends and family that when a child asks them a question, they rush to answer it. And when they do they often tend to tell the child the answer, as if plucking a memory from their brain. The memory is how they perceive the answer. A story. An interpretation of how their senses tell them the reason "why". Here this type of answer would have been something like: "We need to chew our food so that we can swallow it." or maybe "If we don't chew our food it gets stuck in our throat". &lt;br&gt;
This does convey an answer, and it's in no way wrong. The child will come away with an adequate model of why it's best to chew their food, and not try to swallow it whole like a snake consumes an egg. But that answer is like taking a model of understanding from one person's brain, and merely trying to copy it into another's. Forcing a memory to exist, whole, fully-formed.&lt;/p&gt;

&lt;p&gt;Recently I got a 3D printer and began the learning curve of moving from bits of stringy plastic emerging to decent quality prints. I felt the urge to find other people's perceptions on how to do this. To copy their mental model into my brain. But I knew I had to understand the principles, and build up my understanding of HOW to print good quality items. And, as it happens, everyone I spoke to about printing has also told me to take my time and understand the why. As a result, my learning has been quite swift. I can reason questions for myself by logically inferring the answer from the things I already know. When I do get chance to speak to someone already knowledgeable about the subject, I can ask focused questions, validate the principles I've learned and get concise answers back. I am conceiving the answers.&lt;/p&gt;

&lt;p&gt;The difference in result between giving someone a perceived answer and helping them conceive the answer, in my opinion, is a stronger, more lasting understanding. With a perceived answer you are relying on the recipient using their memory to store your mental model. With conceived learning, you are helping them to understand the principles behind the answer and facilitate them constructing them logically into a model they build themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patterns
&lt;/h2&gt;

&lt;p&gt;The other thing that learning from first principles gives someone, is the opportunity to find patterns. Different experiences of learning often build on top of the same principles, and so patterns of principles form which re-enforce the new understanding. I'm no neuro-scientist, but I do know that the brain is structured as neural pathways connecting neurons together. And it seems logical that learning principles and connecting them with patterns would cause a brain to re-enforce that same structure within the brain, making a stronger understanding, than trying to store an abstract mental model gleaned from another source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we chew?
&lt;/h2&gt;

&lt;p&gt;As Oscar came over to me, to better hear the answer he expected me to give, I wafted the air with my hand so that it blew onto his face. "What's that you can feel?" I asked. "The air" he said, with eyes wide and focused. "Is it a liquid?" I went on. "No" and he paused, "it's a gas!". We reminded ourselves about the 3 states of matter, and spoke about how water can be a vapor, a liquid or ice. "Could you swallow an ice cube" I asked. "No, but I could suck it until it turns to water, and then drink it" Oscar replied. "Yes!" I said, "and could you swallow that sugar cube we did that experiment with the other day?" I asked, linking him back to an investigation we did about things dissolving. "No, but when it dissolved I could drink it!". "Can you remember what happened when we smashed a sugar cube and stirred it in the water?" I asked. "It dissolved quicker!" Oscar said, the patterns forming, his face lit up.&lt;/p&gt;

&lt;p&gt;"So why do we chew our food, Oscar?" I asked.&lt;br&gt;
"Because we need to try and turn it into a liquid so that it can go into our tummy" he said confidently. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Serendipity Engineering - part 1</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Tue, 15 Feb 2022 09:13:14 +0000</pubDate>
      <link>https://dev.to/phildwilson/serendipity-engineering-part-1-15d1</link>
      <guid>https://dev.to/phildwilson/serendipity-engineering-part-1-15d1</guid>
      <description>&lt;p&gt;Back in the summer of 2021 I spent 5 weeks making a Raspberry Pi into a box of puzzles, for no other reason than for fun. It's one of the most valuable things I have ever done at &lt;a href="http://balena.io"&gt;balena&lt;/a&gt;. Here's why:&lt;/p&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Since balena is a remote-first company we put a lot of thought into making sure we try to connect with each other and have fun. In the past one of the ways we did this was to spend a week, once or twice a year, to physically collect together and spend time with each other. We call these sessions Summit, and there will usually be some swag there, such as devices and SD cards and sensors, t-shirts and hoodies and snacks. However, for obvious reasons, in the last couple of years we have been unable to fly the team around the world and spend time together in the same building, so our summits have had to move to a virtual event. The first time this happened, in 2020, a group of people at balena decided to build a project (the &lt;a href="https://github.com/balenalabs/inkyshot"&gt;inkyshot&lt;/a&gt; ) and send one to everyone on the team as part of the swag box. The idea was that it was connecting to all be receiving the same message, initially about summit itself, but latterly to share quotes and insights.&lt;/p&gt;

&lt;p&gt;In 2021, about 6 weeks before summit, one of the team rang me up and asked if I had any ideas for a device we could build and send in that year's swag. Of course I did. I rarely have zero ideas. :) However 2021 had an additional constraint: &lt;a href="https://en.wikipedia.org/wiki/2021_Suez_Canal_obstruction"&gt;a boat got stuck&lt;/a&gt; and suddenly buying hardware components became almost impossible. With only 6 weeks to think of an idea, design it, build a proof of concept, buy ~100 sets of hardware, build them and send to the four corners of the earth... it was never going to happen.&lt;br&gt;
Then the idea struck me - what if we relied on the hardware the team already had, and just gave them some software? Some fun software....&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;So before we get into the details of the idea, let's address the crux of the post: why did I spend 5 weeks (it took me a whole week to think about it) on a puzzle for the team? Worse-still, I recruited a bunch of other balenistas to help me. So why did I spend 5 weeks of several people's time, making a puzzle?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lajAxGme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v57mvvo684eupg82vdxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lajAxGme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v57mvvo684eupg82vdxk.png" alt="definition of serendipity" width="880" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When &lt;a href="https://allthingsd.com/20130222/physically-together-heres-the-internal-yahoo-no-work-from-home-memo-which-extends-beyond-remote-workers/"&gt;Yahoo banned&lt;/a&gt; it's employees from working at home, it stated:&lt;/p&gt;

&lt;p&gt;"Some of the best decisions and insights come from hallway and cafeteria discussions, meeting new people, and impromptu team meetings."&lt;/p&gt;

&lt;p&gt;Whilst I don't agree with the decision Yahoo made, I do agree that good things happen when people hang out together and hack on stuff. So how do we do that at balena, a remote-first company, when we don't have a coffee machine to linger around? We enable everyone to self-organise into projects to build something together, and have fun doing it. &lt;/p&gt;

&lt;p&gt;This puzzle project I had conceived, quickly snowballed from an idea which raised a slight smirk when I told a select few people (the project was kept secret until summit), to one erupting with lessons learned, product feedback and possible future use-cases. It might even turn into another official balena product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea in a nutshell
&lt;/h2&gt;

&lt;p&gt;The idea was to provide the balenistas with nothing more than an SD card and a postcard printed with a QR code. The code would lead them to an &lt;a href="https://www.balena.io/blog/the-road-to-multi-app-transitioning-balenacloud-applications-to-fleets/"&gt;open fleet&lt;/a&gt; on &lt;a href="http://hub.balena.io"&gt;balenaHub&lt;/a&gt; which they could then join by flashing the SD card and popping it into a device they already had. The instructions on the fleet card in hub told them to open &lt;code&gt;http://cattlegrid.local&lt;/code&gt; on a browser, which opened a web server now running on their RaspberryPi device. Here's how it looked:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7tDPQ8t---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5rsprazs8i5myqimqar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7tDPQ8t---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5rsprazs8i5myqimqar.png" alt="Quorum" width="880" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quorum is the minimum number of participants in a system to make it work, and at balena we use the term to mean the number of people who've joined a meeting before we kick off. This was a hark back to a previous teammate, Shaun, who used to say it all the time at the start of the weekly team meeting. I wanted this puzzlebox to tell some of the folklore to new balenistas and stir memories to those that have been here a while.&lt;/p&gt;

&lt;p&gt;The "Devices in the herd" line would lead teammates to add more devices to the open fleet, until quorum was reached (60/100) upon which the site would redirect to a page with this image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MnfxKyki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga6lkpus5ingfu2n7nl1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MnfxKyki--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ga6lkpus5ingfu2n7nl1.png" alt="Raspberry pi board" width="880" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The page also had a textbox and a submit button.&lt;/p&gt;

&lt;p&gt;The idea was that the user had to try and find more puzzles to solve, by inspecting the device, and each puzzle would provide a code. By entering that code, a centralised API (running on an edge device in my house, obvs) would register that the puzzle had been solved, and everyone's fleet would show the updated count of puzzles solved. This fleet was a &lt;strong&gt;team&lt;/strong&gt; effort to find the puzzles and solve them to get the codes. :)&lt;/p&gt;

&lt;p&gt;The picture of the pi was actually another hark back to some balena folklore. Alex (CEO) had sat with Chris (hairy labs geezer) looking at a pi together, trying to spot what every chip and port on it was, and whether they could think of a labs project for each one. Here I wanted a puzzle for each.&lt;br&gt;
Additionally, I wanted all of the team to have a physical device in their hands (or on the desk) which they then needed to interact with. It occurred to Chris and I during this project that not everyone on the team has had this experience of physical computing. Actually making the device do something, like light an LED, or produce a noise. Connecting GPIO pins together with wires, making stuff happen! We thought it was super valuable to give the whole team the experience of interacting with real hardware.&lt;/p&gt;

&lt;p&gt;Which brings me onto an example of a puzzle. There were puzzles hidden as WiFi access points, bluetooth pairing challenges, digital steganography delivered through the HDMI port, audio clues though the 3.5mm jack, and more. But the first one I made was using the GPIO pins. When the user clicked the pins on the picture of the pi, they got redirected to this page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JivQRdUM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5sn3wawf538iie675d6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JivQRdUM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5sn3wawf538iie675d6x.png" alt="Pi GPIO Puzzle" width="880" height="1020"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This puzzle needed them to earth the pins in a particular sequence, to unlock the code. And any wrong pin earthed, took them back to the beginning of the sequence. :D&lt;br&gt;
I loved this one, because it made people use wires and pins and interact with the device in a way a lot of the team probably hadn't before.&lt;/p&gt;

&lt;p&gt;A counter on this page told the team how many puzzles could be found and solved on the device, and when they solved all the puzzles....they were sent to a website (running on a NUC in my house) where there were MORE puzzles to solve:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q4hfcRQj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8wmks5x0jgxlidtvnrc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q4hfcRQj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8wmks5x0jgxlidtvnrc.png" alt="Cattlegrid API" width="880" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actually this is an old screengrab, we ended up with 33 puzzles for the team on this page. Each one uses a &lt;a href="https://www.balena.io/docs/learn/deploy/deploy-with-balena-button/"&gt;Deploy With Balena&lt;/a&gt; button, which puts the puzzle onto the users device. They then have to find and solve the puzzle, and put the resulting code into the main website to tick it off. The range of puzzles we had here was amazing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;turning the pi into an FM transmitter with a GPIO wire antenna, and using text-to-speech to broadcast the code&lt;/li&gt;
&lt;li&gt;having to learn and navigate the &lt;a href="https://www.balena.io/os/docs/architecture/#Image-Partition-Layout"&gt;balenaOS image partitions&lt;/a&gt; to find otherwise hidden files&lt;/li&gt;
&lt;li&gt;using the &lt;a href="https://www.balena.io/docs/learn/develop/hardware/i2c-and-spi/#using-uart-or-serial-on-raspberry-pi-3"&gt;UART GPIO pins&lt;/a&gt; to form a loopback&lt;/li&gt;
&lt;li&gt;cryptography puzzles&lt;/li&gt;
&lt;li&gt;balena trivia quiz puzzles&lt;/li&gt;
&lt;li&gt;morse code LED puzzles
.....etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we could also make puzzles that relied on additional hardware, since that just caused the team to work together to find someone with that hardware. I made a version of the &lt;a href="https://www.itsnicethat.com/features/taneli-armanto-the-history-of-snake-design-legacies-230221"&gt;Nokia Snake game&lt;/a&gt; that used a &lt;a href="https://www.raspberrypi.com/products/sense-hat/"&gt;SenseHAT&lt;/a&gt;, which necessitated someone getting a high enough score to make it display the code. Not everyone has a SenseHAT, but I knew SOMEONE on the team would. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Next part
&lt;/h2&gt;

&lt;p&gt;In the next post I'll explain how I managed to deliver to build an open fleet, an API and puzzle frontend, 33 deploy with balena puzzles, 7 open fleet puzzles, all tested and proven working inside 5 weeks WITH NO DEDICATED RESOURCES. No orders, no hierarchy, just pure &lt;a href="https://www.game-b.org/"&gt;gameB&lt;/a&gt; ways of working with others. :)&lt;/p&gt;

</description>
      <category>balena</category>
      <category>iot</category>
    </item>
    <item>
      <title>balena - 24 months in</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Mon, 14 Feb 2022 13:24:26 +0000</pubDate>
      <link>https://dev.to/phildwilson/balena-24-months-in-1ch5</link>
      <guid>https://dev.to/phildwilson/balena-24-months-in-1ch5</guid>
      <description>&lt;p&gt;When I had been at balena for 12 months, I wrote a &lt;a href="https://dev.to/phildwilson/balena-12-months-in-59bd"&gt;blogpost&lt;/a&gt; about my experience so far. That post allowed me to explore my own thoughts, but it also seemed to help other people inside and outside of the company to read about my experiences. So here's the next "exciting" installment.&lt;/p&gt;

&lt;h2&gt;
  
  
  2021 - 2022
&lt;/h2&gt;

&lt;p&gt;Straight away I'm having to browse my calendar from this time last year, to try and remember what I was doing. And that's a good sign that I don't reflect back enough, and probably lose sight of things I have accomplished.&lt;br&gt;
But here's a short list of things I've focused on in the past 12 months:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Interviewing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I've become much more involved with the hiring process at balena, especially running a  system design task which we ask all candidates to do. I've really enjoyed hanging out with the candidates, and trying to help shape the hiring process at balena. I'm passionate about it being &lt;strong&gt;fun&lt;/strong&gt; for everyone, the candidate and the balenista. I don't want any power dynamic, I want us to be hacking on something together, and seeing if we both feel like it's a good, two-way, fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Coaching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I've also spent a great deal of time trying to help some people at balena who need some extra guidance with their career and with things they are working on. Candidly I've found this hard, and I'm still trying to find my way here. I care about these people, and I want them to succeed, but I'm yet to find the way to efficiently help them do that. My early approaches saw me lose a LOT of my own time and energy, and begin to lose my way with my own work. Subsequent approaches have been too "hands off" and the relationship dwindles. Definitely a WIP.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Blocks&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Blocks are like code packages but for containerised applications. It's not a concept I own or control, but I am a passionate advocate for it and chief cheerleader. I've continued to make some blocks, but mostly my focus in the past year has been about communicating about blocks and encouraging others to get involved. The number of blocks on &lt;a href="http://hub.balena.io/blocks"&gt;hub.balena.io&lt;/a&gt; has grown from 5 to almost 40, despite a pretty terrible (soon to be sorted) experience for adding them there. I've also noticed the wonderful signs of the concept gaining momentum. People are PRing fixes and features to the blocks repos on GitHub. People are answering questions about blocks in the forums. Developers inside and outside of balena are using blocks and &lt;strong&gt;making&lt;/strong&gt; blocks that could help others.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Labs residencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once it became clear, to a few of us, that the way people tried to onboard to balena was not fit for purpose, we decide to try another way: asking new joiners to spend a month in the labs making a project of their choosing. This became the labs residency programme. I wrote more about it &lt;a href="https://www.balena.io/blog/balenalabs-residencies-our-quest-to-improve-onboarding-at-balena/"&gt;here&lt;/a&gt;. Part of that programme is having experienced balenistas guide them, which I wrote about &lt;a href="https://balenaltd.io/phil-d-wilson/blog/labs-residency-guides/"&gt;here&lt;/a&gt;. Candidly, this has been &lt;strong&gt;HARD&lt;/strong&gt;. There have been times I have wished I hadn't started it. There have been times this caused me a significant decline in my mental health. But I think this might have been the most worthwhile use of my energy so far at balena. We're only 8 months into running this programme, but I'm hearing good feedback, I'm seeing new joiners finding their way inside balena with more ease, and the momentum is growing. Over the next 12 months I want the whole residency programme to be run and developed by the whole company, without any dependence upon me. And I want to see it to be expanded, to cover cases we haven't explored yet: such as people joining balena &lt;strong&gt;only&lt;/strong&gt; to do a residency, while they build a product on balena, and then go seek funding for it. Like a product incubator. I'd love to see that! &lt;/p&gt;

&lt;h2&gt;
  
  
  Personal Growth
&lt;/h2&gt;

&lt;p&gt;My technical skills are still growing all the time. I had never used Docker before I joined balena, so I've always had a steep learning curve here, and that's fine with me. I'm constantly getting myself involved in things I don't know how to do, and then working with others to do them. So naturally my technical skills continue to evolve.&lt;br&gt;
But I'm actually more interested in how my non-technical skills are growing. Here's some things I've observed:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;sunk cost and Occam's razor&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When I am excited about an idea, like a toddler with a new crayon, I just &lt;em&gt;have&lt;/em&gt; to go and work with it. My brain is &lt;strong&gt;obsessed&lt;/strong&gt; and I'll get no inner peace until I've scratched the itch to hack on the idea. That doesn't mean I rush in without thinking it through - that happens all the time I cannot physically hack on it. My brain will be whirring through designs and solving problems every moment that I am not asleep. And then after a while I will have something I want to share with others. In the past when those people then gave me feedback, sometimes it would contain views that my thing was too complicated. Maybe they would question why some, or all, of it needed to be there at all. They would question if there was a "need" for something I had made. &lt;/p&gt;

&lt;p&gt;On several of these occasions I experienced an almost "out of body" experience where I saw myself explaining why something was in my product, and realised I was defending it because of emotional reasons. I'd spent time making it. I remembered the hard work to get it to function. I had imagined a future user finding it useful and being happy. I had emotionally motivated reasoning for the thing, not a logical reason for the thing. A sunk cost.&lt;/p&gt;

&lt;p&gt;I still do this, to a degree. But I am a LOT better at noticing when this is happening, and correcting myself. I try to implement the simplest thing, not the most configurable thing. And I've also noticed that I'm noticing where things can be simplified more often in other places within balena. For instance it occurred to me that checking references as part of the hiring process took up a lot of people's time (not mine) and never actually contributed to our decision to hire or not. So I advocated for us to stop doing that. I love the fact I can get involved anywhere in the company, advocate for change and that change happens if when we all logically agree, not because I am or am not more senior than someone else. :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Assuming positive intent
&lt;/h3&gt;

&lt;p&gt;This is another one I continue to get better at, but with more to do: assuming that someone's behaviour comes from a place of positive intent, and any aspects that seem negative are communicating they need more help. &lt;/p&gt;

&lt;p&gt;There's something about my upbringing, or previous career experience, or both, that makes my brain sometimes jump to negative conclusions when someone does something I disagree with. Especially so if I am really convinced it's a behaviour that is counter to the culture we're trying to grow at balena. But by talking these events occur I make sure I talk them through with someone else, who's ability to see positive intent is more honed than mine (I'm looking at you Alison, Chris and Andrew) and actively try to challenge my own thoughts about the person and what happened.&lt;/p&gt;

&lt;p&gt;More and more I am noticing my own thoughts can initially seize upon an event negatively, and then catch hold of themselves and course correct. I'm still not perfect, but I'm making significant progress here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimise for fun!
&lt;/h3&gt;

&lt;p&gt;I say this a lot, and my certainty that it's THE most important thing to focus on in work and life, is all the more resolute. Just as I am sure that only happy children learn to their potential, only happy people build products to their potential. I think there are only a very few things that are not made better by having fun whilst doing them (the dentist is NOT a fun place...). At balena hiring should be fun. Testing things should be fun. Meetings should be fun. &lt;/p&gt;

&lt;p&gt;In my personal life I am &lt;strong&gt;determined&lt;/strong&gt; that fun is priority numbers 1, 2, 3 and 4. Everything else is low down the list. My children's learning &lt;strong&gt;must&lt;/strong&gt; be fun. There is a phrase we have at home: "it's fun, or it's not done" and both of my children are empowered to stop doing anything they find not fun. Same goes for me. :)&lt;br&gt;
When we clean the house, we put loud music on, sing loudly, dance like nobody is watching and clean at the same time. When we wash the car, we have a hosepipe fight and giggle about spraying the hose over next door's hedge. Bedtime is spent enjoying reading stories together, the love of language, giggling at characters until we feel sleepy enough to sleep. It's fun, or it's not done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;Well, I can't predict the future, so I don't know for sure. But a bit of staring into the void leads me to believe my path in the next 12 months looks something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explore the boundaries of what we can do with the labs residency&lt;/li&gt;
&lt;li&gt;continue to push for improvements to the blocks developer experience&lt;/li&gt;
&lt;li&gt;get more involved in generating outreach content to communicate the balena culture&lt;/li&gt;
&lt;li&gt;experiment with ways of working more and more in the open&lt;/li&gt;
&lt;li&gt;MORE FUN!!!!!&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Lightweight .NET5 containers on balena</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Sat, 30 Jan 2021 17:14:16 +0000</pubDate>
      <link>https://dev.to/phildwilson/lightweight-net5-containers-on-balena-55dh</link>
      <guid>https://dev.to/phildwilson/lightweight-net5-containers-on-balena-55dh</guid>
      <description>&lt;p&gt;Before joining balena I was a pure .NET guy. I've been coding .NET since it was released in 2002, back when I was a university student actively avoiding lectures on &lt;a href="https://en.wikipedia.org/wiki/ALGOL"&gt;ALGOL&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Joining balena saw me take a break from .NET and focus my energy on learning the balena stack and improving my docker, python and node.js skills. Lately, however, I've had the itch for .NET again, mostly so that I can play with &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0/"&gt;.NET5&lt;/a&gt;. I had dabbled with &lt;a href="https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor"&gt;Blazor&lt;/a&gt; in my &lt;a href="https://github.com/balenalabs-incubator/balena-locating"&gt;balenaLocating&lt;/a&gt; project but hadn't paid very much attention to the docker image size. I was so focused on releasing my first ground-up project, which was all my own code, that I merely used a &lt;a href="https://docs.docker.com/develop/develop-images/multistage-build/"&gt;multi-stage dockerfile&lt;/a&gt; and left it at that. The result is a ~300Mb image, for a single page webapp that doesn't do a whole lot.&lt;/p&gt;

&lt;p&gt;Surely we can do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan
&lt;/h2&gt;

&lt;p&gt;Since the, soon to be released, version 2 of the &lt;a href="https://github.com/balenablocks/browser"&gt;browser block&lt;/a&gt; has an API to dynamically configure it - I wanted to make a remote control for it. I'll use Blazor on .NET5, and explore some of the options to get the image size down to as small as possible.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting a baseline
&lt;/h2&gt;

&lt;p&gt;I knocked up a quick Blazor page which sends some API calls to the browser block and displays the results. Nothing complicated. Building that project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⚡ phil@DESKTOP-I18LU69  C:\Source\Balena_Playground\BrowserRemoteControl                                                                                                 [10:06]
❯ dotnet build
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET
Copyright (C) Microsoft Corporation. All rights reserved.   

  Determining projects to restore...
  All projects are up-to-date for restore.
  BrowserRemoteControl -&amp;gt; C:\Source\Balena_Playground\BrowserRemoteControl\bin\Debug\net5.0\BrowserRemoteControl.dll
  BrowserRemoteControl -&amp;gt; C:\Source\Balena_Playground\BrowserRemoteControl\bin\Debug\net5.0\BrowserRemoteControl.Views.dll

Build succeeded.        
    0 Warning(s)        
    0 Error(s)

Time Elapsed 00:00:10.16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;resulted in a HUUUUUUUUUUGE 1Mb executable. :D&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vkx8JPUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z0z9m0q7tt6w0fbl8mrn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vkx8JPUg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z0z9m0q7tt6w0fbl8mrn.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then I did a bog basic, single stage dockerfile to build the project and push it to my balena app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; balenalib/%%BALENA_MACHINE_NAME%%-debian-dotnet:5.0-sdk-buster-build as build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./src/* /usr/src/app/&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet restore

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt;  ["dotnet", "BrowserRemoteControl.dll"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;whoa!!!!!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Info]     Uploading images
[Success]  Successfully uploaded images
[Info]     Built on x64_01
[Success]  Release successfully created!
[Info]     Release: b15a7405a5be9ab5df4081bdc34d0678 (id: 1678274)
[Info]     ┌─────────┬────────────┬────────────┐
[Info]     │ Service │ Image Size │ Build Time │
[Info]     ├─────────┼────────────┼────────────┤
[Info]     │ main    │ 1.04 GB    │ 17 seconds │
[Info]     └─────────┴────────────┴────────────┘
[Info]     Build finished in 1 minute, 5 seconds
                            \
                             \
                              \\
                               \\
                                &amp;gt;\/7
                            _.-(6'  \
                           (=___._/` \
                                )  \ |
                               /   / |
                              /    &amp;gt; /
                             j    &amp;lt; _\
                         _.-' :      ``.
                         \ r=._\        `.
                        &amp;lt;`\\_  \         .`-.
                         \ r-7  `-. ._  ' .  `\
                          \`,      `-.`7  7)   )
                           \/         \|  \'  / `-._
                                      ||    .'
                                       \\  (
                                        &amp;gt;\  &amp;gt;
                                    ,.-' &amp;gt;.'
                                   &amp;lt;.'_.''
                                     &amp;lt;'
⚡ phil@DESKTOP-I18LU69  C:\Source\Balena_Playground\BrowserRemoteControl 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1Gb....! That's because I'm pulling the WHOLE .NET5 SDK, which I don't need just to run my little executable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multistage dockerfile
&lt;/h2&gt;

&lt;p&gt;First port of call is a multi-stage dockerfile. We don't need all of the build dependencies to run the .NET executable once it's built. So we can build it, and then copy the result into a slimmer run image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; balenalib/%%BALENA_MACHINE_NAME%%-debian-dotnet:5.0-sdk-buster-build as build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./src/* /usr/src/app/&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet restore

&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet publish &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/src/app/publish

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; balenalib/%%BALENA_MACHINE_NAME%%-debian-dotnet:5.0-aspnet-run&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /usr/src/app/publish .&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt;  ["dotnet", "BrowserRemoteControl.dll"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Success]  Release successfully created!
[Info]     Release: 09beeb66c9be98cc10f362c14a4519c0 (id: 1678468)
[Info]     ┌─────────┬────────────┬────────────┬────────────┐
[Info]     │ Service │ Image Size │ Delta Size │ Build Time │
[Info]     ├─────────┼────────────┼────────────┼────────────┤
[Info]     │ main    │ 280.44 MB  │ 666.39 KB  │ 1 second   │
[Info]     └─────────┴────────────┴────────────┴────────────┘
[Info]     Build finished in 56 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK! So we're down to 280Mb just by using a multi-stage dockerfile and not keeping all the build dependencies. This is on par with my previous Blazor project....but there's more to be done. Let's play with an Alpine image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving the Alpine
&lt;/h2&gt;

&lt;p&gt;Alpine is a lightweight linux distribution. We can use it to make smaller images for our containers, but the onus is pushed onto the developer to make sure all the runtime dependencies are there. For this project, I need to make sure the .NET5 runtime deps are installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; balenalib/%%BALENA_MACHINE_NAME%%-debian-dotnet:5.0-sdk-buster-build as build&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./src/* /usr/src/app/&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet restore &lt;span class="nt"&gt;--runtime&lt;/span&gt; linux-musl-x64

&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet publish &lt;span class="nt"&gt;-r&lt;/span&gt; linux-musl-x64 &lt;span class="nt"&gt;-p&lt;/span&gt;:PublishSingleFile&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/src/app/publish

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; balenalib/%%BALENA_MACHINE_NAME%%-alpine as run&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;install_packages ca-certificates &lt;span class="se"&gt;\
&lt;/span&gt;        krb5-libs &lt;span class="se"&gt;\
&lt;/span&gt;        libgcc &lt;span class="se"&gt;\
&lt;/span&gt;        libintl &lt;span class="se"&gt;\
&lt;/span&gt;        libssl1.1 &lt;span class="se"&gt;\
&lt;/span&gt;        libstdc++ &lt;span class="se"&gt;\
&lt;/span&gt;        zlib

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DOTNET_SYSTEM_GLOBALIZATION_INVARIANT 1&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; ASPNETCORE_URLS=http://+:80&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DOTNET_RUNNING_IN_CONTAINER=true&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /usr/src/app/publish .&lt;/span&gt;

&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt;  ["./BrowserRemoteControl"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see there, that I'm using an Alpine image and using &lt;code&gt;install_packages&lt;/code&gt; to bring in the .NET runtime dependencies. Then I do a couple of ENV statements to set the container up for running an AspNetCore HTTP server (Kestrel) and run the compiled executable.&lt;/p&gt;

&lt;p&gt;And the image size? Well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Success]  Release successfully created!
[Info]     Release: ce1f65a85e457b4c8a116cbc933262b9 (id: 1678500)
[Info]     ┌─────────┬────────────┬────────────┬────────────┐
[Info]     │ Service │ Image Size │ Delta Size │ Build Time │
[Info]     ├─────────┼────────────┼────────────┼────────────┤
[Info]     │ main    │ 157.69 MB  │ 0 bytes    │ 1 second   │
[Info]     └─────────┴────────────┴────────────┴────────────┘
[Info]     Build finished in 38 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;157Mb! That's great.&lt;br&gt;
...&lt;br&gt;
But there's even more.&lt;/p&gt;
&lt;h2&gt;
  
  
  .NET publishing optimisations
&lt;/h2&gt;

&lt;p&gt;.NET now has a few tricks up it's sleeve to get your image size down even smaller. These are:&lt;/p&gt;
&lt;h3&gt;
  
  
  -p:PublishSingleFile=true
&lt;/h3&gt;

&lt;p&gt;Create a single file distributable, rather than an exe and a bunch of DLL dependencies&lt;/p&gt;
&lt;h3&gt;
  
  
  --self-contained true
&lt;/h3&gt;

&lt;p&gt;Package the .NET runtime in with the executable, so that we don't need a runtime to be installed. Note this was also in the Alpine step above, but I've explained it here. :)&lt;/p&gt;
&lt;h3&gt;
  
  
  -r linux-musl-x64
&lt;/h3&gt;

&lt;p&gt;The self-contained file needs to target a device architecture (otherwise it would need to target them all and waste space). I'm running this experiment on my Intel NUC, so I'm targeting x64, and since it's an Alpine image I need to target the musl C library. The choice of RIDs (runtime identifies) can be found &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/rid-catalog#linux-rids"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  -p:PublishTrimmed=True
&lt;/h3&gt;

&lt;p&gt;Here's the magic part: bundle trimming. This step causes the source to be analysed (it takes a few minutes) and unnecessary .NET framework components removed from the published executable.&lt;/p&gt;
&lt;h3&gt;
  
  
  -p:TrimMode=Link
&lt;/h3&gt;

&lt;p&gt;More magic. In a nutshell, without this parameter the resulting executable will have the whole of a framework assembly, even if only a part of it is being used. With this option, each member of each assembly is assessed, and only those being referenced will be included. This worked find for me, but I have seen reports of runtime issues - so YMMV. Not setting this for my project causes a difference of ~10MB, so do some testing or just err on the side of caution and leave this optimisation out.&lt;/p&gt;
&lt;h2&gt;
  
  
  Final result
&lt;/h2&gt;

&lt;p&gt;So now the publish line in my dockerfile from above looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;publish&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PublishSingleFile&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;musl&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x64&lt;/span&gt; &lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;contained&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PublishTrimmed&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;TrimMode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Link&lt;/span&gt;  &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Release&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;publish&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which gives me a final image size of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Success]  Release successfully created!
[Info]     Release: 621d73fa5676e5924f7a885726bc20d5 (id: 1678525)
[Info]     ┌─────────┬────────────┬────────────┬────────────┐
[Info]     │ Service │ Image Size │ Delta Size │ Build Time │
[Info]     ├─────────┼────────────┼────────────┼────────────┤
[Info]     │ main    │ 95.06 MB   │ 23.78 MB   │ 48 seconds │
[Info]     └─────────┴────────────┴────────────┴────────────┘
[Info]     Build finished in 1 minute, 30 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;95Mb down from the baseline of 1Gb. Sweet!&lt;/p&gt;

&lt;h2&gt;
  
  
  So what?
&lt;/h2&gt;

&lt;p&gt;So, if you're thinking about using .NET in docker, including a balena app, then take a look into multi-stage Alpine dockerfiles with some publish optimisation. You can pack quite a lot of functionality into a pretty small image.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>balena</category>
      <category>dotnet</category>
      <category>blazor</category>
      <category>docker</category>
    </item>
    <item>
      <title>Pandemic brain</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Sun, 24 Jan 2021 12:06:00 +0000</pubDate>
      <link>https://dev.to/phildwilson/pandemic-brain-271a</link>
      <guid>https://dev.to/phildwilson/pandemic-brain-271a</guid>
      <description>&lt;p&gt;I joined balena from a startup company where I was the CTO, and the technical architect....and the lead developer.....and technical pre-sales....and directly involved with convincing the investors to keep investing to keep the company afloat. Back then I couldn't think long term. I had to fix that bug to keep the customer happy else they refused to pay. I had to design and develop yet another solution to yet another use case that the customer HAD to have, or they would refuse to pay. The very most I could ever think about, was getting through the next day.&lt;/p&gt;

&lt;p&gt;When I joined balena it took me at least 6 months to allow my brain to think long term. balena practice "short term pain for long term gain", or let's do the right thing and solve for the future rather than just the quick win that we have to re-fix later. Several times I would see a problem and propose a quick fix, as was my conditioned mentality, only to be told the real solution was a much bigger piece of work. I needed patience, and I needed long-term thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Healing and unlearning
&lt;/h2&gt;

&lt;p&gt;With enough time and the empathetic guidance of great colleagues I was able to let go of that need to fix the now. I focused my attention on some long term pieces of work such as &lt;a href="https://www.balena.io/blog/introducing-balenablocks-jumpstart-your-iot-app-development/"&gt;balenaBlocks&lt;/a&gt;, and found/made my place in the company mission.&lt;/p&gt;

&lt;h2&gt;
  
  
  A return to short-term thinking
&lt;/h2&gt;

&lt;p&gt;However, recently I have realised I've reverted back to old habits. Twice in the past couple of weeks those same empathic colleagues have had to point out that I'm trying to solve a problem now, not build the product that solves that and many other problems later. So why has this happened?&lt;/p&gt;

&lt;h3&gt;
  
  
  Pandemic mentality
&lt;/h3&gt;

&lt;p&gt;After giving it some thought, I realised that the current world situation has caused me to think in short timeframes. On the Sunday the prime minister says the children will go to school. On the Monday evening he closes all the schools. One day my wife's business is running. The next day it has to close again. One day someone I love is healthy. The next day they are not.&lt;/p&gt;

&lt;p&gt;My brain is back to just thinking about 1 day at a time. Actually sometimes it's been as granular as thinking about the next couple of hours. How do I have that meeting, whilst helping two children home school? How do I concentrate on the bug I'm figuring out, when my elderly neighbours are unable to get a food delivery?&lt;/p&gt;

&lt;h3&gt;
  
  
  A need for quick wins
&lt;/h3&gt;

&lt;p&gt;It's not just me. I've heard a number of colleagues say "I need a quick win" recently. Dopamine is in short supply after multiple national lockdowns and social isolation. Sources of fun have reduced: the pubs are closed, the shops are shut, leisure activities are now not allowed. I almost can't remember taking the children swimming. Long gone are the days of wandering through a town and spontaneously stopping somewhere for some food. Holidays...ha!&lt;/p&gt;

&lt;p&gt;I'm not at all surprised that my brain is jumping to short term yay over short term pain. I've plenty of pain. My brain is swimming in it. I guess it's a form of &lt;a href="https://en.wikipedia.org/wiki/Bounded_rationality"&gt;bounded rationality&lt;/a&gt;: something seems like the right thing to do, when my mentality is about survival in the now.&lt;/p&gt;

&lt;h2&gt;
  
  
  And so, what to do?
&lt;/h2&gt;

&lt;p&gt;Step one is done: I've reflect and noticed the thought patterns. I can't change the situation I'm in, so the only avenue for progress is to try and periodically remind myself of the goal and how I participate with my daily work. balena do a good job of communicating the mission, and have lately worked hard to break it down into multiple sagas. The &lt;a href="//hub.balena.io"&gt;hub&lt;/a&gt; is one of those sagas, and I know how to add to that story. I need to make sure I keep talking to colleagues, and recount the sagas. Our tribal ancestors used gatherings around the fire to recount stories and jointly sing songs. That practice of story telling and syncing keeps the tribe together, and deepens the impression of the future they are building.&lt;/p&gt;

&lt;p&gt;We also need to "find the fun". It's a phrase I say to my children so often they now eyeroll at it. But it's true: no day is perfect. Perfect isn't real. But whatever the day brings, there is fun to be found. Rain means jumping in puddles. A lockdown means we build a slide in the garden.&lt;/p&gt;

&lt;p&gt;There is no reason that work can't or shouldn't be fun. In fact, I think it's an imperative. People shouldn't need to find a quick win for that dopamine hit. We should make the time to laugh together and turn the short term pain into part of the game. If I had a big mound of shit to dig, the worst thing I could do is moan about it. Instead I would need to turn it into a game. Let's compete over who can dig the most shit in a day. Let's throw the shit into the wheelbarrow from the top of the pile. Let's sing silly songs about digging shit, do some dad dancing and make a shit castle complete with flag. Let's turn our spades into shit sledges. &lt;/p&gt;

&lt;p&gt;If we find a way to smile and laugh while we dig, one day there will be no more shit.&lt;/p&gt;

&lt;p&gt;Peace out.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>balena: 12 months in</title>
      <dc:creator>Phil Wilson</dc:creator>
      <pubDate>Wed, 20 Jan 2021 16:53:34 +0000</pubDate>
      <link>https://dev.to/phildwilson/balena-12-months-in-59bd</link>
      <guid>https://dev.to/phildwilson/balena-12-months-in-59bd</guid>
      <description>&lt;p&gt;In January 2020 I joined &lt;a href="http://balena.io" rel="noopener noreferrer"&gt;balena&lt;/a&gt; as a &lt;code&gt;Hardware Hacker in Residence&lt;/code&gt; or HHR as balena call them. I joined a group of other HHRs in, what is now known as, the balenaLabs team and started on my balena journey. My first few weeks were exciting and daunting in equal measure...and then 2020 happened. Here's a look back on my first 12 months at balena.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some background
&lt;/h3&gt;

&lt;p&gt;During my career I've worked for big corporations such as IBM and &lt;a href="https://www.cgi.com/en/overview" rel="noopener noreferrer"&gt;CGI&lt;/a&gt;, and have been embedded into Microsoft development teams. I've worked on Space, SatComm, UK Defence, National Security, Telecoms and Energy projects. I started working on IOT projects back when most people (in the UK, at least) hadn't heard the term. Back then I had to give those "20 billion devices by the year..." presentations and answer countless questions about internet connected fridges from loud men in bright trousers whom people still referred to as "Major".&lt;/p&gt;

&lt;p&gt;So I've been around a bit and experienced lots of different ways of working. I wasn't one of the people who had to learn how to do remote working in 2020 - as I've been a remote worker since my first son was born in 2011. &lt;/p&gt;

&lt;p&gt;However, nothing in my career before 2020 prepared me for what it's like to work at balena. Here's why:&lt;/p&gt;

&lt;h4&gt;
  
  
  Globally asynchronous
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwrow5zk7srrhvw45eh7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwrow5zk7srrhvw45eh7r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The first thing that struck me when I joined balena was that there was always someone online working and chatting. Although I'd worked on projects that spanned timezones, I'd never worked somewhere that spanned ALL the timezones. I was used to work communication stopping by about 6PM, so I never really had to think about notifications when I wasn't working. Back then I needed to see emails immediately, and reply ASAP, or else my peers would assume I'm not working, not dedicated, undeserving of a good annual review. It took me a good month to fully realise that balena meant it when they said "you don't need to answer everything straight away. We expect you to be async and reply whenever you can.". What that means is that I can turn off all my notifications. Nothing beeps at me any more. I don't constantly check emails or messages. I'm trusted to work when it fits in with my life, and to answer questions when it suits me and my brain.  &lt;/p&gt;

&lt;p&gt;The great benefit of this global team, though, is that there is almost always someone around to chat to, or hang out while we work. Often, during periods of national lockdown, I'll tend to family during the day and catch up on work in the evening, and hang out with some U.S colleagues while I do.&lt;/p&gt;
&lt;h4&gt;
  
  
  Organisation
&lt;/h4&gt;

&lt;p&gt;The next thing I needed to adapt to, was the way balena organises itself. No longer was I siloed into a given team, or an industry, or even a role. Sure I am a Hardware Hacker, and I tend to hang out in the labs, but literally nothing stops me from attending any meeting or getting involved with any piece of work technical or otherwise. All work is conducted in the open, so I can see all conversations, and contribute to anything I feel able.&lt;/p&gt;

&lt;p&gt;Nobody tells me what to do, and nobody "manages" me. We make huge efforts to make sure everyone knows and shares the mission, and then finds ways to contribute towards this. We collect together in brainstorm and checkin meetings, share our ideas and progress, and get genuinely excited about each others work.&lt;/p&gt;
&lt;h4&gt;
  
  
  Engineer-driven Support
&lt;/h4&gt;

&lt;p&gt;Nope, we don't do support like most other companies either. At balena all the technical people share support. We all do a few shifts per week, and we do this so that everyone gets to help customers, hear about issues and pain points, and dig into other bits of the stack which we might not otherwise touch. I'll be honest: support isn't my favourite part of the job, but it can be rewarding and does push me to learn more about system as a whole. This type of support puts the team into the user's shoes, and drives us to continuously make the product better and further reduce the friction of IOT.&lt;/p&gt;
&lt;h4&gt;
  
  
  Culture
&lt;/h4&gt;

&lt;p&gt;This is my favourite thing about balena. The people who work here are SO clever and so fun. Work meetings used to be the worst parts of my week. At balena, they are genuinely some of the best. We make sure we have fun together, because making work fun stops it feeling like work. We hack projects together. We play games together. Even our brainstorm meetings are a game. &lt;/p&gt;

&lt;p&gt;You can get a window into how we chill together by watching our IOT Happy Hour on youtube:  &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Mllay6Z2-qQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  First 12 months?
&lt;/h3&gt;

&lt;p&gt;Well what has it been like? Amazing. Genuinely. Despite a crazy global situation in 2020, for me it was a great year professionally. I met and got to know amazing people who have become close friends. I've learned a shed load about linux, docker, single board computers, node.js, python and lots more. I've written &lt;a href="https://www.balena.io/blog/make-yourself-a-security-camera-system-in-30-minutes-or-less/" rel="noopener noreferrer"&gt;blog posts&lt;/a&gt;, appeared on the IOT Happy Hour (--^) and M.C'ed &lt;a href="https://www.youtube.com/watch?v=H9WdDZooL4Q" rel="noopener noreferrer"&gt;release parties&lt;/a&gt; where we work live on YouTube and release a new feature. I've released labs &lt;a href="https://github.com/balenalabs-incubator/balena-locating" rel="noopener noreferrer"&gt;projects&lt;/a&gt; and put apps onto our &lt;a href="//hub.balena.io"&gt;hub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the first time in my professional life, I'm REALLY excited about the year to come. Let's go!&lt;/p&gt;

</description>
      <category>balena</category>
    </item>
  </channel>
</rss>
