<?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: 5 Mins Learn</title>
    <description>The latest articles on DEV Community by 5 Mins Learn (@5minslearn).</description>
    <link>https://dev.to/5minslearn</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%2F916371%2Fe7cb2fa8-656a-4718-883b-303655b29bca.png</url>
      <title>DEV Community: 5 Mins Learn</title>
      <link>https://dev.to/5minslearn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/5minslearn"/>
    <language>en</language>
    <item>
      <title>How to simplify database operations using MySQL stored procedures</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Fri, 01 Sep 2023 05:01:33 +0000</pubDate>
      <link>https://dev.to/5minslearn/how-to-simplify-database-operations-using-mysql-stored-procedures-3mm8</link>
      <guid>https://dev.to/5minslearn/how-to-simplify-database-operations-using-mysql-stored-procedures-3mm8</guid>
      <description>&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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2A7aLnLdEQeWXVZvSdnUbZHA.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%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2A7aLnLdEQeWXVZvSdnUbZHA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the realm of database management, MySQL has emerged as one of the most popular and reliable choices. MySQL not only offers robust data storage capabilities but also provides a powerful feature called “procedures” that allows developers to streamline complex database operations. In this blog post, we will delve into the concept of MySQL procedures, explore their benefits, and provide a step-by-step guide on how to use them effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  SQL Procedures
&lt;/h2&gt;

&lt;p&gt;SQL procedures are a set of SQL statements grouped together to form a logical unit of work. They are similar to functions or methods in programming languages, enabling you to encapsulate complex queries and operations into a single reusable entity. Procedures enhance code modularity, readability, and maintainability, making it easier to manage and execute repetitive or intricate database tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use stored procedures
&lt;/h2&gt;

&lt;p&gt;Let’s consider an e-commerce website, where we have the functionality to Generate sales reporting. For that let’s consider a Table called sales.&lt;/p&gt;

&lt;p&gt;Generating sales reports in real-time can be resource-intensive, especially when dealing with large datasets. By creating stored procedures that aggregate and summarize sales data, we can optimize the reporting process. These procedures can calculate metrics like total sales, top-selling products, or revenue by category, making it easier to retrieve valuable insights quickly and efficiently.&lt;/p&gt;

&lt;p&gt;Here’s the schema of sales table.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADv3lh2-Edi7Y0ytU09QyLQ.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2ADv3lh2-Edi7Y0ytU09QyLQ.png" alt="DB Schema of sales table"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To illustrate a simple example, let’s consider a table called “sales” that is populated with 1 million rows of mock data.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJFxwCRa_KzTleEmB.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJFxwCRa_KzTleEmB.png" alt="Sales table data count"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select count(*) from sales;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, The goal is to get sales reports for a particular period of time.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE GenerateSalesReport (
    IN start_date DATE,
    IN end_date DATE
)
BEGIN
    SELECT DATE_FORMAT(order_date, '%Y-%m-%d') AS Date,
           COUNT(order_id) AS TotalOrders,
           SUM(total_amount) AS TotalSales
    FROM orders
    WHERE order_date BETWEEN start_date AND end_date
    GROUP BY DATE_FORMAT(order_date, '%Y-%m-%d');
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The example stored procedure GenerateSalesReport takes two input parameters: start_date and end_date, which defines the date range for the sales report. The procedure selects the order date, counts the number of orders, and calculates the total sales amount within the specified date range. The result is grouped by the date, using the DATE_FORMAT function to display it in the desired format.&lt;/p&gt;

&lt;p&gt;Now, you might have a question:&lt;/p&gt;

&lt;p&gt;“&lt;strong&gt;Can’t we achieve the same outcome using a simple query instead of creating a stored procedure?&lt;/strong&gt;” While it’s true that using a simple query is a viable option, there are several compelling reasons to consider utilizing a stored procedure.&lt;/p&gt;

&lt;p&gt;Here are few reasons that feels promising to use stored procedures at some places.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A stored procedure offers the advantage of code reusability. By encapsulating the query logic within a stored procedure, we can reuse it multiple times without duplicating the code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instead of rewriting the same query in different parts of the application, we can simply call the stored procedure whenever needed, streamlining the codebase and making it easier to manage and update.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using a stored procedure can lead to improved performance in certain scenarios. When a stored procedure is executed, the database server can optimize the execution plan and cache it for subsequent invocations. This optimization can result in faster execution times, as the database engine leverages the cached plan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Furthermore, stored procedures can minimize network round trips by combining multiple queries into a single call, reducing the overhead associated with individual query executions. This optimization can significantly enhance overall performance, especially when dealing with complex operations or large datasets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another significant advantage of stored procedures is enhanced security. By granting execution privileges only to the stored procedure and not directly to underlying tables, you can enforce access control and protect sensitive data.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, while a simple query can achieve the desired outcome, utilizing a stored procedure offers distinct benefits such as code reusability, improved performance through query optimization and reduced network overhead, and enhanced security.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building blocks of Stored Procedures
&lt;/h2&gt;

&lt;p&gt;Let’s break down the stored procedure and examine each component individually. We will understand creating and running the stored procedure in MySQL. There are several MySQL IDEs available, and I recommend using MySQL Workbench. However, you are free to choose any IDE that suits your preference and needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Procedure Name&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every stored procedure has a unique name that identifies it within the database. The name should be descriptive and relevant to the procedure’s purpose.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsvQkBoGGMQ5aI4Uz.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AsvQkBoGGMQ5aI4Uz.png" alt="Create stored procedure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE `GenerateSalesReport`()
BEGIN
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Parameters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stored procedures can have input parameters that allow you to pass values into the procedure at runtime. We define start_date and end_date as our input parameters.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADnEhfGOANyRv4NlN.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ADnEhfGOANyRv4NlN.png" alt="Add parameter to the stored procedure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE `GenerateSalesReport`(
    IN start_date DATE,
    IN end_date DATE
)
BEGIN
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Variables are used to store and manipulate data within the stored procedure. They can be declared and assigned values as needed. There are two types of variables in SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session Variables&lt;/strong&gt;: Session variables in MySQL are prefixed with the @ symbol (e.g., @variable_name). These variables are associated with the current session or connection and retain their values throughout the session until they are explicitly changed or the session ends.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AB3qpqpWW_oOMnOxo.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AB3qpqpWW_oOMnOxo.png" alt="Using session variables in a stored procedure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE `GenerateSalesReport`(
    IN start_date DATE,
    IN end_date DATE
)
BEGIN
   SELECT @totalSales := 0;
   SELECT SUM(sales_amount) INTO @totalSales FROM sales;
   SELECT @totalSales As total_sales;
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Normal Variables&lt;/strong&gt;: Normal variables, also known as local variables, are declared using the DECLARE keyword within the scope of a stored procedure. Unlike session variables, normal variables do not have the @ prefix (e.g., variable_name). They are temporary and exist only within the block of code where they are declared.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIQ6dApG3rcdyyFXO.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AIQ6dApG3rcdyyFXO.png" alt="Using normal variables in a stored procedure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE `GenerateSalesReport`(
    IN start_date DATE,
    IN end_date DATE
)
BEGIN
   DECLARE totalSales INT;
   SELECT SUM(sales_amount) INTO totalSales FROM sales;
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;SQL Statements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core functionality of a stored procedure is defined by SQL statements. These statements can include SELECT, INSERT, UPDATE, DELETE, and other SQL commands to interact with the database.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AvmCTHjCgFVSdOf7H.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AvmCTHjCgFVSdOf7H.png" alt="Using SQL queries in stored procedures"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE PROCEDURE `GenerateSalesReport`(
    IN start_date DATE,
    IN end_date DATE
)
BEGIN
    SELECT DATE_FORMAT(saled_date, '%d-%m-%Y') AS Date,
           COUNT(sale_id) AS TotalOrders,
           SUM(total_amount) AS TotalSales
    FROM sales
    WHERE saled_date BETWEEN start_date AND end_date
    GROUP BY DATE_FORMAT(saled_date, '%d-%m-%Y');
END
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Procedure Call&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To execute the stored procedure and generate a detailed sales report for a specific date range, we can use the following syntax:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CALL (, ...);

CALL GenerateSalesReport('2021-01-01', '2023-12-31');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Result of the stored procedure, This query processed around 1 million data in a second.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2824%2F0%2AWF4JceFanQLaYGh8.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%2Fcdn-images-1.medium.com%2Fmax%2F2824%2F0%2AWF4JceFanQLaYGh8.png" alt="Usage of calling a stored procedure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Importance of using MySQL stored procedures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Improved Performance
&lt;/h3&gt;

&lt;p&gt;Stored procedures offer a significant performance advantage over ad-hoc SQL queries. Once a stored procedure is created, it is compiled and stored in a pre-optimized form. This compilation process eliminates the need for repetitive query parsing and optimization, resulting in faster execution times. By reducing the overhead associated with query processing, stored procedures enhance the overall performance of database operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enhanced Security
&lt;/h3&gt;

&lt;p&gt;Security is a critical aspect of database management. Stored procedures allow database administrators to define access rights and permissions for executing specific procedures. This fine-grained control ensures that only authorized users can interact with the database through the procedures, minimizing the risk of unauthorized data access or modifications. By encapsulating sensitive operations within stored procedures, security vulnerabilities are reduced, strengthening the overall database security posture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Reusability and Maintainability
&lt;/h3&gt;

&lt;p&gt;Stored procedures promote code reusability, modularity, and maintainability. By encapsulating frequently used SQL statements and operations within a single procedure, you can avoid code duplication and ensure consistent execution across multiple instances. This modularity makes it easier to maintain and update the database logic. Additionally, when modifications are required, changes can be made in a single location (the stored procedure) rather than in multiple places, simplifying the maintenance process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transaction Control
&lt;/h3&gt;

&lt;p&gt;Stored procedures enable transaction control within the database. Transactions ensure data integrity by grouping multiple database operations into a single logical unit. By executing a series of operations within a transaction, you can ensure that either all the operations are successfully completed, or none of them are applied. This atomicity ensures data consistency and protects against data corruption. Stored procedures allow you to define transaction boundaries, ensuring that complex operations are handled reliably and consistently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Optimization and Query Plan Caching
&lt;/h3&gt;

&lt;p&gt;Another advantage of using stored procedures is the ability to optimize query execution plans. Since stored procedures are compiled and stored, the database engine can generate optimized execution plans based on the stored procedure’s statistics and data distribution. These optimized plans can significantly improve query performance. Furthermore, the query execution plans for stored procedures are cached, which further reduces the overhead of plan generation for subsequent executions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Stored procedures are a valuable tool in database management, and their usage should be considered in specific scenarios. When dealing with complex business logic, aiming for performance optimization, enhancing security and access control, promoting code reusability and maintainability, handling complex transactions, or integrating with legacy systems, stored procedures can provide significant benefits. By leveraging their power effectively, you can streamline your database operations, improve application performance, and simplify code maintenance, leading to a more efficient and scalable database environment.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading the article. If you wish to learn more about SQL, subscribe to my article by entering your email address &lt;a href="https://5minslearn.gogosoon.com/?ref=devto_sql_store_procedures" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/blogs/?ref=devto_sql_store_procedures" rel="noopener noreferrer"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

</description>
      <category>5minslearn</category>
      <category>mysql</category>
      <category>dbms</category>
      <category>sql</category>
    </item>
    <item>
      <title>How to build a custom widget in Flutter — GoGoSoon</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Thu, 10 Aug 2023 16:35:59 +0000</pubDate>
      <link>https://dev.to/5minslearn/how-to-build-a-custom-widget-in-flutter-gogosoon-mpl</link>
      <guid>https://dev.to/5minslearn/how-to-build-a-custom-widget-in-flutter-gogosoon-mpl</guid>
      <description>&lt;p&gt;As we all know Flutter is gaining more and more popularity day by day. Flutter apps has been loved by people for its smoothness. One such example app is Zerodha’s Kite. Kite is a trading app released by India’s biggest stock broker Zerodha. Similar to this there were many complex applications built with Flutter. However, building complex applications is not so simple. You have to refactor your code as and when needed to maintain the app’s performance. One such refactoring technique is extracting the duplicated code/component and reuse them at multiple places.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll be learning about replacing a duplicated component by building a custom widget in Flutter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Custom Widget
&lt;/h2&gt;

&lt;p&gt;In Flutter, a custom widget refers to a user-defined widget that encapsulates a specific set of functionality or visual representation. Custom widgets are the building blocks of a Flutter application. They allow developers to create reusable UI components that can be used throughout the application.&lt;/p&gt;

&lt;p&gt;If you’re switching from React Native, assume Custom Widget as a custom React component and what we call as props in React will be called as parameters in Flutter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Custom Widgets
&lt;/h2&gt;

&lt;p&gt;Custom widgets enable you to encapsulate complex UI elements, promote code re-usability, and enhance the maintainability of your Flutter applications. Developers should build custom widgets in Flutter for several reasons. Here are a few,&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Re-usability
&lt;/h3&gt;

&lt;p&gt;It allow developers to encapsulate complex functionality and appearance into reusable components. Once created, custom widgets can be used multiple times throughout the application, reducing code duplication and promoting a modular development approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintainability
&lt;/h3&gt;

&lt;p&gt;It contribute to the maintainability of the codebase. By encapsulating specific functionality or visual representation, custom widgets create a separation of concerns. This separation makes it easier to locate, modify, and debug code related to a particular UI component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistent UI
&lt;/h3&gt;

&lt;p&gt;It enable developers to define a consistent and unified UI design across their application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Abstraction
&lt;/h3&gt;

&lt;p&gt;It provide a level of abstraction that hides the implementation details and complexity of a particular UI element. Developers can create high-level widgets that expose a simplified interface and handle the internal logic, allowing other developers to use the widget without worrying about its internal workings. This abstraction promotes modularity, making it easier to understand, test, and maintain the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a Custom Widget
&lt;/h2&gt;

&lt;p&gt;Let’s start building our custom widget.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone the repo
&lt;/h3&gt;

&lt;p&gt;Instead of starting from the scratch, I’ve created a Flutter app in Github and added a duplicated code/components in that repo. Let’s begin from there.&lt;/p&gt;

&lt;p&gt;Pull the code from Github by running either of the below commands&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/5minslearn/Flutter-Custom-Widget.git

git clone [email protected]:5minslearn/Flutter-Custom-Widget.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ARTmQpegPYL8vBMSy.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2ARTmQpegPYL8vBMSy.png" alt="Clone the Flutter Custom Widget repo from GitHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, it’ll be in master branch. I'm switching to a refactor branch (you don't need to) because I want you all to have a look at my initial and final code. Initial code will be in master branch and final code will be in refactor branch.&lt;/p&gt;

&lt;p&gt;Run the following command to install all the dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Flutter-Custom-Widget/ 

flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AnYRFs12kiVMDXU_i.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AnYRFs12kiVMDXU_i.png" alt="Install Flutter dependencies"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the app
&lt;/h3&gt;

&lt;p&gt;Open the repo in Visual Studio Code and spin up your emulator (you may connect your mobile device too). Once your emulator is up and running, press F5 to run the app in the emulator.&lt;/p&gt;

&lt;p&gt;Here’s the view of your app on the first run.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8daCZpSW4l5M73Ww.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A8daCZpSW4l5M73Ww.png" alt="Initial app run screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve come so far, that’s great.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyze the code
&lt;/h3&gt;

&lt;p&gt;Let’s look at the code. Open lib/main.dart file.&lt;/p&gt;

&lt;p&gt;We have MyApp class called at the beginning. This in-turn calls MyHomePage class.&lt;/p&gt;

&lt;p&gt;Here we go. Our code for the entire UI.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXwqzE5AXjXa1H3nW.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXwqzE5AXjXa1H3nW.png" alt="Code for the app UI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re someone who loves writing clean code, you would definitely say that it’s a ugly code. Here’s the reason for it. Look at the code carefully where the lines from 44 to 56 and the lines from 58 to 70 are completely duplicated except a very few handpicked words. Example, the word “Twitter” has been replaced with “Instagram”.&lt;/p&gt;

&lt;p&gt;The Clean coder will definitely refactor this code before working on adding new features/functionalities. Let us follow the clean coding practice too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refactor — Build a custom widget
&lt;/h3&gt;

&lt;p&gt;We have to extract the text and button into a separate component. This component should accept the platform and onPressed as it's parameters. We can template out the common text from them.&lt;/p&gt;

&lt;p&gt;So, our code to build the custom widget looks like below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CustomButton extends StatelessWidget {
  final String platform;
  final VoidCallback onPressed;
  const CustomButton(
      {super.key, required this.platform, required this.onPressed});
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
      Text("Press the below button to follow me on $platform"),
      ElevatedButton(
        onPressed: () {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text("Pressed Follow on $platform button"),
              duration: const Duration(seconds: 1),
            ),
          );
          onPressed();
        },
        child: Text("Follow on $platform"),
      )
    ]));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;As we discussed above, we’ve the template text and accept platform and onPressed parameters. We replace platform wherever we need and call onPressed method as the extension of showing a snack bar.&lt;/p&gt;

&lt;p&gt;Add the above code at the very end of the main.dart file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrate Custom Widget
&lt;/h3&gt;

&lt;p&gt;Let’s integrate our custom widget into our code.&lt;/p&gt;

&lt;p&gt;Replace lines 44 to 56 with the following code,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CustomButton(
  platform: 'Twitter',
  onPressed: () {
    // Open Twitter App
  },
),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace lines 58 to 70 with the following code,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CustomButton(
  platform: 'Instagram',
  onPressed: () {
    // Open Instagram App
  },
),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AcO_KXebJg0iIAEKR.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AcO_KXebJg0iIAEKR.png" alt="After refactoring your code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run your app now.&lt;/p&gt;

&lt;p&gt;Unfortunately, you’ll not notice any change in the UI. However your underlying code has changed. That’s exactly what refactoring is.&lt;/p&gt;

&lt;p&gt;Quoting from Martin Fowler,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;**&lt;em&gt;Refactoring **is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://refactoring.com/" rel="noopener noreferrer"&gt;*https://refactoring.com/&lt;/a&gt;*&lt;/p&gt;
&lt;/blockquote&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUHaugtuctYd0fa7Q.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AUHaugtuctYd0fa7Q.png" alt="Final app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You may ask a question by look at the above code. The line numbers 43 and 50 also contain the same code ( const SizedBox(height: 16),). Why don't you include that into your component.&lt;/p&gt;

&lt;p&gt;That’s great if this question really hit your mind.&lt;/p&gt;

&lt;p&gt;There is no need for the custom widget component to include the SizedBox component. Because, SizedBox component is added in the Home page to give some space between each component. It is not mandatory that whenever we use this button, we have to give a space at the top/bottom of the widget. However if such case arise, you can add the SizedBox widget inside your custom widget.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the benefit of building custom widget
&lt;/h2&gt;

&lt;p&gt;You don’t see a direct benefit right away. However, you may experience it in the future. Here’s a quick example for you.&lt;/p&gt;

&lt;p&gt;Let’s assume you’ve built this app for a client. It has become a complex app and you’ve used this custom widget around 20 places in your app. The app is released and people enjoy using it. Around 6 months later, your client come back to you with the next version of changes. One of the items in the huge list is, “We’re coming up with a slight change in theme. Replace all the social media referral buttons to be in outlined shape and change the color to green”.&lt;/p&gt;

&lt;p&gt;It is one simple configuration change in our custom widget. However assume, if you have not built the custom widget and copy/pasted the same code in all the 20 places. Then you have to carefully look at each place and replace them with care without touching other pieces of code.&lt;/p&gt;

&lt;p&gt;These are the only 2 lines we have to change in the our custom widget&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OutlinedButton(
        style: OutlinedButton.styleFrom(foregroundColor: Colors.green),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXqT2_xuFeErbONEd.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AXqT2_xuFeErbONEd.png" alt="After refactoring your code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have not refactored your code, you have to make this change in 20 places.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzrIsIOA3oyFPXFJE.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AzrIsIOA3oyFPXFJE.png" alt="Small change reflects everywhere"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve pushed my code to the same &lt;a href="https://github.com/5minslearn/Flutter-Custom-Widget" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt;. Refer master branch for the non-refactored code and refactor branch for refactored code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Note
&lt;/h3&gt;

&lt;p&gt;Always use custom widgets for it’s specific use cases. For example, in our case, it is for Social media redirects. This widget should not be used at places which is unrelated to it’s context. If you do so, remember the above case where the client requirement was to change the design of only the social media referral buttons, but our change will be applied to all the other places where this widget has been used, leading to unexpected bugs. It is always advised to write unit test cases for Custom Widgets which will help us to mitigate the bugs earlier.&lt;/p&gt;

&lt;p&gt;One more tip would be to name your component more readable. This makes the other developer know what the widget does just by reading it’s name. In our case, I’ve named it as CustomButton which makes no sense. Instead the best possible alternatives would be SocialMediaButton, SocialButton, etc. which fits into our use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this blog, we learnt about building a custom widget by removing a duplicated code/component. Building custom widgets in Flutter promotes code re-usability, maintainability, consistency, abstraction, flexibility, and community collaboration. Custom widgets are a powerful tool in the Flutter developer’s toolkit, enabling the creation of beautiful and functional user interfaces while maximizing efficiency and maintainability.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading the article. If you wish to learn more about Flutter, subscribe to my article at my &lt;a href="https://5minslearn.gogosoon.com/?ref=dev_to_flutter_custom_widget" rel="noopener noreferrer"&gt;site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gogosoon.com/blog/how-to-build-a-custom-widget-in-flutter" rel="noopener noreferrer"&gt;https://www.gogosoon.com&lt;/a&gt; on June 7, 2023.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>5minslearn</category>
      <category>flutter</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>What is RabbitMQ and How to use it with NodeJS</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Mon, 31 Jul 2023 05:38:13 +0000</pubDate>
      <link>https://dev.to/5minslearn/what-is-rabbitmq-and-how-to-use-it-with-nodejs-18o8</link>
      <guid>https://dev.to/5minslearn/what-is-rabbitmq-and-how-to-use-it-with-nodejs-18o8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ON03jvug--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AMsjdEVnCvKXy7Px-hTZ5ig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ON03jvug--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AMsjdEVnCvKXy7Px-hTZ5ig.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re exploring the world of distributed systems and real-time data pipelines, it is likely that you would have come across the concept of message queues. Two names stand out among the pantheon of technologies in this field: RabbitMQ and Apache Kafka. While both are renowned for their robustness and reliability, they have unique features and use cases that make them distinct.&lt;/p&gt;

&lt;p&gt;RabbitMQ, an open-source message broker, is widely recognized for its flexibility and support for various messaging protocols. On the other hand, Apache Kafka is rapidly gaining popularity and is known for its ability to handle real-time data feeds with low latency.&lt;/p&gt;

&lt;p&gt;This blog post will focus on RabbitMQ, its core features, and how it can effectively build scalable, loosely coupled applications.&lt;/p&gt;

&lt;p&gt;Stay with us as we explore into the world of RabbitMQ, its unique capabilities, and how it sets itself apart in the ever-evolving landscape of message queue technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is RabbitMQ?
&lt;/h2&gt;

&lt;p&gt;RabbitMQ is an open-source message broker software (also called message-oriented middleware) that implements the Advanced Message Queuing Protocol (AMQP). It provides a common platform for sending and receiving messages. It supports multiple messaging protocols and can be deployed in distributed and federated configurations to meet high-scale, high-availability requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use RabbitMQ?
&lt;/h2&gt;

&lt;p&gt;Consider an e-commerce website (like Amazon) where users can place orders, which need to be processed. The order processing system might involve several steps, such as inventory checks, payment processing, shipping, etc., each of which can potentially take some time and are ideally handled asynchronously.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inventory Checks:&lt;/strong&gt; When a user places an order, the system should check whether the ordered products are in stock. You can send a message to a queue that is consumed by a service responsible for checking inventory. This way, even if the inventory service is temporarily down or overloaded, the order messages won’t be lost; they’ll be processed as soon as the service is available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Payment Processing:&lt;/strong&gt; The payment processing might be done by another microservice. Once the inventory check is completed, a message can be sent to a queue for the payment service. This decouples the payment processing from the inventory checking, allowing these operations to scale independently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Shipping:&lt;/strong&gt; After payment confirmation, a message can be sent to another queue that’s responsible for handling shipping. Again, this service might take some time, but because it’s decoupled from the rest of the system, it won’t slow down other operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notification system:&lt;/strong&gt; After every successful order placement, payment, and shipment, notifications (Email or SMS) must be sent to the customer. This can be handled by separate services that listen to specific queues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Install &amp;amp; Run RabbitMQ
&lt;/h2&gt;

&lt;p&gt;In this example, I’ll be showcasing using Docker to run RabbitMQ. However, if you prefer, you can install and run it manually on your system. The official &lt;a href="https://www.rabbitmq.com/install-windows.html"&gt;documentation&lt;/a&gt; provides a detailed guide on how to do this.&lt;/p&gt;

&lt;p&gt;I find Docker to be a convenient tool for running RabbitMQ because it simplifies the setup and management processes. If you’re new to Docker, I recommend (not mandatory) reading my &lt;a href="https://www.freecodecamp.org/news/how-to-get-started-with-docker-using-nodejs/"&gt;previous&lt;/a&gt; blog posts related to Docker for a thorough understanding.&lt;/p&gt;

&lt;p&gt;To get started, you’ll need to pull the Docker image from Docker Hub.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull rabbitmq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H5y2XjUw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Aea7QPrlbp7yqIbgP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H5y2XjUw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Aea7QPrlbp7yqIbgP.png" alt="" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before running the image, We need to map the two port numbers (15672 and 5672).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port 5672&lt;/strong&gt;: This is the default port for RabbitMQ when using AMQP (Advanced Message Queuing Protocol). Clients that connect with AMQP typically use this port. So, if you’re using an AMQP client library to connect to RabbitMQ, it’s likely to connect on port 5672.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Port 15672&lt;/strong&gt;: This is the default port for the RabbitMQ Management UI, when using the rabbitmq_management plugin. The Management UI is a web-based interface that allows you to monitor and control your RabbitMQ server.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’m running the RabbitMQ on the Docker by adding the above-mentioned ports. Refer to the below screenshot for additional reference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O60QZPYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AVQ4iv1UcZJfi7spE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O60QZPYx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AVQ4iv1UcZJfi7spE.png" alt="" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our RabbitMQ Server is up and running in docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RHWoL57E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AYJzCmtdVxb6JoMIc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RHWoL57E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AYJzCmtdVxb6JoMIc.png" alt="" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implement Message Queue in NodeJS
&lt;/h2&gt;

&lt;p&gt;I’ll be using amqplib, which is a popular NodeJS library that provides an API for interacting with RabbitMQ. It supports all the features of RabbitMQ’s AMQP 0-9-1 model, including things like confirm channels, exchanges, queues, bindings, and message properties.&lt;/p&gt;

&lt;p&gt;I have been using the term AMQ Protocol in this blog and I feel this is the right time to give a quick introduction about it.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is AMQP
&lt;/h2&gt;

&lt;p&gt;AMQP stands for Advanced Message Queuing Protocol. It is an open-standard protocol for message-oriented middleware. The defining features of AMQP are message orientation, queuing, routing (including point-to-point and publish-and-subscribe), reliability, and security.&lt;/p&gt;

&lt;p&gt;AMQP has the following components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Producer&lt;/strong&gt; — It’s an application that sends messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consumer&lt;/strong&gt; — It’s an application that receives messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Queue&lt;/strong&gt; — It’s a buffer that stores the messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Message&lt;/strong&gt; — Information that is sent from the producer to a consumer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exchange&lt;/strong&gt; — Receives messages from producers and pushes them to queues depending on rules defined by the exchange type. The exchange type determines how messages are routed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Binding&lt;/strong&gt; — Links the queue to the exchange&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The AMQP protocol enables standardized communication between different applications, making it a good choice for a messaging system in a micro-services architecture. This protocol can ensure that a message is delivered not just to the messaging system, but all the way to the correct consumer.&lt;/p&gt;

&lt;p&gt;Remember the example that I described at the beginning of this blog about the high-level implementation of message queues in an E-commerce site?&lt;/p&gt;

&lt;p&gt;Let’s go through the same but a bit deeper in the RabbitMQ context.&lt;/p&gt;
&lt;h3&gt;
  
  
  Order Placement
&lt;/h3&gt;

&lt;p&gt;When a customer places an order on the e-commerce website, the order service produces a message to a RabbitMQ exchange. The message contains information about the product ID and the quantity ordered.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inventory Update
&lt;/h3&gt;

&lt;p&gt;An inventory service is set up for a consumer to receive messages from a queue bound to the exchange. Once it gets a message, it reduces the inventory for the specified product by the ordered quantity. If the inventory is insufficient, it can send a message back to the order service to indicate the problem.&lt;/p&gt;
&lt;h3&gt;
  
  
  Order Confirmation
&lt;/h3&gt;

&lt;p&gt;Once the inventory service successfully updates the inventory, it’ll send a message to the order service. The order service, set up as a consumer for this exchange, can then update the order status and notify the customer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Resilience
&lt;/h3&gt;

&lt;p&gt;Let’s assume your inventory service is down for some time, then the messages in the RabbitMQ queue will stay there and won’t be lost. Once the inventory service is back online, it’ll continue processing the messages from where it left off.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scalability
&lt;/h3&gt;

&lt;p&gt;During high traffic periods, more instances of the inventory service can be launched, all-consuming messages from the same queue, enabling load balancing and ensuring the system can handle the increased load.&lt;/p&gt;

&lt;p&gt;Let’s come back to our implementation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create a Sender / Producer
&lt;/h2&gt;

&lt;p&gt;This is the component or part of our application that creates and sends messages to the messaging queue. The sender does not send messages directly to the consumer. Instead, it sends the messages to an exchange in RabbitMQ. The exchange then routes the messages to the appropriate queue based on certain criteria.&lt;/p&gt;

&lt;p&gt;Here I am Creating a queue called product_inventory.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
We can send only byte arrays in the message, So I convert the message object to a string and send it to the queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Receiver / Consumer
&lt;/h2&gt;

&lt;p&gt;This is the component or part of our application that receives and processes the messages from the queue. A consumer can continuously poll the queue for new messages or be set up to automatically trigger when a new message is added to the queue.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In the above code, we’re listening for messages (consume) and print them on the console once we receive it.

&lt;p&gt;In the context of our specific use case, the file containing the message sender (or producer) should typically be located in the root directory of our e-commerce site project. This is where we generate and send messages based on user actions, such as placing an order.&lt;/p&gt;

&lt;p&gt;On the other hand, the file containing the message receiver (or consumer) should ideally be located in the inventory management service. This is because the inventory management service is responsible for processing these messages, such as updating the inventory when an order is placed.&lt;/p&gt;

&lt;p&gt;Let’s run our receiver service first,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The initial output of the consumer service,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CwzxWi3m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2At-eam31HoyGh5TpR.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CwzxWi3m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2At-eam31HoyGh5TpR.png" alt="Initial output in the consumer service — Listening for messages" width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we run our sender, a message will be sent to the consumer.&lt;/p&gt;

&lt;p&gt;Here’s the output of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YPYYacxu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2030/0%2AjJHf3ptbjNeaiyRP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YPYYacxu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2030/0%2AjJHf3ptbjNeaiyRP.png" alt="Sending a message from the producer to the consumer" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hurray, We received a message from the RabbitMQ producer in our consumer service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fmvfLbGA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJeIj0G1FJc00F0eY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fmvfLbGA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJeIj0G1FJc00F0eY.png" alt="Received message from the RabbitMQ producer in our consumer service" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we’ve explored the basics of RabbitMQ, a robust and efficient message broker, and demonstrated its application in a NodeJS environment. Using a simple e-commerce scenario, we showcased how to set up a sender (producer) and a consumer to handle asynchronous messages between different components of our application. However, in real-world applications, you will likely encounter more complex scenarios that require advanced integrations and the usage of RabbitMQ.&lt;/p&gt;

&lt;p&gt;To navigate these complexities, it’s crucial to have a solid understanding of RabbitMQ’s underlying concepts and its AMQP protocol. As you delve deeper into RabbitMQ, you’ll find it to be an incredibly versatile tool, capable of handling a wide range of messaging needs, and ultimately, helping you build scalable, decoupled, and resilient applications.&lt;/p&gt;

&lt;p&gt;Check out the source code of the project on GitHub: &lt;a href="https://github.com/5minslearn/rabbit-sender"&gt;rabbit-sender&lt;/a&gt;, &lt;a href="https://github.com/5minslearn/rabbit-receiver"&gt;rabbit-receiver&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wish to learn more about RabbitMQ, subscribe to my article at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devto_com_rabbitmq"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Learn Networking in Flutter</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Thu, 20 Jul 2023 05:04:46 +0000</pubDate>
      <link>https://dev.to/5minslearn/learn-networking-in-flutter-42g3</link>
      <guid>https://dev.to/5minslearn/learn-networking-in-flutter-42g3</guid>
      <description>&lt;p&gt;Almost all apps you use today will run by accessing the internet. You can hardly find an app that runs without connecting to the internet. Internet has become inevitable part of our life as it solves one of the most critical problems of humans i.e., data transfer. You either receive or send a data to someone. Be it a social media app, news app or whatever type it may be, there’s a data transfer.&lt;/p&gt;

&lt;p&gt;Hence it is super important to learn networking if you’re learning mobile app development. In this article I’ll be sharing about building a super simple mobile app that fetches the data from internet and render it on the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create the Project
&lt;/h2&gt;

&lt;p&gt;Navigate to the folder where you want to create your project in the terminal and run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/5minslearn/Flutter-Boilerplate.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Navigate to the Flutter-Boilerplate folder and run the flutter pub get command to install the dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Flutter-Boilerplate/ 
flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That’s it. We’ve got our dependencies installed.&lt;/p&gt;

&lt;p&gt;Open the project in Visual Studio Code by running the code ./ command in the terminal.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Av9J69-z71yd-LS0o.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2Av9J69-z71yd-LS0o.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start your emulator/connect your device and press F5 in VS Code to run your app.&lt;/p&gt;

&lt;p&gt;At the moment, the app will just contain an empty screen as shown in the below screenshot.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AxW4kqMQ08lhXup7Q.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AxW4kqMQ08lhXup7Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s build our networking app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to get the data
&lt;/h2&gt;

&lt;p&gt;It is the most obvious question. If we were to fetch something from the internet and render, we need an API server exposing the data we need. But, most people cannot afford to do that for learning purpose. To overcome this many people are offering free API services.&lt;/p&gt;

&lt;p&gt;You can consume the data from their API services for learning purpose. However, we cannot validate the originality of the data as most of them will be random.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll be using the API exposed by &lt;a href="https://sampleapis.com/" rel="noopener noreferrer"&gt;https://sampleapis.com/&lt;/a&gt;. They expose an API endpoint that lists the Coding Resources. The URL of the endpoint is &lt;a href="https://api.sampleapis.com/codingresources/codingResources" rel="noopener noreferrer"&gt;https://api.sampleapis.com/codingresources/codingResources&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In our app, we’ll fetch the data from this endpoint and list them in our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the dependencies
&lt;/h2&gt;

&lt;p&gt;Let’s install the dependencies needed to build this app. We need 2 dependencies. They are,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;http&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;url_launcher&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;http package is used to make a call to the API endpoint. The url_launcher package is used to open a url in a external browser.&lt;/p&gt;

&lt;p&gt;Open pubspec.yml file and add the following two packages in the dependencies section.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http: ^0.13.6 
url_launcher: ^6.1.11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkpSrX8Hg55rEwXPs.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AkpSrX8Hg55rEwXPs.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re using VS Code as your IDE, the dependencies will be installed automatically by saving this file. For the other IDE’s, run flutter pub get on your project root folder to install the dependencies.&lt;/p&gt;

&lt;p&gt;Import the http package in the lib/main.dart file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:http/http.dart' as http;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Initialize a list object in the _MyHomePageState class by adding the following code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List _resources = [];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s write a method that makes a call to our API endpoint and decode them into a JSON object.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void _fetchResources() async {
    final response = await http.get(Uri.parse(
        'https://api.sampleapis.com/codingresources/codingResources'));
    if (response.statusCode == 200) {
      final data = json.decode(response.body) as List;
      setState(() {
        _resources = data;
      });
    } else {
      throw Exception('Failed to load resources');
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Paste the above code into the _MyHomePageState class. In the above method, we're making a call to the API endpoint ( &lt;a href="https://api.sampleapis.com/codingresources/codingResources" rel="noopener noreferrer"&gt;https://api.sampleapis.com/codingresources/codingResources&lt;/a&gt;). From the response, we're validating if it is successful in receiving the data by checking if it's status code is 200 and throw error if it's not. We then decode the received data and save it in our app's state.&lt;/p&gt;

&lt;p&gt;You may notice an error on pasting the above code at the json.decode part. In order to decode a JSON, we need import a convert package in our file. Add the following code at the top of the file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'dart:convert';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hopefully the error should be gone now.&lt;/p&gt;

&lt;p&gt;We have a method that makes a call to the API endpoint and save the data in the state. Our next step is to trigger this method when we open the app.&lt;/p&gt;

&lt;p&gt;We can do that by overriding the initState method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@override
  void initState() {
    super.initState();
    _fetchResources();
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From the Flutter documentation,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;initState is called when this object is inserted into the tree. The framework will call this method exactly once for each &lt;a href="https://api.flutter.dev/flutter/widgets/State-class.html" rel="noopener noreferrer"&gt;State&lt;/a&gt; object it creates.&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://api.flutter.dev/flutter/widgets/State/initState.html" rel="noopener noreferrer"&gt;*https://api.flutter.dev/flutter/widgets/State/initState.html&lt;/a&gt;*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the above code, we called our method _fetchResources() in the initState() method.&lt;/p&gt;

&lt;p&gt;We got the list of items whenever we open the app. Our next step is to render them on UI.&lt;/p&gt;

&lt;p&gt;Copy the below code and replace it with the build method of the _MyHomePageState class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: _resources.isEmpty
            ? const Center(
                child: CircularProgressIndicator(),
              )
            : ListView.builder(
                itemCount: _resources.length,
                itemBuilder: (context, index) {
                  final resource = _resources[index];
                  return InkWell(
                      onTap: () =&amp;amp;gt; {},
                      child: Card(
                          child: ListTile(
                        title: Text(resource['description']),
                        subtitle: Text(resource['url']),
                        leading: const CircleAvatar(
                            backgroundImage: NetworkImage(
                                "https://images.unsplash.com/photo-1547721064-da6cfb341d50")),
                        trailing: Text(resource['types'].join(', ')),
                      )));
                }));
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s understand the above code.&lt;/p&gt;

&lt;p&gt;We show a loader if our state has empty values. If it has some values in it, we’ll iterate through as a ListView builder and we render a Card widget for each item, displaying the description, url, and types of the resource.&lt;/p&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;Run the app by pressing F5 and you should be able to see the following screenshot.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ae4sp2D2CLhPrY0pd.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2Ae4sp2D2CLhPrY0pd.png"&gt;&lt;/a&gt;&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALn0vGbofXMC5wn-F.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ALn0vGbofXMC5wn-F.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s Awesome!!! Isn’t it?&lt;/p&gt;

&lt;p&gt;But I feel there’s one small thing that’s missing in this. Briefing it here.&lt;/p&gt;

&lt;p&gt;We’re able to see the list of the resources. But, we’re not able to view those resource. Some resources has small link that we can easily remember and type. But, few of them have a long url which is not possible for a typical human being to remember. Let’s add a small enhancement that when we press a resource, it’s link should be opened in our default browser.&lt;/p&gt;

&lt;p&gt;The implementation of it is so simple in Flutter. This is the reason we added url_launcher package at the beginning of this blog.&lt;/p&gt;

&lt;p&gt;Import the url_launcher package in our app.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:url_launcher/url_launcher.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the following method in the _MyHomePageState class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_launchURL(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above method accepts a url and validates the link and opens it in the browser.&lt;/p&gt;

&lt;p&gt;We have to call this method on tapping the card. We can achieve that by calling this method in the onTap property of the InkWell widget.&lt;/p&gt;

&lt;p&gt;Here’s the code for it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;onTap: () =&amp;gt; {_launchURL(resource['url'])},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s run our app and test this.&lt;/p&gt;

&lt;p&gt;Hope you were disappointed on tapping a card. Yes. I’m also disappointed while working on this.&lt;/p&gt;

&lt;p&gt;You would have faced this error.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AyIcpEaILH0KbbHFk.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AyIcpEaILH0KbbHFk.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Though the url is right, why is our system not opening this in a browser.&lt;/p&gt;

&lt;p&gt;Well. We have to learn about intent action.&lt;/p&gt;

&lt;p&gt;Quoting it from Android Developers documentation,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed.&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://developer.android.com/reference/android/content/Intent" rel="noopener noreferrer"&gt;*https://developer.android.com/reference/android/content/Intent&lt;/a&gt;*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This basically means when we hand over something to the external app, we have to declare that in our app. For Android we have to define it in AndroidManifest.xml and for iOS most of these configurations go into Info.plist file.&lt;/p&gt;

&lt;p&gt;Add the queries block in the following code to your AndroidManifest.xml file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;manifest&amp;gt;
    &amp;lt;application&amp;gt;
        ...
    &amp;lt;/application&amp;gt;
    &amp;lt;queries&amp;gt;
        &amp;lt;intent&amp;gt;
            &amp;lt;action android:name="android.intent.action.VIEW" /&amp;gt;
            &amp;lt;category android:name="android.intent.category.BROWSABLE" /&amp;gt;
            &amp;lt;data android:scheme="https" /&amp;gt;
        &amp;lt;/intent&amp;gt;
    &amp;lt;/queries&amp;gt;
&amp;lt;/manifest&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Uninstall the app from your mobile and run the app again.&lt;/p&gt;

&lt;p&gt;Hopefully you should be able to see the link opened in the browser.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7YFvfvdHRO5mL_a6.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2A7YFvfvdHRO5mL_a6.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you’ve learnt about networking in Flutter. We made a request to an API, render the list, and open the url in the browser.&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://github.com/5minslearn/Flutter-Networking" rel="noopener noreferrer"&gt;repo&lt;/a&gt; has my code. You can use it for your reference.&lt;/p&gt;

&lt;p&gt;If you wish to learn more about Flutter, subscribe to my article by entering your email address in the below box.&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/?ref=DevDotTo_flutter_navigation_types" rel="noopener noreferrer"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>networking</category>
    </item>
    <item>
      <title>How to use Elastic Beanstalk to deploy NodeJS app</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Mon, 10 Jul 2023 05:12:50 +0000</pubDate>
      <link>https://dev.to/5minslearn/how-to-use-elastic-beanstalk-to-deploy-nodejs-app-1gan</link>
      <guid>https://dev.to/5minslearn/how-to-use-elastic-beanstalk-to-deploy-nodejs-app-1gan</guid>
      <description>&lt;p&gt;Building and managing applications on the cloud can be a daunting task, especially when it comes to handling different environments, scaling, and deploying updates. But there’s a service in AWS that can simplify this. AWS Elastic Beanstalk is here to make your life easier. It provides an easy-to-use platform for deploying, managing, and scaling your applications in the AWS Cloud.&lt;/p&gt;

&lt;p&gt;In this blog post, we’ll dive into the basics of Elastic Beanstalk, and then walk you through the process of deploying a NodeJS app connected to RDS database. Let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Elastic Beanstalk?
&lt;/h2&gt;

&lt;p&gt;AWS Elastic Beanstalk is a fully managed service that helps you deploy, manage, and scale applications on AWS. It takes care of provisioning the required resources, such as EC2 instances, RDS databases, and load balancers. Elastic Beanstalk also handles application deployment, monitoring, and maintenance tasks so that you can focus on writing code and delivering features.&lt;/p&gt;

&lt;p&gt;Elastic Beanstalk uses CloudFormation to provision resources. The good thing is you don’t need to write CloudFormation templates. It’ll be taken care by Elastic Beanstalk automatically.&lt;/p&gt;

&lt;p&gt;Now that we have a basic understanding of Elastic Beanstalk, let’s dive into deploying our NodeJS app with an RDS connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing NodeJS source code
&lt;/h2&gt;

&lt;p&gt;We cannot deploy our app straight to Elastic Beanstalk (similar to deploying at EC2), we need to follow a few steps before deployment. It took hours for me to figure out this but I’ll help you to deploy it in 5 minutes.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll be deploying this &lt;a href="https://github.com/5minslearn/eb-nodejs-rds"&gt;Node.js application&lt;/a&gt;. But to deploy our code we don’t need a repo, instead we need a zip of our source code. You can download the zip file of the above repo &lt;a href="https://github.com/5minslearn/eb-nodejs-rds/blob/master/nodejs-rds-sample.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Adding the steps here if you want to deploy your own app. But if you want to just deploy the above code, you can move to the next section (How to Create Elastic Beanstalk).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure your package.json file has the start command and this start command should be configured to run your app. Beanstalk will execute npm start by default and throws error if it can't find it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S4P9BSwW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A4pBNGV6kLWRXH3IF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S4P9BSwW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A4pBNGV6kLWRXH3IF.png" alt="" width="490" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There’s super important thing about configuring environment variables. AWS follows pre-defined environment variables for RDS connections. Ensure you used the right naming. You can read this article by &lt;a href="https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.managing.db.html"&gt;AWS&lt;/a&gt; for additional information. A quick example for you if you don’t understand this point. To configure the hostname for the RDS, you have to use RDS_HOSTNAME environment variable. You app will not be able to connect if you used some other variable name (Eg. DB_HOSTNAME).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can define custom environment variables in AWS Elastic Beanstalk console as per your need.&lt;/p&gt;

&lt;p&gt;Here’s how your DB connection configuration should look like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3RskxVkV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJs3mLN3zfuN9ffex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3RskxVkV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJs3mLN3zfuN9ffex.png" alt="" width="746" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Elastic Beanstalk (EBS) by default run on port 8080, so we have to configure our app to run on port 8080. It’s always best practice to add the port number in environment variables and configure it in the EBS console.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MtanLEkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AWze8rwyCY6azKGli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MtanLEkC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AWze8rwyCY6azKGli.png" alt="" width="611" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In order for Elastic Beanstalk to read our environment variables, we should add a file called .ebextensions in the project root directory with the following code.&lt;/p&gt;

&lt;p&gt;commands:&lt;br&gt;
    setvars:&lt;br&gt;
        command: /opt/elasticbeanstalk/bin/get-config environment | jq -r 'to_entries | .[] | "export (.key)=\"(.value)\""' &amp;gt; /etc/profile.d/sh.local&lt;br&gt;
packages:&lt;br&gt;
    yum:&lt;br&gt;
        jq: []&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the dependencies by executing npm install and zip your code along with &lt;strong&gt;node_modules&lt;/strong&gt; by executing the following command.&lt;/p&gt;

&lt;p&gt;zip [filename].zip -r ./&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember the zipped file should contain all files and subdirectories in the root folder and should not be inside any other folders. Because Elastic Beanstalk will check for package.json file in the root folder and throws error if it can't find it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F2xKnE0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A_5L6tJMUSuXHjnXS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F2xKnE0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A_5L6tJMUSuXHjnXS.png" alt="An example of correct folder structure" width="677" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kR5eV9Ed--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A2RrBIl2XLUOJMY24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kR5eV9Ed--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A2RrBIl2XLUOJMY24.png" alt="Wrong folder structure (all files are inside the folder called source-code)" width="677" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now our app is ready lets create the Elastic Beanstalk application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Create Elastic Beanstalk
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Step 1: Configure Your Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the AWS Management Console and select Elastic Beanstalk from the Services menu. Click on “Create Application” button.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the Web server environment and provide a name for your app.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3bDzXTYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2172/0%2A1RDRPNT1uzyUMR4w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3bDzXTYL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2172/0%2A1RDRPNT1uzyUMR4w.png" alt="" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j0hs_YFx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2128/1%2AP5ctV9IwQNojRRcIMpOekA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j0hs_YFx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2128/1%2AP5ctV9IwQNojRRcIMpOekA.png" alt="" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Choose Managed platform in “Platform type”, and Node.js in “Platform”, and leave the rest as it is.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose Upload your code in “Application code” section and upload the zip file.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e0fkxYDP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Ah4YjkA9p4EAm_FzW5SbYTw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e0fkxYDP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2Ah4YjkA9p4EAm_FzW5SbYTw.png" alt="" width="785" height="869"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set the version label to 1 and choose Single instance in “Presets”  section and click Next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Prefer High availability for production environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ane15UxL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzPtA8rrVbcp-Yk7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ane15UxL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzPtA8rrVbcp-Yk7q.png" alt="" width="792" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure service access
&lt;/h2&gt;

&lt;p&gt;In this section, we have to configure IAM roles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We need to create two IAM roles, one for Elastic Beanstalk and one for EC2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For service role, select Create and use new service role. It'll automatically create and provide required permissions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you want to ssh into your EC2 instance via terminal, create a key-value pair and select it. Ignore this step if you don’t want to login into EC2.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create an IAM role with the following permissions and add the role to “EC2 instance profile” and proceed Next&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWSElasticBeanstalkWebTier&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWSElasticBeanstalkWorkerTier&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AWSElasticBeanstalkMulticontainerDocker&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wHUfOlV7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2168/0%2AP1hViq7-V2KJ_GMK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wHUfOlV7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2168/0%2AP1hViq7-V2KJ_GMK.png" alt="" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set up networking, database, and tags
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Turn on the Enable database toggle and choose mysql Engine&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill up the other fields based on your needs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f1I5-KLs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AZmt7WpGWxwRxt-aM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f1I5-KLs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AZmt7WpGWxwRxt-aM.png" alt="" width="748" height="865"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be super careful while selecting the “Database deletion policy”. As I’m creating the sample app I selected Delete  option which will delete the database when the Elastic Beanstalk  application is deleted. If you’re working on a production database, it’s  always a best practice to choose Create Snapshot or Retain option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--91Bc9Idd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ASstmWq-gakpTR-wEjENuvQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--91Bc9Idd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ASstmWq-gakpTR-wEjENuvQ.png" alt="" width="784" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure instance traffic and scaling
&lt;/h2&gt;

&lt;p&gt;You don’t need to change anything here unless you exclusively need it. If you’re building this sample app leave the fields with default value. By default Elastic Beanstalk will create Amazon Linux machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yVqSyntN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJPFveiKcenCPhk_m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yVqSyntN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJPFveiKcenCPhk_m.png" alt="" width="796" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Configure updates, monitoring and logging
&lt;/h2&gt;

&lt;p&gt;Choose Basic in “Health reporting” and uncheck Managed updates activation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6ZSdVZ4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A2Ty78X4Oq_fvg_Xc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6ZSdVZ4E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A2Ty78X4Oq_fvg_Xc.png" alt="" width="785" height="866"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add your environment variables and click Next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Il0sUN74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Ak6boGxz2pYn5d8ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Il0sUN74--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Ak6boGxz2pYn5d8ay.png" alt="" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, review all your configurations and proceed with next. It takes time to provision RDS, so set back and have your coffee&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9rKm1QtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3246/0%2AiG7FBtFoaxn6_j10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9rKm1QtR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3246/0%2AiG7FBtFoaxn6_j10.png" alt="" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By now you could’ve understand why I spent hours on it 😂. Every time I made a mistake I have to wait for about 10 to 15 minutes to check the result and redo all the above steps if something goes wrong. Elastic Beanstalk will definitely test your patience, so be calm and relax.&lt;/p&gt;

&lt;p&gt;Once everything is done you could see health becomes green 🎉 and a domain URL will be generated 🥳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mUEELtSD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AzAz3AJgdNWeM3L6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mUEELtSD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AzAz3AJgdNWeM3L6w.png" alt="" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you used my example &lt;a href="https://github.com/5minslearn/eb-nodejs-rds"&gt;repo&lt;/a&gt; you’ll see the following page on opening the URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3I-k3G1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AxVzJF0OQY2xGJNSz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3I-k3G1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AxVzJF0OQY2xGJNSz.png" alt="" width="459" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you hit domain-url/hikes you can see the below page. Type some data and hit Record Hike button, the data will be stored in hikes table in RDS MySQL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7h_O_GUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Ai8HNWhwIvYsU-WzC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7h_O_GUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Ai8HNWhwIvYsU-WzC.png" alt="" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we’ve successfully deployed a NodeJS app with an RDS connection using AWS Elastic Beanstalk. This powerful service simplifies the deployment and management process, allowing us to focus on developing and scaling our applications.&lt;/p&gt;

&lt;p&gt;If you are stuck at any point feel free to drop your queries to me at my &lt;a href="https://www.gogosoon.com/cdn-cgi/l/email-protection#721300071c32151d151d011d1d1c5c111d1f"&gt;email&lt;/a&gt;. I’ll be happy to help you.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading this article!&lt;/p&gt;

&lt;p&gt;If you wish to learn more about AWS, subscribe to my newsletter by entering your email address in the below box.&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devto_com_aws_ebs"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gogosoon.com/blog/how-to-use-elastic-beanstalk-to-deploy-nodejs-app"&gt;https://www.gogosoon.com&lt;/a&gt; on May 15, 2023.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>elasticbeanstalk</category>
      <category>node</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Docker Extensions to Help You Improve Your Workflow</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Mon, 03 Jul 2023 05:19:28 +0000</pubDate>
      <link>https://dev.to/5minslearn/docker-extensions-to-help-you-improve-your-workflow-56ko</link>
      <guid>https://dev.to/5minslearn/docker-extensions-to-help-you-improve-your-workflow-56ko</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lUKIEBgw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2Azb6bbwj2ZkjnJLUYItrRpA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lUKIEBgw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2Azb6bbwj2ZkjnJLUYItrRpA.png" alt="Poster" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We all know that docker is getting popular day by day. A Lot of organizations also started using docker in their development lifecycle. So it is very important to update ourselves in terms of software development. ie, Docker itself is an automation tool in software development.&lt;/p&gt;

&lt;p&gt;If you are new to docker please read our previous blogs related to docker, Then you can easily understand the workflow in docker.&lt;/p&gt;

&lt;p&gt;In this blog, we can see about the top 5 simple and powerful docker extensions,&lt;/p&gt;

&lt;h2&gt;
  
  
  Drone CI
&lt;/h2&gt;

&lt;p&gt;Before getting into this extension we should know about CI. CI — Continous Integration. Whenever we start with DevOps the first thing we need to learn is continuous integration. Nowadays, developers expect the code changes should immediately reflect the production or testing server. So to automate this we should enable the CI / CD Pipelines in the development lifecycle.&lt;/p&gt;

&lt;p&gt;DroneCI is an open-source application that helps us to deploy our app continuously into our desired server. So DronCI is simple to set up and use. Let’s see how to deploy our NodeJS Application using DroneCI.&lt;/p&gt;

&lt;p&gt;We can install it from the Docker extensions marketplace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5W3ryi6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AYkq8WpJAIA_Km7W0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5W3ryi6g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AYkq8WpJAIA_Km7W0.png" alt="JFrog installation in docker marketplace" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b1wcVxhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AN9_Cec2KlDkbELhg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b1wcVxhP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AN9_Cec2KlDkbELhg.png" alt="Import new pipelines" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;.drone.yml configuration. Put this file into the root of your Node project.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: pipeline
type: docker
name: default

platform:
 os: linux
 arch: arm64

steps:
- name: message
  image: busybox

- name: test
  image: node
  commands:
  - npm install
  - npm test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Wdd-uc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ALJf4PdJC-4lkv0Xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wdd-uc6n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ALJf4PdJC-4lkv0Xe.png" alt="Imported pipelines" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After importing the pipeline, you can run the pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FpGhZthV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AhB_TnpRf2zW6W5NDtqYJAA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FpGhZthV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AhB_TnpRf2zW6W5NDtqYJAA.png" alt="" width="785" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we are running only for testing the nodejs application, We can follow the same step to achieve the deployment also&lt;/p&gt;

&lt;h2&gt;
  
  
  JFrog Scan
&lt;/h2&gt;

&lt;p&gt;We all know about docker images, and sometimes we need to work on some open-source docker images. This extension will be useful for the people who are all using open-source docker images.&lt;/p&gt;

&lt;p&gt;Using the JFrog docker extension, We can scan any type of docker image, Moslty our internal docker images do not have any harmful configurations, So this is only useful for open-source or third-party docker images.&lt;/p&gt;

&lt;p&gt;We can install it from the docker marketplace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ThyrKnht--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AXjDomofsLq2Ogv0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ThyrKnht--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AXjDomofsLq2Ogv0A.png" alt="JFrog installation in docker marketplace" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before using the JFrog, We need an active account from JFrog, So we create an account for free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PxjKoGtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJHk75uFKh1QeJAut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PxjKoGtQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AJHk75uFKh1QeJAut.png" alt="JFrog Sign in console" width="717" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a successful sign in we can choose an Image to scan for vulnerabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kz1u-wIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A4c16enPXWAoBuDnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kz1u-wIY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A4c16enPXWAoBuDnm.png" alt="Choose an Image to scan for vulnerabilities" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that, The image is being scanned for vulnerabilities. It took some time&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tuI3tf9r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Ag80G5Mm1HfqZ2cHz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tuI3tf9r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Ag80G5Mm1HfqZ2cHz.png" alt="JFrog Scanning the images" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Oops, our docker image has 25 critical vulnerabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6J0EC1Yj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Acb6JecatghhiS89F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6J0EC1Yj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Acb6JecatghhiS89F.png" alt="Vulnerabilities found in the docker image" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Portainer
&lt;/h2&gt;

&lt;p&gt;Portainer provides a web-based interface for managing containers, images, volumes, networks, and other Docker-related resources.&lt;/p&gt;

&lt;p&gt;This extension is used to manage container hosts, Docker Swarm clusters, and Kubernetes clusters in a much simpler way.&lt;/p&gt;

&lt;p&gt;Using portainer we can manage the running containers, Images, and Environments in a uniform UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KO1ul5vZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AqxfwlZSX1Buw1B6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KO1ul5vZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AqxfwlZSX1Buw1B6z.png" alt="Managing containers using portainer dashboard" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can quickly take any type of action on the containers and Images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disk Usage
&lt;/h2&gt;

&lt;p&gt;Disk Usage is an official Docker extension that provides developers with insights into their Docker disk usage. Once installed, this extension thoroughly examines and categorizes the disk space occupied by various entities, such as images, containers, local volumes, and build cache. By utilizing this extension, users can efficiently manage their disk space by removing unnecessary objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YklSAm39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AVdub1a5FJ7atWy8B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YklSAm39--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AVdub1a5FJ7atWy8B.png" alt="Disk space usage by docker" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This optimization process is crucial to free up disk space for critical resources. The Disk Usage extension is readily accessible on the Docker extensions tab and can be easily enabled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SSvV9UGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AbSB3aThqSKtqGnRb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SSvV9UGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AbSB3aThqSKtqGnRb.png" alt="Details of disk usage by docker images, containers and local volumes" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can reclaim the space by removing unused images, dangling images and build caches. So this disk image extension itself gives some suggestions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o5RbnZdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ADCk99zQXUHY-bmNs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5RbnZdc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ADCk99zQXUHY-bmNs.png" alt="Reclaim disk space usage by docker" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Okteto
&lt;/h2&gt;

&lt;p&gt;Okteto is a useful tool that enhances your productivity and satisfaction by providing you with pre-configured environments. This helps free up your time from manually setting up environments.&lt;/p&gt;

&lt;p&gt;This accelerates the software development process and release cycles when combined with a proper CI/CD platform. It also enables you to create preview environments resembling test and development environments, allowing you to test changes before deploying them to production. With Okteto, cloud-native development becomes much easier.&lt;/p&gt;

&lt;p&gt;The Okteto extension is readily available in the Docker desktop extension marketplace and you can install it with a simple click.&lt;/p&gt;

&lt;p&gt;To leverage the benefits of Okteto, you’ll need to configure the Okteto manifest for your application. After installing the extension, it prompts you to launch a remote environment. Choose the application folder with the Okteto manifest file and start exploring.&lt;/p&gt;

&lt;p&gt;In simple words, you can connect to a remote environment using Okteto cloud. For more information on how to set up and use Okteto, refer to their &lt;a href="https://www.okteto.com/docs/"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qg1Y4ilI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AWoUkZgbzUQm4oxF_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qg1Y4ilI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AWoUkZgbzUQm4oxF_.png" alt="Octeto connect to remote environment" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to sign in to Okteto, you need a business email.&lt;/p&gt;

&lt;p&gt;After successful login, you have to choose the docker-compose.yml file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v0f6ZB8v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ABui7hx2NNIA8s9cz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0f6ZB8v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ABui7hx2NNIA8s9cz.png" alt="Okteto connect to remote environment" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker is a powerful tool that simplifies the development process and enables developers to build, test, and deploy applications quickly and efficiently.&lt;/p&gt;

&lt;p&gt;By using these Docker extensions, you can take advantage of additional features and functionality to streamline your workflow and optimize your Docker environment.&lt;/p&gt;

&lt;p&gt;If you wish to learn more about Docker, subscribe to my article by visiting my &lt;a href="https://5minslearn.gogosoon.com/?ref=devto_docker_extensions"&gt;site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devto_docker_extensions"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gogosoon.com/blog/docker-extensions-to-help-you-improve-your-workflow"&gt;https://www.gogosoon.com&lt;/a&gt; on May 7, 2023.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>5minslearn</category>
      <category>softwareengineering</category>
      <category>extenstion</category>
    </item>
    <item>
      <title>Types of Navigation in Flutter</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Sat, 03 Jun 2023 06:31:15 +0000</pubDate>
      <link>https://dev.to/5minslearn/types-of-navigation-in-flutter-4kkm</link>
      <guid>https://dev.to/5minslearn/types-of-navigation-in-flutter-4kkm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c6hAnA4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AwtyJIgd2i-hIut9Nc3fkJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c6hAnA4---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2400/1%2AwtyJIgd2i-hIut9Nc3fkJg.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Almost all the apps designed and developed will have either one of the 3 or all 3 types of navigation. These 3 types of navigation has been common to all apps. Flutter is no exemption to that convention. Flutter also supports all these 3 types of navigation. Navigation in flutter is almost exactly similar to other apps. But I felt it was super smooth when I built it on Flutter.&lt;/p&gt;

&lt;p&gt;In this article, let’s try to build a Flutter app implementing all the 3 types of navigation in a single app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of Navigation
&lt;/h2&gt;

&lt;p&gt;As I have been saying 3 types of navigation from the beginning, you may wonder what are the 3?&lt;/p&gt;

&lt;p&gt;Here it is,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Stack Navigation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tab Navigation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Drawer Navigation&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s understand quickly about each of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack Navigation
&lt;/h3&gt;

&lt;p&gt;Picture a deck of cards, where you can add or remove cards from the top of the stack. Stack Navigation in Flutter works in a similar fashion. It helps you navigate between pages or screens by stacking new pages on top of existing ones. When you move to a new screen, the current screen is pushed onto the navigation stack, and when you return, the top screen is popped off the stack. This navigation type is commonly used for hierarchical and linear flows within an app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tab Navigation
&lt;/h3&gt;

&lt;p&gt;Tabs are a staple of mobile app navigation, allowing users to quickly switch between different sections or views without losing their current context. Flutter makes it easy to implement tabbed navigation with its built-in widgets, such as TabBar and TabBarView. By using these widgets, you can create a beautiful and functional tab navigation experience, perfect for organizing content into logical sections. With Flutter, you have the freedom to customize the appearance of your tabs, making it simple to create a unique look and feel for your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawer Navigation
&lt;/h3&gt;

&lt;p&gt;The Drawer Navigation pattern, also known as the “hamburger menu” or “side menu,” is a popular navigation style in mobile apps. It consists of a hidden panel that slides out from the side of the screen, revealing a menu with various navigation options. This space-saving technique keeps your app’s main content visible while providing easy access to additional features or sections.&lt;/p&gt;

&lt;p&gt;Let’s start building the app&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the Project
&lt;/h2&gt;

&lt;p&gt;Instead of creating a new project everytime from the scratch, I’ve created a boilerplate app and uploaded in &lt;a href="https://github.com/5minslearn/Flutter-Boilerplate"&gt;Github&lt;/a&gt;. You can pull the code and run. Hope that make project creation simple.&lt;/p&gt;

&lt;p&gt;Navigate to the folder where you want to create your project in Terminal and run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/5minslearn/Flutter-Boilerplate.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Navigate to the Flutter-Boilerplate folder and run flutter pub get command to install the dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Flutter-Boilerplate/ flutter pub get
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That’s it. We got our dependencies installed.&lt;/p&gt;

&lt;p&gt;Open the project in Visual Studio Code by running code ./ command in Terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_xJCff4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A4jVUWjerACQdVDE_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_xJCff4X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A4jVUWjerACQdVDE_.png" alt="Clone repo and install dependencies" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start your emulator/connect your device and press F5 in VS Code to run our app.&lt;/p&gt;

&lt;p&gt;Our app will just contain an empty screen as shown in the below screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fTZ4Ds3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AB7FYDtMWLti3Cakv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fTZ4Ds3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AB7FYDtMWLti3Cakv.png" alt="Flutter app with empty screen" width="364" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s build all 3 types of navigation into our app.&lt;/p&gt;

&lt;p&gt;This is how our final app will look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--04AMFQGW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AI99eCCp2gUAiMJ0P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--04AMFQGW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AI99eCCp2gUAiMJ0P.png" alt="Look of our final app" width="361" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll have a Drawer &amp;amp; Tab Navigator at the top. Pressing on the button in the first tab will take us to the next page via Stack Navigator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tab Navigation
&lt;/h2&gt;

&lt;p&gt;Let’s begin with building the tab navigator. Let’s assume the tab will be on the home page (ideally it’ll be).&lt;/p&gt;

&lt;p&gt;Create a new filed named tab.dart in the lib/ directory. Add the following code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
import './tabs/tab1.dart';
import './tabs/tab2.dart';
import './tabs/tab3.dart';
class HomePage extends StatelessWidget {
  const HomePage({super.key});
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
          appBar: AppBar(
            title: const Text("Home"),
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.phone_android)),
                Tab(icon: Icon(Icons.tablet_android)),
                Tab(icon: Icon(Icons.laptop_windows)),
              ],
            ),
          ),
          body: const TabBarView(
            children: [
              Tab1(),
              Tab2(),
              Tab3(),
            ],
          )),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, we’re creating a class named HomePage. In the build method, we return DefaultTabController widget, which is basically a tab view. We define that we need 3 tabs in the length property. At the bottom of the appBar property we have defined icons for each tab (Phone, Tablet, and Computer icons). Below that we define the body property with a TabBarView rendering all the tabs inside it.&lt;/p&gt;

&lt;p&gt;Immediately you paste the above code, you’ll notice lot of errors being highlighted in your VS Code editor. The reason is, if you look at the top 4 lines, the 1st line is the import of Flutter’s Material UI package whereas the rest 3 are import from the user defined files. We haven’t created them yet. So, your code editor will throw an error in those lines and at the last 3 lines where we call Tab1(), Tab2(), and Tab3(). Because, these classes are imported from those files. Let's resolve this issue now.&lt;/p&gt;

&lt;p&gt;Create a new folder named tabs inside lib/ directory and create 3 files naming them as tab1.dart, tab2.dart, and tab3.dart.&lt;/p&gt;

&lt;p&gt;Copy the below content into tab1.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
class Tab1 extends StatelessWidget {
  const Tab1({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text("Mobiles"),
          Padding(
            padding: const EdgeInsets.only(top: 16.0),
            child: ElevatedButton(
              onPressed: () {
                Navigator.of(context).pushNamed("/secret");
              },
              child: const Text('Disclose Secret'),
            ),
          ),
        ],
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copy the below content into tab2.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
class Tab2 extends StatelessWidget {
  const Tab2({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: const [
          Text("Tablets"),
        ],
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Copy the below code into tab3.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
class Tab3 extends StatelessWidget {
  const Tab3({super.key});
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: const [
          Text("Laptops"),
        ],
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you look at the code for all the 3 files, you’ll notice everything is common except that the first tab file ( tab1.dart) has an additional button called "Disclose Secret" and pressing that will navigate to the /secret route. It'll not throw any error as this route has not been defined yet. The other 2 files ( tab2.dart and tab3.dart) will show only the text.&lt;/p&gt;

&lt;p&gt;All the errors you saw in tab.dart file will be resolved now. But, if you run your app, you will not notice any changes in the output. This is because, we have just created the tab layout and we haven't mapped it to our main.dart file.&lt;/p&gt;

&lt;p&gt;Add the following line at the top of the main.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './tab.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace home: const MyHomePage(title: 'Home'), with home: const HomePage(), in the build method of the MyApp class.&lt;/p&gt;

&lt;p&gt;Save the file and run your app. You should be able to see the tab layout on your screen now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wGWWt2NO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AgeHMM3PtMJEGAvFK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wGWWt2NO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AgeHMM3PtMJEGAvFK.png" alt="Tab Layout in Flutter App" width="362" height="764"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don’t press the “Disclose Secret” button. If you press it, it will throw an error. Because, remember I mentioned earlier, we setup a route navigation in the onPress property of this button, while the route is not yet defined.&lt;/p&gt;

&lt;p&gt;“Let’s click that and see what happens”,&lt;/p&gt;

&lt;p&gt;Hopefully, this thought would have hit your mind by now. It’s not your mistake, but it’s human mentality. We’ll be curious to explore the things which the other (experienced person) do not recommend to do. You’ll see the following error (Exception in programming terminology) if you click on the button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bKKQPlPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AFic5R0FTA0Oxb8UG.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bKKQPlPW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AFic5R0FTA0Oxb8UG.png" alt="Flutter Router Exception" width="750" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell, this error screenshot describes that the provided route does not exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawer Navigation
&lt;/h2&gt;

&lt;p&gt;Own next target is to add a drawer navigation. But before that, we have to create 2 files. They are,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;drawer.dart - To show the Navigation Drawer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;about.dart - An option will be provided on Drawer Navigator to navigate here&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create drawer.dart file inside lib/ directory and not inside tab/ directory. tab/ directory is only for tabs and we don't need to touch that further as we're done with the tabs. Copy the below code into the drawer.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';

class MyDrawer extends StatelessWidget {
  const MyDrawer({super.key});

  navigateTo(String route, BuildContext context) {
    Navigator.of(context).pushReplacementNamed(route);
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        padding: const EdgeInsets.all(16.0),
        children: &amp;lt;Widget&amp;gt;[
          ListTile(
            leading: const Icon(Icons.home),
            title: const Text('Home'),
            onTap: () {
              navigateTo("/home", context);
            },
          ),
          ListTile(
            leading: const Icon(Icons.info),
            title: const Text('About'),
            onTap: () {
              navigateTo("/about", context);
            },
          ),
        ],
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, we define the class named MyDrawer. In the build method we render the Drawer widget with Home and About options in list. Click on those options will navigate us to the appropriate routes.&lt;/p&gt;

&lt;p&gt;Create about.dart file in the same directory and copy the below code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './drawer.dart';
import 'package:flutter/material.dart';

class About extends StatelessWidget {
  const About({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: const MyDrawer(),
      appBar: AppBar(title: const Text("About")),
      body: const Center(child: Text("About")),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, we create a class named About which returns a Scaffold widget containing the drawer which we defined right before this file. The appBar and the body will show the text "About".&lt;/p&gt;

&lt;p&gt;Again, you’ll not be able to see these changes immediately in the app. Because, we haven’t linked it into the main.dart file.&lt;/p&gt;

&lt;p&gt;Before we linking them, we have one item in our backlog. Let’s finish it and come back to linking them altogether.&lt;/p&gt;

&lt;p&gt;Create a file named secret.dart in the lib/ directory and copy the below code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';

class SecretPage extends StatelessWidget {
  const SecretPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          // backgroundColor: Colors.red,
          title: const Text("Secret"),
        ),
        body: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: const &amp;lt;Widget&amp;gt;[
              Text("Nothing to show"),
            ],
          ),
        ));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this file, we have created a class named SecretPage and return just a Text in the &lt;code&gt;body&lt;/code&gt;. Nothing fancy here. It's a super simple Flutter widget.&lt;/p&gt;

&lt;p&gt;Our backlog item is also done. This is the most awaited time. We’re going to define our routes now.&lt;/p&gt;

&lt;p&gt;Open main.dart file and add the following imports at the top of the file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './about.dart';
import './secret.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the build method of MyApp class with the below code.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: &amp;lt;String, WidgetBuilder&amp;gt;{
        "/about": (BuildContext context) =&amp;gt; const About(),
        "/home": (BuildContext context) =&amp;gt; const HomePage(),
        "/secret": (BuildContext context) =&amp;gt; const SecretPage(),
      },
      initialRoute: "/home",
      title: 'Flutter Navigation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const HomePage(),
    );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, you can see we’re defining the MaterialApp to contain routes. They’re defined as key-value pairs, mapping a route with a Widget. We have defined 3 routes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;/about - Route for drawer navigator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/home - Route for tab navigator&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;/secret - Route for stack navigator&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have set the initial route to be /home, which has the tab navigator.&lt;/p&gt;

&lt;p&gt;Run the app and you should be able to see the following output on your device.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--an0srMsg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Aa6WuN45BlPQQWQCO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--an0srMsg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2Aa6WuN45BlPQQWQCO.png" alt="Merged Tab and Drawer View" width="288" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On pressing the “Disclose Secret” button you’ll be taken to the Secret page which we created (ideally it does not have any secret). You should also be scroll through the tabs smoothly.&lt;/p&gt;

&lt;p&gt;By now, I hope you would have noticed an error here. If not, I’m revealing here for you. The back button is shown on the 1st screen of our app.&lt;/p&gt;

&lt;p&gt;“What is the need to show the back button on the 1st screen?”&lt;/p&gt;

&lt;p&gt;That’s an error and we have to resolve it. Press the back button and let’s see what happens. Hopefully, you saw the same I saw. The back button was hidden and we see just the “Home” title in the appBar (similar to the below screenshot).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HA6jhs0s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AnD8rls8h0jatN8Fo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HA6jhs0s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AnD8rls8h0jatN8Fo.png" alt="Back button issue" width="288" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But there’s an another issue available in the same screen. Hopefully you got that too. If not, don’t worry, I’m revealing it right here.&lt;/p&gt;

&lt;p&gt;“Can you access the drawer navigator by any means?”&lt;/p&gt;

&lt;p&gt;No. Right?&lt;/p&gt;

&lt;p&gt;But, do you know the fix for above two issues is the same. If we fix the 2nd issue, the 1st issue will automatically be fixed.&lt;/p&gt;

&lt;p&gt;That’s great. But, How to fix the 2nd issue?&lt;/p&gt;

&lt;p&gt;You have to show the drawer navigator button (Hamburger icon) on the top left. This will eventually hide the back button.&lt;/p&gt;

&lt;p&gt;Open tab.dart file and import the drawer file at the top of this file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import './drawer.dart';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the following line inside the Scaffold widget of the build method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;drawer: const MyDrawer(),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;Here’s the output you can see when you run your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IT8eJYVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AhtXRFFHhJtlt6EvZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IT8eJYVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AhtXRFFHhJtlt6EvZ.png" alt="App look after the issues are fixed" width="289" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;n this article, you’ve learnt about navigation in Flutter. We’ve implemented all 3 types of navigation in a single app. Ideally, this will not be the case with any real app you build. Most apps will be built on either 1 or 2 types of navigation.&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://github.com/5minslearn/Flutter-Navigation-Types"&gt;repo&lt;/a&gt; has my code. You can use it for your reference.&lt;/p&gt;

&lt;p&gt;If you wish to learn more about Flutter, subscribe to my article by entering your email address in the below box.&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devdotto_flutter_navigation_types"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gogosoon.com/blog/types-of-navigation-in-flutter"&gt;https://www.gogosoon.com&lt;/a&gt; on April 24, 2023.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>5minslearn</category>
      <category>softwaredevelopment</category>
      <category>flutternavigation</category>
    </item>
    <item>
      <title>What is CloudFormation &amp; How to use it to deploy NodeJS</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Fri, 02 Jun 2023 11:57:54 +0000</pubDate>
      <link>https://dev.to/5minslearn/what-is-cloudformation-how-to-use-it-to-deploy-nodejs-2dh4</link>
      <guid>https://dev.to/5minslearn/what-is-cloudformation-how-to-use-it-to-deploy-nodejs-2dh4</guid>
      <description>&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%2Fuploads%2Farticles%2F0a8rp0xf8ukdmjgfw2wo.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%2Fuploads%2Farticles%2F0a8rp0xf8ukdmjgfw2wo.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine you have built a great product. The user base of your product has been increasing rapidly. You want to scale your product to the people around the world. To achieve that you should have a good cloud infrastructure.&lt;/p&gt;

&lt;p&gt;But you’ll definitely be exhausted if you manage your cloud infrastructure manually? You would be wondering, “Well. How are the enterprise companies managing now?”.&lt;/p&gt;

&lt;p&gt;They automate their cloud infrastructure management via code. Well, that’s exactly AWS CloudFormation offers — a way to manage your cloud infrastructure as code!&lt;/p&gt;

&lt;p&gt;In this blog, we’ll explore the basics of AWS CloudFormation and how it can help you automate your infrastructure management. Let’s dive into the world of infrastructure as code!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CloudFormation
&lt;/h2&gt;

&lt;p&gt;AWS CloudFormation is a service that helps you automate creating and managing your cloud resources. Imagine you’re building a house, and you want to ensure everything is in the right place — the walls, the roof, the doors, and the windows. With CloudFormation, you can create a blueprint for your house, and specify exactly what you want and where you want it.&lt;/p&gt;

&lt;p&gt;Similarly, CloudFormation allows you to create a blueprint for your cloud infrastructure. You can specify what resources you want to create, (Eg. EC2 servers, databases, storage, etc.) and how they should be configured. CloudFormation takes care of creating and managing those resources for you automatically.&lt;/p&gt;

&lt;p&gt;CloudFormation will be extremely helpful in few cases. Listing few of them below,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Managing the infrastructure changes in multiple environments (Development, Staging, Production)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-create the same infrastructure in a different region / account&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unfortunate accidental deletion of a resource can be re-created with the exact configuration in seconds (not manually, as you have all configurations in your code)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The best part is that CloudFormation makes updating your infrastructure super simple and automatic. If you want to add a new resource, change a configuration, or delete a resource, you can update your blueprint, and CloudFormation will handle the changes for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  How CloudFormation works
&lt;/h2&gt;

&lt;p&gt;You may wonder how CloudFormation works? It’s simple, we’ll upload our CloudFormation templates in Amazon S3 behind the scenes and then CloudFormation will pull our template from the S3. One important point to note is we cannot edit the template once uploaded. We need to re-upload the updated template to AWS and then CloudFormation will compare and figure out what needs to be updated&lt;/p&gt;

&lt;p&gt;One awesome feature is you can delete all resources created by CloudFormation in one click by deleting the stack. CloudFormation stack is nothing but a collection of AWS resources that you can manage as a single unit. You define a stack by creating a CloudFormation template that describes the resources you want to create, and then you create the stack by running the template&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying CloudFormation Templates
&lt;/h2&gt;

&lt;p&gt;We can deploy the CloudFormation template in two ways. One is using CloudFormation Designer and the other is writing the code in a YAML file. If you’re not familiar with YAML then you can go for CloudFormation Designer. It’s also recommended for those who don’t know to code. It allows you to create and edit templates graphically, making it easier to visualize your infrastructure and simplify the template creation process. However, in this blog we’ll be writing YAML code to deploy our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create CloudFormation Template to deploy NodeJS
&lt;/h2&gt;

&lt;p&gt;CloudFormation Template can be created using YAML or JSON file but we’re going to use YAML file. In this template, we’ll be creating an EC2 instance, security group and add a script to deploy a simple NodeJS app.&lt;/p&gt;

&lt;h2&gt;
  
  
  CloudFormation Template to create EC2 instance
&lt;/h2&gt;

&lt;p&gt;There are over 224 types of resources but now we need to create EC2 resource. &lt;strong&gt;Resources&lt;/strong&gt; represent the different AWS Components that will be created and configured. The &lt;strong&gt;Resource&lt;/strong&gt; types identifiers are in below form.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWS::aws-product-name::data-type-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So for the EC2 instance, the resource is Aws::EC2::Instance. To learn more about AWS resources and syntax check out the AWS official &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and play with it. If you look at &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html" rel="noopener noreferrer"&gt;EC2 documentation&lt;/a&gt; and scroll down you can see how to declare EC2 instance. Both JSON and YAML syntax is available but we'll stick with YAML for this blog. There will be lot of properties available to customize the creation of EC2 instances. But for now, we'll be configuring AvailabilityZone, ImageId and InstanceType which are very basic properties to create an EC2 instance.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resources:
  SampleNodejsDeploy:
    Type: AWS::EC2::Instance
    Properties:
      AvailabilityZone: us-east-1a
      ImageId: ami-a4c7edb2
      InstanceType: t2.micro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here SampleNodejsDeploy refers to the name of the block. You can name your resource as your wish.&lt;/p&gt;

&lt;p&gt;Let’s see the process to deploy the NodeJS app.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to deploy NodeJS App using CloudFormation template
&lt;/h2&gt;

&lt;p&gt;We’re going to deploy the NodeJS app using the UserData property in the EC2 resource. For people who don't know about EC2 user data, it is a feature of AWS EC2 which allows us to pass information during the launch of the EC2 instance. It can be used to perform custom actions, such as installing software and executing the script. Let's write the bash script to deploy NodeJS app and attach it to the user data.&lt;/p&gt;

&lt;p&gt;Here is the simple script to deploy the NodeJS app&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -e
curl -sL https://deb.nodesource.com/setup_16.x | bash -
sudo apt install nodejs
node -v
npm -v
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install yarn
yarn --version
sudo -i -u ubuntu bash &amp;amp;lt;&amp;amp;lt; EOF
set -e
cd /home/ubuntu
sudo npm install -g pm2
git clone https://github.com/5minslearn/node_with_docker.git
cd node_with_docker
yarn install
pm2 start yarn --time --interpreter bash --name sample_node -- start -p 8000
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above script installs the nodejs, yarn and pm2. Clones the NodeJS project from &lt;a href="https://github.com/5minslearn/node_with_docker.git" rel="noopener noreferrer"&gt;git&lt;/a&gt;, installs the dependencies and starts the app with PM2.&lt;/p&gt;

&lt;p&gt;Having this script, let’s attach it to the CloudFormation template.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attaching UserData into CloudFormation Template
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resources:
  SampleNodejsDeploy:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-014d05e6b24240371
      UserData:
        Fn::Base64:
          |
          #!/bin/bash
          set -e
          curl -sL https://deb.nodesource.com/setup_16.x | bash -
          sudo apt install nodejs
          node -v
          npm -v
          curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
          echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
          sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install yarn
          yarn --version
          sudo -i -u ubuntu bash &amp;amp;lt;&amp;amp;lt; EOF
          set -e
          cd /home/ubuntu
          sudo npm install -g pm2
          git clone https://github.com/5minslearn/node_with_docker.git
          cd node_with_docker
          yarn install
          pm2 start yarn --time --interpreter bash --name sample_node -- start -p 8000
          EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can notice the UserData property is added to the EC2 block. Fn::Base64 is a function in AWS CloudFormation that allows users to encode a string to base64 format. This function can be used to pass sensitive information, such as credentials, to AWS resources in a secure manner. Since EC2 user data is not encrypted it's always best practice to encode it. Right below the line, you can notice a small vertical bar (|). It is used for multi-line string support as our script is more than 1 line.&lt;/p&gt;

&lt;p&gt;Alright. Now we have a script to deploy the NodeJS. But, we have to remember one super important item. By default NodeJS applications run on port 8000. We should expose the port 8000 from EC2. Here comes the need to create a security group configuration for our EC2 instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create a security group using CloudFormation Template
&lt;/h2&gt;

&lt;p&gt;It’s exactly similar to creating an EC2 instance, except replacing the type from Instance to SecurityGroup.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SampleNodejsDeploySG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for the app nodes that allow ssh, http, 8000
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '8000'
        ToPort: '8000'
        CidrIp: 0.0.0.0/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above code is self explanatory that we defined a Security group, allowing ports 22(SSH port), 80(HTTP port), 8000 (for NodeJS). We named the Resource as SampleNodejsDeploySG.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link Security Group to EC2
&lt;/h2&gt;

&lt;p&gt;You may encounter an obvious question, “We’ve created a template for creating Security group but how will this be linked to EC2 instance?”.&lt;/p&gt;

&lt;p&gt;The solution is simple, CloudFormation provides an intrinsic function called !Ref that allows us to reference a resource or parameter within a CloudFormation template.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resources:
  SampleNodejsDeploy:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-014d05e6b24240371
      SecurityGroups:
        - !Ref SampleNodejsDeploySG
      UserData:
        Fn::Base64:
          |
          #!/bin/bash
          set -e
          curl -sL https://deb.nodesource.com/setup_16.x | bash -
          sudo apt install nodejs
          node -v
          npm -v
          curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
          echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
          sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install yarn
          yarn --version
          sudo -i -u ubuntu bash &amp;amp;lt;&amp;amp;lt; EOF
          set -e
          cd /home/ubuntu
          sudo npm install -g pm2
          git clone https://github.com/5minslearn/node_with_docker.git
          cd node_with_docker
          yarn install
          pm2 start yarn --time --interpreter bash --name sample_node -- start -p 8000
          EOF
  SampleNodejsDeploySG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for the app nodes that allow ssh, http
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '8000'
        ToPort: '8000'
        CidrIp: 0.0.0.0/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can notice the SecurityGroups property is added to the EC2 instance and the created Security Group configuration is linked to the EC2 instance by using the !Ref parameter. Now we have the CloudFormation template. But we're not yet complete. We still miss one more thing. Can you figure it out? We created an EC2 instance, and we allowed an SSH port but to log in using SSH we need to attach a key-value pair right? Let's do that.&lt;/p&gt;

&lt;p&gt;We can attach Key-value pair name directly into the template. For example, let’s say your key-value pair name is 5minslearn you can attach the property KeyName directly to the EC2 resource block like this or we can use parameters.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Resources:
  SampleNodejsDeploy:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-014d05e6b24240371
      KeyName: 5minslearn
      SecurityGroups:
        - !Ref SampleNodejsDeployS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  How to use parameters in the CloudFormation template
&lt;/h2&gt;

&lt;p&gt;We can use parameters to get the name of the key-value pair from the user while creating the stack. Basically, parameters allow us to pass input values into CloudFormation templates at runtime. Let’s see how to do that&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameters:
  SSHKey:
    Type: AWS::EC2::KeyPair::KeyName
    Description: name of the key pair to ssh into the instance
Resources:
  SampleNodejsDeploy:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t2.micro
      ImageId: ami-014d05e6b24240371
      KeyName: !Ref SSHKey
      SecurityGroups:
        - !Ref SampleNodejsDeploySG
      UserData:
        Fn::Base64:
          |
          #!/bin/bash
          set -e
          curl -sL https://deb.nodesource.com/setup_16.x | bash -
          sudo apt install nodejs
          node -v
          npm -v
          curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
          echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
          sudo apt update &amp;amp;amp;&amp;amp;amp; sudo apt install yarn
          yarn --version
          sudo -i -u ubuntu bash &amp;amp;lt;&amp;amp;lt; EOF
          set -e
          cd /home/ubuntu
          sudo npm install -g pm2
          git clone https://github.com/5minslearn/node_with_docker.git
          cd node_with_docker
          yarn install
          pm2 start yarn --time --interpreter bash --name sample_node -- start -p 8000
          EOF
  SampleNodejsDeploySG:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: for the app nodes that allow ssh, http
      SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: '80'
        ToPort: '80'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '22'
        ToPort: '22'
        CidrIp: 0.0.0.0/0
      - IpProtocol: tcp
        FromPort: '8000'
        ToPort: '8000'
        CidrIp: 0.0.0.0/0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above template, we added a parameter to get the key-pair name and referenced it to KeyName property.&lt;/p&gt;

&lt;p&gt;Great! We successfully created a CloudFormation template to create an EC2 instance and security group. In addition to that, we also added a script to deploy the NodeJS app. Now it’s time to create a CloudFormation stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create CloudFormation stack
&lt;/h2&gt;

&lt;p&gt;The first step is to log in to the AWS console and search for CloudFormation in the search bar. You can see the below page. Click on stacks in the left sidebar to get started with CloudFormation.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AY1DZv43Dksj7ec3e.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AY1DZv43Dksj7ec3e.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on create stack button to create the CloudFormation stack.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AZDTpmS5rSvjAc8Bd.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AZDTpmS5rSvjAc8Bd.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we have our template ready, select “Template is ready” and choose “Upload a template file” in the Template source and upload the template file.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJV9SQ5gAqcp1YQAX.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AJV9SQ5gAqcp1YQAX.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you upload the file, “View in Designer” button will be enabled. Click on it to view our template design.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to validate the CloudFormation template
&lt;/h2&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AARTLDC12apadoDna.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AARTLDC12apadoDna.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To validate our template click on the “Tick” icon on top left in the designer. It will validate and show us errors if any. Once the validation is done, click on the “Cloud” icon to the left of “Tick” icon. It will take you to create stack page.&lt;/p&gt;

&lt;p&gt;In the stack details page, enter the stack name and select your key-value pair. If you don’t have key-value pair create one and select it.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ASSJA130GoyOQB-jD" 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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ASSJA130GoyOQB-jD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Leave the Configure stack options section as it is and click continue since we don’t need any IAM permissions or advanced options.&lt;/p&gt;

&lt;p&gt;Then review the page and submit the template. The template will start creating the resources&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AzXWPZS79lrCbJQh1" 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%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AzXWPZS79lrCbJQh1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once creation is done click on resources tab, you’ll be able to see the resources we created (EC2 and Security group resources).&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AFJQDGCbXIt9oFcqq.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AFJQDGCbXIt9oFcqq.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the EC2 instance, you can see our instance will be up and running. Copy the public IPv4 address&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AhsbD1PLPmZDhrMMa.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%2Fcdn-images-1.medium.com%2Fmax%2F2048%2F0%2AhsbD1PLPmZDhrMMa.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now go to browser and type &lt;a href="http://:8000" rel="noopener noreferrer"&gt;http://:8000&lt;/a&gt; (In my case it is &lt;a href="http://54.176.19.18:8000/" rel="noopener noreferrer"&gt;http://54.176.19.18:8000/),&lt;/a&gt;,) you can see the below page&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARvjLxSxFdjz3YdSX.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2ARvjLxSxFdjz3YdSX.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means our NodeJS app successfully got deployed!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;EC2 user data will take some time to install dependencies. So for the first time, the page will take long time to load. Please be patient till the site is loaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting CloudFormation Stack
&lt;/h2&gt;

&lt;p&gt;If you no longer need the stack, you can delete it from the CloudFormation console. Select the stack you want to delete, click “Delete Stack,” and confirm the action. This action will delete all resources created using this stack. In our case, it’ll delete both EC2 and Security Group. You don’t need to delete the EC2 instance and Security Group individually.&lt;/p&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%2Fcdn-images-1.medium.com%2Fmax%2F2170%2F0%2AJBUZk6nfeaYcx_do" 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%2Fcdn-images-1.medium.com%2Fmax%2F2170%2F0%2AJBUZk6nfeaYcx_do"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we learned what is CloudFormation, it’s working, creating and deleting a template stack.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading this article! If you are stuck at any point feel free to drop your queries to me at my &lt;a href="https://www.gogosoon.com/cdn-cgi/l/email-protection#3f5e4d4a517f585058504c505051115c5052" rel="noopener noreferrer"&gt;email&lt;/a&gt;. I’ll be happy to help you!&lt;/p&gt;

&lt;p&gt;If you wish to learn more about AWS, subscribe to my &lt;a href="https://5minslearn.gogosoon.com/?ref=devTo_aws_CF" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;&lt;/p&gt;

</description>
      <category>awscloudformation</category>
      <category>aws</category>
      <category>nodejsdeployment</category>
    </item>
    <item>
      <title>What is Docker Compose? When and How to use it?</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Wed, 24 May 2023 03:30:00 +0000</pubDate>
      <link>https://dev.to/5minslearn/what-is-docker-compose-when-and-how-to-use-it-2p2</link>
      <guid>https://dev.to/5minslearn/what-is-docker-compose-when-and-how-to-use-it-2p2</guid>
      <description>&lt;p&gt;Docker helps you to setup development environment on your machine quickly. It hardly takes a couple of minutes for the entire process to complete. But let’s assume you were assigned on a project which requires at least 10 different services in running state to run your project. Assuming your project requires Java 8, Node 14, MySQL, MongoDB, Ruby on rails, RabbitMQ, etc. Ideally this may not be the case, but it’s just an assumption. In such case, you have to pull all those images individually from Docker and start all of them in their containers. At some point, one process may depend on another to run. So, you have to order them. It would be good if it’s a one time process. But, not just once, every day, every time you start working on your project, you have to start all these services.&lt;/p&gt;

&lt;p&gt;That’s a tedious process right?&lt;/p&gt;

&lt;p&gt;To overcome this Docker introduced a concept called Multi Containers (Docker Compose). Before learning about docker compose, let’s quickly learn how to start a database host in docker. In the example part of this tutorial, we’ll spin up a NodeJS container and MongoDB container together. Learning about MongoDB at the beginning will give you a good understanding when we move to docker compose.&lt;/p&gt;

&lt;p&gt;Let’s split this tutorial into 2 sections.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;How to use docker as a Database host (MongoDB)&lt;/li&gt;
&lt;li&gt;Docker compose with an example (NodeJS &amp;amp; MongoDB)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to use docker as a Database host
&lt;/h2&gt;

&lt;p&gt;If you had experience on backend development, you might have a chance to handle multiple database. Databases like MySQL/Postres to handle relational data and Cassandra/MongoDB to handle unstructured data.&lt;/p&gt;

&lt;p&gt;Do you know a secret, We can work on Back-end development without installing the database on your machine locally. Yes, we can use the docker as a database host. It has all the dependencies by default in the particular image file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need to use Database in Docker instead of Local?
&lt;/h2&gt;

&lt;p&gt;As I’ve already mentioned in my old blog, Docker helps us maintain consistent versions across platforms &amp;amp; environments. Let’s consider there are a group of people working in your team on MongoDB version 5.0. If a new techie joins your team, he/she needs to set up the same version with the exact configuration manually. What if they install the latest version of MongoDB (6.0) which will lead to some conflict. This will be nightmare if it spreads to everyone’s device.&lt;/p&gt;

&lt;p&gt;To overcome this, We can use the MongoDB in docker with a custom configuration and push the MongoDB Image to the docker hub internally. If a new person comes in they can pull the image and start the implementation without any manual configuration.&lt;/p&gt;

&lt;p&gt;Let’s quickly get into the advantages of using a database in docker.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By using this implementation we can ensure that everyone in a team uses the exact runtimes and configuration without any external resources.&lt;/li&gt;
&lt;li&gt;It’s very easy to set up and we can start/stop the server quickly using the docker desktop&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to setup MongoDB using Docker
&lt;/h2&gt;

&lt;p&gt;Hope you’re aware of Docker Hub. If not, here’s a short intro. Docker hub is a platform where we can find, and share docker images in public or private. It is more similar to GitHub / GitLab. In a nutshell, it’s a repository for docker images.&lt;/p&gt;

&lt;p&gt;The first step is to pull the official docker image from the docker hub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ksywyf_g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbrw8hkbpcryzm6o6e6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ksywyf_g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vbrw8hkbpcryzm6o6e6v.png" alt="MongoDB image in Docker Hub" width="800" height="247"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull mongo:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tyqo60Ma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g80cqgrepxq0aouzg3ex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tyqo60Ma--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g80cqgrepxq0aouzg3ex.png" alt="Pull MongoDB image from Docker" width="734" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’re done pulling the mongo image, open your Docker Desktop and you’ll be able to see it there.&lt;/p&gt;

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

&lt;p&gt;Let’s run our MongoDB image using the docker run command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -p 27017:27017 --name mongo-server-local mongo: latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;We successfully run the docker image. Now we can see the container running on the docker desktop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q8YBkRa1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7aeu6se4dsolq6nr2y9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q8YBkRa1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n7aeu6se4dsolq6nr2y9.png" alt="Docker Desktop Container Dashboard" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the MongoDB server is running on your machine. Let’s ensure this in the browser. Hit &lt;a href="http://localhost:27017"&gt;http://localhost:27017&lt;/a&gt; on your browser and you should be able to see the message as shown in the screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CQDWchll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/av4isem4t8bty1f6ui8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CQDWchll--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/av4isem4t8bty1f6ui8n.png" alt="Output from MongoDB when accessing via HTTP" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Interesting right?&lt;/p&gt;

&lt;p&gt;We can stop/start the MongoDB server using docker whenever we need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Note
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;It is not recommended to use the docker as a database for production&lt;/li&gt;
&lt;li&gt;Do not use docker database for large scale applications&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is docker-compose
&lt;/h2&gt;

&lt;p&gt;Let’s come back to docker-compose.&lt;/p&gt;

&lt;p&gt;Docker Compose is a tool used to define and share multi-container applications. This means we can run a project with multiple containers using a single source.&lt;/p&gt;

&lt;p&gt;For example, assume you’re building a project with NodeJS and MongoDB together. We can create a single image that starts both containers as a service, you don’t need to start each separately.&lt;/p&gt;

&lt;p&gt;Interesting right? And this solves the problem which I called out at the very beginning of this article.&lt;/p&gt;

&lt;p&gt;To achieve this we need to define a &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  docker-compose.yml
&lt;/h4&gt;

&lt;p&gt;The compose file is a YML file defining services, networks, and volumes for a docker container. There are several versions of the Compose file format available – 1, 2, 2.x, and 3.x.&lt;/p&gt;

&lt;p&gt;Before proceeding further, here’s a important note to us from the &lt;a href="https://docs.docker.com/compose/"&gt;Docker Compose team&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;From the end of June 2023 Compose V1 won’t be supported anymore and will be removed from all Docker Desktop versions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are using version 3 in this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
services:
  app:
    image: node:latest
    container_name: app_main
    restart: always
    command: sh -c "yarn install &amp;amp;amp;&amp;amp;amp; yarn start"
    ports:
      - 8000:8000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: localhost
      MYSQL_USER: root
      MYSQL_PASSWORD:
      MYSQL_DB: test
  mongo:
    image: mongo
    container_name: app_mongo
    restart: always
    ports:
      - 27017:27017
    volumes:
      - ~/mongo:/data/db
volumes:
  mongodb:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s dismantle the above code and understand one by one.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;version&lt;/code&gt; – Refers to the docker-compose version (Latest 3)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;services&lt;/code&gt; – Define the services that we need to run&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app&lt;/code&gt; – Custom name for one of your containers&lt;/p&gt;

&lt;p&gt;&lt;code&gt;image&lt;/code&gt; – Image which we have to pull. Here we are using node:latest and mongo.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;container_name&lt;/code&gt; – Name for each container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;restart&lt;/code&gt; – Start/Restart a service container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;port&lt;/code&gt; – Define the custom port to run the container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;working_dir&lt;/code&gt; – The current working directory for the service container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;environment&lt;/code&gt; – Define the environment variables, such as DB credentials, etc.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;command&lt;/code&gt; – Command to run the service&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run the multi-container?
&lt;/h2&gt;

&lt;p&gt;We need to build it using docker build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After successfully building, We can run the containers using up Command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to run the container in detached mode just use &lt;code&gt;-d&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NMkQDIc7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k33rfn5dcfiiah80jtr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NMkQDIc7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k33rfn5dcfiiah80jtr9.png" alt="Run all images in a single compose command" width="763" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fine, We are good to go. The containers are up and running. Let’s check the container list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t8SYhpBD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ec5j28mfmhzlbg21hvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t8SYhpBD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ec5j28mfmhzlbg21hvb.png" alt="Status of running docker containers" width="800" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hurray, We can see that there are two containers running at the same time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e0R11hTT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qwxoxizaish1gb8zmkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e0R11hTT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qwxoxizaish1gb8zmkr.png" alt="Testing NodeJS" width="614" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;To have a look at the data in your MongoDB, you have to install MongoDB Compass.&lt;/p&gt;

&lt;p&gt;Here’s the screenshot of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BRbgYcd3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76zubvqkk9wvua1ny4ml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BRbgYcd3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/76zubvqkk9wvua1ny4ml.png" alt="MongoDB Compass" width="597" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you have learnt about Docker Compose with an example. Using this multiple containers you can spin up any type of service such as RabbitMQ, Apache Kafka and run in a single source of service. Hope you enjoyed reading this article. &lt;/p&gt;

&lt;p&gt;Hit &lt;code&gt;Like&lt;/code&gt; if you like the blog and comment your feedback and suggestions. &lt;/p&gt;

&lt;p&gt;If you wish to learn more about Docker, subscribe to my article at my &lt;a href="https://5minslearn.gogosoon.com/?ref=dev_to_docker_compose"&gt;site&lt;/a&gt; (&lt;a href="https://5minslearn.gogosoon.com/?ref=dev_to_docker_compose"&gt;https://5minslearn.gogosoon.com&lt;/a&gt;). It also has a consolidated list of all my blogs. &lt;/p&gt;

&lt;p&gt;Cheers!!!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>compose</category>
      <category>javascript</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Learn state management in Flutter by building a simple todo app</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Tue, 16 May 2023 13:09:43 +0000</pubDate>
      <link>https://dev.to/5minslearn/learn-state-management-in-flutter-by-building-a-simple-todo-app-ihg</link>
      <guid>https://dev.to/5minslearn/learn-state-management-in-flutter-by-building-a-simple-todo-app-ihg</guid>
      <description>&lt;p&gt;State management is a complex topic and is also a necessary topic in mobile application development. It plays a major role in building dynamic mobile apps. You’ll be able to build any kind of dynamic application if you master state management. This is because the UI that’s being rendered on the mobile will be determined by the state of the data that your app holds at that time. Hence, it becomes inevitable to master state management in front-end application development.&lt;/p&gt;

&lt;p&gt;In this article, we’ll learn state management by building a Todo app in Flutter.&lt;/p&gt;

&lt;p&gt;A quick little theory on state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is State
&lt;/h2&gt;

&lt;p&gt;State defines the user interface of your app. In other words, the user interface is built by the current state of the app. When a state of the Flutter app changes, it’ll trigger the re-draw of the user interface. This is called Declarative UI and Flutter follows the same, whereas the native mobile apps (Android &amp;amp; iOS) are built with Imperative UI, where the user interface is defined earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of State
&lt;/h2&gt;

&lt;p&gt;There are 2 types of state. They are,&lt;/p&gt;

&lt;h3&gt;
  
  
  Ephemeral State
&lt;/h3&gt;

&lt;p&gt;Ephemeral state is the state that is contained in a single widget or a screen/page of an app.&lt;/p&gt;

&lt;h3&gt;
  
  
  App State
&lt;/h3&gt;

&lt;p&gt;It is the state that is shared between user sessions and is used across many parts of the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose the state for my app
&lt;/h2&gt;

&lt;p&gt;There is no single rule to choose either state. It’s depends on your use case. It’s advised to prefer Ephemeral state at first and refactor your code in future if you face any need to use App state.&lt;/p&gt;

&lt;h2&gt;
  
  
  What will we build
&lt;/h2&gt;

&lt;p&gt;We’ll be building a Todo app. This app will have the functionality to create a todo item, list all the added items, update an item and delete an item. Here’s the sneak peak (screenshot) for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UihpcWCc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A7cSV-l9bxLmwvyi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UihpcWCc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A7cSV-l9bxLmwvyi5.png" alt="Todo App" width="316" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  App Development
&lt;/h2&gt;

&lt;p&gt;Let’s put on our development shoes and start building our app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a project
&lt;/h3&gt;

&lt;p&gt;Here are the super simple steps to create our Flutter project. If you want a detailed explanation, please read the &lt;a href="https://www.freecodecamp.org/news/how-to-build-a-simple-login-app-with-flutter/"&gt;“How to Create the Project” section in the blog&lt;/a&gt; and come back here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open your VS Code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hit “CTRL+SHIFT+P” (Mac user replace CTRL with CMD key)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type “Flutter”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select “Flutter: New Project” option&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select “Application” from the next list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the folder to create your project in the next prompt&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On the final prompt, enter your app name and press “Enter”&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s it!!! Our boilerplate app is ready.&lt;/p&gt;

&lt;p&gt;Select the preferred device to run your app on the bottom right and hit “F5”. Your app will run on your selected device. You should see the following screen in next few seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s6VWb5R5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A9wuvlR7y7315h_1Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s6VWb5R5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A9wuvlR7y7315h_1Q.png" alt="Flutter Boilerplate App" width="312" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Refactor
&lt;/h2&gt;

&lt;p&gt;We have a Flutter boilerplate app. By default, it’ll have a lot of items, let’s refactor our code. We’ll be working on main.dart file in lib/ folder to build this entire app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize Git
&lt;/h3&gt;

&lt;p&gt;Initialize Git by running git init in the root folder of your repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove comments
&lt;/h3&gt;

&lt;p&gt;I’ve removed all the comments in the main.dart file and added a commit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rename Classes
&lt;/h3&gt;

&lt;p&gt;Rename MyApp to TodoApp in the main method by pressing F2 key in VS Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x5vkh9Ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0VPsMVY3ja4Zzk9P.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x5vkh9Ia--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0VPsMVY3ja4Zzk9P.png" alt="" width="447" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the first page, we’ll be listing the created to-do items. Let’s rename it from MyHomePage to TodoList.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5YJbS-Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AgrflMKkG6jR2pY_c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5YJbS-Xk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AgrflMKkG6jR2pY_c.png" alt="" width="599" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screenshot, the title of the MaterialApp is set to “Flutter Demo” and title passed in TodoList is set to “Flutter Demo Home Page”. Let’s change both of that to “Todo Manager”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build Todo App
&lt;/h2&gt;

&lt;p&gt;Let’s build the core functionality of our app.&lt;/p&gt;

&lt;p&gt;We need a Todo class. This class will define the properties of a todo. In our case, we'll having the following items.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Name of todo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Status of todo (Backlog / Completed)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s define a Todo class with the above properties.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Todo { 
Todo({required this.name, required this.completed}); 
String name; 
bool completed; 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Add the above code at the bottom of the main.dart file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Todo
&lt;/h3&gt;

&lt;p&gt;Look at your code for a class named _TodoListState. In the body of the build method, set the children property to empty array. Refer the below screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--igWhFASY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A79z5nWHLPQ6wAl5x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--igWhFASY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A79z5nWHLPQ6wAl5x.jpg" alt="Before and After of removing the Text widgets" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remove the 2 Text widget inside that children property.&lt;/p&gt;

&lt;p&gt;Replace the counter variable with a todo list.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int _counter = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the above line with the following lines. The first line is the todo list and the second line defines the controller to get the name of the todo from the user.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final List _todos = []; 
final TextEditingController _textFieldController = TextEditingController();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remove the _incrementCounter method and add the method to add a todo.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void _addTodoItem(String name) { 
setState(() { _todos.add(Todo(name: name, completed: false)); }); 
_textFieldController.clear(); 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So far we have defined our todo list, a input controller and created a method that accepts an input text and add that to the todo list with completed status set to false and clear the input field. The reason we have used the setState method is to refresh the UI after we update the todo list. As our component is a stateful widget, whenever a change in state is detected, the UI will render again with the updated state.&lt;/p&gt;

&lt;p&gt;We have built the functionality code to add a todo. Let’s build the UI code. Let’s ask the user the name of todo on pressing the Floating action button at the bottom right. When the user try to save the todo, we’ll call the _addTodoItem method defined above.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;floatingActionButton: FloatingActionButton( 
onPressed: () =&amp;gt; _displayDialog(), 
tooltip: 'Add a Todo', 
child: const Icon(Icons.add), ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_3Em0G-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzoyUKBKLfHt6qIbB.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_3Em0G-u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzoyUKBKLfHt6qIbB.jpg" alt="Before and After of Floating Action Button code" width="771" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above method, we have changed the onPressed property to call _displayDialog method. As it’s not defined yet, it’ll shown an error. We’ll define the method next. We have also changed the tooltip property to “Add a Todo”.&lt;/p&gt;

&lt;p&gt;Here’s the code (_displayDialog method) to show a dialog box with a input field, add, and cancel button. Add this method inside the _TodoListState class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future _displayDialog() async { 
return showDialog( 
context: context, 
T: false, 
builder: (BuildContext context) { 
return AlertDialog( 
title: const Text('Add a todo'), 
content: TextField( 
controller: _textFieldController, 
decoration: const InputDecoration(hintText: 'Type your todo'), 
autofocus: true, ), 
actions: [ 
OutlinedButton( 
style: OutlinedButton.styleFrom( 
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12),
 ), ), 
onPressed: () { 
Navigator.of(context).pop(); 
}, child: const Text('Cancel'), ), 
ElevatedButton( 
style: ElevatedButton.styleFrom( 
shape: RoundedRectangleBorder( 
borderRadius: 
BorderRadius.circular(12), ), ), 
onPressed: () { 
Navigator.of(context).pop(); 
_addTodoItem(_textFieldController.text); }, 
child: const Text('Add'), 
), 
], 
); 
}, ); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s understand this huge piece of code.&lt;/p&gt;

&lt;p&gt;The Future class is used for asynchronous computation.&lt;/p&gt;

&lt;p&gt;Quoting from the &lt;a href="https://api.flutter.dev/flutter/dart-async/Future-class.html"&gt;documentation&lt;/a&gt;,&lt;/p&gt;

&lt;p&gt;“An asynchronous computation may need to wait for something external to the program (reading a file, querying a database, fetching a web page) which takes time. Instead of blocking all computation until the result is available, the asynchronous computation immediately returns a Future which will &lt;strong&gt;&lt;em&gt;eventually&lt;/em&gt;&lt;/strong&gt; 'complete' with the result. "&lt;/p&gt;

&lt;p&gt;In our case, it’ll wait for the user to tap the Add or Cancel button.&lt;/p&gt;

&lt;p&gt;The _displayDialog method will return the showDialog method by building the UI.&lt;/p&gt;

&lt;p&gt;The barrierDismissible property is used to define if the pop up has to be closed if the user taps outside of the alert dialog. We have set that to false which means the alert dialog will not be closed on taping outside.&lt;/p&gt;

&lt;p&gt;The builder of this showDialog method, returns an AlertDialog consisting of title, content, and actions property. The title is set to display a text "Add a todo". The content property will render an text input field with automatic focus enabled and the hint "Type your todo". The actions property will render 2 buttons. They're Cancel and Add buttons. The Cancel button is an outlined button, pressing it will close the dialog. The Add button adds the text to the todo list and closes the dialog.&lt;/p&gt;

&lt;p&gt;Let’s test our app. Click on the floating action button and you should see the UI similar to the one below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--By8eD0-D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AjuHClEjOJCUXx776.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--By8eD0-D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AjuHClEjOJCUXx776.png" alt="" width="315" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you try to add a todo, it’ll be added to our todo list. But, you’ll not be able to see any change on UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  List the Todos
&lt;/h3&gt;

&lt;p&gt;We have added the code to add todos to the list. But Wait. How can we verify that? We have to find if the todo is actually added to the list.&lt;/p&gt;

&lt;p&gt;Let’s verify that by rendering the list of todo items in the UI. To do so, we have to design the UI for a single todo. Let’s do that.&lt;/p&gt;

&lt;p&gt;Add the following code at the end of main.dart file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TodoItem extends StatelessWidget { 
TodoItem({required this.todo}) : super(key: ObjectKey(todo)); 
final Todo todo; 
TextStyle? _getTextStyle(bool checked) { 
if (!checked) return null; 
return const TextStyle( 
color: Colors.black54, 
decoration: TextDecoration.lineThrough, ); } 
@override 
Widget build(BuildContext context) { 
return ListTile( onTap: () {}, 
leading: Checkbox( checkColor: 
Colors.greenAccent, 
activeColor: Colors.red, 
value: todo.completed, 
onChanged: (value) {}, ), 
title: Row(children: [ 
Expanded( child: Text(todo.name, 
style: _getTextStyle(todo.completed)), ), 
IconButton( 
iconSize: 30, 
icon: const Icon( Icons.delete, color: Colors.red, ), 
alignment: Alignment.centerRight, 
onPressed: () {}, ), ]), ); } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s the brief explanation of the above code.&lt;/p&gt;

&lt;p&gt;We created a class with the TodoItem and we extend it from StatelessWidget class as we don't need to maintain state for this class. We accept a Todo, which is passed via constructor to our class. The code in the build method determines the UI. It renders the ListTile widget with the Checkbox widget passed to the leading property. The title property renders a row of Text and IconButton widgets. The Text widget shows the name of the todo and the IconButton widget displays the delete icon. Notice the _getTextStyle method passed to the style property of the Text widget. This method strikes the text if the todo is marked as complete. Nothing changes on tapping any of these widgets as the corresponding properties are left empty (onTap, onChanged, and onPressed).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ListView( 
padding: const EdgeInsets.symmetric(vertical: 8.0), 
children: _todos.map((Todo todo) { 
return TodoItem( 
todo: todo, ); }).toList(), ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s the highlighted screenshot showing the changes on the build method of _TodoListState class.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k5LNUvpm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0Eo2q1xylxXFDZ7U.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k5LNUvpm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0Eo2q1xylxXFDZ7U.jpg" alt="" width="497" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above code defines a ListView widget iterating over the created todos and passing each todo to the TodoItem widget.&lt;/p&gt;

&lt;p&gt;We’re done with listing the todos. Let’s verify if both creating and viewing a todo works fine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LcOPoU5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzNci2m2y9AqBd51L.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LcOPoU5C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AzNci2m2y9AqBd51L.png" alt="" width="313" height="667"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool!!! Here are our todos.&lt;/p&gt;

&lt;p&gt;Tapping on either Checkbox or Delete button will have no effect.&lt;/p&gt;

&lt;p&gt;Hope you’ll got a clue on what we’ll be doing next. Yes, we’ll be adding the code to mark the todo as completed and delete a todo item.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update a Todo
&lt;/h3&gt;

&lt;p&gt;Let’s mark the todo as complete on pressing the checkbox near each todo.&lt;/p&gt;

&lt;p&gt;We have 2 fields in our Todo class. They’re name and completed status. Whenever a Todo is created, the default value of completed field is set to false. This means the todo is in progress. We can change that to true, whenever we complete the task.&lt;/p&gt;

&lt;p&gt;Define a method called _handleTodoChange in the _TodoListState class. Add this method below the _addTodoItem method which we defined to add a todo to the list.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void _handleTodoChange(Todo todo) { 
setState(() { 
todo.completed = !todo.completed; }); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, we accept a todo and change the completed status of the todo. So, whenever this method is called with a todo, it’s completed status will change from true to false or vice versa. Remember we have wrapped this inside a setState method to render the UI after making the change.&lt;/p&gt;

&lt;p&gt;We have to trigger this method when a user taps on a todo or taps on a checkbox. We should pass this method to the TodoItem class. While calling the TodoItem in the build method of the _TodoListState class, pass the _handleTodoChange method as shown below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return TodoItem( todo: todo, onTodoChanged: _handleTodoChange, );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bUEytWCn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AfJoPDD-UPVl6983O.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bUEytWCn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AfJoPDD-UPVl6983O.jpg" alt="" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we’re passing the method to TodoItem class, we should receive the same method in TodoItem class. To do so, we have to define this method in the constructor of TodoItem class. Go to TodoItem and change the constructor to include onTodoChanged method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TodoItem({required this.todo, required this.onTodoChanged}) : super(key: ObjectKey(todo));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You could notice in the above code that we use &lt;strong&gt;this.&lt;/strong&gt;onTodoChanged, which means we're binding the method passed to a method in this TodoItem class.&lt;/p&gt;

&lt;p&gt;Let’s define a method with the same name and set the return type to void (as we don't expect anything from that method).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final void Function(Todo todo) onTodoChanged;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, wherever we call this method in our code, the status of our todo will be changed to the opposite. Let’s call this method in the onTap property of ListTile widget and onChanged property of Checkbox widget.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;onTap: () { onTodoChanged(todo); },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oQNYLe0V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0CCj0piy3I25cmRQ.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oQNYLe0V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2A0CCj0piy3I25cmRQ.jpg" alt="" width="412" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it. We’re done. Let’s run our app and verify if we’re able to complete the todo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p72fUwyV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ATU5Bh4N4EWe64XWZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p72fUwyV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ATU5Bh4N4EWe64XWZ.png" alt="" width="314" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s Awesome right? We’re able to mark the todo as complete and revert back.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete a Todo
&lt;/h3&gt;

&lt;p&gt;We have only one item left to complete this app. We should be able to delete a todo which we may create by mistake or you may feel that it’s no longer applicable.&lt;/p&gt;

&lt;p&gt;Steps to delete a todo is almost similar to updating a todo. We’ll doing the exact 4 steps as we did for updating a todo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Define the _deleteTodo method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pass the method on TodoItem render&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Receive the method on TodoItem constructor&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind the method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the method on button tap&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would recommend you to try this by yourself as we’ll be repeating the steps we did earlier. After you’re done, you can verify your implementation by cross checking with my steps.&lt;/p&gt;

&lt;p&gt;Here’s the method to delete the todo. Add this in the _TodoListState class below the _handleTodoChange method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void _deleteTodo(Todo todo) { setState(() { _todos.removeWhere((element) =&amp;gt; element.name == todo.name); }); }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This method accepts a todo. Compares it with the todo list and identifies the todo which matches with this name and deletes it from the list and finally updates the state.&lt;/p&gt;

&lt;p&gt;Let’s pass the method reference to TodoItem in the build method of _TodoListState class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return TodoItem( todo: todo, onTodoChanged: _handleTodoChange, removeTodo: _deleteTodo);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change the constructor to accept removeTodo method.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TodoItem( {required this.todo, required this.onTodoChanged, required this.removeTodo}) : super(key: ObjectKey(todo));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Define a method with the same name and set the return type to void (as we don't expect anything from this method).&lt;/p&gt;

&lt;p&gt;Our final step is to call this method on pressing the delete button.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IconButton( iconSize: 30, icon: const Icon( Icons.delete, color: Colors.red, ), alignment: Alignment.centerRight, onPressed: () { removeTodo(todo); }, ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That’s it. I hope it’s super simple. Let’s test our app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6HRv5sbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ATRPaftZGzir8Yhb-.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6HRv5sbH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2ATRPaftZGzir8Yhb-.jpg" alt="" width="640" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wow!!! That works.&lt;/p&gt;

&lt;p&gt;In the above screenshot, you can see I created a todo with the name “Call SC service men” which should be created as “Call AC service men”. So, that was a mistake. I don’t want that todo now as it’ll confuse me. I would rather create a new todo with right spelling. So, I pressed the delete button which almost instantly deleted my todo.&lt;/p&gt;

&lt;p&gt;Cool! We have built our own todo app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, you’ve learnt about state management in Flutter. Along with that, we’ve built a simple todo app in Flutter implementing CRUD functionality. CRUD stands for Create, Read, Update, and Delete. We created a todo, listed that on UI, updated it’s status, and finally deleted it.&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://github.com/5minslearn/Flutter-Todo-App"&gt;repo&lt;/a&gt; has my code. You can use it for your reference.&lt;/p&gt;

&lt;p&gt;Here are few exercise to challenge yourself. Try to extend this app by adding the following functionalities.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Show a message saying “No todo exist. Please create one and track your work”, if no todo was created&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I know a bug in this app. I hope you don’t know. I’m revealing it here. But you have to fix it. Create two todos with same name and try to delete one. You’ll be amazed to see both of them deleted together. Here’s a tip for you to fix. Assign a random id for each todo and while deleting filter the todo by id.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add functionality to edit the name of a todo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This app was completely built on Ephemeral state. So, if you close and open the app again, your old todo items will not be there. Add a functionality to store the todo in the device storage. Show the todos to the user when they reopen the app by reading them from your device storage.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you wish to learn more about Flutter, subscribe to my &lt;a href="https://5minslearn.gogosoon.com/?ref=devTo_flutter_getting_started"&gt;newsletter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have a look at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devTo_flutter_getting_started"&gt;site&lt;/a&gt; which has a consolidated list of all my blogs.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>statemanagement</category>
      <category>todoap</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Deploy Next.js App &amp; setup CI/CD using AWS</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Wed, 03 May 2023 13:07:29 +0000</pubDate>
      <link>https://dev.to/5minslearn/how-to-deploy-nextjs-app-setup-cicd-using-aws-15ia</link>
      <guid>https://dev.to/5minslearn/how-to-deploy-nextjs-app-setup-cicd-using-aws-15ia</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v0MOIuoN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AvXAe-xrX6zEnf_WZld_pHw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v0MOIuoN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/1%2AvXAe-xrX6zEnf_WZld_pHw.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello Everyone!&lt;/p&gt;

&lt;p&gt;Deploying a web application is a challenging task (at least for me), especially when it comes to keeping it updated. It can take up a lot of time and energy if it has to be deployed manually every time a change is made. But I recently discovered a way to automate the deployment process for the Next.js app using AWS CodeDeploy and CodePipeline. It made my life so much easier, and I’m excited to share it with you.&lt;/p&gt;

&lt;p&gt;In this blog, I’ll guide you through the process of setting up auto-deployment for your Next.js app using AWS services such as CodePipeline and CodeDeploy. By the end of it, you’ll be able to save a lot of time by deploying your app automatically every time you push the code.&lt;/p&gt;

&lt;p&gt;Let’s get started!&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;EC2 Machine running Ubuntu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Very basic knowledge of EC2 and IAM AWS Services&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to deploy the Next.js app to AWS EC2
&lt;/h2&gt;

&lt;p&gt;To start simple, let’s manually deploy the sample Next.js boilerplate app “hello-world” to EC2. The steps are almost the same for all Next.js applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Login to EC2
&lt;/h2&gt;

&lt;p&gt;Login to the EC2 machine which you’ve created using the below command&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh -i /path/key-pair-name.pem [email protected]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When you try to log in to EC2, this is the common error that most people will encounter (including me).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UQssSu5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AGWVttJkXg2FdaC4-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UQssSu5N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AGWVttJkXg2FdaC4-.png" alt="Permissions 0664 for .pem file is too open error" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This error describes that the .pem should be read-protected. Only the root user should be able to read it. So, you have to set the file permission to 400. Run the following command to achieve that.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod 400 key-pair-name.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;EC2 by default come with no software installed. Once you logged into EC2, install NodeJS. There’s an excellent &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04"&gt;article&lt;/a&gt; published by Digital Ocean and I use it every time I have to install NodeJS on the server.&lt;/p&gt;

&lt;p&gt;I have uploaded the &lt;a href="https://github.com/5minslearn/deploy_nextjs_app"&gt;boilerplate repo&lt;/a&gt; to Github. You can clone the repo by running the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/5minslearn/deploy_nextjs_app.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Navigate to the project repo and install the project dependencies by running the below commands.&lt;/p&gt;

&lt;p&gt;A Quick note here. I’m a big fan of yarn for its lightning-fast dependency management. But I see most people use npm to manage their dependencies. If you like to use npm, you can replace yarn install with npm install in the below commands.&lt;/p&gt;

&lt;p&gt;If you like to go with yarn, install yarn by following this &lt;a href="https://classic.yarnpkg.com/lang/en/docs/install/#debian-stable"&gt;tutorial&lt;/a&gt; first.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd deploy_nextjs_app 
yarn install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s run the Application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hit “&lt;a href="http://ec2-public-ip-address:3000/"&gt;http://ec2-public-ip-address:3000/&lt;/a&gt;" on your browser and you should be able to see the following page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_hLrfZ7x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ASAEjSSxdVNOdI29u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_hLrfZ7x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ASAEjSSxdVNOdI29u.png" alt="Next.js Hello World App" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s another common issue that most people face here.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fix timeout error (EC2)
&lt;/h2&gt;

&lt;p&gt;“Oh, My God!!! My site is loading for a long time and finally, it’s throwing a timeout error. What could be the issue? Where did I made mistake?”&lt;/p&gt;

&lt;p&gt;If this happens to you, then you can follow the below steps to fix that.&lt;/p&gt;

&lt;p&gt;This issue basically occurs if your server does not expose port 3000. Remember people, by default NextJS app, will be running on port 3000. But, you have to allow port 3000 from the Security Group of your EC2 console to access from your browser.&lt;/p&gt;

&lt;p&gt;Login to your AWS console, select your EC2 instance and then select the Security group option. Click on the “Edit inbound rules” button. Add port 3000 to the list as shown in the below screenshot. Then hit the “Save rules” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3CQFMiiQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A8LrGwfnNLy-I6qeT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3CQFMiiQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A8LrGwfnNLy-I6qeT.png" alt="Adding a port 3000 to a security group" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visit the link “&lt;a href="http://ec2-public-ip-address:3000/"&gt;http://ec2-public-ip-address:3000/&lt;/a&gt;", and you’ll be amazed to see your page loaded like magic.&lt;/p&gt;

&lt;p&gt;So far, we just ran our app in development mode and verified that it’s working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run Next.js App in Production Mode
&lt;/h2&gt;

&lt;p&gt;To deploy the app in Production Mode, you have to build your app first. Run yarn build to build the app and yarn start to start the app in production mode.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn build 
yarn start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hit “&lt;a href="http://ec2-public-ip-address:3000/"&gt;http://ec2-public-ip-address:3000/&lt;/a&gt;" again and this time you’ll note that your app loads faster than earlier.&lt;/p&gt;

&lt;p&gt;Because the apps running in Production mode will always be faster when compared to the ones running in Development mode. And the reason for it is, the Production apps will be optimized for performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to run Next.js app forever when console is closed?
&lt;/h3&gt;

&lt;p&gt;So, you have your app running now. You could notice that it’s blocking you from closing your terminal and exiting from server connection. If you do so, your site will be down. That’s where PM2 comes to play. Basically, PM2 is a process manager that helps to keep NodeJS applications alive all the time. It runs in the background managing NodeJS applications for you.&lt;/p&gt;

&lt;p&gt;Install PM2 using the following command&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yarn global add pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After PM2 installation, run the below command to run and manage your app in the background.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 start yarn --name [name-of-your-app] -- start -p [port-number]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace [name-of-your-app] with your app name and [port-number] with 3000. Here's an example command,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 start yarn --name next_hello_world_app -- start -p 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Hit “&lt;a href="http://ec2-public-ip-address:3000/"&gt;http://ec2-public-ip-address:3000/&lt;/a&gt;" and you’ll again be amazed to see your app is up and running.&lt;/p&gt;

&lt;p&gt;It’s always a best practice to save the PM2 process. When you reboot your instance, your PM2 instances will be lost. In order to restore it to its old state, you have to save the PM2 process. Here’s the command for that.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s the command to restore your PM2 instances.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 resurrect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We have successfully deployed the Next.js app manually. But remember, every time you make a code change and want to see them on your site, you have to login into EC2, pull the latest changes, build the app, and restart the app. This will consume plenty of time and I’m super lazy to do this. Let’s automate this in the next step!&lt;/p&gt;

&lt;p&gt;Before setting up automatic deployment you have to have a knowledge of CodeDeploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  CodeDeploy
&lt;/h2&gt;

&lt;p&gt;CodeDeploy is used to deploy our application automatically to any number of EC2 instances. We need to get ready with two items before beginning this.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;CodeDeploy Agent must be installed in EC2 instance — It is used to continuously poll CodeDeploy and deploy if anything is available&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A file called appspec.yml must be present in the root folder - This file describes the steps to be followed for the deployment&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is awesome &lt;a href="https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html"&gt;documentation&lt;/a&gt; by AWS to install CodeDeploy Agent. Please follow each and every step in the &lt;a href="https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html"&gt;documentation&lt;/a&gt; to install CodeDeploy Agent on your EC2 machine.&lt;/p&gt;

&lt;p&gt;To verify CodeDeploy agent is installed run the below command. If you see &lt;em&gt;active (running)&lt;/em&gt; Kudos to you! CodeDeploy was installed successfully!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service codedeploy-agent status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XNRdEHDh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AycRQgB8NBk4e_Ats.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XNRdEHDh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AycRQgB8NBk4e_Ats.png" alt="CodeDeploy Agent running status" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s create the appspec.yml file. I've written the deployment instructions in deploy.sh file. It's enough to run the file in appspec.yml file. If you want to learn more about appspec.yml check out AWS official &lt;a href="https://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file-structure.html"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a file called appspec.yml and add the following contents&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.0 
os: linux 
hooks: 
  ApplicationStart: 
    - location: deploy.sh 
      timeout: 300 
      runas: ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope you understand the instruction in the above file. If not, here’s a super simple explanation. I’m advising the CodeDeploy Agent that I’m running a Linux OS in my instance and instructing it to run the deploy.sh file as ubuntu user with the timeout being 300 seconds.&lt;/p&gt;

&lt;p&gt;Here’s my deploy.sh file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
cd /path/to/project/on/EC2 
git pull origin master
yarn install &amp;amp;&amp;amp;
yarn build &amp;amp;&amp;amp;
pm2 restart [name]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This file contains instructions to navigate to the project folder on EC2, pull the latest code from source control, install dependencies, build the project, and restart the project instance.&lt;/p&gt;

&lt;p&gt;Commit these files and push them to Git. Now it’s time to set up automatic deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup auto deployment using CodePipeline and CodeDeploy
&lt;/h2&gt;

&lt;p&gt;Two IAM roles have to be created to set up auto-deployment. Some complications will begin from here. To make things simple, I’ve attached screenshots with the appropriate items highlighted with red boxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create IAM Role for CodeDeploy
&lt;/h2&gt;

&lt;p&gt;Navigate to IAM in AWS Console by searching on the search bar at the top. Click Roles on the left pane and Click Create role button at the top right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KbbkxtWs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ArdchTnIREZmcz4mu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KbbkxtWs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ArdchTnIREZmcz4mu.png" alt="Create IAM role" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose AWS service in Trusted entity types and choose CodeDeploy in Use cases and proceed to the next step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u9O5_6SP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Az8VehvLlgkupyhdF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u9O5_6SP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Az8VehvLlgkupyhdF.png" alt="IAM role for CodeDeploy" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can see AWSCodeDeployRole policy is the only policy available, and it’ll be chosen by default in this (Permissions) step. Let’s proceed to the next section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YAV7ad0b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AYRtV0uoEl1Zxwp06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YAV7ad0b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AYRtV0uoEl1Zxwp06.png" alt="AWSCodeDeploy Permission" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter a name for your IAM role. It’s advised to choose a meaningful name to identify this in the future. I’m calling it &lt;em&gt;service-role-for-code-deploy&lt;/em&gt;. Review the permission in the JSON and Click Create role button at the bottom.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cGe2M6Mk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AVATtmLmZdYwvlym5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cGe2M6Mk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AVATtmLmZdYwvlym5.png" alt="AWSCodeDeploy Permission Review" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create IAM role for EC2
&lt;/h2&gt;

&lt;p&gt;Let’s create the next role. This role is for EC2. Choose AWS service in the Trusted entity type, EC2 in the Common use cases section and choose CodeDeploy in Use cases for other AWS services. Click Next to proceed to the next section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_YpD1fUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AAGWIHKepVhQLHWfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_YpD1fUv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AAGWIHKepVhQLHWfb.png" alt="IAM role for EC2" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are lot of policies available for EC2 and CodeDeploy. In the Add permissions section, search for &lt;em&gt;codedeploy&lt;/em&gt; (No space between code and deploy) and select “AmazonEC2RoleForCodeDeploy” and proceed to the next step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jFAk3GI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Ar9vdF62wINQnuRlB.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jFAk3GI9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Ar9vdF62wINQnuRlB.png" alt="Adding AmazonEC2RoleForCodeDeploy permission" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No change in this step. Review and give a meaningful name for your role and click Create role button.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Attach the IAM role to EC2
&lt;/h2&gt;

&lt;p&gt;Once the IAM role for EC2 is created, we have to attach it to the EC2 instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2CrRmWyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJsdRkAqD-FbsVDsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2CrRmWyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJsdRkAqD-FbsVDsw.png" alt="EC2 instance before attaching the IAM role" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To attach the IAM role to the EC2 instance, open your EC2 instance, click on the “Actions” button on the top right and select “Security” in the drop-down, then select “Modify IAM role”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8-sPCyEh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A-sTWQyWDSkVKVJ7K.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8-sPCyEh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A-sTWQyWDSkVKVJ7K.png" alt="Modify IAM role for EC2 instance" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the IAM role which you created last and click the “Update IAM role” button. Reboot the EC2 for the changes to take effect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Zj5rDYHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AEFt9giubn58fsLRh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Zj5rDYHD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/0%2AEFt9giubn58fsLRh.png" alt="Update IAM role for EC2 instance" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EQTZIupr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJoBELFKchKxbh6xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EQTZIupr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJoBELFKchKxbh6xd.png" alt="EC2 instance after attaching IAM role" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After rebooting the EC2, login to EC2 with SSH and run pm2 resurrect command to restore the pm2 processes. Missing to do this may land you at "PM2 Process or Namespace not found error".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qHDzdRUd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AUjYtHo5i90ZfJk9N.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qHDzdRUd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AUjYtHo5i90ZfJk9N.png" alt="PM2 process restore" width="800" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6wN9oOtd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2At4kOVXVyjvyBwdH-.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6wN9oOtd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2At4kOVXVyjvyBwdH-.png" alt="PM2 process or namespace not found an error" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to create CodeDeploy Application
&lt;/h2&gt;

&lt;p&gt;In the AWS Console, search “CodeDeploy” in the search bar at the top. Select “Applications” in the left pane. Click on the “Create application” button on the top right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k-GdsZE4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2APQ7I_HdTOZfwGsVg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k-GdsZE4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2APQ7I_HdTOZfwGsVg.png" alt="Choose an application in the CodeDeploy" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the Application name, choose the “EC2/On-premises” compute platform, and click the “Create application” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SVHZo7gE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AoBuFVjrWU6a83g7E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SVHZo7gE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AoBuFVjrWU6a83g7E.png" alt="Create CodeDeploy application" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EnZaqwKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/NaN/undefined" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EnZaqwKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/NaN/undefined" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it’s done, you’ll automatically be redirected to the Deployment groups section. We have to create a deployment group. Click on the “Create deployment group” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Wi_kB8t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AqNivJ2JVX1dIKiky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Wi_kB8t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AqNivJ2JVX1dIKiky.png" alt="Create CodeDeploy Deployment group" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the deployment group name, select the service role (1st created role) you created, and select the deployment type as In-place&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7mq8LD7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AqXUnOTSy5HifDfn0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7mq8LD7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AqXUnOTSy5HifDfn0.png" alt="Create CodeDeploy Deployment group" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Environment configuration section, select “Amazon EC2 instances” and select the key as Name, enter your EC2 instance name in the value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Oa1fTzD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Arl7ijnK_P6-a3paz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Oa1fTzD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2Arl7ijnK_P6-a3paz.png" alt="Code Deployment Group Environment configuration" width="800" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Agent configuration section, select Never, as we installed CodeDeployAgent already. Select “CodeDeployDefault.AllAtOnce” in the Deployment settings section. Leave the “Enable load balancing” checkbox unchecked. Finally, click Create a deployment group button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HfqY7Lhy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AO3qfYFD5DWdYSU3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HfqY7Lhy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AO3qfYFD5DWdYSU3r.png" alt="CodeDeploy deployment group configurations" width="800" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CodePipeline
&lt;/h2&gt;

&lt;p&gt;AWS CodePipeline helps you to automate your release pipelines for fast and reliable application and infrastructure updates. Now it’s time to create CodePipeline. In the AWS Console, search for “CodePipeline” in the search bar.&lt;/p&gt;

&lt;p&gt;Select “Pipelines” in the left pane and click on “Create pipeline” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T8-DlYi2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AW92nx5Xh1KouLo2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T8-DlYi2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AW92nx5Xh1KouLo2j.png" alt="Create CodePipeline" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the Pipeline name, and enter the Role name. Remember, we created a Role for EC2 and CodeDeploy and not for CodePipeline. AWS by default creates it from here and we have to enter the Role name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dIotLTPM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AkCK02VW-cRRYGAeF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dIotLTPM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AkCK02VW-cRRYGAeF.png" alt="CodePipeline settings" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Add Source Stage
&lt;/h3&gt;

&lt;p&gt;We have to connect our repo with CodePipeline to deploy the changes immediately after the code is pushed.&lt;/p&gt;

&lt;p&gt;We’ll be using GitHub as our source. The next step is to add a GitHub repo to CodePipeline. Choose GitHub(version 2) in the source provider, and click on the “Connect to GitHub” button, which will open up a new pop-up window, click the “Connect to GitHub” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rs9KF5Cd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ANGb8FoNCKR_WLuS2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rs9KF5Cd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ANGb8FoNCKR_WLuS2.png" alt="CodePipeline adding source stage" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will take you to the GitHub authorization page where you have to sign into your GitHub account, and click the “Install a new app” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mr6_nQiz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AaZBDCiIvDFyItNtl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mr6_nQiz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AaZBDCiIvDFyItNtl.png" alt="CodePipeline Github Authorization" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose “Only select repositories” and choose your repository below that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6Ckfivr9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ARN1wQldBACslpIe3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6Ckfivr9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2ARN1wQldBACslpIe3.png" alt="Installing AWS connector for GitHub" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once installed it will prompt you for the password. Click the “Connect” button once you’re done with your authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jPKtJBpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AYodiv9TbYeU6zNY4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jPKtJBpE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AYodiv9TbYeU6zNY4.png" alt="Connecting GitHub to AWS" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After connecting to GitHub, select the Repository name and branch name. To start the CodePipline on code change, it’s important to select the check box “Start the pipeline on source code change” otherwise auto deployment will not happen. For “Output and artifact format”, select “CodePipeline default” and click the “Next” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n-d7JRPd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AgONeHoexzHSDVgmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n-d7JRPd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AgONeHoexzHSDVgmu.png" alt="CodePipeline — Select source code repo" width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to add the build stage, since we’re deploying a simple app we don’t need a build stage. If you want me to write about CodeBuild let me know. I will cover it in my upcoming blogs, but for now, let’s keep things simple and simply skip the build stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add deploy Stage
&lt;/h3&gt;

&lt;p&gt;In the deployment stage, choose “AWS CodeDeploy” for the “Deploy provider” and select the region where you created the above CodeDeploy application. Then select the “Application name” and “Deployment group” that we created in the previous steps and click the “Next” button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--F7Qmd8zr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AUs3l30aBKhRhpw__.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--F7Qmd8zr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AUs3l30aBKhRhpw__.png" alt="CodePipleine — Adding Deployment stage" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step is “Review”. Review everything carefully and click on the “Create pipeline” button. Once the pipeline is created it will start the deployment process. If you followed all the above steps the pipeline should be “Succeeded” on your very first build.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BtCrOjT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2APrs-h3J2y7EDZ5GM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BtCrOjT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2APrs-h3J2y7EDZ5GM.png" alt="Pipeline Succeeded" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EnZaqwKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/NaN/undefined" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EnZaqwKo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/NaN/undefined" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying Auto Deployment
&lt;/h2&gt;

&lt;p&gt;Now let’s verify if the Auto-deployment works properly. This is the Home page of our project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pv9_MU_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A9a54nNX9p_UB_jbx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pv9_MU_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A9a54nNX9p_UB_jbx.png" alt="Next.js Hello World App" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s change the text from “Hello World” to “Welcome to 5minslearn” and push the code to GitHub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D5aNuAzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A7qtqnJsgCckdniUt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D5aNuAzz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2A7qtqnJsgCckdniUt.png" alt="Git code diff" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we go!!! The CodePipeline has triggered automatically and the changes are successfully deployed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MC8jyauK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJd5pGfIpzQLLAEm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MC8jyauK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AJd5pGfIpzQLLAEm7.png" alt="CodeDeploy getting triggered automatically on code changes in Git" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now head to “&lt;a href="http://ec2-public-ip-address:3000/"&gt;http://ec2-public-ip-address:3000/&lt;/a&gt;", you will see the below page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sSi3DH4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AP-aA5WTqsbEJicq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sSi3DH4i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2048/0%2AP-aA5WTqsbEJicq7.png" alt="" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats! 🎉 We successfully completed setting up the auto-deployment for Next.js app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this article, we learned how to deploy Next.js manually on EC2 and set up auto-deployment using AWS services such as CodeDeploy and CodePipeline.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed reading this article! If you are stuck at any point feel free to drop your queries to me at my &lt;a href="https://www.gogosoon.com/cdn-cgi/l/email-protection#4b2a393e250b2c242c243824242565282426"&gt;email&lt;/a&gt;. I’ll be happy to help you!&lt;/p&gt;

&lt;p&gt;If you wish to learn more about AWS, subscribe to my email newsletter at my &lt;a href="https://5minslearn.gogosoon.com/?ref=devdotto__aws_autodeploy"&gt;site&lt;/a&gt; (&lt;a href="https://5minslearn.gogosoon.com/?ref=devdotto__aws_autodeploy"&gt;https://5minslearn.gogosoon.com&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.gogosoon.com/blog/how-to-deploy-next-js-app-setup-ci-cd-using-aws"&gt;https://www.gogosoon.com&lt;/a&gt; on March 28, 2023.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to get started with Docker using NodeJS? - GoGoSoon</title>
      <dc:creator>5 Mins Learn</dc:creator>
      <pubDate>Thu, 27 Apr 2023 03:30:00 +0000</pubDate>
      <link>https://dev.to/5minslearn/how-to-get-started-with-docker-using-nodejs-gogosoon-mkh</link>
      <guid>https://dev.to/5minslearn/how-to-get-started-with-docker-using-nodejs-gogosoon-mkh</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JHYRD5lr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6drii15t85x7n9fch55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JHYRD5lr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r6drii15t85x7n9fch55.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nowadays, We can see most people using software with the logo of a whale lifting some squares ( containers ). Yes, I am talking about the docker. Actually, the Docker logo symbolizes software that brings together a huge amount of organized information. This is a hint of convenience and ease of work.&lt;/p&gt;

&lt;p&gt;Most enterprises adapted to Docker-based deployments (also called containerized deployments) nowadays. This blog will be the best fit for those who know nothing apart from the term "Docker".&lt;/p&gt;

&lt;p&gt;In this article, you'll learn about the fundamentals of Docker, build your own Docker image and publish it to the Docker Hub.&lt;/p&gt;

&lt;p&gt;Let's understand why we need docker with a simple example.&lt;/p&gt;

&lt;p&gt;Let's assume you're joining a new company and you have been allocated to an extremely huge project to work on. You received a brand new laptop and are ready to put on your development shoes. The first step whenever you are onboarded into a project is to set up the development environment. Since it's an extremely huge enterprise project, it consumes a bunch of time to set up the development environment. You may need to install project-specific dependencies, tools, and many more. In the middle, you may face errors that you can mostly solve by following the README guide, but a couple of them might happen for the first time (might happen due to laptop configuration) and you have to solve them on your own.&lt;/p&gt;

&lt;p&gt;Imagine if you have to follow the same process for large team members. It'll be horrible to handle right?&lt;/p&gt;

&lt;p&gt;This is where docker comes really handy. Docker will create containerized applications that run on any type of environment and It has all the dependencies within it. Docker solves many use cases, the above scenario is one among them.&lt;/p&gt;

&lt;p&gt;By using docker we can standardize application operations, ship code faster, and seamlessly deploy to Production.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Docker work?
&lt;/h2&gt;

&lt;p&gt;Docker provides a standardized way to develop, test and deploy code.&lt;/p&gt;

&lt;p&gt;Docker can be imagined as a super-powered advanced virtual machine. Let's learn it with an example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--omiiUq87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zxt5xzkbnxpu06z8l17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--omiiUq87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zxt5xzkbnxpu06z8l17.png" alt="Image description" width="668" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before getting started to work on docker, we should understand some fundamentals of it. They are,&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Docker Engine?
&lt;/h2&gt;

&lt;p&gt;The Docker engine is an open-source containerization technology to build a containerizing application. We can use the docker engine on a variety of platforms through Docker Desktop or Binary Installation. To simplify, the software that hosts the containers is called Docker Engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Docker Container?
&lt;/h2&gt;

&lt;p&gt;A container is a standard unit of software that packages up the code and all required dependencies to run an application on different platforms or computing environments.&lt;/p&gt;

&lt;p&gt;Containers are fully isolated from the computing environment, so applications run quickly and reliably from one computing environment to another.&lt;/p&gt;

&lt;p&gt;Docker containers are built from container images.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Docker image?
&lt;/h2&gt;

&lt;p&gt;A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application. It includes code, runtime, system tools, system libraries, and settings.&lt;/p&gt;

&lt;p&gt;As we discussed, Containers are built from images. Images become containers when the it starts running on a Docker Engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should I use docker?
&lt;/h2&gt;

&lt;p&gt;Docker gives the ability to run an application in any type of environment which is completely isolated from the current environment, and that is called a container. This isolation and security allow us to run as many containers in a host. Docker helps developers to work in a standardized environment using local containers which provide all the packages and dependencies to run an application. &lt;/p&gt;

&lt;p&gt;Let's see the use cases of docker,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developers can write code locally and share their work using Docker Containers&lt;/li&gt;
&lt;li&gt;We can use the docker to push our applications into a test/production environment and execute automated and manual tests&lt;/li&gt;
&lt;li&gt;When developers need to fix something, they can easily make the changes and push the docker image to the testing or production environment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just like git, we can use docker, If we make any changes we can just push the docker images and pull them into the host machine, No changes need to be done in the host server.&lt;/p&gt;

&lt;p&gt;Here are the ideal deployment steps before the arrival of Docker,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pull/clone the code from the Git&lt;/li&gt;
&lt;li&gt;Install dependencies, Run migrations, etc. in the host machine.&lt;/li&gt;
&lt;li&gt;Start the application&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will repeat the steps on every server whether it is a testing/production environment.&lt;/p&gt;

&lt;p&gt;Here is the deployment steps using Docker&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pull the docker image&lt;/li&gt;
&lt;li&gt;Run the container in the host machine&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is Docker Hub?
&lt;/h2&gt;

&lt;p&gt;Docker Hub is the largest community for the docker images. It allows us to share the container images among the team, or the Docker community. Imagine Docker Hub as a similar version of GitHub. Here, Docker images reside instead of project's code.&lt;/p&gt;

&lt;p&gt;We can pull the open-source docker images also. To use this we have to create an account in the &lt;a href="https://hub.docker.com/"&gt;docker hub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Containerize NodeJS Application using Docker?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A Basic understanding of Nodejs Applications&lt;/li&gt;
&lt;li&gt;Docker desktop application&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can install the Docker Desktop application by following their original &lt;a href="https://docs.docker.com/desktop/install/windows-install/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can verify if docker is installed on your machine by querying it's version,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W5HRPjC2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dstp0s9t9esdnh634780.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W5HRPjC2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dstp0s9t9esdnh634780.png" alt="Image description" width="387" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is preferrable to have Node version 14 and above. You can quickly check that by running the below command,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UX89voHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs37w6gprbiys2wmanfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UX89voHd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cs37w6gprbiys2wmanfz.png" alt="Image description" width="373" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start our implementation.&lt;/p&gt;

&lt;p&gt;Instead of starting over from scratch, I have created a super simple Express API that exposes only one endpoint. I pushed the code to a public repo on Github. Clone the repo by running the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/5minslearn/node_with_docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the project's structure.&lt;/p&gt;

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

&lt;p&gt;I have created only one endpoint ("/") and calling it will return "Greeting from 5minslearn". I've simplified as much as possible to focus more on docker. &lt;/p&gt;

&lt;h2&gt;
  
  
  Create docker file
&lt;/h2&gt;

&lt;p&gt;You have to create a file named "Dockerfile" in the root directory. It is the default file name for the docker engine. Paste the following code into the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:latest
WORKDIR /app
COPY . /app
RUN npm install
EXPOSE 8000
CMD ["npm","start"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's understand these command line by line.&lt;/p&gt;

&lt;p&gt;Defining the parent image is the first step of the docker engine. You have to define the parent image from which you're building the project. In our case it's Node. There are a lot of parent images available in Docker Hub. You have to define the Image Variant next to the parent image. I always prefer to use the latest node image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second step is to define the working directory in docker. Let's define our working directory as &lt;code&gt;app&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WORKDIR /app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the project to the &lt;code&gt;app&lt;/code&gt; directory, Ensure to exclude the &lt;code&gt;node_modules&lt;/code&gt; directory. We will see how to ignore file/folder in the upcoming steps.&lt;/p&gt;

&lt;p&gt;In the above command, the &lt;code&gt;.&lt;/code&gt; indicates that all the files and directories are to be copied to the &lt;code&gt;app&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Next step is to install the required dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RUN is an image build step. The state of the container after a RUN command will be committed to the container image. A Dockerfile can have many RUN steps that can layer on top of one another to build the image.&lt;/p&gt;

&lt;p&gt;Expose the port in which application should run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPOSE 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime.&lt;/p&gt;

&lt;p&gt;Finally run the execution command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CMD ts-node src/index.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CMD is the command the container executes by default when we launch the built image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tips:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recommend you to install &lt;code&gt;Docker&lt;/code&gt; extension if you're using VS Code. It'll help you with it's solid suggestions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g2WL3l2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf5dp1ejy9qj0ofiqefe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g2WL3l2Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf5dp1ejy9qj0ofiqefe.png" alt="Image description" width="461" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to ignore files to be copied into a docker container
&lt;/h2&gt;

&lt;p&gt;You have to exclude the unwanted files to be copied to the container. &lt;code&gt;.dockerignore&lt;/code&gt; file helps you with that. It works like &lt;code&gt;.gitignore&lt;/code&gt; for Git.&lt;/p&gt;

&lt;p&gt;You can define all the files you have to ignore from copying.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YoEO2LfA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1y9is72knq7d355u6d1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YoEO2LfA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1y9is72knq7d355u6d1.png" alt="Image description" width="798" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! You completed the docker configuration. Let's run the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to build docker images
&lt;/h2&gt;

&lt;p&gt;Docker images can be built by running &lt;code&gt;docker build&lt;/code&gt; command. Here's the syntax for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t image_name:version_number .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;image_name&lt;/code&gt; indicates the container image name and &lt;code&gt;version_number&lt;/code&gt; indicates the image version. Hope you notice the dot (&lt;code&gt;.&lt;/code&gt;) at the end of the command. It indicates that the docker image should be built from the current directory.&lt;/p&gt;

&lt;p&gt;I'm entering a random name for my image as &lt;code&gt;aanandggs/node_with_docker&lt;/code&gt;. You may choose to enter whatever you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t aanandggs/node_with_docker:0.0.1 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Once building your Docker image, you'll be able to see it on your Docker Desktop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4j1BqdDT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0z4tjmxvc4066pv0cec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4j1BqdDT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0z4tjmxvc4066pv0cec.png" alt="Image description" width="744" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run the docker image
&lt;/h2&gt;

&lt;p&gt;As we build the docker image, our next step is to run the docker image. When an image started running on a Docker Engine, it'll become a container.&lt;/p&gt;

&lt;p&gt;Let's run our image which we built in the previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d --name docker_with_node -p 8000:8000 aanandggs/node_with_docker:0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V5v2oLuI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r8xcbrg9ikmeu9w8g9x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V5v2oLuI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8r8xcbrg9ikmeu9w8g9x.png" alt="Image description" width="797" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's understand the above command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker container run&lt;/code&gt; command is used to create and run a new container from an image. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; flag instructs the container to run on the background (detach). It prints the container id.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--name&lt;/code&gt; parameter is used to give a name to our container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-p&lt;/code&gt; parameter is used to publish a container's port to the host. It'll bind the port 8000 of your local machine with the port 8000 of the docker container&lt;/p&gt;

&lt;p&gt;&lt;code&gt;image_name:version&lt;/code&gt; indicates the image and it's version that this container should run&lt;/p&gt;

&lt;p&gt;You can have a look at the running containers in the Docker Desktop app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PpVTHVsX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bylqkdll3730nbsnaryn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PpVTHVsX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bylqkdll3730nbsnaryn.png" alt="Image description" width="731" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our app is running. Let's check the output on the browser by trying to access the "/" endpoint. Hit &lt;code&gt;locahost:8000/&lt;/code&gt; on your browser. You should see a message similar to the one in the below screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9KkkLbJl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03yoc9vgbhl0kogr1rrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9KkkLbJl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03yoc9vgbhl0kogr1rrv.png" alt="Image description" width="623" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have successfully ran a app with the docker container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
You can bind any local port to the docker port. Ensure your local port is not used by any other process.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to push the image to the DockerHub
&lt;/h2&gt;

&lt;p&gt;Create your profile on Docker Hub. Come back to terminal and run the below command to login to Docker CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you face any issues with login, Please follow this doc to login to the Dockerhub on your machine.&lt;/p&gt;

&lt;p&gt;After the successful login, We can push the image to the docker hub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push aanandggs/node_with_docker:0.0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Hurray!!! Images are uploaded to the docker hub.&lt;/p&gt;

&lt;p&gt;You'll be able to see them in the docker hub console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U3QfIKWk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5axoa8qzwctz5l1tp32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U3QfIKWk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p5axoa8qzwctz5l1tp32.png" alt="Image description" width="798" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since our image is public, anyone on the internet can pull the image and run it on their machines without any third-party installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hope you folks enjoyed reading this blog. Will see you in another interesting blog. Do comment with your thoughts. If you have any queries or corrections regarding this blog, feel free to reach out.&lt;/p&gt;

&lt;p&gt;If you wish to learn more about Docker, subscribe to my email newsletter at my &lt;a href="https://5minslearn.gogosoon.com/?ref=dev_to_docker_getting_started"&gt;site&lt;/a&gt; (&lt;a href="https://5minslearn.gogosoon.com/?ref=dev_to_docker_getting_started"&gt;https://5minslearn.gogosoon.com&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Cheers !!!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
