Software Architecture

Muhammad Ardivan
7 min readApr 27, 2020

--

http://patorjk.com

Catatan: Tulisan ini dibuat sepenuhnya dalam rangka kegiatan mata kuliah PPL. Segala isi dari artikel ini tidak menjamin kelengkapan dan keutuhan sebagai pedoman untuk diimplementasikan dalam suatu proyek.

Arsitektur Sistem Informasi Praktikum (SIP)

Sistem Informasi Praktikum dibangun dengan arsitektur semi — microservice. Alasan menggunakan microservice karena proyek kami berisi 10 orang (2 kelompok) sehingga untuk mempercepat iterasi pembuatan produk, continuous deployment, dan produktifitas developer rencana untuk beralih ke microservice menjadi pilihan pertama, meskipun pada awal-awal Setup agak sulit karena perbedaan-perbedaan pendapat mengenai arsitektur dan lain-lain.

Selanjutnya, bentuk dari arsitektur proyek Sistem Informasi Praktikum adalah sebagai berikut.

Pada bagian Frontend kami menggunakan React JS, Backend menggunakan Django Rest Framework, Nginx sebagai Reverse Proxy dan Load Balancer, SSO sebagai auth third party yang disediakan Universitas Indonesia, dan Relational Database yang digunakan PostgreSQL karena memiliki banyak support + tim kami sudah cukup mengenal karena pernah menggunakan itu sebelumnya. Lalu setelah melihat arsitekur tersebut bagaimana peran Docker dalam mengkontainerisasi servis backend kami? Jadi apa itu Docker sebenarnya?

Apa itu Docker?

Docker adalah suatu alat yang dapat mereduksi gap antara Development dan Deployment pada fase iterasi Software Development.

Sebagai contoh saja, misal kita ingin menyesuaikan kode yang berjalan di mesin kita, asumsi teman Anda mengerjakan di Linux dan yang lain menggunakan Windows. Lalu salah satu dari anggota tadi memiliki problem seperti dependencies, setup database, line-break (linter), dan masalah lainnya. Proses ini tentunya akan memakan waktu sehingga produktifitas kemungkinan mengalami penurunan. Mungkin salah satu yang terfikirkan adalah menggunakan VM (VirtualMachine), tapi sorry bro susah dan repot kalau setup VM + memakan resource cukup besar untuk server.

Kenapa Docker?

Sebenernya banyak jenis-jenis container , seperti CRI-O, Podman, Docker, LXD, dan lain-lain. Namun, kali ini kami menggunakan Docker karena sudah cukup populer dan memiliki banyak support.

Lalu kenapa Docker? dibandingkan VM, Docker lebih ringan karena Docker tidak mengcopy seluruh bagian operasi sistem. Docker menggunakan beberapa instance dari hal-hal di Linux seperti namespace Linux (etc, mount, net, pid) sehingga ukuran umumnya lebih kecil dibandingkan VM.

Arsitektur Docker

Docker berjalan independen dan terisolasi sehingga tidak menginterupsi proses lain. Oleh karena itu, Docker dapat dijalankan sebanyak mungkin (tetapi tetap melihat resource server OS yang sedang berjalan).

Bagaimana Docker diimplementasikan pada proyek?

Setelah docker diinstall, langkah selanjutnya adalah mendefinisikan project tersebut menjadi suatu Docker Image.

Docker image adalah ekivalen dengan istilah “snapshot” pada virtual machine. Docker image berisi file proyek yang ingin di-execute dan nantinya siap dijalankan pada suatu container. Docker images bersifat immutable yang artinya tidak dapat dimodifikasi, namun bisa diduplikasi dan dibagikan atau dihapus. Positifnya jika ada perubahan atau ingin melakukan rollback (kembali ke versi sebelum), image tadi masih terdapat disana dan dapat digunakan kembali. Berikut langkah-langkahnya

Pertama, siapkan Dockerfile dan definisikan bagaimana aplikasi tersebut siap di-execute pada saat perintah docker dijalankan ketika runtime.

# DockerfileFROM python:3.8ENV PYTHONUNBUFFEREDENV PYTHONDONTWRITEBYTECODE 1RUN mkdir /appWORKDIR /appCOPY requirements.txt /app/RUN pip install -r requirements.txtCOPY . /app/

Langkah selanjutnya, pastikan posisi tempat path dari proyek kita berada, dan build image tersebut dengan menjalankan perintah

docker build -t <nama-image>:<tag> .

Pada proyek kami nama dan tag dari image yang di build adalah

// berada pada path root project "."docker build -t mkppl-backend:latest .

Setelah itu, kita jalankan container (dari image) dengan perintah :

docker run -p 8000:8000 mkppl-backend:latest

Deployment dengan docker-compose.yml

Ketika kita dihadapkan untuk melakukan serve suatu aplikasi dengan berbagai stacks yang terikat, maka docker compose dapat membantu mendefinisikan stacks apa saja yang dapat di-link ke aplikasi yang bersangkutan. Stacks disini sudah berupa container-container untuk memprovide multi container service.

docker-compose image

Disini kelompok kami menggunakan PostgreSQL sebagai DBMS dan Django sebagai Backend nya pada lingkungan staging, namun sebelum di serve ke staging, saya melakukan test terlebih dahulu di lingkungan development, lalu docker compose hadir untuk membantu hal itu. Kenapa memakai docker dan docker-compose? karena saya malas melakukan instalasi + bisa mengganggu dependensi lain pada PC Host.

Tahapan-tahapan yang perlu dilakukan untuk menggunakan docker compose:

  1. Pastikan image dari PostgreSQL atau DBMS(MySQL, MariaDB, dll) sudah ada atau di-define di docker-compose.yml .
  2. Definisikan Dockerfile dari aplikasi seperti penjelasan sebelumnya.
  3. Definisikan docker-compose.yml, isinya berupa environment yang dibutuhkan untuk masing-masing service. Service yang digunakan kali ini db (database-PostgreSQL) dan web (backend-django).

Berikut adalah docker-compose.yml proyek kelompok kami

version: "3.7"
services:
db:
image: postgres
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "5432"
volumes:
- ./db_backend:/var/lib/postgresql/data/
networks:
- backend
web:
build: .
command: python3 manage.py runserver 0.0.0.0:9000 --settings=sip.settings.staging
volumes:
- .:/app
- ./sip/settings/static:/app/static
environment:
SECRET_KEY: ${SECRET_KEY}
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASS: ${DB_PASS}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
ports:
- "8001:9000"
depends_on:
- db
networks:
- backend
networks:
backend:
driver: bridge

docker-compose.yml memerlukan notasi-notasi untuk mendefinisikan apa saja yang dibutuhkan seperti services dan networks.

Pada servis db kita lihat port yang didefinisikan adalah 5432 (default) dan volume database di mount dari /var/lib/postgresql/data ke /db_backend (lokasi di host PC).

Selanjutnya adalah servis web, servis diatas mengekspos port dari dalam (docker), yaitu port 9000 dan di binding keluar (public) dengan port 8001. Tidak lupa untuk menyiapkan .env file untuk menyimpan environment variables sehingga siap di load oleh konfigurasi settings dari servis web backend-django. Setiap environment variables yang di-load menggunakan notasi${NAMA_ENV} .

Lalu bagaimana environment tersebut dapat dilihat?

Tentunya ada file config yang bernama .env . File tersebut akan dibaca oleh docker-compose dan secara otomatis variable yang akan dibutuhkan akan disesuaikan. Pada implementasi kami menggunakan gitlab sebagai version control untuk mem-passing variable tersebut.

environment variables

Yang terakhir adalah context network disini menggunakan bridge agar container tadi dapat berkomunikasi dalam network yang sama (untuk development).

Setelah file-file yang dibutuhkan telah ada, maka langkah selanjutnya adalah menjalankan perintah sebagai berikut:

  1. docker-compose build
  2. docker-compose up -d (daemon), disini untuk serve up aplikasi

Jika servis aplikasi sudah berhasil di up, maka selanjutnya jalankan perintah docker ps untuk melihat status container, kurang lebih perintah akan menghasilkan tampilan seperti ini

Melihat status container

Setelah itu, kita akses container tersebut untuk menjalankan migrate pada aplikasi backend-django tersebut. Perintah untuk mengeksekusinya adalah

docker exec -it <container_id> /bin/bash

Jika sudah masuk environment container, jalankan perintah

python manage.py makemigrations dan python manage.py migrate

Kita bisa akses servis backend tersebut pada port 8001

Servis backend

Jika sudah selesai, maka servis dapat dimatikan dengan perintah

docker-compose down

Continuous Deployment

Pada bagian sebelumnya kami masih melakukan hal manual, yaitu dengan masuk ke dalam container dan melakukan up service dari dalam.

Oleh karena itu kami menerapkan yang namanya continuous deployment agar bisa mempercepat iterasi pada pengembangan sistem di produksi.

Sudah diberitahukan diawal bahwa kami menggunakan gitlab sebagai bagian dari CD itu sendiri, maka script .gitlab-ci.ymldiperlukan didalamnya. Berikut adalah script yang kami gunakan:

.gitlab-ci.yml

Yang perlu diperhatikan dari script diatas adalah pada bagian job deploy_vm disini kami menggunakan Ubuntu sebagai base image dan jika dilihat perlu scp dan ssh dalam proses deploy. Kembali ke masalah .env tadi, jadi untuk mengirimkan berkas .env agar dapat dibaca oleh docker-compose.yml yaitu dengan mendeskripsikan before_script dan melakukan echo environment variables ke .env .

Setelah itu, .env akan di copy ke proxy server (dalam kasus ini kami tidak bisa langsung ke server tujuan untuk deploy) dan selanjutnya file .env di copy lagi ke server tujuan setelah melakukan ssh ke proxy server.

Jika sudah masuk ke server tujuan langkah selanjutnya adalah masuk ke directory yang diinginkan dan kita melakukan pull dengan git. Jika sudah masuk, maka service dimatikan, di-build, dan di-up lagi dengan perintah docker-compose.

Command:

cd ~/Documents/mkppl-si-penilaian-dan-evaluasi-praktikum && git pull origin staging && docker-compose down && docker-compose build && docker-compose up -d

Bagaimana jika ingin deploy pada Cloud? seperti AWS atau Azure

Sebenarnya tahapan yang diperlukan mirip-mirip, jika pada Cloud atau VPS biasa kita menggunakan jenkins, travis-ci, gitlab-ci sebagai helper CI/CD tentunya akan ada perbedaan config dan sintaks, namun konsep untuk melakukan deploy adalah sama yaitu dari manual kita otomasi. Mungkin pada Cloud akan agak sedikit berbeda karena ada masalah konfigurasi yang perlu di-setting lebih lanjut, seperti IaM, Ingress/Egress, dll. Untuk lebih lanjut bisa dibaca pada dokumentasi masing-masing provider.

Sekian artikel mengenai Software Architecture, semoga bermanfaat.

Reference:

https://dev.to/matthias/getting-started-with-docker-compose-4gg9

https://searchitoperations.techtarget.com/definition/Docker-image

--

--