Deployment Aplikasi Dengan Docker
Hello, world!
Pernahkah kita bertanya-tanya bagaimana cara aplikasi web dapat diakses oleh banyak orang melalui internet? Apa saja yang diperlukan untuk melakukannya? Jika masih bertanya-tanya mengenai hal tersebut, kita perlu berkenalan dengan deployment.
Apa Itu Deployment?
Seorang programmer yang sudah menulis kode sebuah aplikasi web mungkin tidak asing dengan localhost. Localhost bisa dibilang sebagai tempat yang bisa dikunjungi saat programmer menjalankan kodenya di dalam komputernya secara lokal. Ketika semuanya sudah berjalan dengan baik di dalam komputernya, dan sudah bisa dikunjungi melalui localhost, biasanya programmer ingin menunjukkannya pada dunia. Programmer tersebut tentunya ingin agar setiap orang yang mengetahui keberadaan website miliknya dapat mengaksesnya melalui internet. Ketika seorang programmer melakukan kegiatan tersebut, itulah yang disebut dengan deployment.
Terdapat berbagai cara yang dapat dipilih oleh seorang programmer untuk men-deploy website-nya. Di antaranya:
- Programmer tersebut dapat memiliki setidaknya sebuah komputer yang terkoneksi pada jaringan internet, dan mengatur routing-nya (melalui router) sehingga dapat diakses oleh banyak orang. Opsi ini mungkin terhalang oleh biaya untuk memiliki komputer tersebut yang cukup cepat dan kuat menerima berbagai request yang dikirimkan oleh pengguna nantinya.
- Tidak punya komputer seperti itu? Tidak masalah. Zaman sekarang, ada banyak penyedia layanan hosting di luar sana yang menyediakan komputer tersebut dengan harga yang terjangkau dan kualitas yang baik. Kita juga dapat melakukan kustomisasi terhadap komputer tersebut, yang biasanya kita sebut server, dengan lebih leluasa.
- Bisa juga dengan menggunakan penyedia layanan platform as a service, seperti Heroku, yang sudah punya standar tersendiri untuk melakukan deployment, sehingga programmer tidak perlu mengatur komputer server-nya sendiri dan hanya fokus pada deployment-nya.
Isu Pada Deployment
Terdapat beberapa isu yang bisa dirasakan programmer terkait deployment. Terutama ketika suatu aplikasi web dikerjakan bersama-sama, bisa saja pengaturan sebuah komputer milik seorang programmer berbeda dengan milik programmer lainnya, sehingga menyebabkan kode yang sudah bisa dijalankan dan diakses melalui localhost di satu komputer belum tentu bisa diakses di komputer lainnya.
Apakah hal tersebut mungkin saja terjadi dengan komputer server? Mungkin saja! Jika kita memilih opsi pertama atau kedua pada contoh pilihan teknik deployment tadi, mungkin saja kita mengalami masalah kompatibilitas tersebut. Jika kita memilih opsi ketiga, bisa saja ada suatu fitur yang agak terbatas. Mungkin banyak orang tidak masalah dengan hal tersebut, tetapi bagi orang-orang yang ingin melakukan kustomisasi lebih, tentu saja mereka akan lebih memilih opsi kedua.
Docker To The Rescue!
Dari permasalahan di atas, docker hadir untuk menjembatani masalah kompatibilitas tersebut. Docker adalah open source platform yang digunakan untuk menjalankan aplikasi di dalam container. Perumpamaan sederhana yang bisa saya katakan mengenai container adalah seperti sebuah komputer lain yang dijalankan di atas komputer kita, namun dengan kemampuan yang bisa kita atur seminimal mungkin agar tidak perlu banyak hal yang diatur, namun tetap dapat menunjang aplikasi kita agar berjalan dengan baik. Dengan menjalankan aplikasi dalam container, kita bisa menjalankan program yang kita buat dalam environment yang sama, dan tidak akan muncul masalah “aplikasi ini bekerja di komputerku, mengapa di komputermu tidak bisa?”
Membuat Docker Image
Dalam praktiknya, aplikasi dapat kita paketkan dalam suatu bentuk yang kita sebut sebagai docker image. Image inilah yang akan diletakkan di server untuk di-deploy. Image ini juga dapat dibagikan ke orang lain dan dijalankan olehnya di komputernya, dan tidak akan mengalami masalah kompatibilitas selama image tersebut tidak diubah. Contoh dari image dapat dilihat di docker registry (tempat kumpulan docker image yang dapat diakses) semisal dockerhub.
Salah satu fitur dari docker adalah kita bisa melakukan ekstensi pada image yang sudah ada. Sehingga kita bisa menggunakan container yang sudah dibuat orang (seperti image ubuntu
, golang
, python
, dsb.) untuk membangun image aplikasi kita.
Cara membuat docker image juga sangat sederhana. Tentunya, yang pertama adalah kita perlu meng-install docker pada sistem kita. Panduan instalasi dapat merujuk pada dokumentasi dari docker.
Kemudian, kita dapat membuat satu file bernama Dockerfile
pada direktori proyek kita. Sebagai contoh, jika saya memiliki aplikasi python
sederhana (bukan aplikasi web) dengan nama file app.py
seperti berikut:
print("Hello, world!")
Kemudian saya ingin mengaksesnya dengan protokol TCP, maka saya mempunyai beberapa pilihan, contohnya:
- Karena sudah belajar mengenai socket di mata kuliah Jaringan Komputer, maka saya bisa membuat program untuk menerima koneksi yang masuk dan menjalankan program tadi.
- Menggunakan aplikasi yang sudah ada seperti
socat
, saya hanya perlu memanggilnya dengan perintah berikut:
socat TCP-LISTEN:5000,reuseaddr,fork EXEC:"python3 app.py"
Setelah itu, saya bisa mengaksesnya lewat TCP. Contohnya lewat browser (karena protokol HTTP juga based on TCP).
Kita sudah bisa melakukannya secara manual, sekarang kita ingin mencoba memasukkannya sebagai docker image. Isi dari Dockerfile
adalah sebagai berikut:
FROM ubuntu:18.04
RUN apt-get update && apt-get -y install python3 socat python3-pip
COPY app.py ./
EXPOSE 5000CMD socat TCP-LISTEN:5000,reuseaddr,fork EXEC:"python3 app.py"
FROM
menunjukkan image lain yang kita gunakan sebagai base bagi aplikasi kita. Kemudian RUN
akan menjalankan command selayaknya saat kita menjalankannya melalui terminal. COPY
akan menyalin file yang kita punya di direktori komputer kita ke dalam container. EXPOSE
akan membuka port sehingga mengizinkan traffic masuk ke dalam container. Kemudian, CMD
akan menjadi command yang kita gunakan untuk menjalankan aplikasi kita. Perlu dicatat bahwa CMD
hanya boleh ada satu di dalam Dockerfile
, dan fungsinya sebagai perintah yang harus dijalankan (thread ini di stackoverflow sudah sangat menjelaskan).
Selain yang di atas, terdapat opsi lain yang dapat digunakan melalui Dockerfile
. Selengkapnya dapat dilihat melalui dokumentasi melalui Dockerfile.
Setelah itu, kita hanya perlu memanggil:
docker build .
Dan image berhasil dibuat. Kita bisa periksa dengan perintah docker images
Terdapat beberapa opsi lain yang dapat kita gunakan saat build
, seperti memberi nama dengan menambahkan flag -t
, dan lain sebagainya. Selengkapnya dapat dilihat pada dokumentasi.
Deployment dengan Docker
Setelah berhasil membuat image, menjalankan docker hanya semudah menjalankan command ini pada komputer server. Contohnya kita ingin menjalankan image yang baru saja kita buat dengan ID 6c8b1155e81c
. Kita bisa menjalankan image tersebut dengan perintah berikut:
docker run 6c8b1155e81c
Kemudian container-nya muncul. Dapat kita cek dengan docker ps
.
Perlu diperhatikan juga bahwa kita bisa memakai nama dari image tersebut. Tetapi pada kasus ini, image-nya belum diberi nama, sehingga harus pakai ID. Kita juga bisa menambahkan beberapa opsi pada command di atas, seperti:
- Port forwarding dari port container (5000) ke port host (8000).
docker run -p 8000:5000 6c8b1155e81c
- Run dengan detach, kita butuh ini agar proses dapat berjalan di background.
docker run -d 6c8b1155e81c
- Beri nama untuk container
docker run --name container_baru 6c8b1155e81c
- Dan lain sebagainya yang bisa dilihat di dokumentasi.
Selain dengan docker run
, terdapat beberapa cara lain untuk deployment seperti menggunakan docker-compose
, atau lebih jauh melalui instrumentasi dengan kubernetes untuk melakukan scaling. Tetapi untuk hal tersebut akan saya bahas di lain waktu.
Contoh Lain Dengan Golang
Contoh lainnya yang lebih praktikal ada pada mata kuliah Proyek Perangkat Lunak yang saya ambil ketika tulisan ini ditulis (Februari 2022). Pada mata kuliah ini, salah satu hal yang saya kerjakan adalah menyusun CI/CD dan teknik deployment untuk sebuah aplikasi web dengan bahasa Go ke sebuah server. Dockerfile
yang saya buat cukup sederhana. Idenya berawal dari sini:
FROM golang:1.17-alpine AS build
WORKDIR /build
COPY ./ ./
RUN go mod download
RUN go build -o /app
EXPOSE 8080
ENTRYPOINT ["/app"]
Dockerfile
ini akan mengunduh dependensi yang dibutuhkan untuk melakukan kompilasi, mengekspos port 8080 agar mengizinkan traffic masuk, lalu menjalankan aplikasi app
yang merupakan hasil kompilasi dari kode Go milik kita.
Jika hanya mengandalkan ini, ada satu masalah, yaitu ukuran image yang ternyata sampai sekitar 700MB. Untuk mengakalinya, terdapat teknik lain yang dapat digunakan, yaitu multistage build.
FROM golang:1.17-alpine AS build
WORKDIR /build
COPY ./ ./
RUN go mod download
RUN CGO_ENABLED=0 go build -o /appFROM gcr.io/distroless/base-debian10
WORKDIR /
COPY --from=build /app /app
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/app"]
Teknik ini melakukan build pada sebuah container, kemudian hanya hasil kompilasinya yang diletakkan pada image lain, sehingga image untuk build dapat dihapus, dan image terakhir yang dihasilkan bahkan hanya sekitar 57 MB! Selengkapnya mengenai multistage build dapat dibaca melalui dokumentasi.
Catatan: Dockerfile di atas belum sepenuhnya lengkap sesuai dengan yang saya kerjakan. Akan saya bahas di kesempatan lain mengenai teknik yang digunakan untuk deployment aplikasi tersebut.
Penutup
Dengan memahami ide dasar pembuatan image yang sederhana, kita pun akan bisa untuk membuat image yang lebih rumit. Kegunaannya pun sangat banyak. Sebagai contoh, CTF COMPFEST (kompetisi Capture The Flag yang diselenggarakan mahasiswa Fasilkom UI di mana saya terlibat dalam penyusunan soalnya pada tahun 2020-2021) juga menggunakan docker untuk deployment. Contohnya bisa dilihat di sini.
Demikianlah yang dapat saya sampaikan kali ini. Semoga bermanfaat 😊.