EXPOSE dan Metadata

EXPOSE sebagai dokumentasi port, LABEL untuk metadata image, dan bedanya dengan publikasi port sebenarnya.

Daftar isi

Selain perintah yang dieksekusi, image juga dapat membawa keterangan tentang dirinya, misalnya port yang dilayani aplikasi dan identitas versinya. Dockerfile menyediakan EXPOSE untuk mendokumentasikan port dan LABEL untuk menyimpan metadata, yaitu pasangan kunci-nilai yang menjelaskan image. Keduanya murni keterangan, karena tidak membuka port apa pun dan tidak mengubah isi sistem berkas image. Topik ini membahas cara menggunakan keduanya serta cara memisahkannya dari publikasi port yang sebenarnya.

EXPOSE sebagai keterangan port#

EXPOSE menginformasikan port yang didengarkan aplikasi di dalam container. Informasi ini tersimpan pada metadata image dan terbaca oleh siapa pun yang memeriksa image, tetapi tidak ada port yang dibuka atau dipetakan oleh instruksi ini. Protokol yang didokumentasikan adalah TCP secara default, sedangkan protokol UDP dinyatakan dengan akhiran, misalnya EXPOSE 53/udp. Beberapa port dapat didokumentasikan sekaligus, baik dalam satu baris maupun satu baris per port, sehingga aplikasi yang melayani lebih dari satu port tetap tergambarkan. Untuk aplikasi catatan, satu baris EXPOSE 8000 sudah cukup, dan Dockerfile berikut menunjukkannya bersama metadata image.

Keterangan tersebut dapat dilihat tanpa membuka Dockerfile. Kolom PORTS pada keluaran docker ps menampilkan port yang tercantum pada EXPOSE bersama protokolnya, sedangkan docker inspect menampilkannya dari bagian konfigurasi image. Dua cara tersebut memeriksa keterangan yang sama, yaitu daftar port yang diklaim aplikasi, bukan daftar port yang benar-benar dipublikasikan ke host.

dockerfile Contoh: EXPOSE dan LABEL pada Dockerfile aplikasi catatan
# Mendokumentasikan port aplikasi, tanpa mempublikasikan apa pun
EXPOSE 8000

# Metadata image menurut konvensi OpenContainers
LABEL org.opencontainers.image.title="Aplikasi Catatan"
LABEL org.opencontainers.image.description="API catatan sederhana berbasis pustaka standar Python."
LABEL org.opencontainers.image.version="1.0"
LABEL org.opencontainers.image.licenses="MIT"

Publikasi port yang sebenarnya#

Publikasi port adalah pemetaan port host, komputer tempat Docker berjalan, ke port container. Pemetaan ini hanya dilakukan oleh opsi -p pada docker run. Opsi -P tanpa argumen mempublikasikan seluruh port yang tercantum pada EXPOSE ke port host yang dipilih acak, sehingga EXPOSE berguna sebagai daftar kandidat bagi -P. Apabila image tidak memuat EXPOSE sama sekali, -P tidak mempublikasikan apa pun, sedangkan -p tetap bekerja tanpa memandang EXPOSE. Karena itu, instruksi EXPOSE bersifat opsional bagi koneksi, tetapi tetap bernilai sebagai dokumentasi niat, sebab pembaca Dockerfile langsung mengetahui port mana yang seharusnya dilayani container.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# publikasi nyata dilakukan oleh -p, bukan oleh EXPOSE
docker run --rm -p 8000:8000 aplikasi-catatan
# -P mempublikasikan seluruh port EXPOSE ke port host acak
docker run --rm -P aplikasi-catatan

Tabel berikut memisahkan peran ketiganya.

AspekEXPOSEOpsi -pOpsi -P
FungsiMendokumentasikan portMempublikasikan port tertentuMempublikasikan seluruh port EXPOSE
Letak penulisanInstruksi DockerfileOpsi docker runOpsi docker run
Port hostTidak memetakan apa punDitentukan secara eksplisitDipilih acak dari daftar EXPOSE

LABEL sebagai metadata image#

LABEL menyimpan pasangan kunci-nilai pada metadata image. Konvensi org.opencontainers.image memuat kunci baku seperti .title, .description, .version, dan .licenses, sehingga image dari proyek yang berbeda dapat dideskripsikan dengan cara yang seragam. Beberapa LABEL dapat digabungkan dalam satu baris dengan pemisah spasi, tetapi satu instruksi per baris lebih mudah dibaca dan diperbarui. Nilai label berupa teks bebas, tetapi nilai yang mengandung spasi diberi tanda kutip sebagaimana kunci .description pada contoh di atas.

Label dari image dasar ikut terbawa ke image baru. Label yang tercantum pada image di baris FROM otomatis menjadi bagian image yang dibangun darinya. Apabila kunci yang sama ditetapkan lagi, nilai yang diterapkan paling akhir yang digunakan. Mekanisme ini berguna untuk menimpa keterangan bawaan image dasar dengan identitas proyek sendiri. Kegunaan metadata tidak berhenti pada pembacaan manusia, sebab alat lain seperti antarmuka registry dan pemindai image membaca label yang sama untuk menampilkan keterangan versi dan lisensi.

Label terbaca kembali melalui docker inspect pada konfigurasi image.

bash
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# label image terbaca dari konfigurasinya melalui docker inspect
docker inspect --format '{{json .Config.Labels}}' aplikasi-catatan

Perintah tersebut mencetak pasangan kunci-nilai label dalam bentuk JSON, sehingga keempat label pada contoh terbaca tanpa membuka Dockerfile. Label juga dapat digunakan sebagai penyaring, misalnya docker images --filter "label=org.opencontainers.image.version=1.0" untuk menemukan image dengan versi tersebut. Metadata semacam ini ikut terbawa ketika image dikirim ke registry, sehingga keterangan versi dan lisensinya dapat diperiksa di sisi penerima.

Kesalahan umum#

  • Menganggap EXPOSE membuka port. Image dengan EXPOSE 8000 tetap tidak terjangkau dari host tanpa opsi -p pada docker run, dan gejalanya adalah kegagalan koneksi dari sisi klien walau container berjalan normal. Perbaikannya adalah mempublikasikan port yang sama pada saat container dijalankan.
  • Menuliskan pemetaan dua port pada EXPOSE, misalnya EXPOSE 8000:9000. EXPOSE hanya menerima satu port container beserta protokol opsionalnya, dan pemetaan port host bukan bagian fungsinya. Perbaikannya adalah menulis EXPOSE 9000 pada Dockerfile, lalu melakukan pemetaan dengan -p 8000:9000 saat container dijalankan.
  • Menyimpan rahasia pada LABEL. Label terbaca siapa pun melalui docker inspect, ikut terbawa ke registry, dan sering tampil pada antarmuka registry, sehingga nilai seperti kata sandi basis data langsung terpapar. LABEL memang diperuntukkan bagi keterangan versi, lisensi, dan identitas, sedangkan rahasia disalurkan lewat mekanisme khusus pada modul Keamanan dan CI.

Ringkasan#

  • EXPOSE mendokumentasikan port dan protokolnya pada metadata image, tetapi tidak memetakan port apa pun.
  • Publikasi nyata dilakukan oleh opsi -p, sedangkan opsi -P menggunakan daftar EXPOSE untuk memilih port host secara acak.
  • LABEL menyimpan metadata menurut konvensi org.opencontainers.image dan terbaca kembali melalui docker inspect.

Referensi#