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:
- Keamanan: Arsitektur terdistribusi mengurangi risiko satu titik kegagalan dan mempersulit peretas untuk memanipulasi hasil.
- Transparansi: Log dan catatan audit yang terdesentralisasi meningkatkan kepercayaan dan akuntabilitas.
- Skalabilitas: Mudah untuk menambah atau mengurangi sumber daya sesuai kebutuhan, memastikan aplikasi dapat menangani lonjakan partisipasi.
- Aksesibilitas: Pemilih dapat berpartisipasi dari mana saja dengan koneksi internet, meningkatkan partisipasi secara keseluruhan.
- 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:
- Aplikasi Web Pemungutan Suara (Voting App): Antarmuka pengguna yang memungkinkan pemilih untuk memilih kandidat.
- Aplikasi Hasil (Result App): Menampilkan hasil pemungutan suara secara real-time.
- Redis: Database dalam memori untuk menyimpan suara sementara.
- PostgreSQL: Database persisten untuk menyimpan hasil akhir pemungutan suara.
- Worker: Proses latar belakang yang mengambil suara dari Redis dan menyimpannya ke PostgreSQL.
Prasyarat
Sebelum kita mulai, pastikan Anda memiliki prasyarat berikut terpasang:
- Docker: Unduh dan pasang Docker.
- Docker Compose: Biasanya disertakan dengan Docker Desktop; jika tidak, pasang Docker Compose.
- Python 3: Untuk menjalankan aplikasi Python.
- pip: Manajer paket untuk Python.
- 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.
- Buat direktori proyek:
mkdir voting-app cd voting-app
- (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 }}
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.
- Voting : Buka `http://localhost:5000` dan lakukan voting untuk setiap kandidat.
- Hasil : Buka `http://localhost:5001` untuk melihat hasil live.
- 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.
“`