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:
- Kontainer layanan siaga: kontainer dengan layanan latar (background service)
- 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 --detach
menandakan 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
padahost
- Ke
/usr/share/nginx/html
dalamcontainer
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
- Siapkan dokumen html
mkdir -p ~/Projects/html
vim ~/Projects/html/index.html
- Lalu jalankan layanan
docker run -d -p 80:80 --name nginxdocker -v ~/Projects/html:/usr/share/nginx/html nginx
- 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