Kita sudah memegang tata bahasa perintah, kebiasaan membaca bantuan, dan kemampuan memilih daemon lewat context — bekal yang cukup untuk ritual inti Docker: menjalankan container. Sebenarnya kita sudah dua kali menyaksikan docker run beraksi — pada Chapter Apa itu Docker? sebagai perkenalan dan pada Chapter Verifikasi Instalasi sebagai uji kesehatan — tetapi keduanya berlangsung kilat tanpa bedah. Chapter ini menjalankan ulang seluruh proses dari nol sambil membongkar setiap fase yang terjadi di balik layar, lalu menutupnya dengan container yang benar-benar bekerja: sebuah web server nginx yang bisa diakses dari browser. Sebagai titik awal yang bersih, sisa container dan image dari latihan section sebelumnya sudah dihapus, sehingga setiap baris output yang akan kita lihat benar-benar lahir dari perintah kita sendiri.

Menjalankan hello-world #

Image hello-world adalah image resmi paling mungil di Docker Hub — ukurannya cuma 13.3kB — yang tugas satu-satunya adalah mencetak pesan lalu selesai. Justru karena sederhana itulah seluruh perjalanan perintah terlihat telanjang tanpa derau. Mari kita jalankan:

bash
$ docker run hello-world

Output yang Dihasilkan:

text
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
ef151d431693: Pull complete
Digest: sha256:6c15599d177bd6b1e977d6aa4e532bdf00dc5c22513503c9cc85c027b3ccab9c
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Ini adalah output asli docker run hello-world pada kondisi mesin kosong. Mari kita telaah baris demi baris:

  1. Unable to find image 'hello-world:latest' locally — langkah pertama docker run selalu memeriksa penyimpanan image lokal; karena mesin kita bersih, daemon melanjutkan dengan menarik image secara otomatis. Perhatikan bahwa tag latest ditambahkan diam-diam karena kita tidak menyebut tag.
  2. latest: Pulling from library/hello-world — daemon mengambil image dari Docker Hub pada namespace library/ untuk image resmi, persis mekanisme registry yang kita bahas pada Chapter Image, Container, dan Registry.
  3. ef151d431693: Pull complete — satu-satunya layer image hello-world selesai diunduh dan disimpan; image yang lebih besar akan menampilkan satu baris per layer.
  4. Digest: sha256:6c15599d... — sidik jari kriptografis image sepanjang 64 karakter heksadesimal; digest adalah identitas permanen yang tidak berubah sekalipun tag digeser.
  5. Hello from Docker! beserta empat langkah — pesan ini dicetak oleh program kecil di dalam container, dan keempat langkah yang dideskripsikannya adalah ringkasan jujur arsitektur client-server: klien menghubungi daemon, daemon menarik image, daemon membuat container baru dari image itu, lalu output dialirkan kembali ke terminal kita.
  6. Tiga paragraf terakhir — saran pemakaian lanjutan beserta tautan Docker Hub dan dokumentasi; bagian ini murni informasi dan boleh dilewati.

Setelah pesan tercetak, program di dalam container selesai dan container berhenti dengan sendirinya — status Exited (0) yang akan kita lihat lagi pada chapter berikutnya. Terminal kita kembali siap, image hello-world tinggal menetap di penyimpanan lokal, dan container yang barusan lahir kini berstatus berhenti menunggu nasib berikutnya.

Siklus Pull, Create, dan Start #

docker run sebenarnya adalah gabungan tiga operasi yang bisa juga dijalankan terpisah. Bila image belum ada di lokal, langkah pull mengunduhnya dari registry. Langkah create menyiapkan container dari image — menumpuk seluruh layer read-only, menambahkan writable layer, dan mengalokasikan ID 64 karakter. Langkah start akhirnya menghidupkan proses di dalamnya. Diagram berikut memetakan alurnya:

Mari kita telaah arti setiap tahap pada diagram di atas:

  1. Titik keputusan — docker run mengecek penyimpanan lokal lebih dulu; pada mesin bersih kita, jalur pull ditempuh sekali di awal, dan pemanggilan docker run hello-world untuk kedua kalinya akan langsung melompat ke tahap create tanpa mengunduh apa pun.
  2. Tahap create — inilah momen image berubah menjadi calon container: writable layer ditambahkan di puncak tumpukan dan ID container dialokasikan, namun prosesnya belum hidup.
  3. Tahap start — proses dijalankan sebagai PID 1 di dalam container; untuk hello-world, prosesnya adalah program cetak-pesan yang langsung menuntaskan pekerjaannya.
  4. Tahap akhir — output dialirkan ke terminal, proses selesai, dan container berhenti; container tidak terhapus, ia hanya berhenti.

Pemisahan create dan start bukan formalitas tanpa guna. Perintah docker create dan docker start akan kita pakai untuk container yang perlu disiapkan dulu konfigurasinya atau dinyalakan ulang berkali-kali — skenario yang menyusul pada Chapter Menghentikan dan Menjalankan Container.

Menjalankan Container web di Latar Belakang #

hello-world adalah contoh container sekali-jalan; sekarang kita naik kelas ke container yang harus tetap hidup melayani permintaan: web server nginx. Kali ini kita pakai tiga flag sekaligus — -d, --name, dan -p — dan biarkan Docker menarik image secara otomatis seperti sebelumnya:

bash
$ docker run -d --name web -p 8080:80 nginx

Output yang Dihasilkan:

text
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
b97706ca828b: Pull complete
ca0385813dba: Pull complete
...
Digest: sha256:348334896a68...
Status: Downloaded newer image for nginx:latest
f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a

Baris-baris layer di tengah serta nilai digest dipotong agar ringkas — nginx varian Debian berukuran 187MB dan tersusun dari beberapa layer. Mari kita telaah flag dan baris terakhirnya:

  1. -d (detached) — container berjalan di latar belakang dan kontrol terminal langsung kembali ke kita; berbeda dengan hello-world yang menempel di terminal sampai selesai, nginx dimaksudkan hidup lama sehingga tidak ada gunanya menahan terminal.
  2. --name web — nama eksplisit untuk container ini; mulai sekarang kita bisa menyebut web pada perintah berikutnya seperti docker logs web tanpa perlu mengingat ID.
  3. -p 8080:80 — menerbitkan port dengan pola host:container: permintaan yang datang ke port 8080 di mesin kita diteruskan ke port 80 di dalam container. Tanpa flag ini, port 80 nginx hanya hidup di jaringan internal container — persis keadaan demo nginx pada Chapter Image, Container, dan Registry yang kolom PORTS-nya hanya menulis 80/tcp. Pemetaan port ini akan kita bedah tuntas pada Chapter Port Publishing.
  4. Baris ID 64 karakter — output tunggal dari mode detached adalah ID lengkap container f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a; dua belas karakter pertamanya, f7c2a91b3e55, adalah bentuk pendek yang akan tampil pada perintah-perintah selanjutnya.

Container web kini hidup. Pertanyaan berikutnya: benarkah port 8080 di mesin kita sudah mengarah ke nginx di dalam container? Kita jawab langsung dengan curl — tanpa prefiks skema, curl otomatis memakai HTTP untuk alamat telanjang:

bash
$ curl localhost:8080

Output yang Dihasilkan:

text
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
...

Sisa halaman dipotong — setelah paragraf itu masih ada tautan dokumentasi dan penutup </body></html>. Mari kita telaah apa yang barusan terjadi:

  1. curl localhost:8080 — permintaan HTTP dikirim ke port 8080 pada mesin kita, tepat port yang kita terbitkan dengan -p; alamat sama persis itu juga bisa kita buka di browser.
  2. Welcome to nginx! — halaman selamat datang bawaan nginx menjawab permintaan tersebut; halaman ini dicetak oleh nginx yang hidup di dalam container, bukan oleh nginx di mesin kita — mesin kita bahkan tidak memasang nginx sama sekali.
  3. Arti keseluruhan — satu perintah docker run barusan menarik image, membuat container, menerbitkan port, dan menghidupkan web server yang kini menjawab permintaan dari luar container.

Dua container kini menghuni mesin kita dengan dua nasib yang berbeda: web hidup melayani permintaan HTTP di latar belakang, sementara container hello-world bernama quirky_einstein sudah selesai dan berhenti. Bagaimana cara melihat keduanya sekaligus, membedakan yang hidup dari yang berhenti, dan menyaring daftar itu sesuai kebutuhan? Jawabannya adalah jendela paling sering kita intip sepanjang hidup sebagai pengguna Docker — perintah docker ps pada Chapter Melihat Container.

Referensi #