Wednesday

18-06-2025 Vol 19

Building a Distributed Voting App with Docker: A Hands-On Guide

Membangun Aplikasi Pemungutan Suara Terdistribusi dengan Docker: Panduan Praktis

Di era digital ini, aplikasi pemungutan suara terdistribusi menjadi semakin penting untuk memastikan transparansi, keamanan, dan aksesibilitas dalam proses pengambilan keputusan. Docker, dengan kemampuannya untuk membuat wadah (container) aplikasi, menawarkan cara yang efisien dan portabel untuk mengembangkan dan menyebarkan aplikasi semacam itu. Dalam panduan praktis ini, kita akan menjelajahi cara membangun aplikasi pemungutan suara terdistribusi menggunakan Docker, dari awal hingga penyebaran.

Mengapa Aplikasi Pemungutan Suara Terdistribusi?

Sebelum kita masuk ke detail teknis, mari kita bahas mengapa aplikasi pemungutan suara terdistribusi menjadi solusi yang menarik:

  1. Keamanan: Arsitektur terdistribusi mengurangi risiko satu titik kegagalan dan mempersulit peretas untuk memanipulasi hasil.
  2. Transparansi: Log dan catatan audit yang terdesentralisasi meningkatkan kepercayaan dan akuntabilitas.
  3. Skalabilitas: Mudah untuk menambah atau mengurangi sumber daya sesuai kebutuhan, memastikan aplikasi dapat menangani lonjakan partisipasi.
  4. Aksesibilitas: Pemilih dapat berpartisipasi dari mana saja dengan koneksi internet, meningkatkan partisipasi secara keseluruhan.
  5. Biaya Efektif: Docker dan teknologi terkait memungkinkan pemanfaatan sumber daya yang efisien, mengurangi biaya infrastruktur.

Arsitektur Aplikasi Pemungutan Suara

Aplikasi pemungutan suara terdistribusi kita akan terdiri dari komponen-komponen berikut:

  1. Aplikasi Web Pemungutan Suara (Voting App): Antarmuka pengguna yang memungkinkan pemilih untuk memilih kandidat.
  2. Aplikasi Hasil (Result App): Menampilkan hasil pemungutan suara secara real-time.
  3. Redis: Database dalam memori untuk menyimpan suara sementara.
  4. PostgreSQL: Database persisten untuk menyimpan hasil akhir pemungutan suara.
  5. Worker: Proses latar belakang yang mengambil suara dari Redis dan menyimpannya ke PostgreSQL.

Prasyarat

Sebelum kita mulai, pastikan Anda memiliki prasyarat berikut terpasang:

  1. Docker: Unduh dan pasang Docker.
  2. Docker Compose: Biasanya disertakan dengan Docker Desktop; jika tidak, pasang Docker Compose.
  3. Python 3: Untuk menjalankan aplikasi Python.
  4. pip: Manajer paket untuk Python.
  5. Git: Untuk mengkloning repositori kode.

Langkah 1: Menyiapkan Lingkungan Pengembangan

Pertama, kita perlu membuat direktori untuk proyek kita dan mengkloning repositori kode (jika ada) atau membuat file yang diperlukan.

  1. Buat direktori proyek:
    mkdir voting-app
          cd voting-app
  2. (Opsional) Klon repositori kode:
    git clone [URL repositori]

Langkah 2: Membuat Dockerfile untuk Aplikasi Web Pemungutan Suara

Buat file bernama `Dockerfile` di direktori proyek Anda dengan konten berikut:

# Gunakan image dasar Python 3
  FROM python:3.9-slim-buster

  # Set direktori kerja
  WORKDIR /app

  # Salin persyaratan dependensi
  COPY requirements.txt .

  # Pasang dependensi
  RUN pip install --no-cache-dir -r requirements.txt

  # Salin kode aplikasi
  COPY . .

  # Set variabel lingkungan
  ENV FLASK_APP=app.py
  ENV FLASK_ENV=development

  # Ekspos port 5000
  EXPOSE 5000

  # Jalankan aplikasi
  CMD ["flask", "run", "--host=0.0.0.0"]
  

Penjelasan:

  • `FROM python:3.9-slim-buster`: Menggunakan image dasar Python 3 yang ringan.
  • `WORKDIR /app`: Menyetel direktori kerja di dalam wadah.
  • `COPY requirements.txt .`: Menyalin file `requirements.txt` ke wadah.
  • `RUN pip install …`: Memasang dependensi Python.
  • `COPY . .`: Menyalin semua kode aplikasi ke wadah.
  • `ENV …`: Menyetel variabel lingkungan untuk konfigurasi Flask.
  • `EXPOSE 5000`: Membuka port 5000 untuk akses eksternal.
  • `CMD …`: Menjalankan aplikasi Flask saat wadah dimulai.

Langkah 3: Membuat file `requirements.txt`

Buat file bernama `requirements.txt` dengan dependensi Python yang diperlukan:

Flask
  redis
  psycopg2-binary
  

Langkah 4: Membuat Kode Aplikasi Web Pemungutan Suara (app.py)

Buat file bernama `app.py` dengan kode berikut:

from flask import Flask, render_template, request, make_response, redirect, url_for
  import redis
  import os
  import uuid

  app = Flask(__name__)

  # Konfigurasi Redis
  redis_host = os.environ.get('REDIS_HOST') or 'redis'
  redis_port = int(os.environ.get('REDIS_PORT') or 6379)
  redis_db = int(os.environ.get('REDIS_DB') or 0)
  r = redis.Redis(host=redis_host, port=redis_port, db=redis_db)

  # Daftar pilihan kandidat
  kandidat = ["Kucing", "Anjing", "Burung"]


  @app.route('/', methods=['GET', 'POST'])
  def vote():
      voter_id = request.cookies.get('voter_id')
      if not voter_id:
          voter_id = uuid.uuid4().hex
      if request.method == 'POST':
          pilihan = request.form['pilihan']
          print(f"Pemilih {voter_id} memilih: {pilihan}")
          r.incr(pilihan)
          response = make_response(redirect(url_for('results')))
          response.set_cookie('voter_id', voter_id)
          return response
      return render_template('vote.html', kandidat=kandidat, voter_id=voter_id)


  @app.route('/results')
  def results():
      votes = {k: r.get(k).decode() if r.get(k) else 0 for k in kandidat}
      return render_template('results.html', votes=votes)

  if __name__ == '__main__':
      app.run(host='0.0.0.0', port=5000, debug=True)

Penjelasan:

  • Menggunakan Flask untuk membuat aplikasi web.
  • Terhubung ke Redis untuk menyimpan suara.
  • Menangani rute `/` untuk menampilkan formulir pemungutan suara dan menerima suara.
  • Menangani rute `/results` untuk menampilkan hasil pemungutan suara.

Langkah 5: Membuat Templat HTML (templates/vote.html dan templates/results.html)

Buat direktori `templates` di direktori proyek Anda dan buat dua file HTML:

templates/vote.html:


  
  
      Aplikasi Pemungutan Suara
  
  
      

Pilih Kandidat Anda

ID Pemilih: {{ voter_id }}

{% for kandidat in kandidat %}
{% endfor %}

templates/results.html:


  
  
      Hasil Pemungutan Suara
  
  
      

Hasil Pemungutan Suara

    {% for kandidat, votes in votes.items() %}
  • {{ kandidat }}: {{ votes }}
  • {% endfor %}

Langkah 6: Membuat Dockerfile untuk Aplikasi Hasil

Buat file bernama `Dockerfile` di direktori proyek Anda untuk aplikasi hasil. Struktur Dockerfile ini mirip dengan aplikasi voting, tetapi perbedaannya adalah bagaimana dia mengambil data dan menampilkannya.

# Gunakan image dasar Python 3
  FROM python:3.9-slim-buster

  # Set direktori kerja
  WORKDIR /app

  # Salin persyaratan dependensi
  COPY requirements.txt .

  # Pasang dependensi
  RUN pip install --no-cache-dir -r requirements.txt

  # Salin kode aplikasi
  COPY . .

  # Set variabel lingkungan
  ENV FLASK_APP=results_app.py
  ENV FLASK_ENV=development

  # Ekspos port 5001
  EXPOSE 5001

  # Jalankan aplikasi
  CMD ["flask", "run", "--host=0.0.0.0", "--port=5001"]
  

Langkah 7: Membuat Kode Aplikasi Hasil (results_app.py)

Buat file bernama `results_app.py` dengan kode berikut:

from flask import Flask, render_template
  import redis
  import os

  app = Flask(__name__)

  # Konfigurasi Redis
  redis_host = os.environ.get('REDIS_HOST') or 'redis'
  redis_port = int(os.environ.get('REDIS_PORT') or 6379)
  redis_db = int(os.environ.get('REDIS_DB') or 0)
  r = redis.Redis(host=redis_host, port=redis_port, db=redis_db)

  # Daftar pilihan kandidat
  kandidat = ["Kucing", "Anjing", "Burung"]

  @app.route('/')
  def results():
      votes = {k: r.get(k).decode() if r.get(k) else 0 for k in kandidat}
      return render_template('results.html', votes=votes)

  if __name__ == '__main__':
      app.run(host='0.0.0.0', port=5001, debug=True)

Perhatikan bahwa template HTML `results.html` sama dengan yang digunakan oleh aplikasi pemungutan suara.

Langkah 8: Membuat Dockerfile untuk Worker

Worker bertanggung jawab untuk mengambil suara dari Redis dan menyimpannya ke PostgreSQL. Buat file Dockerfile berikut:

FROM python:3.9-slim-buster

  WORKDIR /app

  COPY requirements.txt .
  RUN pip install --no-cache-dir -r requirements.txt

  COPY worker.py .

  CMD ["python", "worker.py"]
  

Langkah 9: Membuat Kode Worker (worker.py)

Berikut adalah kode untuk `worker.py`:

import redis
  import os
  import time
  import psycopg2

  # Konfigurasi Redis
  redis_host = os.environ.get('REDIS_HOST') or 'redis'
  redis_port = int(os.environ.get('REDIS_PORT') or 6379)
  redis_db = int(os.environ.get('REDIS_DB') or 0)
  r = redis.Redis(host=redis_host, port=redis_port, db=redis_db)

  # Konfigurasi PostgreSQL
  pg_host = os.environ.get('POSTGRES_HOST') or 'db'
  pg_port = int(os.environ.get('POSTGRES_PORT') or 5432)
  pg_user = os.environ.get('POSTGRES_USER') or 'postgres'
  pg_password = os.environ.get('POSTGRES_PASSWORD') or 'postgres'
  pg_db = os.environ.get('POSTGRES_DB') or 'postgres'


  def connect_to_postgres():
      conn = None
      while not conn:
          try:
              conn = psycopg2.connect(
                  host=pg_host,
                  port=pg_port,
                  user=pg_user,
                  password=pg_password,
                  database=pg_db
              )
              print("Terhubung ke PostgreSQL!")
          except psycopg2.Error as e:
              print(f"Gagal terhubung ke PostgreSQL: {e}")
              time.sleep(2)
      return conn


  conn = connect_to_postgres()
  cur = conn.cursor()

  # Membuat tabel jika belum ada
  cur.execute("""
      CREATE TABLE IF NOT EXISTS votes (
          id SERIAL PRIMARY KEY,
          kandidat VARCHAR(255),
          votes INTEGER
      )
  """)
  conn.commit()


  def get_votes_from_redis():
      kandidat = ["Kucing", "Anjing", "Burung"]
      votes = {}
      for k in kandidat:
          vote_count = r.get(k)
          votes[k] = int(vote_count.decode()) if vote_count else 0
      return votes


  def insert_votes_into_postgres(votes):
      for kandidat, vote_count in votes.items():
          cur.execute("INSERT INTO votes (kandidat, votes) VALUES (%s, %s)", (kandidat, vote_count))
      conn.commit()


  if __name__ == '__main__':
      while True:
          try:
              votes = get_votes_from_redis()
              insert_votes_into_postgres(votes)
              print("Menyimpan suara ke PostgreSQL:", votes)
          except Exception as e:
              print(f"Error: {e}")
          time.sleep(5) # Jeda 5 detik sebelum mengambil suara lagi
          r.flushall() # Hapus voting data di Redis setelah di pindahkan ke PostgreSQL
          print("Membersihkan Redis!")
  

Langkah 10: Membuat file `docker-compose.yml`

Buat file `docker-compose.yml` untuk mengatur dan menghubungkan semua layanan kita:

version: "3.9"
  services:
    redis:
      image: redis:alpine
      ports:
        - "6379:6379"

    db:
      image: postgres:13
      environment:
        POSTGRES_USER: postgres
        POSTGRES_PASSWORD: postgres
        POSTGRES_DB: postgres
      ports:
        - "5432:5432"
      volumes:
        - db_data:/var/lib/postgresql/data

    voting-app:
      build: .
      ports:
        - "5000:5000"
      depends_on:
        - redis

    result-app:
      build: .
      ports:
        - "5001:5001"
      depends_on:
        - redis
        - db
      environment:
        - REDIS_HOST=redis
        - POSTGRES_HOST=db

    worker:
      build: .
      depends_on:
        - redis
        - db
      environment:
        - REDIS_HOST=redis
        - POSTGRES_HOST=db

  volumes:
    db_data:
  

Penjelasan:

  • Mendefinisikan lima layanan: `redis`, `db`, `voting-app`, `result-app`, dan `worker`.
  • Menggunakan image Docker resmi untuk Redis dan PostgreSQL.
  • Membangun image Docker untuk aplikasi web pemungutan suara, aplikasi hasil, dan worker dari Dockerfile kita.
  • Mengekspos port untuk aplikasi web pemungutan suara dan aplikasi hasil.
  • Menentukan dependensi antar layanan untuk memastikan urutan startup yang benar.
  • Menggunakan volume bernama (`db_data`) untuk menyimpan data PostgreSQL secara persisten.

Langkah 11: Membangun dan Menjalankan Aplikasi

Buka terminal di direktori proyek Anda dan jalankan perintah berikut:

docker-compose up --build

Ini akan membangun image Docker dan memulai semua layanan yang ditentukan dalam file `docker-compose.yml`. Anda dapat mengakses aplikasi web pemungutan suara di `http://localhost:5000` dan aplikasi hasil di `http://localhost:5001`.

Langkah 12: Verifikasi Hasil

Setelah aplikasi berjalan, lakukan beberapa pemungutan suara melalui aplikasi pemungutan suara dan periksa aplikasi hasil untuk melihat hasil yang diperbarui secara real-time. Anda juga dapat memverifikasi bahwa data disimpan dengan benar di database PostgreSQL.

  1. Voting : Buka `http://localhost:5000` dan lakukan voting untuk setiap kandidat.
  2. Hasil : Buka `http://localhost:5001` untuk melihat hasil live.
  3. PostgreSQL : Terhubung ke database PostgreSQL dan jalankan query `SELECT * FROM votes;` untuk melihat suara yang disimpan.

Langkah 13: Menguji Ketahanan Sistem

Salah satu manfaat utama dari aplikasi terdistribusi adalah ketahanan. Untuk menguji ini, Anda dapat secara acak menghentikan salah satu container (misalnya, Redis atau Worker) dan memastikan bahwa sistem pulih secara otomatis. Docker Compose harus secara otomatis me-restart container yang gagal, dan aplikasi harus melanjutkan operasinya tanpa kehilangan data (terutama karena Worker akan terus memproses antrian dari Redis dan menyimpan data ke PostgreSQL setelah di-restart).

Langkah 14: Skalabilitas

Aplikasi ini dapat ditingkatkan skalanya dengan mudah menggunakan Docker Compose. Misalnya, untuk meningkatkan jumlah worker, Anda dapat memodifikasi file `docker-compose.yml` dan menjalankan `docker-compose up –scale worker=3`.

Langkah 15: Monitoring dan Logging

Untuk aplikasi produksi, penting untuk menerapkan pemantauan dan pencatatan log yang tepat. Anda dapat menggunakan alat seperti Prometheus dan Grafana untuk memantau kinerja aplikasi dan log Docker untuk mendiagnosis masalah.

Praktik Terbaik untuk Aplikasi Pemungutan Suara Terdistribusi

Saat membangun aplikasi pemungutan suara terdistribusi, pertimbangkan praktik terbaik berikut:

  • Keamanan: Gunakan protokol aman (HTTPS) untuk semua komunikasi, terapkan autentikasi dan otorisasi yang kuat, dan lindungi dari serangan umum seperti injeksi SQL dan skrip lintas situs (XSS).
  • Audit: Pertahankan jejak audit yang komprehensif dari semua aktivitas pemungutan suara untuk memastikan akuntabilitas.
  • Kriptografi: Gunakan teknik kriptografi untuk melindungi data sensitif, seperti identitas pemilih dan suara.
  • Uji Coba: Lakukan uji coba dan pengujian penetrasi yang ketat untuk mengidentifikasi dan mengatasi kerentanan.
  • Pencadangan dan Pemulihan: Terapkan strategi pencadangan dan pemulihan yang komprehensif untuk mencegah kehilangan data.
  • Skalabilitas: Desain aplikasi untuk diskalakan secara horizontal untuk menangani lonjakan lalu lintas.
  • Pemantauan: Pantau kinerja aplikasi dan lacak metrik utama untuk mengidentifikasi dan mengatasi masalah.

Kesimpulan

Dalam panduan ini, kita telah menjelajahi cara membangun aplikasi pemungutan suara terdistribusi menggunakan Docker. Kami membahas arsitektur, menyiapkan lingkungan pengembangan, membuat Dockerfile, menulis kode aplikasi, dan menyebarkan aplikasi menggunakan Docker Compose. Dengan mengikuti langkah-langkah ini, Anda dapat membuat aplikasi pemungutan suara terdistribusi yang aman, transparan, dan dapat diskalakan yang dapat digunakan untuk berbagai keperluan.

Ingatlah untuk selalu memprioritaskan keamanan, audit, dan skalabilitas saat membangun aplikasi pemungutan suara. Dengan perencanaan dan implementasi yang cermat, Anda dapat menciptakan sistem pemungutan suara yang meningkatkan kepercayaan dan partisipasi dalam proses pengambilan keputusan.

“`

omcoding

Leave a Reply

Your email address will not be published. Required fields are marked *