<?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>Forem: Agastya Darma</title>
    <description>The latest articles on Forem by Agastya Darma (@gedeagas).</description>
    <link>https://forem.com/gedeagas</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%2F457120%2Fdf5fe6f9-303d-48a5-a24e-668252b2fbec.jpeg</url>
      <title>Forem: Agastya Darma</title>
      <link>https://forem.com/gedeagas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gedeagas"/>
    <language>en</language>
    <item>
      <title>Middle Management Is Hard</title>
      <dc:creator>Agastya Darma</dc:creator>
      <pubDate>Sat, 02 Nov 2024 01:48:10 +0000</pubDate>
      <link>https://forem.com/gedeagas/middle-management-is-hard-fi3</link>
      <guid>https://forem.com/gedeagas/middle-management-is-hard-fi3</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbigq5ech1ujqf1gdg43l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbigq5ech1ujqf1gdg43l.jpeg" alt="Cover Image" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lately, I’ve been reflecting a lot on the challenges of middle management, particularly after a conversation with a former coworker. Even though this individual isn’t a middle manager, their insights about feeling constant pressure from leadership really got me thinking. They described how leadership consistently pushes for higher performance and demands results, often without understanding the realities on the ground. It struck me that, while they bear the weight of these demands from leadership, middle managers face a similar pressure but from multiple directions.&lt;/p&gt;

&lt;p&gt;Being middle management is incredibly challenging. You are expected to balance pressure from all directions above, below, and even from the sides. My experience comes from the tech industry, but I believe these observations resonate across multiple sectors. Middle managers are the glue that holds organizations together, but they are often underappreciated and left to face unique struggles. Sandwiched between company leadership and employees, they must navigate conflicting demands, limited authority, and, at times, an overwhelming sense of isolation.&lt;/p&gt;

&lt;p&gt;In middle management, you constantly find yourself wedged between the high expectations of leadership and the needs of your subordinates. You're tasked with executing strategies from top management while simultaneously motivating and managing your team to deliver results. At times, you may agree with your team’s frustrations and concerns, yet you're still forced to put on a smile and enforce decisions that come from above, even when you didn’t have a hand in making them. It’s not uncommon for middle managers to find out about tough decisions such as budget cuts, reassignments, or new initiatives at the last moment, just like the rest of their team. This disconnection fuels a feeling of being left out or even powerless, yet you’re still tasked with being accountable for the success of your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Many Pressures Facing Middle Management
&lt;/h3&gt;

&lt;p&gt;Middle managers face a unique set of challenges that stem from being positioned between upper management and front-line teams. This intermediary space creates a range of pressures that require constant navigation.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Top-Down Pressure:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;At the core of middle management's struggles is top-down pressure. Leadership has high expectations for performance, efficiency, and goal achievement. Strategic decisions are made at the higher levels, but middle managers are often left in the dark, tasked with implementing orders without being part of the decision-making process. For example, Jack Zenger and Joseph Folkman, in their studies of employee engagement, found that middle managers, particularly those with five to ten years of experience, are often disillusioned because they feel undervalued. They’re given tasks to execute but have little say in policy-making, causing frustration and disengagement. Many employees under middle managers don’t realize that these managers are frequently just as frustrated with the decisions from the top.&lt;/p&gt;

&lt;p&gt;Middle managers, being closest to the workplace's actual dynamics, often have the most practical knowledge of what will and won’t work. However, they frequently find themselves informed about decisions after the fact and left to carry them out without the support or resources necessary for success. They are, in essence, expected to deliver results from policies in which they had no say.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Bottom-Up Frustrations:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;On the flip side, middle managers bear the brunt of employee frustrations. For example, in the study by Zenger and Folkman, middle managers are often seen as the “face of management,” and when things go wrong or decisions don’t make sense, employees direct their complaints at these middle-tier leaders. Team members may not be aware that many of their objections are shared by their manager. As Anicich and Hirsh describe in their research on role-switching, middle managers are stuck in a “vertical code-switching” dilemma, where they must alternate between being an authoritative leader and a deferential subordinate, often within the same day. &lt;/p&gt;

&lt;p&gt;This constant shifting takes a toll on mental and emotional well-being, leading to high levels of stress and emotional burnout. Middle managers are expected to maintain their team’s morale and motivation, even when upper management decisions leave them just as frustrated and powerless. They absorb complaints from below and directives from above with very little control of their own.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Side-to-Side Politics:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Middle managers also face significant peer pressure. Departments within organizations often operate in silos, and middle managers must compete with their peers for resources, recognition, and strategic visibility. Anicich and Hirsh emphasize that middle managers experience high levels of stress not only from above and below but also from their same-level colleagues. Whether it's negotiating resources, competing for development opportunities, or even juggling inter-departmental expectations, the middle manager experiences ongoing tension with little relief.&lt;/p&gt;

&lt;p&gt;In highly competitive corporate environments, especially fast-paced industries like tech, collaboration often turns into a tug-of-war among middle managers, each vying for more bandwidth, budget, or visibility with leadership. If one department doesn’t deliver, the middle manager will feel the pressure from their leadership, even when the root cause of the issue is entirely external.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Emotional Labor Involved
&lt;/h3&gt;

&lt;p&gt;One of the most unseen aspects of middle management is its emotional toll. Julie Zhuo, who became a manager at Facebook (now Meta) at the young age of 25, recalls her early experience feeling like she was "in over her head." Zhuo reflects on the constant emotional labor required to support her subordinates while projecting confidence to her higherups. Like many middle managers, Zhuo initially believed that leadership meant projecting unwavering authority, but she found that approach ultimately alienating. Over time, she realized that successful management was much more about fostering collaboration than rigid top-down decision-making.&lt;/p&gt;

&lt;p&gt;Middle managers often feel emotionally drained by the tension of mediating between the frustrations of their team and the demands of their leadership. Eric Anicich and Jacob B. Hirsh argue that middle managers experience high levels of "role conflict," where they're often caught between incompatible expectations. They must be empathetic to their subordinates while projecting confidence and competence to their superiors. This emotional balancing act places middle managers at a higher risk for burnout and mental health issues, including anxiety and depression, compared to employees at either end of the hierarchy.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Isolation of Middle Management
&lt;/h3&gt;

&lt;p&gt;Perhaps the most pervasive struggle faced by middle managers is the feeling of isolation. Both Zhuo and Zenger highlight how middle managers are often excluded from key strategic discussions. Many decisions are made at the executive leadership level, leaving middle managers responsible for enforcing and explaining these decisions, often without fully understanding them or having the opportunity to weigh in beforehand. The result is an overwhelming feeling of disconnect. You're expected to deliver results, but you’re not always given the tools or knowledge necessary to do so.&lt;/p&gt;

&lt;p&gt;A study cited by Anicich and Hirsh involving over 21,000 employees revealed that middle managers reported higher rates of anxiety, stress, and burnout than those in lower or upper-level positions. This is compounded by the fact that middle managers lack the same support networks that senior executives or frontline employees might have available. Zhuo advises that in her own experience, middle managers need more access to leadership development and strategic involvement to feel less isolated and more connected to the larger mission.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Can We Do to Improve Middle Management?
&lt;/h3&gt;

&lt;p&gt;In my view, the traditional approach to managing middle managers just isn't cutting it anymore. The ongoing pressures and emotional strain that come from being sandwiched between leadership and teams need to be addressed. Here’s what I think can be done to alleviate some of these challenges.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Bring Middle Managers into Strategic Conversations Early&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;From what I’ve seen, one of the primary reasons middle managers feel disengaged is simply because they’re left out of major strategic decisions. As Jack Zenger and Joseph Folkman point out, this disconnection makes their job ten times harder. If leadership wants to get the best out of middle managers, they need to be brought into the conversation from the start. Whether it’s helping to shape company policies or providing feedback on new initiatives, direction will stick far better if middle managers understand and feel a part of the “why” behind these decisions. Giving them this sense of ownership fosters better implementation and ensures strategic objectives are grounded in the realities of the workplace.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Recognize and Reward the Emotional Labor of Middle Management&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Let’s face it, emotional labor is a huge part of a middle manager’s role and often goes unrecognized. These managers aren’t just managing tasks and project outcomes, they’re balancing the emotional well-being of their teams while meeting deadlines. &lt;/p&gt;

&lt;p&gt;But unfortunately, this aspect of the job is often perceived as transactional something that just comes with the territory. This is where companies need to step up. Recognize the complexity of the role. We need to do more than just acknowledge it, we need to actively reward it. And by reward, I don’t mean just compensation, but through recognition, support systems, and creating work cultures that reinforce the value they bring. Providing mental health resources is also crucial because it helps middle managers cope with the stress and ensures their emotional well-being, which in turn benefits the entire team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Middle management is often one of the toughest, most thankless jobs in any organization. These individuals are tasked with balancing competing expectations, processing complex emotions, and producing excellent results despite limited authority and frequent isolation. However, the good news is that these challenges are not set in stone they can be managed and improved upon.&lt;/p&gt;

&lt;p&gt;To make middle management more effective and sustainable, we need to start by rethinking the role. Empowering them with decision-making autonomy, involving them earlier in strategic discussions, prioritizing their own leadership development, building supportive peer networks, and recognizing the weight of their emotional labor are all essential steps. While these changes require deliberate effort from leadership, they are essential if organizations want to get the most out of their middle-tier management.&lt;/p&gt;

&lt;p&gt;As Jack Zenger and Joseph Folkman have pointed out, middle managers aren’t disengaged because they lack ability they are disengaged because they aren’t managed well. The sooner organizations realize the centrality and importance of middle management, the sooner they can align themselves for sustainable success. After all, when middle managers thrive, so does the entire organization from the frontlines to the C-level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended Reading Materials
&lt;/h3&gt;

&lt;p&gt;While making this article, I consulted multiple reading materials and papers to gain deeper insights into the challenges of middle management and strategies to overcome them. These resources provided me with useful frameworks and data that helped shape my understanding of this complex role.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://hbr.org/podcast/2024/01/how-to-become-a-better-manager" rel="noopener noreferrer"&gt;How to Become a Better Manager&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hbr.org/2017/03/why-being-a-middle-manager-is-so-exhausting" rel="noopener noreferrer"&gt;Why Being a Middle Manager Is So Exhausting&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hbr.org/2014/11/why-middle-managers-are-so-unhappy" rel="noopener noreferrer"&gt;Why Middle Managers Are So Unhappy&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hbr.org/2024/02/a-guide-for-new-middle-managers" rel="noopener noreferrer"&gt;A Guide for New Middle Managers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.researchgate.net/publication/313739114_The_Psychology_of_Middle_Power_Vertical_Code-Switching_Role_Conflict_and_Behavioral_Inhibition" rel="noopener noreferrer"&gt;The Psychology of Middle Power: Vertical Code-Switching, Role Conflict, and Behavioral Inhibition&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>management</category>
      <category>leadership</category>
    </item>
    <item>
      <title>GitHub Actions for Easy ARM64 and AMD64 Docker Image Builds</title>
      <dc:creator>Agastya Darma</dc:creator>
      <pubDate>Thu, 16 Nov 2023 15:36:35 +0000</pubDate>
      <link>https://forem.com/gedeagas/github-actions-for-easy-arm64-and-amd64-docker-image-builds-fn</link>
      <guid>https://forem.com/gedeagas/github-actions-for-easy-arm64-and-amd64-docker-image-builds-fn</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--46_OuLTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9pjzb9y2lofos33nuxc.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--46_OuLTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i9pjzb9y2lofos33nuxc.jpeg" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In today's rapidly evolving software development landscape, the ability to efficiently build and deploy applications across diverse architectures is crucial. This article will explore an advanced yet accessible approach to creating multi-architecture Docker images, specifically for ARM64 and AMD64 platforms, using GitHub Actions. We will dissect a YAML configuration for a GitHub Actions workflow named 'Deploy Production,' illustrating how to automate the building and pushing of Docker images to Docker Hub.&lt;/p&gt;

&lt;p&gt;Our focus will be on leveraging the capabilities of GitHub Actions, including setup of QEMU for emulation and Docker Buildx for building images, along with caching strategies and security practices for Docker Hub integration. This guide aims to equip developers with the knowledge and tools needed to streamline their CI/CD pipelines, ensuring seamless deployment across varied computing environments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Production&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-push-docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up QEMU&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-qemu-action@v1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker Buildx&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Docker layers&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/.buildx-cache&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-buildx-${{ github.sha }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-buildx-&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Docker Hub&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_TOKEN }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./Dockerfile&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agasdrm/blog:latest,agasdrm/blog:${{ github.run_number }}&lt;/span&gt;
          &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64,linux/arm64/v8&lt;/span&gt;
          &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,src=/tmp/.buildx-cache&lt;/span&gt;
          &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,dest=/tmp/.buildx-cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Overview of Docker and GitHub Actions
&lt;/h3&gt;

&lt;p&gt;Docker has revolutionized how we build, share, and run applications by enabling them to run in isolated containers. These containers package up code and all its dependencies, ensuring that the application runs quickly and reliably in various computing environments.&lt;/p&gt;

&lt;p&gt;GitHub Actions, on the other hand, is a CI/CD (Continuous Integration/Continuous Delivery) platform that allows you to automate your build, test, and deployment pipeline. It is seamlessly integrated into GitHub, providing an efficient way to apply DevOps practices without leaving the GitHub ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Importance of Multi-Architecture Builds
&lt;/h3&gt;

&lt;p&gt;With the growing diversity in computing hardware, it's become crucial to ensure that applications can run on different architectures. ARM64 and AMD64 are two prevalent architectures in use today. ARM64 is commonly found in mobile devices, newer desktops, and servers, while AMD64 (x86_64) is widely used in traditional laptops and desktops. Supporting both architectures ensures that your application can reach a wider audience and function in a broader range of environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before diving into the process, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;GitHub account&lt;/strong&gt; - for accessing GitHub and using GitHub Actions.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Docker Hub account&lt;/strong&gt; - for storing and managing your Docker images.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic understanding of Docker&lt;/strong&gt; - familiarity with Docker concepts like images, containers, and Dockerfiles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic understanding of Git and GitHub&lt;/strong&gt; - knowledge of repositories, branches, commits, and pulls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access to a code editor&lt;/strong&gt; - like Visual Studio Code, Sublime Text, or any editor of your choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding the Dockerfile
&lt;/h2&gt;

&lt;p&gt;A Dockerfile is a text document containing all the commands a user could call on the command line to assemble an image. Using a Dockerfile, Docker can automatically build an image that includes your application and its dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Components of a Dockerfile
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FROM&lt;/strong&gt;: Specifies the base image from which you are building.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RUN&lt;/strong&gt;: Executes any commands in a new layer on top of the current image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COPY&lt;/strong&gt;: Copies files or directories from your project into the Docker container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CMD&lt;/strong&gt;: Provides defaults for executing a container.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EXPOSE&lt;/strong&gt;: Informs Docker that the container listens on specific network ports at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ENV&lt;/strong&gt;: Sets environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each instruction in a Dockerfile creates a layer in the image. When you change the Dockerfile and rebuild the image, only those layers that have changed are rebuilt. This is part of what makes images so lightweight, small, and fast when compared to other virtualization technologies.&lt;/p&gt;

&lt;p&gt;In the next section, we will dive deeper into setting up our GitHub Actions workflow to automate the building and publishing of our Docker images for ARM64 and AMD64 architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding GitHub Actions
&lt;/h2&gt;

&lt;p&gt;GitHub Actions is a powerful automation tool that integrates deeply with GitHub, providing a platform for automating software workflows. It's particularly useful in implementing Continuous Integration (CI) and Continuous Delivery (CD) processes directly within your repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are GitHub Actions?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated Workflows&lt;/strong&gt;: GitHub Actions allows you to create custom software development life cycle (SDLC) workflows directly in your GitHub repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-Driven&lt;/strong&gt;: These workflows can be triggered by a variety of events within GitHub, such as push, pull requests, issue creation, or even a manual trigger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable&lt;/strong&gt;: GitHub Actions provides a wide range of built-in actions, but you can also create and share your own actions or use actions shared by the GitHub community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containers and Virtual Environments&lt;/strong&gt;: Actions can run in containers or virtual environments that you specify, ensuring consistency across different runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI/CD with GitHub Actions
&lt;/h3&gt;

&lt;p&gt;In Continuous Integration (CI), code changes are automatically tested and merged into a central repository. Continuous Delivery (CD) extends CI by automatically deploying all code changes to a testing or production environment. GitHub Actions facilitates both CI and CD by automating these processes, enhancing software quality and development speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow Syntax Explanation
&lt;/h2&gt;

&lt;p&gt;GitHub Actions utilizes workflows, which are defined by a YAML file stored in your repository's &lt;code&gt;.github/workflows&lt;/code&gt; directory. These workflows specify the actions to be executed based on defined events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the &lt;code&gt;workflow_dispatch&lt;/code&gt; Trigger
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manual Trigger&lt;/strong&gt;: The &lt;code&gt;workflow_dispatch&lt;/code&gt; event allows you to manually trigger a workflow run. This is useful when you want to have control over when to run the workflow, as opposed to automatic triggers like push or pull requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inputs&lt;/strong&gt;: You can define inputs for the &lt;code&gt;workflow_dispatch&lt;/code&gt; trigger, allowing you to pass parameters to the workflow at runtime.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Production&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Environment'&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;staging'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the workflow_dispatch is configured with an input named environment. When triggering the workflow manually, you can specify the environment to which you want to deploy.&lt;/p&gt;

&lt;p&gt;Workflow Anatomy A typical workflow file consists of the following key sections:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A name for your workflow.&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;The event that triggers the workflow.&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A set of jobs that the workflow will execute.&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Individual tasks that run within a job.&lt;/span&gt;
&lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Specifies the type of machine to run the job on.&lt;/span&gt;
&lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Refers to an action to execute as part of a step.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Preparing for Docker Build
&lt;/h2&gt;

&lt;p&gt;Before diving into the actual Docker build process, it's crucial to understand the role of QEMU in this workflow and how it's set up using GitHub Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is QEMU?
&lt;/h3&gt;

&lt;p&gt;QEMU (Quick Emulator) is an open-source emulator that performs hardware virtualization. It is a key tool in the process of running software that is built for one type of processor architecture on another. This capability is particularly important when dealing with Docker images intended for multiple architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Role of QEMU in Docker Builds
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Emulation of Architectures&lt;/strong&gt;: QEMU allows us to emulate different processor architectures, such as ARM64, on machines that have a different architecture (like AMD64). This is vital for building Docker images that are meant to run on multiple architectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform Compatibility&lt;/strong&gt;: By using QEMU, we ensure that the Docker images built are compatible across different architectures, making our application more versatile and accessible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting Up QEMU in GitHub Actions
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker/setup-qemu-action@v1&lt;/code&gt; action is used to set up QEMU in the GitHub Actions runner environment. This action simplifies the process of installing and configuring QEMU for our build process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up QEMU&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-qemu-action@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the workflow file, this step ensures that QEMU is correctly set up and ready to enable emulation for different architectures during the Docker build process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Buildx Setup
&lt;/h2&gt;

&lt;p&gt;Docker Buildx is an extended build feature of Docker that enables the creation of multi-architecture images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding Docker Buildx
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extended Features&lt;/strong&gt;: Docker Buildx extends the capabilities of the standard Docker build commands, allowing for more advanced features, including building for multiple architectures from a single platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplifying Multi-Arch Builds&lt;/strong&gt;: With Buildx, you can easily build images for architectures like ARM64 and AMD64, even if your build environment is different.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting Up Docker Buildx in GitHub Actions
&lt;/h3&gt;

&lt;p&gt;The docker/setup-buildx-action@v1 action in GitHub Actions is used to set up Docker Buildx in the workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker Buildx&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By including this step in our workflow file, we enable the GitHub Actions runner to utilize Docker Buildx for building multi-architecture Docker images. This step is critical in ensuring that our Docker images are built correctly for the desired architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching for Efficiency in Docker Builds
&lt;/h2&gt;

&lt;p&gt;Efficient Docker builds often require a smart caching strategy. This section delves into the use of caching in Docker builds with GitHub Actions, particularly focusing on the &lt;code&gt;actions/cache@v2&lt;/code&gt; action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Caching Docker Layers
&lt;/h3&gt;

&lt;p&gt;Caching is crucial in reducing build time, especially when dealing with Docker images. Docker builds can be time-consuming, primarily due to the downloading of image layers and rebuilding steps. By caching, we can significantly decrease this time.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Caching Works in Docker
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Layer Caching&lt;/strong&gt;: Docker builds images in layers. By caching these layers, Docker can reuse them in subsequent builds, avoiding the need to rebuild identical layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact on Build Times&lt;/strong&gt;: Caching can drastically reduce build times, making your CI/CD pipeline more efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementing Caching with &lt;code&gt;actions/cache@v2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;GitHub Actions provides a caching action, &lt;code&gt;actions/cache@v2&lt;/code&gt;, which can be used to cache dependencies and build outputs to improve workflow execution time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cache Docker layers&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp/.buildx-cache&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-buildx-${{ github.sha }}&lt;/span&gt;
    &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;${{ runner.os }}-buildx-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this snippet, the caching action is configured to cache the Docker layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache Keys and Paths
&lt;/h3&gt;

&lt;p&gt;Understanding how to effectively use cache keys and paths is vital for maximizing the efficiency of your caching strategy.&lt;/p&gt;

&lt;h4&gt;
  
  
  Defining Cache Paths
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache Location&lt;/strong&gt;: In our workflow, the cache is stored in /tmp/.buildx-cache. This path is where Docker Buildx stores its cache data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cache Keys
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key Generation&lt;/strong&gt;: The key for the cache is a unique identifier. In our example, it's a combination of the runner's operating system, buildx, and the SHA of the commit (&lt;code&gt;${{ github.sha }}&lt;/code&gt;). This ensures that each build has its unique cache.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restoration of Cache&lt;/strong&gt;: The restore-keys option provides a list of keys to try when restoring the cache. In our case, it attempts to find the most recent cache that matches the specified pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Benefits of Effective Caching
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Build Times&lt;/strong&gt;: By reusing the cached layers, Docker can skip rebuilding unchanged layers, significantly reducing the overall build time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Efficiency&lt;/strong&gt;: Efficient caching leads to faster CI/CD pipelines, which is crucial for agile development and quick deployment cycles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker Hub Integration in GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Integrating Docker Hub with GitHub Actions is a key step in automating the Docker image build and push process. This section covers the essential steps for secure Docker Hub login and handling secrets within GitHub Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Hub Login
&lt;/h3&gt;

&lt;p&gt;Logging into Docker Hub from GitHub Actions is a crucial step to push the built images to your Docker Hub repository. This is where the &lt;code&gt;docker/login-action@v1&lt;/code&gt; action comes into play.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importance of Secure Login
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Securely logging into Docker Hub ensures that your credentials are protected and your Docker Hub account is safe from unauthorized access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt;: Automated login is essential for seamless CI/CD pipelines, enabling the automated pushing of Docker images to Docker Hub without manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementing Docker Hub Login
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Docker Hub&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_USERNAME }}&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this step, the docker/login-action@v1 action is used to log into Docker Hub. The credentials are provided through GitHub secrets to ensure security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Secrets
&lt;/h3&gt;

&lt;p&gt;GitHub secrets provide a secure way to store and use sensitive information, like Docker Hub credentials, in your GitHub Actions workflows.&lt;/p&gt;

&lt;h4&gt;
  
  
  What are GitHub Secrets?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security Feature&lt;/strong&gt;: Secrets are encrypted environment variables that you can create in any repository or organization in GitHub. They are not exposed in log files or to unauthorized users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage in Workflows&lt;/strong&gt;: Secrets can be used in GitHub Actions workflows to securely manage sensitive data like API keys, passwords, and Docker Hub credentials. Configuring and Using Secrets&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Adding Secrets&lt;/strong&gt;: Secrets can be added to your GitHub repository under the settings tab. Once added, they can be referenced in your workflow file. Referencing Secrets in Workflows: In the Docker Hub login step, the username and password are referenced as &lt;code&gt;${{ secrets.DOCKERHUB_USERNAME }}&lt;/code&gt; and &lt;code&gt;${{ secrets.DOCKERHUB_TOKEN }}&lt;/code&gt;. This allows the workflow to use these credentials without exposing them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Benefits of Using Secrets
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: By using secrets, sensitive information is kept secure and is not exposed in your workflow files or logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Secrets can be easily updated in the GitHub repository settings without changing the workflow files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building and Pushing the Docker Image
&lt;/h2&gt;

&lt;p&gt;The culmination of our GitHub Actions workflow is the building and pushing of the Docker image. This section provides a detailed walkthrough of this process, highlighting the use of &lt;code&gt;docker/build-push-action@v2&lt;/code&gt; and explaining image tagging and multi-architecture support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Docker Image
&lt;/h3&gt;

&lt;p&gt;Building the Docker image is a critical step in the workflow. The &lt;code&gt;docker/build-push-action@v2&lt;/code&gt; action simplifies this process within GitHub Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;docker/build-push-action@v2&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This action enables us to build and push the Docker image to a registry like Docker Hub. It supports advanced features like multi-platform builds and caching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user/myapp:latest, user/myapp:${{ github.run_number }}&lt;/span&gt;
    &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64,linux/arm64/v8&lt;/span&gt;
    &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,src=/tmp/.buildx-cache&lt;/span&gt;
    &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=local,dest=/tmp/.buildx-cache&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;context&lt;/code&gt; specifies the build context (typically the root of the repository).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;file&lt;/code&gt; points to the Dockerfile.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;push&lt;/code&gt; set to true enables the pushing of the image to the registry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tags&lt;/code&gt; defines the tags for the built image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;platforms&lt;/code&gt; lists the target architectures.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cache-from&lt;/code&gt; and &lt;code&gt;cache-to&lt;/code&gt; handle caching to speed up the build process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tagging and Multi-Architecture Support
&lt;/h3&gt;

&lt;p&gt;Tagging images correctly and supporting multiple architectures are crucial for a robust Docker deployment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tagging Images
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose of Tags&lt;/strong&gt;: Tags are used to specify different versions of your Docker images. It's a best practice to tag your images with meaningful identifiers, like version numbers or environment names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag Syntax in GitHub Actions&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user/myapp:latest, user/myapp:${{ github.run_number }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use two tags - latest for the most recent build and a tag with the GitHub run number for specific builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Architecture Support
&lt;/h3&gt;

&lt;p&gt;Supporting multiple architectures ensures that your Docker images can run on various hardware platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specifying Architectures&lt;/strong&gt;: In the platforms field of the docker/build-push-action@v2, we specify the target architectures.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64,linux/arm64/v8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benefits&lt;/strong&gt;: This approach ensures that the built Docker images are compatible with both AMD64 and ARM64 architectures, broadening the usability of your application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion and Best Practices
&lt;/h2&gt;

&lt;p&gt;We've now reached the end of our comprehensive guide on building and pushing multi-architecture Docker images using GitHub Actions. Let's recap the steps we've taken and go over some best practices and troubleshooting tips.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review of the Process
&lt;/h3&gt;

&lt;p&gt;Our journey through this tutorial involved several key steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Introduction to Docker and GitHub Actions&lt;/strong&gt;: We began by understanding the basics of Docker, GitHub Actions, and the need for multi-architecture builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setting Up the Workflow&lt;/strong&gt;: We then explored the workflow syntax in GitHub Actions and how to trigger workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment Preparation&lt;/strong&gt;: Setting up QEMU and Docker Buildx were crucial steps for cross-platform Docker builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching for Efficiency&lt;/strong&gt;: Implementing caching using &lt;code&gt;actions/cache@v2&lt;/code&gt; improved our build times significantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Hub Integration&lt;/strong&gt;: We securely logged into Docker Hub using GitHub secrets, ensuring a secure pipeline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Building and Pushing Images&lt;/strong&gt;: Finally, we used &lt;code&gt;docker/build-push-action@v2&lt;/code&gt; to build and push images, tagging them appropriately and supporting multiple architectures.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;p&gt;Following best practices can significantly enhance the efficiency and security of your Docker builds and GitHub Actions workflows.&lt;/p&gt;

&lt;h5&gt;
  
  
  Docker Builds
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Multi-Stage Builds&lt;/strong&gt;: This helps keep your images small and efficient.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage Caching&lt;/strong&gt;: Proper caching can drastically reduce build times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep Images Secure&lt;/strong&gt;: Regularly update and scan your images for vulnerabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  GitHub Actions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Workflows Simple&lt;/strong&gt;: Complex workflows are harder to maintain and debug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Secrets&lt;/strong&gt;: Always use GitHub secrets to handle sensitive information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Your Workflows&lt;/strong&gt;: Clear documentation helps maintain and understand workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Troubleshooting Tips
&lt;/h3&gt;

&lt;p&gt;Here are some common issues and tips for troubleshooting Docker builds and GitHub Actions workflows.&lt;/p&gt;

&lt;h5&gt;
  
  
  Docker Builds
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build Failures&lt;/strong&gt;: Check for syntax errors in your Dockerfile. Ensure all necessary files are included in the build context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long Build Times&lt;/strong&gt;: Investigate caching strategies and consider optimizing your Dockerfile for better layer caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  GitHub Actions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflow Errors&lt;/strong&gt;: Review logs provided by GitHub Actions for specific error messages. Ensure all steps are correctly configured.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets Not Working&lt;/strong&gt;: Double-check secret names in the repository settings and their references in the workflow file.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;With this knowledge, you're now equipped to create efficient, automated Docker workflows using GitHub Actions. Happy coding!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>githubactions</category>
      <category>raspberrypi</category>
      <category>arm</category>
    </item>
    <item>
      <title>From Cloud to Couch, My Blog's Quirky Journey Home</title>
      <dc:creator>Agastya Darma</dc:creator>
      <pubDate>Thu, 16 Nov 2023 04:53:31 +0000</pubDate>
      <link>https://forem.com/gedeagas/from-cloud-to-couch-my-blogs-quirky-journey-home-3f89</link>
      <guid>https://forem.com/gedeagas/from-cloud-to-couch-my-blogs-quirky-journey-home-3f89</guid>
      <description>&lt;p&gt;Welcome to my latest digital escapade – a tale that’s part tech, part humor, and entirely real. I’m here to tell you about how my blog, once a mere visitor in the vast cloud, found its way to the cozy confines of my own home. Yes, you read that right. My blog now lives on a Raspberry Pi 4 server, right here under my roof. Let’s dive into this delightful journey of migration, shall we?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Origin Story
&lt;/h2&gt;

&lt;p&gt;Every great adventure starts with a vision. Mine was built with Docusaurus – a fantastic platform that makes documentation a breeze but also doubles up as a brilliant blog framework. It’s like having a Swiss Army knife, but for blogging. Neat, right?&lt;/p&gt;

&lt;p&gt;Now, I must confess, I’m a bit of a neat freak when it comes to my digital life. So, naturally, my blog was dockerized. Think of it like packing your entire house into a single, magical suitcase – ready to move anywhere, anytime. This nifty trick made the migration process smoother than my morning espresso.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Raspberry Homecoming
&lt;/h2&gt;

&lt;p&gt;Now, let’s talk about the star of our show – the Raspberry Pi 4. This tiny yet mighty device transformed from a hobbyist's plaything into the powerhouse behind my blog. Hosting a blog on a Raspberry Pi? Sounds crazy, right? But that's exactly what I did. In the quiet corner of my home, this little gadget hums with the life of my blog, proving that you don't need a massive server to make a big impact on the digital stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tunnels and Clouds
&lt;/h2&gt;

&lt;p&gt;Navigating the complexities of the internet, especially when hosting a website or blog, requires a secure and reliable connection. This is where Cloudflared's Argo Tunnel comes into play in my setup. It's not just any regular internet connection – it's a fortified, encrypted pathway designed to ensure secure and efficient communication between my Raspberry Pi and the wider internet. Imagine a secret underground tunnel, hidden away from the chaos of surface traffic, providing a safe and speedy route for my data. This setup guarantees that my blog remains accessible and secure, avoiding potential cyber threats and ensuring uninterrupted service to my readers.&lt;/p&gt;

&lt;p&gt;The domain of a blog is more than just a web address; it’s an integral part of its identity, its brand. For my blog, &lt;a href="http://www.agas.dev"&gt;www.agas.dev&lt;/a&gt; is that digital signature, a unique identifier in the vast sea of the internet. Linking this domain to my Raspberry Pi hosted blog was an essential step in establishing its new home. By routing &lt;a href="http://www.agas.dev"&gt;www.agas.dev&lt;/a&gt; through the Cloudflared Argo Tunnel, I’ve created a direct and efficient pathway for traffic to reach my blog. It’s akin to setting up a bespoke postal service, one that ensures prompt and secure delivery of content – my digital letters, if you will – to my audience without any detours or delays.&lt;/p&gt;

&lt;p&gt;This journey of migration is not just about moving a blog from one hosting environment to another; it's about reimagining what's possible with technology. It's a blend of the old and the new – the tried and tested Raspberry Pi, a favorite among tech hobbyists, coming together with modern solutions like Cloudflared's Argo Tunnel to create a robust, home-based web hosting environment. This blend of technology demonstrates that with the right tools and a bit of ingenuity, you can create a powerful digital presence without relying on traditional, often expensive, hosting solutions.&lt;/p&gt;

&lt;p&gt;In essence, this project is a testament to the power of small-scale, home-based technology solutions in a world that's increasingly moving towards decentralization and personal control over digital assets. Hosting my blog on a Raspberry Pi 4, connected securely to the internet through Cloudflared's Argo Tunnel, and accessible via a personalized domain, embodies a shift in how we approach web hosting and content delivery. It’s a shift towards more personal, customizable, and cost-effective solutions, proving that sometimes, the best way to move forward is by bringing things closer to home.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker, but Easier
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--82noEGNR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdy26xyentc6emt389y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--82noEGNR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdy26xyentc6emt389y7.png" alt="Portainer" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Handling Docker can be a bit like juggling digital cats. To simplify this, I turned to Portainer. It’s a graphical interface that brings simplicity and clarity to managing Docker containers. With Portainer, I could easily update, modify, and maintain my blog’s backend without diving into the command-line abyss. It’s like having a sleek, user-friendly dashboard for your car, making driving (or in this case, managing a blog) a breeze.&lt;/p&gt;

&lt;h2&gt;
  
  
  Counting the Costs
&lt;/h2&gt;

&lt;p&gt;Running a blog doesn't have to break the bank, and my setup is a testament to that. By moving to a Raspberry Pi hosted at home, I've slashed hosting costs without sacrificing performance. For a blog with modest traffic like mine, this is a game-changer. It's like discovering a secret recipe that makes your favorite dish not just tastier but also cheaper to cook.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>docker</category>
      <category>selfhosted</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Recoil, A State Management Library For React</title>
      <dc:creator>Agastya Darma</dc:creator>
      <pubDate>Mon, 09 Aug 2021 08:30:52 +0000</pubDate>
      <link>https://forem.com/gedeagas/recoil-a-state-management-library-for-react-2049</link>
      <guid>https://forem.com/gedeagas/recoil-a-state-management-library-for-react-2049</guid>
      <description>&lt;p&gt;Biggest Challenge in React application is the management of global state. In large applications, React alone is not sufficient to handle the state complexity which is why some developers use React hooks, Redux and others state management libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do You Need A State Management Library?
&lt;/h3&gt;

&lt;p&gt;For reasons of compatibility and simplicity, it's best to use React's built-in state management capabilities rather than external global state like Recoil. But as i said before React has certain limitations when it comes to a global state management.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Component state can only be shared by pushing it up to the common ancestor, but this might include a huge tree that then needs to re-render.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context can only store a single value, not an indefinite set of values each with its own consumers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both of these make it difficult to code-split the top of the tree (where the state has to live) from the leaves of the tree (where the state is used).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  So When Should We Use A State Management Library Like Recoil?
&lt;/h5&gt;

&lt;p&gt;Applying a global state management is not so easy, it is a lot off hard work and it also takes time to implement. So, it is very important for you to know when to implement the state-management.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If your application contains a large number of components and a lot of requests are being sent to the back-end for data retrieval, then it becomes mandatory to implement the state-management, as it will boost the user experience and speed of the application to a great extent. With a global state, you don't have to fetch the same request multiple times as the data will already be "cached" from the first request and can be consumed by other part of your screen.&lt;/li&gt;
&lt;li&gt;If you use redundant data throughout the whole app, for example, a list of customers is being used in the invoice creation and sales report generation then there is no need to fetch customers again and again from the database. You could simply just put the data in the global state.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is it about Recoil.js that’s so appealing?
&lt;/h3&gt;

&lt;p&gt;Recoil feels just like React. The syntax is similar to React and it looks like a part of &lt;a href="https://medium.com/habilelabs/brahmos-js-a-new-frontend-ui-framework-with-react-like-api-8d1309b17de"&gt;React API&lt;/a&gt;. Other than that, it has many other upsides like it solves the problem of global state management, shared state, derived data, etc. The team at Recoil make sure that the semantics and behavior of Recoil be as Reactish as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Recoil Concept.
&lt;/h3&gt;

&lt;p&gt;Recoil is an &lt;strong&gt;experimental&lt;/strong&gt; state management library at Facebook, created by Dave McCabe. The reason why i like Recoil better than Redux is because Recoil solves all our complex state management problems but its configuration is surprisingly simple, unlike Redux. And we do not need to write much boilerplate code as we would have by using other state management library like Redux.&lt;/p&gt;

&lt;h5&gt;
  
  
  Installing Recoil
&lt;/h5&gt;

&lt;p&gt;As Recoil is a state management library for React, you need to make sure that you have React or React Native installed and running before getting started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;recoil
// or
yarn add recoil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Core Concept of Recoil
&lt;/h4&gt;

&lt;p&gt;There are two core concepts of Recoil that you need to understand. This are Atoms and Selectors.&lt;/p&gt;

&lt;h5&gt;
  
  
  Atoms
&lt;/h5&gt;

&lt;p&gt;Atoms are units of state. They're updateable and subscribable: when an atom is updated, each subscribed component is re-rendered with the new value. They can be created at runtime, too. Atoms can be used in place of React local component state. If the same atom is used from multiple components, all those components share their state.&lt;/p&gt;

&lt;p&gt;You can create Atoms with the &lt;code&gt;atom&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;countState&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Atoms use a unique key for debugging, persistence, and mapping of all atoms. &lt;strong&gt;You can't have a duplicate key among the atoms&lt;/strong&gt;. So because of that you need to make sure they're globally unique. And also like a React component state, they also have a default value.&lt;/p&gt;

&lt;p&gt;To read and write an atom from a component, we use a hook called &lt;code&gt;useRecoilState&lt;/code&gt;. It's just like React's &lt;code&gt;useState&lt;/code&gt;, but now the state can be shared between components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;CountButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;countValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCountValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRecoilState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count Value &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;countValue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setCountValue&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Click to Increase Count
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Selectors
&lt;/h5&gt;

&lt;p&gt;A selector is basically a piece of derived state, where ‘derived state’ can be defined as the ‘the output of passing state to a pure function that modifies the given state in some way’. So in short when these upstream atoms or selectors are updated, the selector function will be re-evaluated. Components can subscribe to selectors just like atoms, and will then be re-rendered when the selectors change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countLabelOddEventState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;countLabelOddEventState&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`isEven`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`isOdd`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see Selectors also have a unique ID like atoms &lt;strong&gt;but not a default value&lt;/strong&gt;. A selector takes atoms or other selectors as input and when these inputs are updated, the selector function gets re-evaluated.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;get&lt;/code&gt; property is the function that is to be computed. It can access the value of atoms and other selectors using the &lt;code&gt;get&lt;/code&gt; argument passed to it. Whenever it accesses another atom or selector, a dependency relationship is created such that updating the other atom or selector will cause this one to be recomputed.&lt;/p&gt;

&lt;p&gt;Selectors can be read using &lt;code&gt;useRecoilValue()&lt;/code&gt;, which takes an atom or selector as an argument and returns the corresponding value. We don't use the &lt;code&gt;useRecoilState()&lt;/code&gt; as the &lt;code&gt;countLabelOddEventState&lt;/code&gt; &lt;strong&gt;selector is not writeable&lt;/strong&gt; (see the &lt;a href="https://recoiljs.org/docs/api-reference/core/selector"&gt;selector API reference&lt;/a&gt; for more information on writeable selectors).&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Personally i think Recoil is a great library but unless you have some specific problems regarding global state management, you don’t really need it. It's nothing that the developer’s world couldn’t survive without. You can even use Recoil partially in your application, exactly where you need, without having to adopt it for the entire application.&lt;/p&gt;

&lt;h5&gt;
  
  
  References
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://recoiljs.org/docs/introduction/core-concepts"&gt;Recoil Core Concepts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/habilelabs/recoil-js-a-new-state-management-library-for-react-3319ca42356f"&gt;Recoil.js — A New State Management Library for React&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>recoil</category>
      <category>reactnative</category>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>React Native Code-Splitting With Repack</title>
      <dc:creator>Agastya Darma</dc:creator>
      <pubDate>Sat, 07 Aug 2021 12:10:06 +0000</pubDate>
      <link>https://forem.com/gedeagas/react-native-code-splitting-with-repack-2i4b</link>
      <guid>https://forem.com/gedeagas/react-native-code-splitting-with-repack-2i4b</guid>
      <description>&lt;p&gt;When you are developing a React Native application you will most likely be writing a lot of JavaScript code that contains dependencies that usually come from external repositories like NPM. The compilation of these many JavaScript files and dependencies will be processed into a single &lt;em&gt;bundle&lt;/em&gt; file that can be read by React Native. In React Native this compilation will be done by default by &lt;strong&gt;&lt;a href="https://facebook.github.io/metro/"&gt;Metro Bundler&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So basically &lt;em&gt;Metro Bundler&lt;/em&gt; works by taking your source code, all external library dependencies as well as static assets that you use and converting them, optimizing them, and packaging them into a single &lt;em&gt;bundle&lt;/em&gt; that can be run by &lt;code&gt;React Native&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Code-Splitting?
&lt;/h3&gt;

&lt;p&gt;Code-Splitting is a technique that allows developers to create &lt;strong&gt;multiple bundle files&lt;/strong&gt; from existing code sources, so the resulting bundle is not just one but consists of many files which are commonly referred to as &lt;em&gt;chunck&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;By default, all your input files (source code, dependencies, and assets) are combined into one file. With Code-Splitting, the bundle will be divided into several parts called &lt;em&gt;chunck&lt;/em&gt;. The main &lt;em&gt;chunck&lt;/em&gt; (also known as the &lt;code&gt;entry chunk&lt;/code&gt;) is commonly referred to as the &lt;em&gt;main bundle&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Do You Need Re.pack To Code-Splitting?
&lt;/h4&gt;

&lt;p&gt;As explained above, by default React Native will use &lt;code&gt;Metro Bundler&lt;/code&gt; to do JavaScript bundling. But unfortunately &lt;em&gt;Metro Bundler&lt;/em&gt; cannot perform &lt;em&gt;Code-Splitting&lt;/em&gt; technique by default. To be able to perform the &lt;em&gt;Code-Splitting&lt;/em&gt; technique, we need a JavaScript bundler other than Metro Bundler.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is Re.pack?
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/callstack/repack"&gt;Re.pack&lt;/a&gt; is basically a toolkit that allows you to use Webpack and its &lt;em&gt;Code-Splitting&lt;/em&gt; functionality and use them on React Native.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Do We Need Code-Splitting in React Native?
&lt;/h3&gt;

&lt;p&gt;Single bundles aren't a bad thing, but as your app grows your bundle size will grow as well. Especially if you use a lot of third-party libraries you need to be very careful about the code that will be included in the application bundle so that you don't accidentally make your bundle so large that it takes a long time for React Native to load your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Increasing App Startup Time
&lt;/h4&gt;

&lt;p&gt;If you have performance issues in the application startup area &lt;em&gt;Code-Splitting&lt;/em&gt; is a technique worth trying when you have those problems.&lt;/p&gt;

&lt;p&gt;Moving code from a single bundle to multiple chunks of &lt;em&gt;chunck&lt;/em&gt; if properly configured can make your React Native app to only load the required code snippets and delay loading of other code on startup. This really helps improve the startup performance of your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Modular Applications
&lt;/h4&gt;

&lt;p&gt;Apps that expose different functionality or different UI based on user details are examples of apps that would benefit greatly from Code-Splitting.&lt;/p&gt;

&lt;p&gt;Let's take an example of an e-learning application like &lt;em&gt;Ruangguru&lt;/em&gt;. With Code-Splitting, you will be able to separate student and teacher functionality in separate bundle files, so that the application only loads one of the bundles, this can improve startup performance by loading only code that is relevant to the user's needs.&lt;/p&gt;

&lt;p&gt;Two other groups of apps where Code-Splitting plays a big role are super apps (like Gojek) as well as apps with mini app stores (like WeChat/Line). Instead of having multiple apps on the App Store and Google Play, you can combine them into one while streamlining development and simplifying management.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use Re.pack for Code-Splitting in React Native
&lt;/h3&gt;

&lt;p&gt;How to use Re.pack? The first step to using Re.pack is to install the required dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; webpack terser-webpack-plugin babel-loader @callstack/repack
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; webpack terser-webpack-plugin babel-loader @callstack/repack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, Create react-native.config.js (if this file is not in your project) and copy the content below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@callstack/repack/commands&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure XCode and Gradle to use the webpack-bundle command. By making this change you will replace the default &lt;code&gt;Metro Bundler&lt;/code&gt; to &lt;code&gt;Re.pack&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XCode: Add &lt;code&gt;export BUNDLE_COMMAND=webpack-bundle&lt;/code&gt; to the &lt;strong&gt;&lt;em&gt;Bundle React Native code and images&lt;/em&gt;&lt;/strong&gt; phase of &lt;strong&gt;&lt;em&gt;Build Phases&lt;/em&gt;&lt;/strong&gt; in your XCode project configuration.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NODE_BINARY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;node
  &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BUNDLE_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;webpack-bundle
  ../node_modules/react-native/scripts/react-native-xcode.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Gradle: Add &lt;code&gt;bundleCommand: "webpack-bundle"&lt;/code&gt; into &lt;code&gt;project.ext.react&lt;/code&gt; in &lt;code&gt;android/app/build.gradle&lt;/code&gt; file, so it looks similar to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;  &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;react&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
      &lt;span class="nl"&gt;enableHermes:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// clean and rebuild if changing&lt;/span&gt;
      &lt;span class="nl"&gt;bundleCommand:&lt;/span&gt; &lt;span class="s2"&gt;"webpack-bundle"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;bundleInDebug:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All configurations have been completed. Now you can use repack in your React Native application.&lt;/p&gt;

&lt;p&gt;To run the development server you can use the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx react-native webpack-start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What are the disadvantages of Repack compared to Facebook Metro Bundler ?
&lt;/h3&gt;

&lt;p&gt;Of course there are some drawbacks when we use &lt;em&gt;Code-Splitting&lt;/em&gt; with &lt;em&gt;Re.pack&lt;/em&gt; instead of &lt;em&gt;Metro Bundler&lt;/em&gt;. One of the biggest drawbacks is that we &lt;strong&gt;can't use &lt;em&gt;Codepush&lt;/em&gt;&lt;/strong&gt; anymore to do &lt;em&gt;Hot Push&lt;/em&gt; code in &lt;em&gt;Production Env&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Besides that at the time this article was written if you use &lt;em&gt;Hermes&lt;/em&gt; with &lt;em&gt;Re.pack&lt;/em&gt; then it can only convert &lt;em&gt;Main Bundle&lt;/em&gt; to &lt;em&gt;Hermes Bytecode&lt;/em&gt;, chunck files outside of &lt;em&gt;Main Bundle&lt;/em&gt; will not be transformed into &lt;em&gt;Hermes Bytecode&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>webpack</category>
      <category>codesplitting</category>
      <category>react</category>
    </item>
  </channel>
</rss>
