Menu Close

Category: Web Deployment

Menjalankan Aplikasi Tanpa Instalasi dengan Docker

Ingin mencoba nginx, ruby, atau golang tapi males repot menginstal dan menghapusnya nanti? Dengan Docker, kita bisa langsung menjalankan aplikasi tanpa harus pusing dengan proses instalasi atau bersih-bersih setelahnya.

Mengunduh image bikinan orang lain

image adalah semacam "installer". Dari image ini, kita bisa menginstallnya sebagai container, yaitu aplikasi yang siap dijalankan. Kita bisa membuat image sendiri, tapi konfigurasi dan proses build membutuhkan waktu lama. Dengan kepakaran yang terbatas, lebih praktis memanfaatkan image bikinan orang lain.

image yang telah dibangun oleh orang lain dapat diperoleh dari Docker Hub. Semacam toko aplikasi atau "App Store" yang di dalamnya telah diorganisasi dengan rapi. Misalnya, kategori "Language & Frameworks" berisikan image dari bahasa php atau ruby yang lumayan ribet jika menginstall secara manual.

Namun, berkat docker kita bisa dengan mudah gunakan image tersebut dengan docker pull NAMA_IMAGE. Contohnya:

docker pull ruby

Kemudian mengecek daftar image dengan perintah

docker image ls
REPOSITORY      TAG               IMAGE ID       CREATED       SIZE
ruby            latest            dc4e58bf5fd5   5 weeks ago   1.46GB

Menghapus image

Image yang tidak dipakai lebih baik dihapus daripada menghabiskan ruang.

Misalnya terdapat image dengan nama nginx. Dua cara menghapusnya, yaitu:

  • Cara intuitif
docker image rm nginx
  • Cara cepat (rmi = remove image)
docker rmi nginx

Menjalankan container

Image adalah sekumpulan aplikasi yang tersedia namun belum siap digunakan, semacam "installer".

Sebelum dijalankan, image perlu dipasang/ diinstall ke sistem sebagai container.

Sebuah image dapat dipasang sebagai beberapa container.

Terdapat dua jenis kontainer:

  1. Kontainer layanan siaga: kontainer dengan layanan latar (background service)
  2. Kontainer buruh: kontainer aplikasi

Kontainer Layanan Siaga

Aplikasi semacam server web, menjalankan proses latar. Di balik layar (tanpa antar muka), proses tersebut berjalan standby menunggu permintaan dari pengguna.

Biasanya aplikasi semacam ini menerima permintaan melalui protokol TCP/IP (aplikasi jaringan) dan HTTP (aplikasi web).

Contohnya, aplikasi nginx memonitor port 80 (bisa diganti di konfigurasi). Selama hidupnya, nginx akan menguasai port 80 sehingga aplikasi lain tidak dapat menggunakannya (port binding).

Perintah berikut akan melakukan tiga hal:

  • Mengunduh image nginx dari "Docker Hub" jika belum tersedia di komputer lokal.
  • Membuat container baru dengan nama otomatis
  • Menjalankan container tersebut.
docker run -d -p 80:80 nginx

-d atau --detachmenandakan bahwa proses dijalankan dilatar ("detach" berarti pengguna tidak perlu menunggu dan menanti sampai kisah ini berakhir).

[!important] Dalam dunia sistem komputer, kita juga mengenal istilah daemon, yaitu proses yang bergentayangan di balik layar.

nginx mangkal di port 80 di dalam kontainer dan siap siaga. Namun, untuk meminta data dari nginx, kita perlu masuk ke dalam kontainer tersebut. Ini akan kita bahas lain waktu. Kita pelajari dulu cara mengakses layanan ini tanpa masuk-masuk.

-p atau --publish berarti layanan yang ada di dalam kontainer akan dipublikasikan oleh host (komputer yang menjalankan kontainer), sehingga bisa diakses tanpa harus masuk ke dalam kontainer.

Kita bisa menggunakan browser dan mengambil file yang tersedia melalui broser dengan alamat URL http://127.0.0.1:80 atau http://127.0.0.1 (:80 adalah port default untuk protokol HTTP).

# Welcome to nginx!

If you see this page, the nginx web server is successfully installed and working. Further configuration is required.

For online documentation and support please refer to [nginx.org](http://nginx.org/).  
Commercial support is available at [nginx.com](http://nginx.com/).

_Thank you for using nginx._

Orang siaga ada batasnya, ada masa-masa dimana aplikasi membutuhkan "me time".

Apakah aplikasi sedang siaga? Pertanyaan bisa dijawab dengan mudah menggunakan perintah berikut:

docker ps

ps adalah perintah umum di linux yang merupakan singkatan dari proses status.

CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS          PORTS                NAMES
24b57acffb5b   nginx                           "/docker-entrypoint.…"   16 minutes ago   Up 16 minutes   0.0.0.0:80->80/tcp   pedantic_sinoussi

Dari luaran di atas, proses dari kontainer nginx sedang berjalan dengan port yang dipublikasikan di 0.0.0.0:80.

[!note] Dalam jaringan dengan TCP-IP, setiap komputer diberi nama menggunakan alamat IP.

Alamat khusus "127.0.0.1" (loopback interface) digunakan untuk menyebut "komputer ini" secara spesific.

Sedangkan "0.0.0.0" (unspecified address) menunjukkan bahwa aplikasi akan melayani "siapapun".

Layanan web sudah berjalan, tapi bagaimana jika file HTML nya ada di laptop (host).

Bayangkan kontainer seperti sebuah komputer yang ada didalam komputer yang sedang kita gunakan. Terdapat dua sistem penyimpanan file, satu di container, dan satu lagi di host.

Supaya layanan nginx dapat membaca file yang ada di host, docker membutuhkan pemetaan dari sistem file host dengan container.

Docker menyediakan parameter -v atau --volume untuk memetakan volume yang ada di host ke container. Pada linux, volume adalah lokasi logis sebuah media penyimpanan. Misalnya kita memiliki sebuah media penyimpanan fisik yaitu sebuah harddisk. Harddisk dapat dipartisi menjadi dua volume. Pada Microsoft Windows, volume adalah drive, misalnya drive C dan D. Alamat dari sebuah volume biasa disebut path, misalnya c:\ dan d:\.

Sehingga, path dibutuhkan untuk menyampaikan memberitahu pemetaan lokasi penyimpanan dari host ke container.

Sintaksnya adalah -v host_path:container_path

Pertama, siapkan dulu dokumen html di komputer yang sedang dipakai. ~/ adalah lokasi data dari user yang sedang login.

Misalnya, ketika login sebagai user aku di Linux,

  • maka ~/ sama dengan /home/aku
  • atau pada MacOS lokasinya adalah /Users/aku
mkdir -p ~/Projects/html
vim ~/Projects/html/index.html

Lalu jalankan layanan nginx dengan memetakan:

  • Dari lokasi ~/Projects/html pada host
  • Ke /usr/share/nginx/html dalam container

Secara default, nginx akan menyajikan semua file yang ada di /usr/share/nginx/html. Lebih detail dijelaskan pada dokumentasi image nginx di hub.docker.com/_/nginx

docker run -d -p 80:80 --name nginxdocker -v ~/Projects/html:/usr/share/nginx/html nginx

Cek di browser http://127.0.0.1 dan pastikan tampilannya sama dengan isi dari ~/Projects/html/index.html.

Kontainer Buruh

Berbeda dengan nginx yang menyediakan layanan siaga, aplikasi semacam php dan ruby hanya bekerja ketika diperintah.

[!tip] Hal ini sangat jarang dilakukan karena biasanya kita menggunakan docker untuk menyediakan layanan.

Ssaat development, semua aplikasi (php, ruby) biasanya sudah terinstall.

Contohnya, menjalankan aplikasi ruby dalam mode interactive dan tty -it, langsung dari dalam kontainer. Dalam mode interactive -i, klien docker akan menunggu masukan (input). Ditambah mode tty -t, docker juga akan menampilkan luaran (output) dari aplikasi yang dijalankan.

docker run -it ruby
irb(main):003> x="hello"
=> "hello"
irb(main):004> puts x
hello
=> nil
irb(main):005> exit

Cocok buat coba-coba tanpa merusak sistem di komputer lokal.

Menjalankan aplikasi di dalam kontainer

Bayangkan container sebagai komputer di dalam komputer yang sedang kita gunakan. Komputer yang menjalankan container, disebut sebagai host.

Jika dalam host kita menjalankan aplikasi ruby dengan perintah berikut (-e menandakan eksekusi argumen berikutnya, yaitu "puts 'hello'"):

ruby -e "puts 'hello'" 

Aplikasi di dalam kontainer dapat dijalankan secara langsung, dengan perintah yang mirip, dengan menjalankan docker run nama_image.

[!note] Ingat: docker run Membuat dan menjalankan kontainer baru dari image

docker run ruby ruby -e "puts 'hello'" 

Setelah aplikasi di dalam kontainer selesai dieksekusi, proses kontainer akan distop namun kontainer TIDAK dihapus.

Cek sendiri kalau tidak percaya.

docker ps
docker container ls -a

Dalam contoh berikut, terdapat tiga container yang telah berhenti Exited (0) dengan nama flamboyant_hellman, admiring_panini, xenodochial_driscoll.

Docker selalu membuat kontainer baru dengan nama otomatis karena kita tidak memberikan nama.

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
f1678868ff5d   ruby      "ruby -e 'puts 'hell…"   37 seconds ago   Exited (0) 36 seconds ago             flamboyant_hellman
c4c40fd1dbeb   ruby      "ruby -e 'puts 'hell…"   39 seconds ago   Exited (0) 39 seconds ago             admiring_panini
6029346e8df7   ruby      "ruby -e 'puts 'hell…"   43 seconds ago   Exited (0) 42 seconds ago             xenodochial_driscoll

Kalau mau bersih-bersih, docker rm bisa dipakai untuk menghapusnya:

docker rm NAMA_CONTAINER

Atu jalur gampang nan berbahaya, hapus semua docker yang sudah tidak berjalan dengan prune (pangkas).

docker container prune

Sekarang, bagaimana caranya agar setiap menjalankan docker run, tidak menghasilkan kontainer baru.

Cara pertama adalah dengan otomatis menghapus container setelah dijalankan, dengan memberi tanda --rm

docker run --rm ruby ruby -e "puts 'hello'" 

Cara kedua adalah dengan memberikan nama kontainer dengan argumen --name.
Berikut sintaksnya:

docker run --name NAMA_CONTAINER NAMA_IMAGE PERINTAH

Sebagai contoh:

docker run --name rubydocker ruby ruby -e "puts 'hello'" 

Setiap perintah di atas dijalankan, maka docker akan mencoba memanfaatkan container yang sudah ada dengan nama yang diberikan.

docker container ls -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
7d9ffbc6aab7   ruby      "ruby -e 'puts 'hell…"   27 seconds ago   Exited (0) 26 seconds ago             rubydocker

Disini hanya terdapat satu kontainer bernama rubydocker.

Perintah docker run yang sama, tidak dapat dijalankan lagi karena kontainer ini sudah ada.

❯ docker run --name rubydocker ruby ruby -e "puts 'hello'"
docker: Error response from daemon: Conflict. The container name "/rubydocker" is already in use by container "7d9ffbc6aab70355725fb8e57c1c63475d8fb0834f6ce83c5658b13c6fd9edc0". You have to remove (or rename) that container to be able to reuse that name.
See 'docker run --help'.

Sehingga, untuk memanfaatkan kembali kontainer ini digunakan perintah docker start NAMA_CONTAINER.

Namun, pada "kontainer buruh", proses ini hanya berjalan sesaat kemudian keluar lagi, karena tidak ada perintah yang diberikan.

Perintah dapat diberikan dengan menggunakan operasi pipe |. Sintaksnya perintah_pertama | perintah_kedua. Proses dari perintah pertama akan menjadi masukan bagi perintah kedua.

docker start rubydocker | ruby -e "puts 'hello'"

Mulai ribet kan?
Demi kenyamanan bersama, perintah panjang ini bisa dijadikan pendek dengan alias.

alias druby="docker start rubydocker | ruby $1"

Sehingga bisa perintahnya menjadi

druby -e "puts 'hello'"

Sekarang kita bisa menjalankan perintah ruby tanpa harus menginstallnya.

Misal terdapat skrip hello.rb pada komputer. Skrip ini bisa dijalankan dengan perintah:

druby hello.rb

Tapi ingat, setiap eksekusi perintah ini akan ada biaya tambahan (overhead cost) untuk menjalankan container.

❯ time druby test.rb
hello
docker start rubydocker  0.01s user 0.01s system 9% cpu 0.233 total
ruby test.rb  0.04s user 0.01s system 96% cpu 0.055 total

❯ time ruby test.rb
hello
ruby test.rb  0.04s user 0.01s system 95% cpu 0.055 total

Ringkasan

Kontainer Layanan

Contoh: Menjalankan server web nginx

  1. Siapkan dokumen html
mkdir -p ~/Projects/html
vim ~/Projects/html/index.html
  1. Lalu jalankan layanan
docker run -d -p 80:80 --name nginxdocker -v ~/Projects/html:/usr/share/nginx/html nginx
  1. Cek di browser http://127.0.0.1

Kontainer Buruh

Menjalankan aplikasi: berikut contoh untuk ruby. Bisa diterapkan untuk aplikasi lain, tinggal mengganti ruby dengan php, python, dll.

docker run --name rubydocker ruby ruby -e "puts 'hello'" 

alias druby="docker start rubydocker | ruby $1"

druby -e "puts 'hello'"
druby hello.rb

Bonus

Aplikasi biasanya dikemas sebagai image dalam sistem operasi Debian, yang dilengkapi dengan paket lengkap sehingga ukurannya cukup besar. Namun, kebutuhan dasar aplikasi umumnya dapat dipenuhi dengan paket yang lebih ringan dari distribusi seperti Debian Bookworm atau Linux Alpine.

Contohnya, aplikasi ruby yang dikemas dalam Debian Bookworm dapat dijalankan dengan menambahkan tag slim, sehingga nama imagenya menjadi ruby:slim. Tag selengkapnya dapat di cek di hub.docker.com/_/ruby

docker run --name rubydockerslim ruby:slim ruby -e "puts 'hello'"

Berikut adalah perbandingan ukuran aplikasi yang didistribusikan dengan tag latest, alpine atau slim:

REPOSITORY   TAG      IMAGE ID       CREATED        SIZE

nginx        latest   048e09038596   10 days ago    197MB
nginx        alpine   577a23b5858b   10 days ago    50.8MB

php          latest   910138e230ec   2 weeks ago    530MB
php          alpine   b6ec2c8a30cb   2 weeks ago    96.7MB

ruby         latest   febc5e18cba3   5 weeks ago    1GB
ruby         slim     137ca6ff3afb   5 weeks ago    212MB
ruby         alpine   e78475f17fab   5 weeks ago    92.5MB

Docker di MacOS

Docker sangat berguna untuk mengemas aplikasi serta dependensinya menjadi image yang dijalankan sebagai container. Kita bisa memasang Aplikasi di komputer lain (macOS, Linux, Windows ) tanpa ribet setting ulang, tanpa drama "Kemarin di komputer saya bisa kok!"

Proses deployment lebih mudah. Image dapat dibangun di laptop, dibagikan lewat Docker Hub dan pull ke server.

Instalasi Docker di MacOS sangat mudah. Beberapa diskusi di forum menyarankan untuk menggunakan OrbStack dibanding Docker Desktop. Katanya sih lebih cepat, ringan, dan mudah digunakan.

Installer bisa didapatkan dari situs resmi OrbStack,
tetapi saya lebih suka menginstall dari terminal menggunakan perintah berikut:

brew install --cask orbstack

Setelah instalasi berhasil, buka aplikasi OrbStack untuk mengaktifkan layanan docker daemon yang dibutuhkan untuk "memproses" perintah docker.


Perintah untuk membangun image dari Dockerfile dapat dijalankan:

docker build -t aplikasi .

Melihat daftar image yang sudah dibuat:

docker image ls

Image tersebut dapat pasang sebagai container baru dengan:

docker run -d -p 80:80 aplikasi

Menampilkan daftar container yang aktif:

docker container ls

Serta mengecek container yang sedang menyala:

docker ps

Sebagai pengguna kasual-profesional, saya lebih suka OrbStack dibandingkan Docker Desktop karena aplikasi ini tidak semena-mena memasang untuk dijalankan setiap awal booting (bisa diatur di "Setting" Cmd+, -> "Start at login"). Selain itu, fiturnya lebih mudah dipahami dan lebih mudah dimatikan. Dan, sepertinya benar terasa lebih ringan.

Docker Desktop dan OrbStack membutuhkan service atau "background process", yang berjalan di balik layar meskipun tidak dipakai. Padahal, lumayan juga penggunaan sumber daya yang dibutuhkan untuk menjaga service tetap standby.

Sehingga demi penghematan maksimal, kaum fakir memori dan CPU akan sering menutup aplikasi. Namun, menutup aplikasi dengan menekan tombol silang atau Cmd+W hanya akan menyembunyikan antarmuka.

Menonaktifkan aplikasi sepenuhnya dapat dilakukan dengan Cmd+Q atau menuju ke menu OrbStack dan memilih Quit OrbStack. Jangan kuatir, ketika aplikasi dijalankan nanti, maka service juga akan dinyalakan secara otomatis.