<?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: Bagas Hariyanto</title>
    <description>The latest articles on DEV Community by Bagas Hariyanto (@bagashyt).</description>
    <link>https://dev.to/bagashyt</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%2F452642%2F33ef86f1-7d42-4c53-b3d4-ac8eedb73c9a.jpg</url>
      <title>DEV Community: Bagas Hariyanto</title>
      <link>https://dev.to/bagashyt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bagashyt"/>
    <language>en</language>
    <item>
      <title>Co-Learning Camp Arbitrum Week 2 Journey</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Fri, 06 Feb 2026 05:53:07 +0000</pubDate>
      <link>https://dev.to/bagashyt/co-learning-camp-arbitrum-week-2-journey-165</link>
      <guid>https://dev.to/bagashyt/co-learning-camp-arbitrum-week-2-journey-165</guid>
      <description>&lt;p&gt;Entering the second week of the Co-Learning Camp by HackQuest, I dove deep into the world of Arbitrum Stylus. My journey began with the Stylus SDK, where I learned to bridge the gap between Rust and smart contracts. Setting up the environment felt like unlocking a new superpower, as I successfully built a basic Counter contract, witnessing firsthand how WASM makes on-chain execution faster.&lt;/p&gt;

&lt;p&gt;The path grew more exciting as I moved toward hands-on examples. I transitioned from simple data storage to building a Greeting contract and a more complex Voting system. Mastering the use of StorageMap to track voters and managing Rust-specific errors taught me how to handle state efficiently. Every successful compilation felt like a victory, bringing me closer to mastering high-performance dApps.&lt;/p&gt;

&lt;p&gt;In the final stretch, I tackled the core of DeFi: token standards. Implementing ERC-20 and ERC-721 in Rust required precision, especially when managing dependencies and storage layouts. Deploying my first custom token to the Arbitrum Sepolia testnet was a defining moment. With these new skills in my toolkit, I am now ready to face the Mini Hackathon and turn these concepts into reality.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>learning</category>
      <category>rust</category>
      <category>web3</category>
    </item>
    <item>
      <title>Co-Learning Camp Arbitrum Week 1 Journey</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Sun, 01 Feb 2026 15:41:41 +0000</pubDate>
      <link>https://dev.to/bagashyt/co-learning-camp-arbitrum-week-1-journey-6i0</link>
      <guid>https://dev.to/bagashyt/co-learning-camp-arbitrum-week-1-journey-6i0</guid>
      <description>&lt;p&gt;I started my journey at the Arbitrum Co-Learning Camp hosted by HackQuest.io, eager to dive into the world of Web3. Starting with the basics, I explored how Arbitrum serves as a Layer 2 scaling solution for Ethereum. Understanding the fundamentals of optimistic rollups was my first step toward mastering this ecosystem and contributing to its growing community of developers.&lt;/p&gt;

&lt;p&gt;As the curriculum progressed, I transitioned from Arbitrum Classic to its advanced iterations: Arbitrum One and Arbitrum Nova. It was fascinating to learn how One handles DeFi with full security, while Nova offers ultra-low fees for gaming and social apps using AnyTrust technology. This distinction helped me see how different projects choose the right chain for their specific needs.&lt;/p&gt;

&lt;p&gt;I then delved into Arbitrum Orbit, a framework for launching dedicated L3 chains. The idea of having a customizable, private blockchain that still benefits from Ethereum's security is revolutionary. Mastering Orbit opened my eyes to the future of hyper-scaling, where specialized chains can cater to massive user bases without congesting the network or increasing transaction costs.&lt;/p&gt;

&lt;p&gt;A major highlight was exploring Arbitrum Stylus. Moving beyond Solidity, I began learning Rust fundamentals for Web3 development. The Stylus SDK allows for writing smart contracts in Rust, which is significantly more efficient. This "next-gen" programming approach promised faster execution and lower gas, making high-performance dApps a reality on the Arbitrum network.&lt;/p&gt;

&lt;p&gt;Finally, I put theory into practice with hands-on examples and the Stylus SDK. Building my first simple projects and seeing code execute on-chain was rewarding. This practical experience at the camp solidified my skills, transforming me from a curious learner into a developer ready to build the next generation of decentralized applications in the Arbitrum ecosystem.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>ethereum</category>
      <category>learning</category>
      <category>web3</category>
    </item>
    <item>
      <title>Reflection of Co-Learning Mantle week 2</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Sun, 21 Dec 2025 19:30:08 +0000</pubDate>
      <link>https://dev.to/bagashyt/reflection-of-co-learning-mantle-week-2-19h6</link>
      <guid>https://dev.to/bagashyt/reflection-of-co-learning-mantle-week-2-19h6</guid>
      <description>&lt;p&gt;After week 1 we learning about basic of Solidity and how to make and deploy smart contract, now we learn about Real World Asset (RWA).&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What exactly is RWA? (The Digital Mirror)
&lt;/h2&gt;

&lt;p&gt;At its core, Real World Assets (RWA) are digital representations of physical or financial assets (like real estate, gold, or government bonds) on the blockchain. This process is called tokenization.&lt;/p&gt;

&lt;p&gt;The most exciting part for me was seeing how RWA solves "old world" problems. In Traditional Finance (TradFi), investing in a commercial building requires millions of dollars. Through RWA, we can have Fractional Ownership, allowing someone to buy a "piece" of a property for as little as $10.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Legal Puzzle: Token vs. Title
&lt;/h2&gt;

&lt;p&gt;One of the biggest questions I had was: "Does owning a token legally mean I own the asset?" The module explains that this depends on the Legal Structuring. I learned about three main models:&lt;/p&gt;

&lt;p&gt;SPV (Special Purpose Vehicle): A company holds the asset, and the token represents shares in that company.&lt;/p&gt;

&lt;p&gt;Direct Ownership: The law directly recognizes the token as the title deed (common in crypto-friendly hubs like Switzerland).&lt;/p&gt;

&lt;p&gt;Contractual Claims: The token acts as a contract between the holder and a custodian (common for gold-backed tokens).&lt;/p&gt;

&lt;p&gt;For those of us in Indonesia, it’s fascinating to see the OJK (Financial Services Authority) developing frameworks to regulate these digital securities by 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why Mantle Network for RWA?
&lt;/h2&gt;

&lt;p&gt;Choosing the right blockchain is critical for RWA because these projects require high security and low costs. Mantle Network stands out to me for a few reasons:&lt;/p&gt;

&lt;p&gt;Efficiency: Its modular architecture keeps transaction fees low, which is essential when you are dealing with small fractional investments.&lt;/p&gt;

&lt;p&gt;Institutional Grade: Mantle provides the performance needed for high-frequency trading of tokenized assets.&lt;/p&gt;

&lt;p&gt;The Ecosystem: With initiatives like the Mantle Global Hackathon (offering $150k in prizes), there is a massive push to make Mantle the go-to home for "RealFi."&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Technical Standards &amp;amp; Compliance
&lt;/h2&gt;

&lt;p&gt;Unlike a standard ERC-20 token that anyone can send to anyone, RWA tokens must be "smart" enough to follow the law. I learned about:&lt;/p&gt;

&lt;p&gt;ERC-3643: A standard that ensures tokens can only be transferred to users who have passed KYC (Know Your Customer) verification.&lt;/p&gt;

&lt;p&gt;Oracles (Chainlink): These provide the "bridge" for data, ensuring the price of the asset on-chain matches the real-world market value.&lt;/p&gt;

&lt;p&gt;Proof of Reserve (PoR): A way to prove on-chain that the physical gold or cash actually exists in a vault.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Practical Application: The IndonesiaPropertyToken
&lt;/h2&gt;

&lt;p&gt;The most hands-on part of the course is the challenge to build the IndonesiaPropertyToken. This project involves creating a decentralized application (DApp) that allows users to invest in Indonesian real estate.&lt;/p&gt;

&lt;p&gt;The Mission: Integrate a KYC Registry with a Property Token contract.&lt;/p&gt;

&lt;p&gt;The Goal: Ensure transparency, liquidity, and 24/7 trading for assets that were previously "locked" behind high barriers to entry.&lt;/p&gt;

&lt;p&gt;Final Thoughts: The Road Ahead&lt;br&gt;
The RWA market is projected to reach $10–30 trillion by 2030. Learning this now feels like being at the start of a massive wave. The Mantle Co-Learning Camp doesn't just teach you how to code; it teaches you how to rebuild the global financial system.&lt;/p&gt;

&lt;p&gt;(#LearnwithHQ #14DaysOfLearning)&lt;/p&gt;

</description>
      <category>web3</category>
      <category>devjournal</category>
      <category>blockchain</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Reflection of Co-Learning Mantle week 1</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Sun, 14 Dec 2025 14:59:12 +0000</pubDate>
      <link>https://dev.to/bagashyt/reflection-of-co-learning-mantle-week-1-348c</link>
      <guid>https://dev.to/bagashyt/reflection-of-co-learning-mantle-week-1-348c</guid>
      <description>&lt;p&gt;In this blog I want to share a reflection of Co-Learning Mantle. This co-learning is held by Hackquest, a platform to learn about Web3. The participant expected to learn and build a web3 project using Mantle Network. Mantle is a L2 ETH Mantle is a Web3 ecosystem built on Ethereum that positions itself as the “Liquidity Chain of the Future,” combining modular blockchain design, zero-knowledge (ZK) proofs, and a large treasury governed by token holders.&lt;/p&gt;

&lt;p&gt;In the first day there is Town Hall for boarding toward Co-Learning Mantle, we learn about Hackquest platform, what is Mantle and the difference between L1 and L2 ETH network. Layer 1 Eth (L1) is mainnet of ETH networks that base of the blockchain itself, it run the smart-contract  directly, provides security through Proof of Stake consensus, and tores all transaction data permanently. But has high gas fees during congestion,  Scalability bottlenecks due to every node needing to process every transaction. The Layer 2 Eth (L2) created to fix that weakness like Much lower fees, Higher throughput (hundreds to thousands of TPS), and inherits Ethereum’s security guarantees.&lt;/p&gt;

&lt;p&gt;On the second Town Hall we Learn about basic Solidity. Solidity is programming language that used to create Smart-Contract. We learn about type data, struct &amp;amp; enum,  Mapping &amp;amp; Array, Modifier &amp;amp; Event, Payable &amp;amp; Time-Based. We also learn to implement that to a simple Smart-Contract project using Remix.&lt;/p&gt;

&lt;p&gt;On the Third Town Hall we learn about Foundry. Foundry is a fast, modular Ethereum development framework written in Rust that helps developers build, test, and deploy Solidity smart contracts efficiently. We learn to build a EduLoan project, a smart contract project that use to lending a money to student, the project can be topup by admin, can transfer the fund to student wallet address, and the student can repay the loan with interest. The project is deployed on Mantle Netwrok.&lt;/p&gt;

&lt;p&gt;#LearnwithHQ #14DaysOfLearning&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>learning</category>
      <category>web3</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>14 Days Journey Learn Web3</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Mon, 17 Nov 2025 09:12:58 +0000</pubDate>
      <link>https://dev.to/bagashyt/14-days-journey-learn-web3-3aib</link>
      <guid>https://dev.to/bagashyt/14-days-journey-learn-web3-3aib</guid>
      <description>&lt;p&gt;I just completed an intensive 14-day dive into Web3, and it's incredible how much I've learned. I went from understanding the basic concepts to actually building my own tokens. Here’s a breakdown of my journey and what I mastered over the two weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1: Mastering Solidity &amp;amp; Smart Contract Fundamentals
&lt;/h2&gt;

&lt;p&gt;My first week was all about building a strong foundation. I focused on Solidity, the primary programming language for the Ethereum blockchain.&lt;/p&gt;

&lt;p&gt;Setting Up My Environment: First, I got my tools ready. I learned to use the Remix IDE, a fantastic browser-based tool for writing and testing contracts. I also set up my MetaMask wallet to interact with the network and used a Sepolia faucet to get free "test" ETH. This was crucial so I could deploy contracts without spending real money.&lt;/p&gt;

&lt;p&gt;Solidity 101 (The Basics): I started with the essential building blocks of the language. I now understand the core data types:&lt;/p&gt;

&lt;p&gt;string: For text.&lt;/p&gt;

&lt;p&gt;uint256: The standard for numbers, like IDs or balances.&lt;/p&gt;

&lt;p&gt;bool: For simple true/false values.&lt;/p&gt;

&lt;p&gt;address: A special type for holding Ethereum wallet addresses, including the critical msg.sender (who is calling the function).&lt;/p&gt;

&lt;p&gt;Organizing Complex Data: Once I had the basics, I learned how to structure data effectively.&lt;/p&gt;

&lt;p&gt;struct: This was a breakthrough. It lets me create my own custom data types, like a Student struct that groups an ID, name, and wallet address.&lt;/p&gt;

&lt;p&gt;mapping: This is the most common way to store and retrieve data. I learned to think of it as a "dictionary" that links a key (like a student ID) to a value (like their Student struct).&lt;/p&gt;

&lt;p&gt;enum and array: I also learned to use enums for predefined states (like Active or Graduated) and arrays for dynamic lists.&lt;/p&gt;

&lt;p&gt;Contract Logic &amp;amp; Security: Finally, I learned how to make my contracts do things and how to keep them safe.&lt;/p&gt;

&lt;p&gt;require(): This is my most important security tool. I learned to use it to check conditions (like require(balance &amp;gt;= amount)) before allowing a function to continue.&lt;/p&gt;

&lt;p&gt;modifier: I learned how to create reusable checks, like the classic onlyOwner modifier, to lock down administrative functions.&lt;/p&gt;

&lt;p&gt;event: I learned how contracts "talk" to the outside world by emitting events, which are essential for any user interface.&lt;/p&gt;

&lt;p&gt;payable: I now know how to write functions that can receive Ether.&lt;/p&gt;

&lt;p&gt;By the end of week one, I had successfully written, deployed, and interacted with my own StudentRegistry smart contract. I was no longer just reading about blockchain; I was writing to one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 2: Building My Own Tokens (ERC20 &amp;amp; ERC721)
&lt;/h2&gt;

&lt;p&gt;In my second week, I took my new Solidity skills and applied them to one of the most exciting parts of Web3: tokens. I focused on the two main standards.&lt;/p&gt;

&lt;p&gt;Part 1: ERC20 (Fungible Tokens):&lt;/p&gt;

&lt;p&gt;I learned that ERC20 is the standard for "fungible" tokens, where every token is identical, like a dollar bill. This is what stablecoins (USDT) and utility tokens (LINK) use.&lt;/p&gt;

&lt;p&gt;I built my own ERC20 token from scratch. This was a fantastic exercise where I had to implement:&lt;/p&gt;

&lt;p&gt;A mapping (using balanceOf) to track how many tokens each wallet holds.&lt;/p&gt;

&lt;p&gt;A transfer function to let users send tokens to each other.&lt;/p&gt;

&lt;p&gt;The approve and transferFrom flow. This was a key concept, as it's what allows other smart contracts (like decentralized exchanges) to spend tokens on my behalf.&lt;/p&gt;

&lt;p&gt;Part 2: ERC721 (Non-Fungible Tokens - NFTs):&lt;/p&gt;

&lt;p&gt;Next, I tackled ERC721, the standard for NFTs. I learned that "non-fungible" means each token is unique and has a specific owner, identified by a tokenId.&lt;/p&gt;

&lt;p&gt;This was the most fun part. I built my own CryptoKitty-style NFT contract. This was more complex and taught me to:&lt;/p&gt;

&lt;p&gt;Use a mapping (for ownerOf) to track the owner of each unique NFT.&lt;/p&gt;

&lt;p&gt;Write a _mint() function to create new NFTs, often with unique properties.&lt;/p&gt;

&lt;p&gt;Implement safeTransferFrom to securely transfer NFT ownership.&lt;/p&gt;

&lt;p&gt;I even experimented with a breed() function to create a new, unique NFT from two "parent" NFTs.&lt;/p&gt;

&lt;p&gt;Putting It All Together: OpenZeppelin&lt;/p&gt;

&lt;p&gt;Finally, I learned the most important lesson for real-world development: don't write these from scratch in production!&lt;/p&gt;

&lt;p&gt;I was introduced to OpenZeppelin Contracts, a library of secure, audited, and optimized smart contracts. I learned how I can create a production-ready ERC20 or ERC721 token in just a few lines of code by simply importing from their library. This is how I'll build projects moving forward.&lt;/p&gt;

&lt;p&gt;After this 14-day journey, I've gone from being a curious outsider to someone who has successfully built and deployed their own fungible tokens and NFTs. I have a solid, practical skill set and I'm excited to keep building in Web3.&lt;/p&gt;

</description>
      <category>learnwithhq</category>
      <category>14daysoflearning</category>
    </item>
    <item>
      <title>ERC20 in Web3 Smart Contract</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Sun, 16 Nov 2025 14:32:31 +0000</pubDate>
      <link>https://dev.to/bagashyt/erc20-in-web3-smart-contract-34ib</link>
      <guid>https://dev.to/bagashyt/erc20-in-web3-smart-contract-34ib</guid>
      <description>&lt;p&gt;Token standard is essential in Web3 Smart Contract development because it ensure &lt;strong&gt;Interoperabilit&lt;/strong&gt;y, &lt;strong&gt;compatibility&lt;/strong&gt;, &lt;strong&gt;Security&lt;/strong&gt; and &lt;strong&gt;Community&lt;/strong&gt;. That mean the smart contract can be used on all Dapp, have compatibility to any Wallet for example Metamask, follow security standard that safe and tested, also has maintained tools and library to develop it. In this article I want to share about Token standard in Web3, ERC20 or known as Fungible Token.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC20
&lt;/h3&gt;

&lt;p&gt;ERC20 also known as Fungible Token is a standard to make a Token that can be tradeable (Fungible), and each Token has the same value. The example of this Token in real-life is USDT, BNB, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC20 Interface
&lt;/h3&gt;

&lt;p&gt;Each ERC20 token must have this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IERC20 {
    // Total supply token
    function totalSupply() external view returns (uint256);

    // Balance dari address
    function balanceOf(address account) external view returns (uint256);

    // Transfer token
    function transfer(address to, uint256 amount) external returns (bool);

    // Approve spending
    function approve(address spender, uint256 amount) external returns (bool);

    // Check allowance
    function allowance(address owner, address spender) external view returns (uint256);

    // Transfer from (by approved spender)
    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    // Events
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup Contract
&lt;/h3&gt;

&lt;p&gt;Make a file named &lt;code&gt;FungibleToken.sol&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

/**
 * @title FungibleToken
 * @dev ERC20 Token implementation from scratch
 */
contract FungibleToken {
    // Token metadata
    string public name;
    string public symbol;
    uint8 public decimals;

    constructor() {
        name = "My First Token";
        symbol = "MFT";
        decimals = 18;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Define Key Variables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract FungibleToken {
    string public name;
    string public symbol;
    uint8 public decimals;

    // Total supply token yang ada
    uint256 public totalSupply;

    // Mapping address -&amp;gt; balance
    mapping(address =&amp;gt; uint256) public balanceOf;

    // Mapping owner -&amp;gt; spender -&amp;gt; amount
    // Untuk approve mechanism
    mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) public allowance;

    constructor() {
        name = "My First Token";
        symbol = "MFT";
        decimals = 18;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Event and Basic Mint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract FungibleToken {
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;

    mapping(address =&amp;gt; uint256) public balanceOf;
    mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) public allowance;

    // Events (wajib untuk ERC20!)
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    constructor() {
        name = "My First Token";
        symbol = "MFT";
        decimals = 18;
    }

    /**
     * @dev Mint new tokens
     * @param _to Address yang menerima token
     * @param _amount Jumlah token (dalam wei)
     */
    function mint(address _to, uint256 _amount) public {
        // Validasi input
        require(_to != address(0), "Mint to zero address");
        require(_amount &amp;gt; 0, "Amount must be greater than 0");

        // Update state
        totalSupply += _amount;
        balanceOf[_to] += _amount;

        // Emit event
        emit Transfer(address(0), _to, _amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Access Control
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

contract FungibleToken {
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;

    address public owner;

    mapping(address =&amp;gt; uint256) public balanceOf;
    mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) public allowance;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    // Modifier untuk restrict ke owner
    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this");
        _;
    }

    constructor() {
        name = "My First Token";
        symbol = "MFT";
        decimals = 18;
        owner = msg.sender;

        // Mint initial supply ke owner
        _mint(msg.sender, 1000000 * 10**decimals); // 1 juta token
    }

    /**
     * @dev Internal mint function
     */
    function _mint(address _to, uint256 _amount) internal {
        require(_to != address(0), "Mint to zero address");

        totalSupply += _amount;
        balanceOf[_to] += _amount;

        emit Transfer(address(0), _to, _amount);
    }

    /**
     * @dev Public mint (only owner)
     */
    function mint(address _to, uint256 _amount) public onlyOwner {
        require(_amount &amp;gt; 0, "Amount must be greater than 0");
        _mint(_to, _amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>web3</category>
      <category>learnwithhq</category>
      <category>14daysoflearning</category>
    </item>
    <item>
      <title>Hands On Docker For Beginners Golang Dev</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Sun, 27 Oct 2024 22:56:41 +0000</pubDate>
      <link>https://dev.to/bagashyt/hands-on-docker-for-beginners-golang-dev-3kpo</link>
      <guid>https://dev.to/bagashyt/hands-on-docker-for-beginners-golang-dev-3kpo</guid>
      <description>&lt;h2&gt;
  
  
  Table of Content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Prerequisite&lt;/li&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;
Docker Compose

&lt;ul&gt;
&lt;li&gt;
Services

&lt;ul&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;Mysql&lt;/li&gt;
&lt;li&gt;Migrate&lt;/li&gt;
&lt;li&gt;API&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Volumes&lt;/li&gt;

&lt;li&gt;Networks&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;References&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This Article wouldn't explain how Docker works on the hood, instead this Article will explain what the purpose on each code that written on &lt;code&gt;Dockerfile&lt;/code&gt; and &lt;code&gt;docker-compose.yml&lt;/code&gt; file so we can write our Docker configuration for other project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We need some project with Dockerfile and docker-compose for example, here we would use Golang Project named &lt;a href="https://github.com/bagashyt/ecom" rel="noopener noreferrer"&gt;Ecom&lt;/a&gt; as example. For using Dockerfile you need to setup Local Database as mentioned on README.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dockerfile &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Dockerfile used to create a container image.(6)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Build application from source
FROM golang:1.23.0 AS build-stage
    WORKDIR /app

    COPY go.mod go.sum ./
    RUN go mod download

    COPY . .

    RUN CGO_ENABLED=0 GOOS=linux go build -o /api ./cmd/main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FROM golang:1.23.0 AS build-stage&lt;/code&gt; this is an Image for our App, it's similar like we download Go engine to our Machine, Docker need specific Image to run our Code.(1)(2)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;WORKDIR /app&lt;/code&gt; this is the working directory we want our Code to be executed at &lt;code&gt;/app&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;COPY go.mod go.sum ./&lt;/code&gt; this code will copying &lt;code&gt;go.mod&lt;/code&gt; and &lt;code&gt;go.sum&lt;/code&gt; file from local machine to &lt;code&gt;./&lt;/code&gt; directory on Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RUN go mod download&lt;/code&gt; this will executed command &lt;code&gt;go mod download&lt;/code&gt; on Docker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;COPY . .&lt;/code&gt; this code will copy all file and folder project from local machine to Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;RUN CGO_ENABLED=0 GOOS=linux go build -o /api ./cmd/main.go&lt;/code&gt; this code will executed command to build Golang app on linux OS to folder &lt;code&gt;/api&lt;/code&gt; on Docker.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Deploy application binary into a lean image
FROM scratch AS build-realease-stage
    WORKDIR /

    COPY --from=build-stage /api /api

    EXPOSE 8080

    ENTRYPOINT [ "/api" ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;FROM scratch AS build-realease-stage&lt;/code&gt; scratch used to create minimal images containing only just what an application needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;WORKDIR /&lt;/code&gt; we will using root &lt;code&gt;/&lt;/code&gt; as working directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;COPY --from=build-stage /api /api&lt;/code&gt; this will copying directory &lt;code&gt;/api&lt;/code&gt; from image &lt;code&gt;build-stage&lt;/code&gt; to &lt;code&gt;/api&lt;/code&gt; on &lt;code&gt;build-realease-stage&lt;/code&gt; image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;EXPOSE 8080&lt;/code&gt; this will expose port &lt;code&gt;8080&lt;/code&gt; so we can access API with port &lt;code&gt;8080&lt;/code&gt; outside Docker.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;ENTRYPOINT [ "/api" ]&lt;/code&gt; this will set default executable at &lt;code&gt;/api&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's try our Dockerfile.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docker build&lt;/code&gt; to build our project into an Image. You can add tags &lt;code&gt;-t project-ecom&lt;/code&gt; to easier identify Images you build.(3)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvncpn50vb4c8lgkxfi6f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvncpn50vb4c8lgkxfi6f.png" alt="Docker Build" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check the Image list with command &lt;code&gt;sudo docker image ls&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r80u8ofq83mxco80ukz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7r80u8ofq83mxco80ukz.png" alt="Image description" width="640" height="56"&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;sudo docker run --rm --network host --env-file .env 98bc0128576e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then Run our Docker Image&lt;br&gt;
&lt;code&gt;--rm&lt;/code&gt; to remove container when stopped&lt;br&gt;
&lt;code&gt;--network host&lt;/code&gt; to connect docker app to localhost machine (4),(5)&lt;br&gt;
&lt;code&gt;--env-file .env&lt;/code&gt; to access environment value through .env file&lt;br&gt;
&lt;code&gt;98bc0128576e&lt;/code&gt; docker image ID&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faczlapgbbk89afq83wwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faczlapgbbk89afq83wwx.png" alt="Image description" width="800" height="42"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Congratulation
&lt;/h3&gt;

&lt;p&gt;You now can testing to Consume API with Postman or other apps. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftthglmns6oafgl2zacsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftthglmns6oafgl2zacsc.png" alt="Image description" width="448" height="365"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Docker Compose &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Docker Compose used to make multiple container services and run it inside Docker. In this project &lt;code&gt;docker-compose.yml&lt;/code&gt; there are 4 services that we will explain.&lt;/p&gt;
&lt;h3&gt;
  
  
  Services &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A service is an abstract definition of a computing resource within an application which can be scaled or replaced independently from other components.(12)&lt;/p&gt;
&lt;h3&gt;
  
  
  Nginx Proxy &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  nginx:
    image: nginxproxy/nginx-proxy:1.6
    networks:
      - default
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    environment:
      HTTPS_METHOD: nohttps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;nginx:&lt;/code&gt; this is the service name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image: nginxproxy/nginx-proxy:1.6&lt;/code&gt; this is the Image that we will use, similar to &lt;code&gt;FROM&lt;/code&gt; at Dockerfile.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;networks:&lt;/code&gt; this is the network inside Docker the service will use.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports:&lt;/code&gt; this is to set port for service to use &lt;code&gt;&amp;lt;local-machine-port&amp;gt;&lt;/code&gt; : &lt;code&gt;&amp;lt;docker-nginx-port&amp;gt;&lt;/code&gt;, 80 is default port for HTTP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volumes:&lt;/code&gt; this is persistent Volume to store data for this service, &lt;code&gt;&amp;lt;local-data-directory&amp;gt;&lt;/code&gt; : &lt;code&gt;&amp;lt;docker-directory&amp;gt;&lt;/code&gt; :ro (read-only).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment:&lt;/code&gt; this is to use environment variable.(8)
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Mysql &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  db:
    image: mysql:8.0
    networks:
      new:
        aliases:
          - database
    healthcheck:
      test: mysqladmin ping -h database -u ${DB_USER} --password=${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3308:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;db:&lt;/code&gt; this is the service name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image: mysql:8.0&lt;/code&gt; this service using Image mysql version 8.0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;networks:&lt;/code&gt; this service using custom network named &lt;code&gt;new&lt;/code&gt; then the &lt;code&gt;new&lt;/code&gt; network using alias-name &lt;code&gt;database&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;healthcheck:&lt;/code&gt; this is to check the service operation by running a test, &lt;code&gt;test: mysqladmin ping -h database -u ${DB_USER} --password=${DB_PASSWORD}&lt;/code&gt; this testing ping a mysql database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volumes:&lt;/code&gt; this is to store persistent data inside volume.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports:&lt;/code&gt; this is port the service will use, in this service we use  &lt;code&gt;3308&lt;/code&gt; as local-machine port because port &lt;code&gt;3306&lt;/code&gt; already used for mysql on our local-machine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment:&lt;/code&gt; this is to using environment variable, in this mysql service we need root password and database name.(7)
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Migrate &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  migrate-up:
    image: migrate/migrate
    networks:
      - new
    volumes:
      - ./cmd/migrate/migrations:/migrations
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    command: ["-path", "/migrations", "-database", "${CONNECT_DB}", "-verbose", "up"]
    links:
      - db
    depends_on:
      db:
        condition: service_healthy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;migrate-up:&lt;/code&gt; this is the service name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;image: migrate/migrate&lt;/code&gt; this service use migrate Image&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;networks:&lt;/code&gt; this service using network &lt;code&gt;new&lt;/code&gt; same as &lt;code&gt;db&lt;/code&gt; service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volumes:&lt;/code&gt; the migrations data from local &lt;code&gt;./cmd/migrate/migrations&lt;/code&gt; got copied to service directory &lt;code&gt;/migrations&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;command:&lt;/code&gt; this is to run a command on this service, &lt;code&gt;["-path", "/migrations", "-database", "${CONNECT_DB}", "-verbose", "up"]&lt;/code&gt; this command similar to &lt;code&gt;migrate -path /migrations -database mysql://root:some-secret-password@tcp(database:3306)/ecom -verbose up&lt;/code&gt;. (9)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;links:&lt;/code&gt; this to link service to another service, this &lt;code&gt;migrate&lt;/code&gt; service linked to &lt;code&gt;db&lt;/code&gt; service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;depends_on:&lt;/code&gt; this to make this service executed after certain condition, &lt;code&gt;db: condition: service_healthy&lt;/code&gt; this mean &lt;code&gt;migrate-up&lt;/code&gt; service will executed when &lt;code&gt;db&lt;/code&gt; service test got result &lt;code&gt;service_healthy&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  API &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  api:
    networks:
      - new
      - default
    build: 
      context: .
      dockerfile: Dockerfile
    restart: on-failure
    volumes:
      - .:/go/src/api
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "8080:8080"
    environment:
      VIRTUAL_HOST: ${PUBLIC_HOST}
      DB_HOST: db
      DB_USER: ${DB_USER}
      DB_PASSWORD: ${DB_PASSWORD}
      DB_NAME: ${DB_NAME}
    links:
      - db
    depends_on:
      migrate-up:
        condition: service_completed_successfully
      db:
        condition: service_healthy
      nginx:
        condition: service_started
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;api:&lt;/code&gt; this is the service name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;networks:&lt;/code&gt; this is network for this service, this service using network &lt;code&gt;new&lt;/code&gt; so it can connect to service &lt;code&gt;db&lt;/code&gt;, also connect to network &lt;code&gt;default&lt;/code&gt; used by service &lt;code&gt;nginx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;build:&lt;/code&gt; this is to build the service, thi service using &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;restart:&lt;/code&gt; this service will restart whenever the service &lt;code&gt;on-failure&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volumes:&lt;/code&gt; this is persistent data that stored on volume &lt;code&gt;/go/src/api&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports:&lt;/code&gt; port for this service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment:&lt;/code&gt; environment value this service needed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;links:&lt;/code&gt; this service linked to &lt;code&gt;db&lt;/code&gt; service because its need to consume mysql database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;depends_on:&lt;/code&gt; this service will executed on several condition, when &lt;code&gt;migrate-up:&lt;/code&gt; already &lt;code&gt;service_completed_successfully&lt;/code&gt;, when &lt;code&gt;db&lt;/code&gt; test result is &lt;code&gt;service_healthy&lt;/code&gt;, and when &lt;code&gt;nginx&lt;/code&gt; &lt;code&gt;service_started&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Volumes &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Volumes are persistent data stores implemented by the container engine.(10)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volumes:
  db_data:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;volumes:&lt;/code&gt; this created persistent volume named &lt;code&gt;db_data:&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Networks &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Networks let services communicate with each other.(11)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;networks:
      new:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;networks:&lt;/code&gt; this created networks named &lt;code&gt;new&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Let's try our Docker Compose&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create images for each services and run each container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbrta65mczql0cnfqcej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbrta65mczql0cnfqcej.png" alt="docker compose up" width="754" height="114"&gt;&lt;/a&gt;&lt;/p&gt;






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

&lt;/div&gt;



&lt;p&gt;You can check the container our &lt;code&gt;docker-compose.yml&lt;/code&gt; created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqrlx9pabrlxu0xtwvdh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqrlx9pabrlxu0xtwvdh0.png" alt="docker compose ps" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker volume ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check volume our &lt;code&gt;docker-compose.yml&lt;/code&gt; created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvs9f9kbgj35v1qfpoxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftvs9f9kbgj35v1qfpoxv.png" alt="docker volume ls" width="745" height="63"&gt;&lt;/a&gt;&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker image ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check images our &lt;code&gt;docker-compose.yml&lt;/code&gt; created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6e5iso1z65ta982qvht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6e5iso1z65ta982qvht.png" alt="docker image ls" width="740" height="111"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Congratulation
&lt;/h3&gt;

&lt;p&gt;You can test Consume API from our project based on documentation on README with Postman or other apps.&lt;/p&gt;

&lt;p&gt;if you have done you can stop the container with,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker compose stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0vxgjjjntntoukhsjde.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff0vxgjjjntntoukhsjde.png" alt="Docker Compose Stop" width="749" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or if you want to delete all container service inside docker compose you can run,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4q6qkfwu9vm1r9m7ilj7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4q6qkfwu9vm1r9m7ilj7.png" alt="docker compose down" width="746" height="148"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(1)&lt;a href="https://docs.docker.com/reference/dockerfile" rel="noopener noreferrer"&gt;Dockerfile Reference&lt;/a&gt;&lt;br&gt;
(2)&lt;a href="https://docs.docker.com/build/building/base-images/" rel="noopener noreferrer"&gt;Docker Base Image&lt;/a&gt;&lt;br&gt;
(3)&lt;a href="https://docs.docker.com/get-started/docker-concepts/building-images/build-tag-and-publish-an-image/" rel="noopener noreferrer"&gt;Docker Build&lt;/a&gt;&lt;br&gt;
(4)&lt;a href="https://docs.docker.com/engine/network/tutorials/host/" rel="noopener noreferrer"&gt;Docker Network Tutorials&lt;/a&gt;&lt;br&gt;
(5)&lt;a href="https://docs.docker.com/engine/network/drivers/host/" rel="noopener noreferrer"&gt;Docker Network Drivers&lt;/a&gt;&lt;br&gt;
(6)&lt;a href="https://docs.docker.com/get-started/docker-concepts/building-images/writing-a-dockerfile/#common-instructions" rel="noopener noreferrer"&gt;Writing a Dockerfile&lt;/a&gt;&lt;br&gt;
(7)&lt;a href="https://hub.docker.com/_/mysql" rel="noopener noreferrer"&gt;Docker Hub Mysql&lt;/a&gt;&lt;br&gt;
(8)&lt;a href="https://github.com/nginx-proxy/nginx-proxy/tree/main/docs" rel="noopener noreferrer"&gt;Nginx-Proxy Docs&lt;/a&gt;&lt;br&gt;
(9)&lt;a href="https://github.com/golang-migrate/migrate" rel="noopener noreferrer"&gt;Golang Migrate&lt;/a&gt;&lt;br&gt;
(10)&lt;a href="https://docs.docker.com/reference/compose-file/volumes/" rel="noopener noreferrer"&gt;Compose-file Volumes&lt;/a&gt;&lt;br&gt;
(11)&lt;a href="https://docs.docker.com/reference/compose-file/networks/" rel="noopener noreferrer"&gt;Compose-file Networks&lt;/a&gt;&lt;br&gt;
(12)&lt;a href="https://docs.docker.com/reference/compose-file/services/" rel="noopener noreferrer"&gt;Compose-file Services&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>backend</category>
      <category>go</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Consume Data From API on Flutter Using DIO Package (1)</title>
      <dc:creator>Bagas Hariyanto</dc:creator>
      <pubDate>Thu, 25 Aug 2022 08:24:00 +0000</pubDate>
      <link>https://dev.to/bagashyt/consume-data-from-api-on-flutter-using-dio-package-1-3n7i</link>
      <guid>https://dev.to/bagashyt/consume-data-from-api-on-flutter-using-dio-package-1-3n7i</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;For Mobile App developer consuming data from API is one of skill set that you must have. Flutter it self have many package to help developer consuming data from API.&lt;/p&gt;

&lt;h1&gt;
  
  
  DIO
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/dio" rel="noopener noreferrer"&gt;DIO&lt;/a&gt; is a popular package for retrive data from API on flutter, it's powefull and easy to use.&lt;/p&gt;

&lt;h1&gt;
  
  
  GET Example
&lt;/h1&gt;

&lt;p&gt;For example we would using &lt;a href="https://reqres.in" rel="noopener noreferrer"&gt;reqres.in&lt;/a&gt; API to perform GET, POST and PUT&lt;/p&gt;

&lt;p&gt;First we should make a data model, this is to store the data from API before we consume it with flutter.&lt;br&gt;
You can make data model based on response data from API, here the response data from method GET reqres.in :&lt;br&gt;
&lt;a href="https://reqres.in/api/users?page=2" rel="noopener noreferrer"&gt;GET:https://reqres.in/api/users?page=2&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;class UserModel {
// this is the data from json response,
// each type data based on success json response
  int? page;
  int? perPage;
  int? total;
  int? totalPages;
  List&amp;lt;Data&amp;gt;? data;

// this is constructor
  UserModel({
    this.page,
    this.perPage,
    this.total,
    this.totalPages,
    this.data,
  });

// this is function to store data base on key-value response
  UserModel.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    page = json['page'];
    perPage = json['per_page'];
    total = json['total'];
    totalPages = json['total_pages'];
    data = json['data'] == null
        ? []
        : (json['data'] as List).map((e) =&amp;gt; Data.fromJson(e)).toList();
// on this data we should mapping each response from List to 'class Data'
  }
}

// this class for store data from each response on List
class Data {
  int? id;
  String? email;
  String? firstName;
  String? lastName;
  String? avatar;

  Data({
    this.id,
    this.email,
    this.firstName,
    this.lastName,
    this.avatar,
  });

  Data.fromJson(Map&amp;lt;String, dynamic&amp;gt; json) {
    id = json['id'];
    email = json['email'];
    firstName = json['first_name'];
    lastName = json['last_name'];
    avatar = json['avatar'];
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then we would make function to Get API with DIO.&lt;br&gt;
Using GET method on DIO is easy, we just need to declare DIO package on a class then make a function to use method GET and passing the URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ApiServices {
  Dio dio = Dio();

  Future&amp;lt;Map&amp;lt;String, dynamic&amp;gt;&amp;gt; getUser() async {
    const String url = 'https://reqres.in/api/users?page=2';
    try {
      Response response = await dio.get(url);
      return response.data;
    } on DioError catch (error, trace) {
      print('DIO error : $error, on : $trace');
      return error.response!.data;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Future&amp;lt;Map&amp;lt;String, dynamic&amp;gt;&amp;gt; getUser() async {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;on this code, we use &lt;strong&gt;Future&lt;/strong&gt; Type data because Dart only allow &lt;em&gt;asyncronous&lt;/em&gt; on &lt;strong&gt;Future&lt;/strong&gt; type data function. Then we use Type data &lt;strong&gt;Map&lt;/strong&gt; of &lt;strong&gt;String&lt;/strong&gt;, and &lt;strong&gt;dynamic&lt;/strong&gt; because the response from GET is still array of json, we need to mapping it later.&lt;/p&gt;

&lt;p&gt;Then we make another function to cast Map of String, dynamic to List of DataModel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Future&amp;lt;List&amp;lt;DataModel&amp;gt;&amp;gt; userServices() async {
    List&amp;lt;DataModel&amp;gt; userList = [];
    var response = await getUser();
    if (response.containsKey('data') &amp;amp;&amp;amp; response['data'] is List) {
      userList =
          (response['data'] as List).map((e) =&amp;gt; DataModel.fromJson(e)).toList();
    }
    return userList;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Future&amp;lt;List&amp;lt;DataModel&amp;gt;&amp;gt; userServices() async {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The return data from &lt;strong&gt;getUser&lt;/strong&gt; is &lt;strong&gt;Map&lt;/strong&gt; of json data, we should convert it to &lt;strong&gt;List&lt;/strong&gt; of &lt;strong&gt;DataModel&lt;/strong&gt; before we consume it on Flutter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;if (response.containsKey('data') &amp;amp;&amp;amp; response['data'] is List) {&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Because we just want to consume array of 'data' we should ensure that the response has it and then we mapping it to DataModel.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;userList =&lt;br&gt;
          (response['data'] as List).map((e) =&amp;gt; DataModel.fromJson(e)).toList();&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And then we have &lt;strong&gt;List&lt;/strong&gt; of &lt;strong&gt;DataModel&lt;/strong&gt;, we can consume it with &lt;strong&gt;ListView.builder()&lt;/strong&gt; on Flutter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common DIO GET Method
&lt;/h3&gt;

&lt;p&gt;Beside of 'path' on dio.get() there another parameter on method get() you can use:&lt;br&gt;
&lt;code&gt;queryParameters:&lt;/code&gt; to give param to API,&lt;br&gt;
&lt;code&gt;options:&lt;/code&gt; this required &lt;strong&gt;Options()&lt;/strong&gt; and have many function like setting header etc.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>api</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
