<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mohammad Anang</title>
    <description>The latest articles on Forem by Mohammad Anang (@mohammadanang).</description>
    <link>https://forem.com/mohammadanang</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%2F481943%2F3ea1bf37-e06d-4b35-82b8-9790f9495fd0.jpeg</url>
      <title>Forem: Mohammad Anang</title>
      <link>https://forem.com/mohammadanang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mohammadanang"/>
    <language>en</language>
    <item>
      <title>Building a Zero-Trust Golang Backend (Part 3): Deploying to GKE with Strict Security Context ☸️🚀</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Sun, 12 Apr 2026 02:10:00 +0000</pubDate>
      <link>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-3-deploying-to-gke-with-strict-security-context-3gdd</link>
      <guid>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-3-deploying-to-gke-with-strict-security-context-3gdd</guid>
      <description>&lt;p&gt;Inilah tahap puncak dari seri &lt;strong&gt;DevSecOps&lt;/strong&gt; kita. Di &lt;a href="https://dev.to/mohammadanang/building-a-zero-trust-golang-backend-part-1-secure-coding-distroless-containers-536a"&gt;Part 1&lt;/a&gt; kita telah membuat aplikasi &lt;strong&gt;Golang&lt;/strong&gt; yang aman, dan di &lt;a href="https://dev.to/mohammadanang/building-a-zero-trust-golang-backend-part-2-cicd-dependency-drift-gcp-iam-2jkh"&gt;Part 2&lt;/a&gt; kita menyusun &lt;em&gt;pipeline CI/CD&lt;/em&gt;. Sekarang, saatnya aplikasi ini hidup di lingkungan &lt;em&gt;production&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Repositori penuh: 👉 &lt;a href="https://github.com/mohammadanang/secure-doc-api" rel="noopener noreferrer"&gt;mohammadanang/secure-doc-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Untuk orkestrasi, kita menggunakan &lt;strong&gt;Google Kubernetes Engine (GKE) Autopilot&lt;/strong&gt;. Mode ini luar biasa karena &lt;strong&gt;Google&lt;/strong&gt; yang mengelola infrastruktur &lt;em&gt;node&lt;/em&gt;-nya, memungkinkan kita fokus murni pada &lt;em&gt;Pod&lt;/em&gt; dan keamanannya.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Manifest Deployment: Mengunci Pod dari Dalam&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Container&lt;/em&gt; yang ramping saja tidak cukup. Kita harus memberi tahu &lt;strong&gt;Kubernetes&lt;/strong&gt; untuk membatasi ruang gerak &lt;em&gt;container&lt;/em&gt; tersebut. Inilah fungsi blok &lt;em&gt;securityContext&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secure-api-deployment&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="c1"&gt;# High Availability&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secure-doc-api&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ...&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65532&lt;/span&gt; &lt;span class="c1"&gt;# User spesifik dari Distroless&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secure-api&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-central1-docker.pkg.dev/PROJECT_ID/REPO/IMAGE:latest&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
        &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# Kunci Zero-Trust!&lt;/span&gt;
          &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kenapa &lt;strong&gt;readOnlyRootFilesystem&lt;/strong&gt; itu penting?&lt;/p&gt;

&lt;p&gt;Bahkan jika penyerang menemukan kelemahan &lt;strong&gt;RCE&lt;/strong&gt; (&lt;strong&gt;Remote Code Execution&lt;/strong&gt;) pada aplikasi, mereka tidak akan bisa mengunduh skrip berbahaya, membuat file konfigurasi palsu, atau menulis &lt;em&gt;malware&lt;/em&gt;. Seluruh &lt;em&gt;filesystem&lt;/em&gt; dikunci secara &lt;em&gt;read-only&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Eksekusi Pipeline (Otomatisasi Penuh)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pada &lt;strong&gt;cloudbuild.yaml&lt;/strong&gt;, kita memerintahkan &lt;em&gt;Cloud Build&lt;/em&gt; untuk men-&lt;em&gt;deploy&lt;/em&gt; &lt;em&gt;image&lt;/em&gt; yang baru saja dibuat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;gcr.io/cloud-builders/kubectl'&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;set'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deployment/secure-api-deployment'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;secure-api=$_REGION-docker.pkg.dev/$PROJECT_ID/$_REPO_NAME/$_IMAGE_NAME:$COMMIT_SHA'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dengan menggunakan tag $COMMIT_SHA (dari GitHub), kita mengimplementasikan konsep &lt;strong&gt;Immutable Infrastructure&lt;/strong&gt;. Kita selalu tahu persis kode mana yang sedang berjalan di &lt;em&gt;production&lt;/em&gt;, membuat &lt;em&gt;rollback&lt;/em&gt; menjadi sangat mudah.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kesimpulan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Membangun infrastruktur &lt;em&gt;Zero-Trust&lt;/em&gt; di &lt;em&gt;Cloud&lt;/em&gt; memang membutuhkan setup yang lebih panjang di awal. Namun, hasil akhirnya adalah sistem yang mampu memvalidasi dirinya sendiri, aman secara &lt;em&gt;default&lt;/em&gt;, dan &lt;em&gt;scalable&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Terima kasih telah mengikuti seri tutorial ini! Jika Anda memiliki pertanyaan atau pengalaman seputar &lt;strong&gt;Kubernetes Security&lt;/strong&gt;, mari berdiskusi di kolom komentar.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>gcp</category>
      <category>go</category>
      <category>devsecops</category>
    </item>
    <item>
      <title>Building a Zero-Trust Golang Backend (Part 2): CI/CD, Dependency Drift &amp; GCP IAM ⚙️🔒</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Fri, 10 Apr 2026 02:05:00 +0000</pubDate>
      <link>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-2-cicd-dependency-drift-gcp-iam-2jkh</link>
      <guid>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-2-cicd-dependency-drift-gcp-iam-2jkh</guid>
      <description>&lt;p&gt;Selamat datang kembali di seri pembangunan &lt;strong&gt;Secure Doc API&lt;/strong&gt;! Jika Anda melewatkan &lt;strong&gt;Bagian 1&lt;/strong&gt; tentang &lt;em&gt;Distroless Container&lt;/em&gt;, Anda bisa membacanya &lt;a href="https://dev.to/mohammadanang/building-a-zero-trust-golang-backend-part-1-secure-coding-distroless-containers-536a"&gt;di sini&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Seluruh kode referensi tersedia di: 👉 &lt;a href="https://github.com/mohammadanang/secure-doc-api" rel="noopener noreferrer"&gt;mohammadanang/secure-doc-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sekarang kita memiliki aplikasi yang aman. Tantangan berikutnya adalah: bagaimana memindahkan kode tersebut dari GitHub ke &lt;em&gt;server&lt;/em&gt; secara otomatis, tanpa meloloskan kode yang rentan? Jawabannya adalah &lt;strong&gt;Shift-Left Security&lt;/strong&gt; menggunakan &lt;strong&gt;Google Cloud Build&lt;/strong&gt; dan &lt;strong&gt;Artifact Registry&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Shift-Left Security dengan Gosec&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kita akan menyisipkan &lt;em&gt;gosec&lt;/em&gt; (&lt;strong&gt;Golang Security Checker&lt;/strong&gt;) di tahap paling awal &lt;em&gt;pipeline&lt;/em&gt;. Jika &lt;em&gt;gosec&lt;/em&gt; menemukan celah, &lt;em&gt;pipeline&lt;/em&gt; akan gagal dan &lt;em&gt;image&lt;/em&gt; tidak akan pernah dibuat.&lt;/p&gt;

&lt;p&gt;Namun, di tahap ini saya menemukan pelajaran berharga tentang &lt;strong&gt;Dependency Drift&lt;/strong&gt;. Awalnya saya menggunakan tag @latest untuk instalasi &lt;em&gt;gosec&lt;/em&gt;. Tiba-tiba &lt;em&gt;pipeline&lt;/em&gt; hancur karena versi terbaru &lt;em&gt;gosec&lt;/em&gt; meminta &lt;strong&gt;Golang 1.25&lt;/strong&gt;, sedangkan saya menggunakan &lt;strong&gt;1.24&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Solusinya? &lt;strong&gt;Version Pinning&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# cloudbuild.yaml (Step 1)&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;golang:1.24'&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bash'&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-c'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;echo "Menginstal Gosec (Version Pinned)..."&lt;/span&gt;
        &lt;span class="s"&gt;go install github.com/securego/gosec/v2/cmd/gosec@v2.22.0&lt;/span&gt;

        &lt;span class="s"&gt;/go/bin/gosec -no-fail -fmt=text -out=results.txt ./...&lt;/span&gt;
        &lt;span class="s"&gt;cat results.txt&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;IAM Roles: Jebakan Batman di Google Cloud&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Google Cloud&lt;/strong&gt; menerapkan prinsip &lt;strong&gt;Least Privilege&lt;/strong&gt; secara &lt;em&gt;default&lt;/em&gt;. Artinya, &lt;em&gt;pipeline&lt;/em&gt; kita awalnya sama sekali tidak bisa menulis &lt;em&gt;log&lt;/em&gt;, mengunggah &lt;em&gt;image&lt;/em&gt; ke &lt;strong&gt;Artifact Registry&lt;/strong&gt;, atau men-&lt;em&gt;deploy&lt;/em&gt; ke &lt;strong&gt;Kubernetes&lt;/strong&gt;.&lt;br&gt;
Kita harus mengatur &lt;em&gt;Service Account&lt;/em&gt; di &lt;em&gt;Cloud Shell&lt;/em&gt; secara eksplisit:&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="c"&gt;# Memberikan izin untuk menulis Log&lt;/span&gt;
gcloud projects add-iam-policy-binding &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:&lt;/span&gt;&lt;span class="nv"&gt;$SA_EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/logging.logWriter"&lt;/span&gt;

&lt;span class="c"&gt;# Memberikan izin untuk push image ke Artifact Registry&lt;/span&gt;
gcloud projects add-iam-policy-binding &lt;span class="nv"&gt;$PROJECT_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:&lt;/span&gt;&lt;span class="nv"&gt;$SA_EMAIL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/artifactregistry.writer"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setelah izin beres, &lt;em&gt;pipeline&lt;/em&gt; berjalan mulus, &lt;em&gt;image Docker&lt;/em&gt; dibungkus, dan &lt;strong&gt;Artifact Registry&lt;/strong&gt; secara otomatis memindai kerentanan OS &lt;em&gt;layer&lt;/em&gt;-nya!&lt;/p&gt;

&lt;p&gt;Di &lt;strong&gt;Bagian 3&lt;/strong&gt; (Terakhir), kita akan membahas &lt;em&gt;deployment&lt;/em&gt; akhir ke &lt;strong&gt;GKE Autopilot&lt;/strong&gt; dengan &lt;em&gt;Security Context&lt;/em&gt; tingkat lanjut. Jangan lewatkan!&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>devops</category>
      <category>cicd</category>
      <category>security</category>
    </item>
    <item>
      <title>Building a Zero-Trust Golang Backend (Part 1): Secure Coding &amp; Distroless Containers 🛡️📦</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Wed, 08 Apr 2026 02:00:00 +0000</pubDate>
      <link>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-1-secure-coding-distroless-containers-536a</link>
      <guid>https://forem.com/mohammadanang/building-a-zero-trust-golang-backend-part-1-secure-coding-distroless-containers-536a</guid>
      <description>&lt;p&gt;Keamanan seringkali dianaktirikan demi kecepatan rilis. Dalam seri tutorial 3 bagian ini, kita akan membalik paradigma tersebut. Kita akan membangun &lt;strong&gt;Secure Doc API&lt;/strong&gt;, sebuah layanan &lt;em&gt;backend&lt;/em&gt; Golang yang dirancang dengan arsitektur &lt;em&gt;Zero-Trust&lt;/em&gt; menggunakan ekosistem &lt;strong&gt;Google Cloud Platform&lt;/strong&gt; (&lt;strong&gt;GCP&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;Anda dapat melihat kode sumber lengkap proyek ini di repositori GitHub saya:&lt;br&gt;
👉 &lt;a href="https://github.com/mohammadanang/secure-doc-api" rel="noopener noreferrer"&gt;mohammadanang/secure-doc-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pada Bagian 1 ini, kita akan fokus pada level aplikasi: menulis kode &lt;strong&gt;Go 1.24&lt;/strong&gt; yang siap produksi dan membungkusnya dalam container yang memiliki permukaan serangan (&lt;em&gt;attack surface&lt;/em&gt;) nyaris nol.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Graceful Shutdown di Golang&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Aplikasi &lt;em&gt;Cloud-Native&lt;/em&gt; harus siap dimatikan kapan saja oleh &lt;strong&gt;Kubernetes&lt;/strong&gt; (misalnya saat proses &lt;em&gt;scaling&lt;/em&gt;). Oleh karena itu, kita tidak bisa hanya menggunakan &lt;code&gt;http.ListenAndServe&lt;/code&gt;. Kita perlu menangkap sinyal interupsi OS dan memastikan semua request yang sedang berjalan diselesaikan terlebih dahulu.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;
&lt;span class="c"&gt;// cmd/server/main.go (Cuplikan)&lt;/span&gt;
&lt;span class="c"&gt;// ... setup mux dan server ...&lt;/span&gt;

&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting secure server on port 8080..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrServerClosed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Server failed to start: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}()&lt;/span&gt;

&lt;span class="c"&gt;// Menunggu sinyal OS&lt;/span&gt;
&lt;span class="n"&gt;quit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syscall&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SIGTERM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;quit&lt;/span&gt;

&lt;span class="c"&gt;// Graceful shutdown dengan timeout 5 detik&lt;/span&gt;
&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Art of Distroless Containers&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Banyak &lt;em&gt;developer&lt;/em&gt; masih men-&lt;em&gt;deploy&lt;/em&gt; aplikasi menggunakan &lt;em&gt;image&lt;/em&gt; seperti &lt;strong&gt;alpine&lt;/strong&gt; atau &lt;strong&gt;debian&lt;/strong&gt;. Masalahnya, &lt;em&gt;image&lt;/em&gt; ini membawa &lt;em&gt;shell&lt;/em&gt; (&lt;strong&gt;/bin/sh&lt;/strong&gt;). Jika &lt;em&gt;hacker&lt;/em&gt; menembus aplikasi, mereka memiliki &lt;em&gt;tools&lt;/em&gt; untuk mengeksekusi &lt;em&gt;malware&lt;/em&gt;.&lt;br&gt;
Kita akan menggunakan teknik &lt;strong&gt;Multi-stage build&lt;/strong&gt; yang diakhiri dengan &lt;strong&gt;Google Distroless Image&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Stage 1: Builder (Go 1.24)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.24-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="c"&gt;# Build binary statis&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build &lt;span class="nt"&gt;-ldflags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-w -s"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; secure-api ./cmd/server/main.go

&lt;span class="c"&gt;# Stage 2: Final (Distroless)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; gcr.io/distroless/static:nonroot&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/secure-api .&lt;/span&gt;

&lt;span class="c"&gt;# Paksa berjalan sebagai user non-root (ID 65532)&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; 65532:65532&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["/secure-api"]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hasilnya adalah &lt;em&gt;image&lt;/em&gt; &lt;strong&gt;Docker&lt;/strong&gt; berukuran sangat kecil (~20MB) yang tidak memiliki &lt;em&gt;shell&lt;/em&gt; sama sekali.&lt;br&gt;
Di &lt;strong&gt;Bagian 2&lt;/strong&gt;, kita akan membangun &lt;strong&gt;pipeline CI/CD&lt;/strong&gt; di &lt;strong&gt;Google Cloud Build&lt;/strong&gt; untuk mengotomatiskan &lt;em&gt;security scan&lt;/em&gt; (&lt;strong&gt;SAST&lt;/strong&gt;) dan mendiskusikan masalah &lt;strong&gt;Dependency Drift&lt;/strong&gt;. Sampai jumpa di artikel selanjutnya!&lt;/p&gt;

</description>
      <category>go</category>
      <category>devsecops</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Bagaimana cara menggunakan PostgreSQL tanpa melakukan instalasi?</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Thu, 07 Mar 2024 14:56:50 +0000</pubDate>
      <link>https://forem.com/mohammadanang/bagaimana-cara-menggunakan-postgresql-tanpa-melakukan-instalasi-2hi8</link>
      <guid>https://forem.com/mohammadanang/bagaimana-cara-menggunakan-postgresql-tanpa-melakukan-instalasi-2hi8</guid>
      <description>&lt;p&gt;Salah satu &lt;em&gt;database&lt;/em&gt; &lt;strong&gt;SQL&lt;/strong&gt; yang cukup populer saat ini adalah &lt;code&gt;PostgreSQL&lt;/code&gt;. Didukung perkembangan bahasa pemrograman yang cukup tinggi, baik ragam dan jenisnya, penggunaan berbagai macam &lt;em&gt;database&lt;/em&gt; mendapatkan pengaruh juga. Hal ini menuntut para &lt;em&gt;software developer&lt;/em&gt; untuk dapat menggunakannya. Bersamaan dengan itu, tuntutan untuk melakukan instalasi juga harus dikerjakan.&lt;/p&gt;

&lt;p&gt;Keberadaan &lt;code&gt;docker&lt;/code&gt; menjadi opsi anti ribet untuk melakukan instalasi serta menggunakannya. Sehingga bekal yang harus dimiliki oleh para &lt;em&gt;developer&lt;/em&gt; cukup &lt;code&gt;docker&lt;/code&gt; saja di lokal komputer masing-masing. Spesifik akan dibahas seputar cara menjalankan &lt;code&gt;PostgreSQL&lt;/code&gt; pada &lt;code&gt;docker&lt;/code&gt;, berikut &lt;em&gt;tools&lt;/em&gt; yang mendukung untuk menggunakannya sebagai &lt;em&gt;software developer&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persiapan awal
&lt;/h2&gt;

&lt;p&gt;Pada tahap ini perlu dipastikan untuk memiliki pengetahuan terkait &lt;code&gt;docker&lt;/code&gt;, khususnya &lt;strong&gt;docker compose&lt;/strong&gt;, dikarenakan akan terdapat &lt;code&gt;code&lt;/code&gt;/&lt;code&gt;script&lt;/code&gt; yang membutuhkan pengalaman di dalamnya. Termasuk &lt;em&gt;tools&lt;/em&gt; yang akan direkomendasikan akan berupa aplikasi yang dijalankan menggunakan &lt;code&gt;docker&lt;/code&gt; dan yang ada di luar dan memerlukan instalasi tersendiri tanpa &lt;code&gt;docker&lt;/code&gt;. Berikut tahapan-tahapannya:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Membuat direktori aplikasi untuk mengelola &lt;code&gt;code&lt;/code&gt; yang selanjutnya akan memudahkan proses menjalankan &lt;code&gt;PostgreSQL&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir &amp;lt;direktori-projek&amp;gt; &amp;amp;&amp;amp; cd &amp;lt;direktori-projek&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Membuat &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;docker compose&lt;/strong&gt; dengan nama &lt;code&gt;docker-compose.yaml&lt;/code&gt; seperti berikut:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'

services:
  pgsql:
    container_name: pgsql-app
    image: 'postgres:latest'
    ports:
      - '${DB_PORT:-5432}:5432'
    environment:
      POSTGRES_DB: '${DB_NAME}'
      POSTGRES_USER: '${DB_USER}'
      POSTGRES_PASSWORD: '${DB_PASSWORD}'
    volumes:
      - './data:/var/lib/postgresql/data'
    restart: always

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Susunan &lt;code&gt;code&lt;/code&gt; tersebut memiliki acuan pada situs &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;docker hub&lt;/a&gt; berdasarkan &lt;em&gt;image&lt;/em&gt; (&lt;a href="https://hub.docker.com/_/postgres" rel="noopener noreferrer"&gt;postgres&lt;/a&gt;) yang akan digunakan. Penggunaan &lt;em&gt;options&lt;/em&gt; dijelaskan detail pada halaman masing-masing &lt;em&gt;image&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Menambahkan &lt;em&gt;file&lt;/em&gt; &lt;code&gt;env&lt;/code&gt; untuk mengisikan &lt;strong&gt;value&lt;/strong&gt; yang akan digunakan pada saat menjalankan &lt;strong&gt;docker compose&lt;/strong&gt;. Lalu menyesuaikan isi berupa &lt;em&gt;value-value&lt;/em&gt; berdasarkan kebutuhan yang diperlukan.&lt;/li&gt;
&lt;/ul&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%2Fv9hnrsoxz4swgil3l3on.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%2Fv9hnrsoxz4swgil3l3on.png" alt="Image description" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Opsional) Menggunakan &lt;code&gt;adminer&lt;/code&gt; sebagai &lt;em&gt;database tools&lt;/em&gt; untuk melakukn &lt;strong&gt;query&lt;/strong&gt; dan transaksi lainnya terkait &lt;code&gt;PostgreSQL&lt;/code&gt;. Pada &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;docker compose&lt;/strong&gt; perlu ditambahkan &lt;em&gt;service&lt;/em&gt; tambahan untuk &lt;code&gt;adminer&lt;/code&gt; di bawah &lt;code&gt;postgres&lt;/code&gt; seperti berikut:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  adminer:
    container_name: adminer-app
    image: adminer
    ports:
      - '${ADMINER_PORT:-8000}:8080'
    restart: always
    depends_on:
      - pgsql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Menjalankan perintah &lt;code&gt;docker&lt;/code&gt; untuk menjalankan &lt;code&gt;PostgreSQL&lt;/code&gt; dan &lt;code&gt;adminer&lt;/code&gt; yang telah diatur sebelumnya dengan perintah:
&lt;/li&gt;
&lt;/ul&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;ul&gt;
&lt;li&gt;Memastikan &lt;em&gt;service-service&lt;/em&gt; telah berjalan sesuai dengan pengaturan di dalam &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;docker compose&lt;/strong&gt; dengan perintah:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
&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%2F6pxc0d2ps7nird6yxzvl.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%2F6pxc0d2ps7nird6yxzvl.png" alt="List of container" width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Untuk memberhentikan &lt;em&gt;service&lt;/em&gt; yang telah dijalankan menggunakan perintah berikut:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Uji lapangan
&lt;/h2&gt;

&lt;p&gt;Setelah menjalankan perintah &lt;code&gt;docker&lt;/code&gt;, dapat dipastikan bahwa &lt;code&gt;PostgreSQL&lt;/code&gt; dan &lt;code&gt;adminer&lt;/code&gt; dapat digunakan di lokal komputer. &lt;code&gt;adminer&lt;/code&gt; dapat diakses melalui browser &lt;a href="http://localhost:8000/" rel="noopener noreferrer"&gt;di sini&lt;/a&gt; dengan &lt;strong&gt;port&lt;/strong&gt; menyesuaikan pada &lt;em&gt;file&lt;/em&gt; &lt;code&gt;.env&lt;/code&gt;. Menyesuaikan juga &lt;em&gt;value-value&lt;/em&gt; yang diisikan ke dalam &lt;em&gt;form&lt;/em&gt; berdasarkan pada &lt;em&gt;file&lt;/em&gt; &lt;code&gt;.env&lt;/code&gt;. Berikut hasil &lt;em&gt;capture&lt;/em&gt; dari penggunaannya di &lt;em&gt;browser&lt;/em&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%2F7iwelw504emho2eifgw6.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%2F7iwelw504emho2eifgw6.png" alt="Halaman Awal" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lalu &lt;code&gt;query&lt;/code&gt; dan transaksi &lt;em&gt;database&lt;/em&gt; lainnya dapat dilakukan melalui halaman &lt;code&gt;adminer&lt;/code&gt; tersebut. Termasuk membuat &lt;strong&gt;table&lt;/strong&gt;, menambahkan &lt;code&gt;record&lt;/code&gt; ke dalam &lt;strong&gt;table&lt;/strong&gt;, menghapus &lt;code&gt;record&lt;/code&gt; dari dalam &lt;strong&gt;table&lt;/strong&gt;, dan lainnya. Berikut tampilan beberapa proses transaksi &lt;em&gt;database&lt;/em&gt; yang dapat dilakukan:&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%2F5tn7i7x1xb1s9bzi9iah.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%2F5tn7i7x1xb1s9bzi9iah.png" alt="Halaman Database" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Membuat sebuah &lt;strong&gt;table&lt;/strong&gt; dengan nama &lt;em&gt;user&lt;/em&gt; beserta kolom-kolomnya.&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%2Fkjc1udmeemvrpaywqyfo.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%2Fkjc1udmeemvrpaywqyfo.png" alt="Image description" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hasil &lt;strong&gt;table&lt;/strong&gt;-nya akan menjadi seperti berikut:&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%2F55ngyt6ofzgbt8b4tmfc.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%2F55ngyt6ofzgbt8b4tmfc.png" alt="Image description" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terdapat &lt;em&gt;tools&lt;/em&gt; lain yang dapat digunakan untuk melakukan manajemen &lt;em&gt;database&lt;/em&gt; yaitu &lt;strong&gt;Dbeaver&lt;/strong&gt;. Diperlukan untuk melakukan instalasi di lokal komputer sebelumnya. &lt;strong&gt;Dbeaver&lt;/strong&gt; lebih nyaman digunakan dan &lt;em&gt;user friendly&lt;/em&gt; karena lebih lengkap fiturnya. Selebihnya masih terdapat banyak &lt;em&gt;tools&lt;/em&gt; lain untuk dapat melakukan manajemen &lt;em&gt;database&lt;/em&gt;. Yang disebutkan pada tulisan ini adalah yang pernah digunakan.&lt;br&gt;
Berikut penampakan konfigurasi pada &lt;strong&gt;Dbeaver&lt;/strong&gt; yang selanjutnya transaksi &lt;em&gt;database&lt;/em&gt; dapat dilakukan. Jangan lupa untuk menyesuaikan &lt;em&gt;value-value&lt;/em&gt; berdasarkan &lt;em&gt;file&lt;/em&gt; &lt;code&gt;.env&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%2Fibhg89lien7kkie7u0i2.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%2Fibhg89lien7kkie7u0i2.png" alt="Image description" width="800" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Penutup
&lt;/h2&gt;

&lt;p&gt;Selain dikenal lebih stabil dikalangan &lt;em&gt;database&lt;/em&gt; &lt;strong&gt;SQL&lt;/strong&gt;, tidak sulit juga dalam penggunaannya untuk &lt;code&gt;PostgreSQL&lt;/code&gt;. Jika sebelumnya pernah menggunakan &lt;code&gt;MySQL&lt;/code&gt;, &lt;code&gt;Oracle&lt;/code&gt;, seharusnya tidak akan kesulitan dalam penggunaan &lt;code&gt;PostgreSQL&lt;/code&gt;. &lt;em&gt;Source code&lt;/em&gt; terkait artikel kali ini dapat dicek &lt;a href="https://gitlab.com/devto182/postgredc" rel="noopener noreferrer"&gt;di sini&lt;/a&gt;. Selanjutnya dapat diteruskan pada saat kebutuhan sebuah aplikasi untuk keperluan &lt;em&gt;database&lt;/em&gt; &lt;strong&gt;SQL&lt;/strong&gt;. Sekian.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Credits:&lt;br&gt;
Image cover by &lt;a href="https://unsplash.com/@frostroomhead?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Rodion Kutsaiev&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/white-paper-roll-on-white-table-6W8H4puOJB0?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Support me on:&lt;br&gt;
&lt;a href="https://saweria.co/angm182" rel="noopener noreferrer"&gt;saweria&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://anangm182.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fforthebadge.com%2Fimages%2Fbadges%2Fpowered-by-black-magic.svg" alt="my-site" width="259" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>docker</category>
      <category>sql</category>
      <category>node</category>
    </item>
    <item>
      <title>Bagaimana melakukan push Docker image ke private container registry secara gratis?</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Thu, 29 Feb 2024 05:12:34 +0000</pubDate>
      <link>https://forem.com/mohammadanang/gitlab-container-registry-202g</link>
      <guid>https://forem.com/mohammadanang/gitlab-container-registry-202g</guid>
      <description>&lt;p&gt;Penggunaan &lt;em&gt;container service&lt;/em&gt; pada saat proses &lt;em&gt;deployment&lt;/em&gt; untuk kebutuhan &lt;em&gt;production&lt;/em&gt; menjadi ketergantungan yang lumayan tinggi. Sejalan dengan kepentingan tersebut, &lt;em&gt;&lt;strong&gt;container registry&lt;/strong&gt;&lt;/em&gt; menjadi gerbang awal sebelum menjalankan sebuah &lt;em&gt;container&lt;/em&gt;. Dia digunakan untuk menyimpan &lt;em&gt;image&lt;/em&gt; yang sudah di-&lt;em&gt;compile&lt;/em&gt;, selanjutnya dapat digunakan untuk dijalankan menjadi &lt;em&gt;container service&lt;/em&gt; di &lt;em&gt;server production&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Umumnya penyedia layanan &lt;em&gt;container registry&lt;/em&gt; tidak sulit ditemukan, salah satunya di situs &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;docker official&lt;/strong&gt;&lt;/a&gt;. Namun di sana memiliki keterbatasan pada akses untuk &lt;em&gt;repository&lt;/em&gt; yang berbentuk &lt;strong&gt;private&lt;/strong&gt;, yaitu 1 kuota saja. Sedangkan pada &lt;em&gt;repository&lt;/em&gt; yang bersifat &lt;strong&gt;public&lt;/strong&gt; tidak ada keterbatasan kuota. Ketentuan tersebut berlaku bagi pengguna yang tidak berbayar atau gratis. Sehingga dibagikan di sini alternatif lain untuk mendapatkan &lt;em&gt;repository&lt;/em&gt; yang lebih leluasa, baik &lt;strong&gt;public&lt;/strong&gt; maupun &lt;strong&gt;private&lt;/strong&gt;. Yaitu menggunakan &lt;a href="https://docs.gitlab.com/ee/user/packages/container_registry/" rel="noopener noreferrer"&gt;&lt;strong&gt;GitLab container registry&lt;/strong&gt;&lt;/a&gt;, yang memiliki bentuk akses sesuai dengan &lt;em&gt;repository&lt;/em&gt; yang telah dibuat. Jika &lt;em&gt;repository&lt;/em&gt; berupa &lt;strong&gt;private&lt;/strong&gt;, maka akses pada &lt;em&gt;container registry&lt;/em&gt; juga berbentuk &lt;strong&gt;private&lt;/strong&gt;. Begitu pula sebaliknya.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persiapan &amp;amp; Langkah-langkah
&lt;/h2&gt;

&lt;p&gt;Untuk memulai membuat &lt;em&gt;container registry&lt;/em&gt; di &lt;strong&gt;GitLab&lt;/strong&gt; dapat dipersiapkan sebuah aplikasi yang ingin dilakukan deployment ke server. Pada kasus ini diberikan contoh sederhana membuat &lt;code&gt;REST API&lt;/code&gt; menggunakan &lt;strong&gt;&lt;em&gt;nodejs&lt;/em&gt;&lt;/strong&gt; dengan framework &lt;strong&gt;&lt;em&gt;nestjs&lt;/em&gt;&lt;/strong&gt;. Agar lebih singkat aplikasi yang digunakan dilakukan &lt;em&gt;generate&lt;/em&gt; dari &lt;a href="https://docs.nestjs.com/cli/overview" rel="noopener noreferrer"&gt;nestjs CLI&lt;/a&gt;. Berikut dijelaskan langkah-langkah pembuatan aplikasi hingga ke proses akhir menjadi &lt;em&gt;container registry&lt;/em&gt; di &lt;strong&gt;GitLab&lt;/strong&gt; &lt;em&gt;repository&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melakukan &lt;em&gt;generate&lt;/em&gt; untuk membuat aplikasi &lt;code&gt;REST API&lt;/code&gt; via terminal. (Pada kasus ini digunakan &lt;em&gt;nodejs&lt;/em&gt; versi 18) Ketik dan jalankan untuk melakukan instalasi &lt;code&gt;nestjs&lt;/code&gt; pada &lt;em&gt;library global&lt;/em&gt; lokal.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -g @nestjs/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Membuat direktori aplikasi dengan menjalankan perintah berikut.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest new &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Membuat &lt;strong&gt;Dockerfile&lt;/strong&gt; yang selanjutnya akan menjadi &lt;code&gt;image&lt;/code&gt; untuk diteruskan ke &lt;em&gt;container registry&lt;/em&gt;. Cuplikannya seperti berikut:&lt;/li&gt;
&lt;/ul&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%2Fffl6shap40toiguagasi.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%2Fffl6shap40toiguagasi.png" alt="Docker" width="800" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Membuat &lt;em&gt;repository&lt;/em&gt; di &lt;strong&gt;GitLab&lt;/strong&gt; untuk menyimpan &lt;code&gt;source code&lt;/code&gt; aplikasi yang telah dibuat, sekaligus menjadi &lt;em&gt;repository&lt;/em&gt; untuk &lt;em&gt;container registry&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2F5vhgpo83sldiqowsz7r7.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%2F5vhgpo83sldiqowsz7r7.png" alt="Gitlab Container Registry Capture" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melakukan &lt;em&gt;push/upload&lt;/em&gt; ke &lt;strong&gt;GitLab&lt;/strong&gt; &lt;em&gt;repository&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2Fvk61m1017wtzmh223qzw.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%2Fvk61m1017wtzmh223qzw.png" alt="Gitlab Repository" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melakukan &lt;em&gt;build/compile&lt;/em&gt; aplikasi berdasarkan &lt;code&gt;Dockerfile&lt;/code&gt; yang telah dibuat. Nama &lt;code&gt;image&lt;/code&gt; diharuskan menyesuaikan pada halaman &lt;em&gt;container registry&lt;/em&gt; di &lt;em&gt;repository&lt;/em&gt; &lt;strong&gt;GitLab&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&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%2Fj3v9ssicdihn1u2olq4t.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%2Fj3v9ssicdihn1u2olq4t.png" alt="Container Registry Command" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memastikan &lt;code&gt;login&lt;/code&gt; ke &lt;strong&gt;GitLab&lt;/strong&gt; &lt;em&gt;container registry&lt;/em&gt; dengan perintah:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker login registry.gitlab.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Menjalankan &lt;em&gt;docker container&lt;/em&gt; di lokal komputer dengan perintah:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -p -d 3000:3000 &amp;lt;image-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Memastikan aplikasi berjalan sesuai di &lt;em&gt;browser&lt;/em&gt; atau &lt;strong&gt;Postman&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&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%2F3ltcl7jw1kabu52pfd6h.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%2F3ltcl7jw1kabu52pfd6h.png" alt="Browser" width="800" height="367"&gt;&lt;/a&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%2Fm9e93ix1ik0ayxr89vrr.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%2Fm9e93ix1ik0ayxr89vrr.png" alt="Postman" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setelah berbentuk &lt;code&gt;image&lt;/code&gt;, perlu dilakukan &lt;em&gt;push/upload&lt;/em&gt; ke &lt;em&gt;container registry&lt;/em&gt; di &lt;em&gt;repository&lt;/em&gt; &lt;strong&gt;GitLab&lt;/strong&gt; yang sebelumnya telah dibuat.&lt;/li&gt;
&lt;/ul&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%2Fn5vbsnoh4z0ti73obep8.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%2Fn5vbsnoh4z0ti73obep8.png" alt="Image Pushed" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pada &lt;em&gt;server&lt;/em&gt; yang ditujukan atau di lokal komputer, &lt;em&gt;docker&lt;/em&gt; &lt;code&gt;image&lt;/code&gt; pada &lt;strong&gt;GitLab&lt;/strong&gt; &lt;em&gt;container registry&lt;/em&gt; dapat dilakukan &lt;em&gt;download/pull&lt;/em&gt; dengan perintah:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Langkah akhir dapat dijalankan &lt;em&gt;docker&lt;/em&gt; &lt;code&gt;image&lt;/code&gt; yang telah diunduh/di-&lt;em&gt;download&lt;/em&gt; dengan perintah:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -p -d 3000:3000 &amp;lt;image-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Akhir Kata
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Source code&lt;/em&gt; lengkap dapat dilihat pada &lt;a href="https://gitlab.com/devto182/nestcr" rel="noopener noreferrer"&gt;link ini&lt;/a&gt;. Sekian.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Credits:&lt;br&gt;
Image cover by &lt;a href="https://unsplash.com/@inidianaa?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Tri Eptaroka Mardiana&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/architectural-photography-of-cargo-containers-stack-hP4ZiN1_kdk?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Support me on:&lt;br&gt;
&lt;a href="https://saweria.co/angm182" rel="noopener noreferrer"&gt;saweria&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://anangm182.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fforthebadge.com%2Fimages%2Fbadges%2Fpowered-by-black-magic.svg" alt="my-site" width="259" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>docker</category>
      <category>api</category>
      <category>container</category>
    </item>
    <item>
      <title>Bagaimana cara menggunakan MongoDB tanpa melakukan instalasi?</title>
      <dc:creator>Mohammad Anang</dc:creator>
      <pubDate>Fri, 14 Oct 2022 22:34:06 +0000</pubDate>
      <link>https://forem.com/mohammadanang/mongo-docker-3394</link>
      <guid>https://forem.com/mohammadanang/mongo-docker-3394</guid>
      <description>&lt;p&gt;Pernahkah merasa sulit dan repot saat dipaksa beradaptasi dengan integrasi baru di suatu aplikasi atau projek? Misalnya penerapan &lt;em&gt;database&lt;/em&gt; jenis baru yang menggunakan &lt;a href="https://www.mongodb.com/" rel="noopener noreferrer"&gt;mongodb&lt;/a&gt;. Mungkin kebanyakan developer pemula atau &lt;strong&gt;junior developer&lt;/strong&gt; yang sering meresakannya. Penyebabnya tidak lain karena minimnya tingkat pengalaman terkait &lt;em&gt;tools&lt;/em&gt; tersebut. Ribetnya adalah instalasi &lt;em&gt;tools&lt;/em&gt; di lokal komputer kita, sebagai perangkat yang digunakan untuk berperang dalam proses pengerjaan aplikasi.&lt;/p&gt;

&lt;p&gt;Dipercaya kehadiran &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;docker&lt;/a&gt; di sini menjadi salah satu solusi untuk memudahkan di bagian instalasinya, baik pada tahap &lt;em&gt;development&lt;/em&gt; maupun &lt;em&gt;deployment&lt;/em&gt;. Cukup satu perintah saja banyak &lt;em&gt;tools&lt;/em&gt; yang dibutuhkan dapat dilakukan instalasinya. Lebih tepatnya memaksimalkan penggunaan &lt;strong&gt;docker compose&lt;/strong&gt; yang menjadi salah satu fitur penting di dalam &lt;u&gt;docker&lt;/u&gt;.&lt;/p&gt;

&lt;p&gt;Kesempatan kali ini akan dibahas proses melakukan &lt;em&gt;containerize&lt;/em&gt; &lt;u&gt;mongodb&lt;/u&gt;, dengan bonus &lt;em&gt;database client tools&lt;/em&gt;. Sehingga memudahkan kita untuk tidak membuka atau melakukan instalasi aplikasi database &lt;em&gt;client&lt;/em&gt; yang kompatibel untuk &lt;u&gt;mongodb&lt;/u&gt;. Faktanya pilihan melakukan &lt;em&gt;dockerize&lt;/em&gt; terhadap database tidak terlalu &lt;em&gt;urgent&lt;/em&gt;. Namun menjadi penting saat aplikasi kita memerlukan banyak sekali integrasi &lt;em&gt;tools&lt;/em&gt;. Mungkin saja keperluan dalam proses &lt;em&gt;caching&lt;/em&gt;, &lt;em&gt;message broker&lt;/em&gt; dan lainnya.&lt;/p&gt;

&lt;h2&gt;
  
  
  Persiapan awal
&lt;/h2&gt;

&lt;p&gt;Agar lebih dimudahkan terkait pemahaman proses &lt;em&gt;containerize&lt;/em&gt; &lt;u&gt;mongodb&lt;/u&gt; dan &lt;em&gt;client tools&lt;/em&gt;-nya, akan diberikan contoh aplikasi yang melakukan koneksi terhadap database. Dalam kasus ini aplikasi ditulis menggunakan &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;nodejs&lt;/a&gt; dengan simpel proses &lt;em&gt;query&lt;/em&gt; terhadap &lt;u&gt;mongodb&lt;/u&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclaimer&lt;/em&gt;:&lt;br&gt;
Aplikasi dan &lt;em&gt;tools&lt;/em&gt; lain tidak termasuk ke dalam proses &lt;em&gt;dockerize&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Kebutuhan &lt;em&gt;library&lt;/em&gt;:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Expressjs&lt;/a&gt;. (&lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mongoosejs.com/" rel="noopener noreferrer"&gt;Mongoose&lt;/a&gt;. (&lt;a href="https://github.com/Automattic/mongoose" rel="noopener noreferrer"&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/dotenv" rel="noopener noreferrer"&gt;Dotenv&lt;/a&gt;. (&lt;a href="https://github.com/motdotla/dotenv" rel="noopener noreferrer"&gt;github&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Berikut potongan &lt;em&gt;code&lt;/em&gt; yang akan diimplementasikan menggunakan docker container dari &lt;u&gt;mongodb&lt;/u&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const mongoose = require('mongoose');
const dotenv = require('dotenv');
const Todo = require('./todo');

dotenv.config();

const app = express();

const PORT = parseInt(process.env.PORT) || 3000;
const DB_HOST = process.env.DB_HOST;
const DB_PORT = process.env.DB_PORT;
const DB_USER = process.env.DB_USER;
const DB_PASSWORD = process.env.DB_PASSWORD;
const DB_NAME = process.env.DB_NAME;
const DB_URI = `mongodb://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}`;

app.use(express.json());

app.get('/todo', async (_req, res) =&amp;gt; {
  const allTodos = await Todo.find();
  return res.status(200).json(allTodos);
});

app.post('/todo', async (req, res) =&amp;gt; {
  const newTodo = new Todo({ ...req.body });
  const created = await newTodo.save();
  return res.status(201).json(created);
});

const start = async () =&amp;gt; {
  try {
    await mongoose.connect(DB_URI);
    app.listen(PORT, () =&amp;gt; console.log('Server started on port 3000'));
  } catch (error) {
    console.error(error);
    process.exit(1);
  }
};

start();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Projek ini membuat aplikasi todo &lt;em&gt;list&lt;/em&gt;, menggunakan &lt;em&gt;framework&lt;/em&gt; &lt;strong&gt;expressjs&lt;/strong&gt; dan &lt;strong&gt;mongoose&lt;/strong&gt; &lt;em&gt;library&lt;/em&gt;. Hanya dibuat 2 &lt;em&gt;endpoints&lt;/em&gt; yaitu, &lt;em&gt;list&lt;/em&gt; data todo dan tambah data todo. Konfigurasi &lt;em&gt;value&lt;/em&gt; yang digunakan pada &lt;em&gt;database&lt;/em&gt; dan aplikasi disimpan di dalam &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;.env&lt;/strong&gt;. Berikut susunan isi di dalam &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;.env&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PORT=3000

DB_NAME=domingo_db
DB_USER=domingo_user
DB_PASSWORD=domingo_pass
DB_PORT=27020
DB_HOST=localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selain digunakan di dalam aplikasi, &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;.env&lt;/strong&gt; ini digunakan juga saat &lt;em&gt;build&lt;/em&gt; &amp;amp; &lt;em&gt;run&lt;/em&gt; pada &lt;strong&gt;docker&lt;/strong&gt;. Khusus konfigurasi &lt;u&gt;mongodb&lt;/u&gt; membutuhkan &lt;em&gt;file&lt;/em&gt; &lt;code&gt;javascript&lt;/code&gt; untuk inisialisasi &lt;em&gt;database user&lt;/em&gt;, &lt;em&gt;database password&lt;/em&gt; &amp;amp; &lt;em&gt;database name&lt;/em&gt;. Berikut &lt;em&gt;file&lt;/em&gt; &lt;code&gt;javascript&lt;/code&gt; yang dibutuhkan sebagai inisialisasi &lt;u&gt;mongodb&lt;/u&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.createUser({
  user: 'domingo_user',        // disesuaikan dengan value di file .env =&amp;gt; DB_USER
  pwd: 'domingo_pass',         // disesuaikan dengan value di file .env =&amp;gt; DB_PASSWORD
  roles: [
    {
      role: 'readWrite',
      db: 'domingo_db',        // disesuaikan dengan value di file .env =&amp;gt; DB_NAME
    },
  ],
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;em&gt;Dockerize&lt;/em&gt; mongodb &amp;amp; &lt;em&gt;Client Tools&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Selanjutnya membuat &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;docker-compose.yaml&lt;/strong&gt; pada &lt;em&gt;directory root&lt;/em&gt; projek. Untuk aplikasi di sini tidak disertakan proses &lt;em&gt;dockerize&lt;/em&gt;-nya, sehingga untuk melakukan &lt;em&gt;running&lt;/em&gt; aplikasi menggunakan perintah di &lt;u&gt;nodejs&lt;/u&gt;. Berikut potongan &lt;em&gt;code&lt;/em&gt; untuk melakukan &lt;em&gt;dockerize&lt;/em&gt;:&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.8'

services:
  mongodb:
    image: mongo:6.0
    container_name: mongodb-domingo
    environment:
      MONGO_INITDB_DATABASE: '${DB_NAME}'
      MONGO_INITDB_ROOT_USERNAME: '${DB_USER}'
      MONGO_INITDB_ROOT_PASSWORD: '${DB_PASSWORD}'
    volumes:
      - ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
      - mongo_vol:/data/db
    ports:
      - ${DB_PORT:-27017}:27017
    networks:
      - domingo
    healthcheck:
      test: echo 'db.runCommand("ping").ok | mongo localhost:27017/test --quiet'
      interval: 1m
      timeout: 10s
      retries: 3
    restart: always

  mongo-express:
    image: mongo-express
    container_name: mongo-express-domingo
    restart: always
    environment:
      ME_CONFIG_MONGODB_SERVER: mongodb-domingo
      ME_CONFIG_MONGODB_AUTH_DATABASE: '${DB_NAME}'
      ME_CONFIG_MONGODB_AUTH_USERNAME: '${DB_USER}'
      ME_CONFIG_MONGODB_AUTH_PASSWORD: '${DB_PASSWORD}'
    ports:
      - 8081:8081
    networks:
      - domingo
    depends_on:
      - mongodb

networks:
  domingo:
    driver: bridge
volumes:
  mongo_vol:
    driver: local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Image docker&lt;/em&gt; &lt;u&gt;mongodb&lt;/u&gt; yang digunakan adalah &lt;a href="https://hub.docker.com/layers/library/mongo/6.0/images/sha256-e0b1614551474ee2f3c3ef7c9706b5e19f2107aa36b73c910522af9fa8eb756e?context=explore" rel="noopener noreferrer"&gt;mongo:6.0&lt;/a&gt;. Sedangkan &lt;em&gt;Image docker&lt;/em&gt; &lt;u&gt;mongodb&lt;/u&gt; &lt;em&gt;client tools&lt;/em&gt; (mongo-express) menggunakan &lt;a href="https://hub.docker.com/_/mongo-express" rel="noopener noreferrer"&gt;mongo-express&lt;/a&gt;. Di dalam &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;docker-compose.yaml&lt;/strong&gt; sudah menggunakan &lt;em&gt;env value&lt;/em&gt; secara otomatis, karena &lt;em&gt;default&lt;/em&gt;-nya membaca &lt;em&gt;value&lt;/em&gt; jika ada &lt;em&gt;file&lt;/em&gt; &lt;strong&gt;.env&lt;/strong&gt; pada direktori yang sama.&lt;/p&gt;

&lt;p&gt;Perintah yang digunakan untuk menjalankan proses &lt;em&gt;dockerize&lt;/em&gt; adalah &lt;code&gt;docker-compose up -d&lt;/code&gt;. Otomatis akan melakukan &lt;em&gt;download&lt;/em&gt; sekaligus &lt;em&gt;build&lt;/em&gt; dan menjalankannya. Untuk mematikan &lt;em&gt;running&lt;/em&gt; proses &lt;u&gt;docker&lt;/u&gt; adalah &lt;code&gt;docker-compose down&lt;/code&gt;. Disarankan untuk mempunyai pengetahuan &lt;em&gt;basic&lt;/em&gt; terkait &lt;u&gt;docker&lt;/u&gt;, sehingga dapat memahami dan melakukan &lt;em&gt;handle&lt;/em&gt; terhadap proses &lt;u&gt;docker&lt;/u&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Melakukan &lt;em&gt;test&lt;/em&gt; menggunakan postman
&lt;/h2&gt;

&lt;p&gt;Sebelum melakukan pengetesan, pastikan &lt;em&gt;docker container&lt;/em&gt; telah dijalankan dan aplikasi todo-nya. Pastikan &lt;u&gt;mongodb&lt;/u&gt; &lt;em&gt;client tools&lt;/em&gt; berhasil dijalankan dengan mengaksesnya melalui &lt;em&gt;browser&lt;/em&gt; seperti berikut:&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%2Fcvysgd4wxg02en1ndlkb.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%2Fcvysgd4wxg02en1ndlkb.png" alt="mongo_1" width="800" height="223"&gt;&lt;/a&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%2Fu3ypmi124eyr50gz4rt6.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%2Fu3ypmi124eyr50gz4rt6.png" alt="mongo_2" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Untuk hasil &lt;em&gt;test&lt;/em&gt; dari &lt;em&gt;get list&lt;/em&gt; todo di &lt;u&gt;postman&lt;/u&gt; sebagai berikut:&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%2Fkqrck8xmssznwpmxf1o2.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%2Fkqrck8xmssznwpmxf1o2.png" alt="mongo_3" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Untuk hasil &lt;em&gt;test&lt;/em&gt; dari tambah data todo di &lt;u&gt;postman&lt;/u&gt; seperti berikut:&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%2Fvhkl95h9zab9i98eintl.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%2Fvhkl95h9zab9i98eintl.png" alt="postman_1" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Selanjutnya penggunaan &lt;u&gt;docker&lt;/u&gt; bergantung berdasarkan improvisasi masing-masing sesuai kebutuhan. Untuk &lt;em&gt;source code&lt;/em&gt; lengkapnya bisa dicek &lt;a href="https://github.com/mohammadanang/domingo" rel="noopener noreferrer"&gt;di sini&lt;/a&gt;. Sekian.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Credits:&lt;br&gt;
Image cover by &lt;a href="https://unsplash.com/@rubaitulazad" rel="noopener noreferrer"&gt;Rubaitul Azad&lt;/a&gt; on &lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Support me on:&lt;br&gt;
&lt;a href="https://saweria.co/angm182" rel="noopener noreferrer"&gt;saweria&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;&lt;a href="https://anangm182.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fforthebadge.com%2Fimages%2Fbadges%2Fpowered-by-black-magic.svg" alt="my-site" width="259" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>mongodb</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
