Membaca log memberi kita gema suara container, tetapi komunikasinya tetap satu arah: kita mengamati keluaran yang dikirim ke luar tanpa pernah bisa meminta container mengerjakan sesuatu yang baru. Padahal kebutuhan sehari-hari penuh situasi dua arah — memeriksa versi program yang terpasang di dalam web, melihat isi direktori konfigurasinya, berbincang langsung dengan Redis di dalam cache, atau sekadar membuka shell untuk berkeliling. Docker menjawab kebutuhan itu dengan docker exec, perintah yang menjalankan proses tambahan di dalam container yang sedang hidup. Chapter ini membedah cara kerjanya, peran flag -i dan -t yang hampir selalu muncul bersamanya, perbedaan mendasarnya dengan docker attach, serta pola pemakaian satu perintah tanpa sesi interaktif.

Menjalankan Perintah Sekali Jalan #

Bentuk paling sederhana docker exec adalah docker exec <container> <perintah> — daemon menjalankan perintah tersebut sebagai proses baru di dalam container, menunggu prosesnya selesai, lalu mengalirkan keluarannya kembali ke terminal kita. Container yang menjadi tuan rumah sama sekali tidak terganggu; proses utamanya terus berjalan seolah tidak ada yang terjadi. Kita mulai dengan memeriksa versi nginx di dalam web:

bash
$ docker exec web nginx -v

Output yang Dihasilkan:

text
nginx version: nginx/1.29.4

Lalu kita jelajahi direktori konfigurasi nginx — perintah ls yang biasa kita pakai di host, kini dijalankan di dalam filesystem container:

bash
$ docker exec web ls /etc/nginx

Output yang Dihasilkan:

text
conf.d
fastcgi_params
mime.types
modules
nginx.conf
scgi_params
uwsgi_params

Mari kita telaah kedua perintah di atas:

  1. nginx -v berjalan di dalam container — versi yang tercetak adalah versi nginx yang terpasang di image nginx:latest, terpisah dari apa pun yang ada di mesin kita; inilah cara tercepat memastikan isi image tanpa membuka shell.
  2. ls /etc/nginx menjelajah filesystem container — ketujuh nama yang tampil adalah isi direktori konfigurasi nginx di dalam web, dilihat dari sudut pandang proses yang hidup di dalamnya; nginx.conf dan conf.d adalah penghuni yang paling sering kita cari saat menelusuri konfigurasi.
  3. Tanpa flag -t sama sekali — kedua perintah ini bersifat sekali jalan: tidak ada interaksi, tidak ada ketikan lanjutan; keluaran dicetak, proses selesai, terminal kembali ke kita.
  4. Perintah harus tersedia di dalam image — docker exec menjalankan biner yang ada di filesystem container; nginx dan ls ditemukan karena keduanya memang terpasang di dalam image nginx.

Membuka Sesi Interaktif dengan -it #

Memeriksa versi dan isi direktori cukup dengan satu perintah, tetapi pemeriksaan yang butuh dialog — mengetik, membaca jawaban, mengetik lagi — membutuhkan sesi interaktif. Redis menyediakan contoh terbaiknya: image redis:7 membawa redis-cli, klien baris perintah resmi Redis, sehingga kita bisa berbicara langsung dengan server yang hidup di dalam cache:

bash
$ docker exec -it cache redis-cli

Output yang Dihasilkan:

text
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> exit

Baris berawalan 127.0.0.1:6379> adalah prompt redis-cli beserta ketikan kita, dan PONG adalah jawaban server. Mari kita telaah anatomi perintah ini:

  1. -i menjaga stdin tetap terbuka — flag interactive membuat saluran masukan dari terminal kita mengalir ke proses redis-cli; tanpa -i, kita tidak bisa mengetik apa pun dan sesi interaktif mustahil.
  2. -t mengalokasikan pseudo-TTY — flag tty meminta daemon menyiapkan terminal semu di dalam container, sehingga redis-cli merasa dijalankan di terminal sungguhan: prompt-nya tampil rapi, ketikan kita bergema, dan perilaku interaktifnya aktif. Tanpa -t, redis-cli jatuh ke mode non-interaktif dan memproses masukan mentah tanpa prompt.
  3. -it adalah pasangan wajib sesi interaktif — keduanya menutupi kebutuhan yang berbeda: -i membuka jalan masuk, -t membuat pengalaman mengetik terasa seperti terminal biasa; hampir semua contoh docker exec untuk shell dan CLI interaktif di dokumentasi maupun internet memakai pasangan ini.
  4. Prompt 127.0.0.1:6379 — redis-cli terhubung ke server di alamat lokal container itu sendiri pada port bawaan 6379; perintah PING menguji koneksi dan jawaban PONG menegaskan bahwa Redis hidup dan mendengar.
  5. exit menutup sesi tanpa mematikan container — perintah ini mengakhiri proses redis-cli saja; container cache beserta proses server Redis-nya tidak ikut berhenti.

Janji pada poin terakhir layak dibuktikan. Kita periksa umur kedua container setelah sesi ditutup:

bash
$ docker ps

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                     NAMES
f7c2a91b3e55   nginx     "/docker-entrypoint.…"   44 minutes ago   Up 22 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   web
3a1c8f2e9b7d   redis:7   "docker-entrypoint.s…"   38 minutes ago   Up 38 minutes   6379/tcp                                  cache

cache masih berstatus Up 38 minutes — umurnya berjalan tanpa putus sedikit pun, karena sesi docker exec hanyalah proses tamu yang datang dan pergi. Pola yang sama berlaku untuk shell: image berbasis Debian seperti nginx dan redis membawa bash, sedangkan image berbasis alpine hanya membawa sh yang ringkas — sehingga membuka shell di container Debian berarti mengetik docker exec -it web bash, sementara di container alpine cukup docker exec -it nama-container sh.

Satu Perintah redis-cli Tanpa Sesi #

Flag -it menjadi tidak perlu begitu perintah kita bersifat sekali jalan — termasuk memanggil redis-cli dengan argumen perintah langsung. Pola ini cocok untuk skrip dan pemeriksaan cepat dari luar:

bash
$ docker exec cache redis-cli SET kunjungan 1

Output yang Dihasilkan:

text
OK
bash
$ docker exec cache redis-cli GET kunjungan

Output yang Dihasilkan:

text
"1"

Mari kita telaah kedua perintah di atas:

  1. redis-cli SET kunjungan 1 sebagai mode sekali jalan — klien redis-cli menerima nama perintah beserta argumennya, menjalankannya sekali, mencetak jawaban, lalu keluar; tidak ada prompt, tidak ada sesi, dan tidak ada kebutuhan terminal semu.
  2. OK sebagai jawaban server — Redis mengonfirmasi kunci kunjungan tersimpan dengan nilai 1 di memorinya; data ini hidup di dalam container cache, bukan di mesin kita.
  3. "1" terbungkus tanda kutip — tampilan khas redis-cli untuk nilai bertipe string; jawaban GET membaca kembali nilai yang barusan kita simpan, membuktikan bahwa kedua pemanggilan exec berbicara dengan server yang sama di dalam container yang sama.

docker exec versus docker attach #

Nama exec sering membingungkan pemula karena Docker punya satu perintah lain yang terdengar serupa: docker attach. Keduanya sama-sama berhubungan dengan container yang sedang hidup, tetapi mekanismenya bertolak belakang. docker exec selalu menciptakan proses baru di dalam container; docker attach tidak menciptakan apa pun — perintah itu cukup menempelkan stdin, stdout, dan stderr terminal kita langsung ke proses PID 1 yang telah berjalan sejak container dinyalakan, persis seperti melanjutkan panggilan telepon yang tersambung.

Tabel berikut merangkum perbedaan keduanya:

Aspekdocker execdocker attach
Proses yang terlibatMenjalankan proses baru di dalam containerMenempel langsung pada PID 1 yang sudah berjalan
Prasyarat containerHarus berstatus RunningHarus berstatus Running
Efek berakhirnya sesiContainer tetap berjalan tanpa terpengaruhBisa ikut berhenti bila sinyal diteruskan ke PID 1
Kebutuhan interaktifFlag -it untuk sesi shell atau CLITerminal terikat langsung; lepas dengan Ctrl-p Ctrl-q
Kasus paling cocokDiagnosis, CLI tool, shell sementara di container hidupMengikuti keluaran proses utama secara langsung

Dengan docker exec, kotak hitam container akhirnya punya pintu dua arah: kita bisa memeriksa, menguji, dan berinteraksi tanpa mengganggu proses utamanya. Namun perhatikan benang merah yang perlahan terbentang sepanjang section ini — setiap proses yang kita jalankan, baik lewat docker run maupun docker exec, pada akhirnya berakhir; dan begitu pula container. Setiap akhir itu meninggalkan satu angka kecil sebagai warisan terakhirnya: exit code. Angka 0 pada quirky_einstein, angka 137 pada web yang kita kill, angka 143 yang akan segera kita jumpai — semuanya menyimpan cerita yang bisa kita baca. Chapter penutup section ini, Memahami Exit Code, mengajari kita cara membacanya sampai tuntas.

Referensi #