Pengenalan Runtime Alternatif

Podman, containerd, dan nerdctl, beserta posisi standar OCI di antara semua runtime.

Daftar isi

Docker adalah nama yang paling sering disebut, tetapi bukan satu-satunya perangkat lunak yang menjalankan container. Topik ini mengenalkan standar OCI yang membuat image dapat berpindah antar runtime, yaitu perangkat lunak yang menjalankan image sebagai container. Kemudian, containerd, Podman, dan nerdctl diperkenalkan sebagai alternatif yang paling sering disebut di luar Docker Engine. Bagian akhir menjelaskan mengapa keterampilan yang terbentuk sepanjang jalur ini tidak hilang ketika runtime-nya berganti.

Standar OCI yang menyatukan runtime#

Open Container Initiative (OCI) adalah proyek standar terbuka yang menetapkan dua spesifikasi inti, yaitu format image dan spesifikasi runtime yang mengatur cara image dijalankan sebagai container. Karena kedua spesifikasi itu, image yang dibangun dengan Docker dapat ditarik dan dijalankan oleh runtime lain tanpa konversi apa pun. Tanpa standar ini, setiap runtime akan membentuk format image sendiri, dan seluruh ekosistem akan terkunci pada satu penyedia. Standar inilah yang membuat pertanyaan berpindah runtime menjadi pertanyaan yang masuk akal.

Pada lapisan image, wujud standar OCI adalah manifest, berkas JSON yang mendeskripsikan satu image. Manifest memuat jenis isi image, penunjuk ke berkas konfigurasi, serta daftar layer beserta penanda keabsahan (digest) dan ukurannya. Contoh berikut menampilkan bentuk ringkasnya dengan nilai digest contoh, bukan image sungguhan.

json Contoh: manifest OCI untuk image aplikasi catatan
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:2b90ef4f0506ac32959c1e9e79d66549c1ef9a2761e2194d473756851079b9dd",
    "size": 703
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:f3b99d2dee73c20c2691da50b282d6fce9f9268dc9b94a2bfbf0542a3c50b0ca",
      "size": 3465000
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:01fa61478038f34b4529df068004a367b4d444113afbcf592d7b4a509dbdc23a",
      "size": 1258000
    }
  ]
}

mediaType menyatakan jenis objek yang sedang dibaca, config menunjuk berkas konfigurasi yang berisi titik masuk dan nilai bawaan image, sedangkan layers mendaftar tumpukan layer yang menyusun sistem berkasnya. Registry, gudang yang melayani unggahan dan unduhan image, tidak mengirim image sebagai satu berkas besar, melainkan manifest beserta layer-layer yang dirujuknya. Karena bentuknya ditetapkan spesifikasi, manifest yang sama dibaca dengan cara yang sama oleh Docker, containerd, maupun Podman.

Deskripsi image sebagai data biasa#

Karena manifest hanyalah data JSON, deskripsi sebuah image dapat disimpan, dibaca, dan diperiksa tanpa menjalankan runtime mana pun. Skrip berikut menuliskan deskripsi image ke berkas JSON, lalu membacanya kembali sebagaimana alat pemeriksa umumnya bekerja.

python deskripsi-image.py
"""Menyimpan dan membaca kembali deskripsi image sebagai data JSON netral."""

import json

MANIFEST = {
    "schemaVersion": 2,
    "mediaType": "application/vnd.oci.image.manifest.v1+json",
    "config": {
        "mediaType": "application/vnd.oci.image.config.v1+json",
        "digest": "sha256:2b90ef4f0506ac32959c1e9e79d66549c1ef9a2761e2194d473756851079b9dd",
        "size": 703,
    },
    "layers": [
        {
            "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
            "digest": "sha256:f3b99d2dee73c20c2691da50b282d6fce9f9268dc9b94a2bfbf0542a3c50b0ca",
            "size": 3465000,
        },
        {
            "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
            "digest": "sha256:01fa61478038f34b4529df068004a367b4d444113afbcf592d7b4a509dbdc23a",
            "size": 1258000,
        },
    ],
}

# deskripsi image disimpan sebagai berkas JSON biasa
with open("image-manifest.json", "w", encoding="utf-8") as berkas:
    json.dump(MANIFEST, berkas, indent=2)
    berkas.write("\n")

with open("image-manifest.json", encoding="utf-8") as berkas:
    print(berkas.read(), end="")

# berkas yang sama dibaca kembali tanpa mengetahui runtime pembuatnya
with open("image-manifest.json", encoding="utf-8") as berkas:
    dibaca = json.load(berkas)

print("jumlah layer :", len(dibaca["layers"]))
print("ukuran total :", sum(layer["size"] for layer in dibaca["layers"]), "byte")
print("config       :", dibaca["config"]["digest"])
text Keluaran
{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.manifest.v1+json",
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:2b90ef4f0506ac32959c1e9e79d66549c1ef9a2761e2194d473756851079b9dd",
    "size": 703
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:f3b99d2dee73c20c2691da50b282d6fce9f9268dc9b94a2bfbf0542a3c50b0ca",
      "size": 3465000
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:01fa61478038f34b4529df068004a367b4d444113afbcf592d7b4a509dbdc23a",
      "size": 1258000
    }
  ]
}
jumlah layer : 2
ukuran total : 4723000 byte
config       : sha256:2b90ef4f0506ac32959c1e9e79d66549c1ef9a2761e2194d473756851079b9dd

Skrip tidak memanggil Docker, containerd, maupun Podman sama sekali, dan keadaan itulah yang menjadi inti bagian ini. Berkas JSON yang dihasilkan dapat dibaca oleh semua alat, sehingga program Python sederhana di atas meniru pekerjaan alat pemeriksa yang membaca manifest tanpa memedulikan runtime pembuatnya. Runtime yang sesungguhnya memakai berkas semacam itu untuk memutuskan layer mana yang harus diunduh dan konfigurasi apa yang membentuk container. Pemisahan antara deskripsi dan pelaksana inilah yang dijaga standar OCI.

containerd, jantung di balik Docker#

containerd adalah runtime daemon, yaitu proses latar yang berjalan terus-menerus dan mengelola image serta eksekusi container. Docker Engine dibangun di atasnya, sehingga setiap docker run sesungguhnya mendelegasikan sebagian besar pekerjaannya ke containerd. containerd juga dapat dipasang sendirian tanpa Docker, dan pemasangan demikian lazim dijumpai pada node Kubernetes, mesin yang menjadi anggota sebuah cluster. Perlu dicatat bahwa proyek ini adalah infrastruktur inti dan bukan alat interaktif, sehingga antarmuka baris perintah bawaannya sengaja dibuat minim.

Podman tanpa daemon#

Podman mengambil arah yang berbeda, yaitu bersifat daemonless atau tanpa proses latar yang terus berjalan. Setiap perintah podman membuat dan mengawasi container yang dimintanya, lalu selesai, sehingga tidak ada daemon yang harus dijaga dan diperbarui. Container juga berjalan sebagai pengguna biasa secara bawaan, sifat yang disebut rootless, sehingga pola daemon yang berjalan dengan hak tertinggi hilang dari desainnya.

Antarmukanya adalah CLI yang kompatibel dengan docker, dengan nama perintah, opsi, dan keluaran yang sengaja dibuat serupa. Kebiasaan yang lazim di lingkungan migrasi adalah memasang alias docker=podman pada shell, sehingga kebiasaan mengetik tetap sama. Perintah-perintah yang telah dilatih pada jalur ini umumnya berjalan apa adanya.

bash
# tidak-dijalankan: Podman tidak tersedia di sandbox
# perintah yang sudah akrab, kali ini tanpa daemon
podman run -d --name web -p 8000:8000 budi/catatan:1.0.0
podman ps

nerdctl, antarmuka docker untuk containerd#

nerdctl melengkapi containerd dengan CLI yang meniru docker. Perintahnya diberi nama sama, mulai dari nerdctl run dan nerdctl ps sampai nerdctl compose, termasuk pembacaan berkas compose.yaml, sehingga kebiasaan yang terbentuk di Docker Engine dapat dipakai di atas containerd. Kasus pemakaiannya berpusat pada lingkungan yang sudah menjalankan containerd tanpa Docker, misalnya node Kubernetes yang ingin diuji dengan perintah yang akrab. Dengan kata lain, pasangan containerd dan nerdctl menyerupai pengalaman Docker tanpa Docker Engine.

Membandingkan runtime dan artinya bagi pembelajar#

AspekDocker EnginecontainerdPodman
Proses utamadaemon yang selalu hidupdaemon yang selalu hidupdaemonless
Hak akses bawaandaemon biasanya berjalan sebagai root, mode rootless tersediamengikuti pemasangannyatanpa root secara bawaan
Antarmuka CLIdocker dan Composeminim bawaan, dilengkapi nerdctlkompatibel dengan docker
Kasus cocokpengembangan sehari-hari dan titik awal belajarnode Kubernetes dan infrastruktur seminimal mungkindesktop tanpa daemon dan kebijakan keamanan ketat

Tabel di atas bermuara pada satu kesimpulan utama, yaitu keterampilan container berpindah antar runtime. Konsep image, layer, registry, jaringan, dan volume yang dipelajari sepanjang jalur ini adalah milik ekosistem container secara umum, bukan milik satu CLI. Yang berubah ketika runtime berganti hanyalah nama perintah dan siapa yang mengawasi prosesnya, sedangkan pendekatan membangun image, menarik image dari registry, dan mengatur jaringan tetap sama.

Ringkasan#

  • Standar OCI menetapkan format image dan spesifikasi runtime, sehingga satu image berjalan di banyak runtime tanpa konversi.
  • Docker Engine dibangun di atas containerd, Podman bekerja tanpa daemon dan tanpa root secara bawaan, sedangkan nerdctl memberi containerd antarmuka bergaya docker.
  • Deskripsi image berwujud manifest JSON yang dapat dibaca alat mana pun, dan keterampilan CLI beserta konsepnya sebagian besar berpindah antar runtime.

Referensi#