Skip to content

Image Build & Versioning Toolkit

By Romi Fadli, S.Kom. 7 min read Environments & Deployment
On this page
Three image layer stacks, each with a version tag of its own colour, blue, orange, and green, each leading to an archive file banded in the same colour

Image Build & Versioning Toolkit adalah kumpulan perintah yang memberi setiap modul dalam satu stack versinya sendiri, mem-build image-nya di bawah versi itu, dan mengarsipkan image dengan cara yang menjaga versi-versinya tetap terpisah. Satu perintah mem-build modul sekaligus menaikkan versinya; satu menaikkan versi tanpa build; dua lagi menyimpan image ke file dan memuatnya kembali.

Stack berisi sembilan modul tak berubah serentak. Ketika satu service mendapat perbaikan, hanya service itu yang layak menerima nomor baru, dan tag yang dibawanya harus berarti tepat satu build, karena staging dan production akan menarik tag itu dan percaya bahwa isinya sama dengan yang diuji.

Sekilas

Toolsbuild-all, upgrade-version-only, backup-docker-images, restore-docker-images
BentukScript command-line; perintah versi saja dan backup memuat library pembantu bersama untuk menurunkan daftar modul, sedangkan build dan restore berdiri sendiri
BahasaBash dengan awk, yang mengendalikan Docker Compose dan Cargo
StatusStabil, berjalan di production
Kode sumberPrivat
Apa toolkit ini, dibangun dengan apa, dan keadaannya.

Yang dikerjakannya

A. Memberi versi pada tiap modul secara terpisah

Setiap modul menyimpan versinya di file environment miliknya sendiri, jadi satu service bisa berada di 2.13.0 sementara sisanya tetap di 2.11.2. Mem-build satu modul hanya menaikkan nomor modul itu; mem-build semuanya adalah opsi tersendiri yang harus disebut, karena menaikkan setiap versi untuk perubahan di satu service menciptakan rilis yang tak pernah terjadi.

B. Mem-build image di bawah versi barunya

Perintah build membaca versi modul saat ini dari file-nya, menuliskan versi baru, lalu mem-build image-nya. Modul yang ditulis dengan Rust meng-compile binary-nya di host lebih dulu, karena image-nya hanya menyalin binary yang sudah jadi; lokasi source-nya bisa dialihkan untuk mesin lain. Modul yang dipakai lintas project di-build dengan nama image universal, tanpa akhiran milik project mana pun, jadi image yang sama melayani setiap project yang memakainya.

C. Menolak memakai ulang versi

Bila modul sudah membawa versi yang diminta, build berhenti dan menjelaskan alasannya. Build ulang yang disengaja di bawah nomor yang sama, misalnya sesudah base image berubah tanpa perubahan source, butuh flag eksplisit.

D. Menaikkan versi tanpa build

Ketika image-nya sudah ada, hasil pull dari registry, perintah kedua hanya menyelaraskan versi modul dengannya. Daftar modulnya diturunkan dari file compose, bukan ditulis tangan, jadi modul baru ikut tercakup tanpa ada yang perlu ingat menambahkannya. Modul yang sudah berada di versi yang diminta dilaporkan baik-baik saja, dan modul tanpa file environment atau tanpa versi yang terbaca dilewati dengan pesan.

E. Mengarsipkan image berdasarkan nama dan tag

Perintah backup menyimpan image tiap modul ke file terkompresi yang dinamai menurut image sekaligus tag-nya, dengan versi tiap modul dibaca dari file miliknya dan nama image dari file compose-nya, yang memilih gagal ketimbang menghasilkan nama kosong. Ia bisa membaca modul environment lain, mencetak bantuannya sendiri, dan menolak opsi tak dikenal dengan exit code 2. Perintah restore memuat kembali semua arsip, atau hanya yang disebut. Nama yang diketik dari root repository ditemukan di folder arsip berdasarkan nama dasarnya. Pemuatan yang gagal menghentikan run.

Cara saya memakainya

bash
build-all thumbnailer 2.13.0          # raise one module and build it
build-all --all 2.13.0                # every module, on purpose
build-all thumbnailer 2.13.0 --rebuild # same number, deliberately
upgrade-version-only thumbnailer 2.12.0
backup-docker-images                  # every module at its own version
restore-docker-images
PerintahYang dikerjakanYang ditolak
build-allmenaikkan versi satu modul dan mem-build image-nyaversi yang sudah dibawa modul itu; modul tak dikenal; build Rust yang gagal
upgrade-version-onlymenaikkan versi tanpa buildmodul tak dikenal
backup-docker-imagesmenyimpan tiap image sebagai <image>__<tag>.tgzmodul tak dikenal; image yang tak ada di daemon dilaporkan dan run dinyatakan gagal
restore-docker-imagesmemuat kembali arsip beserta tag-nyarun tanpa satu pun arsip untuk dimuat
Empat perintah dan kesalahan yang dicegah masing-masing.

Keputusan rancangan

Versi milik modul, dan versi lama dibaca, tak pernah diketik. Perintah build dulu meminta versi lama dan versi baru sekaligus. Salah ketik pada versi lama membuat penggantian tak menemukan apa pun, file-nya tetap seperti semula, dan script tetap melaporkan sukses. Kini versi lama diambil dari file milik modul itu. Penalaran yang sama sampai ke backup image: dengan satu argumen versi untuk seluruh stack, tak ada nilai yang benar, karena 2.11.2 melewatkan modul yang di 2.13.0 dan 2.13.0 melewatkan enam lainnya, dan keduanya tetap menulis backup separuh yang tampak lengkap.

Satu tag berarti satu build. Satu service storage pernah di-build ulang dengan endpoint baru di bawah tag 1.0.0 yang sudah ada, sementara registry masih menyimpan 1.0.0 yang lebih lama. Development menjalankan image lokal yang segar, staging menarik yang lama, dan pemeriksaan identitas gagal dengan 404 yang menunjuk ke mana-mana kecuali ke tag-nya. Karena itu build menolak menimpa versi yang sudah dibawa modulnya; staging dan production yang menarik satu tag menerima isi yang memang diuji.

Langkah yang gagal menghentikan build, bukan menghilang. Build Rust dulu duduk di rantai satu baris yang || true-nya menelan compile yang gagal, sehingga image mengemas binary sebelumnya di bawah versi baru lalu melaporkan sukses. Rantai itu sudah dibuang, dan error compile kini menghentikan semuanya. Di perintah build, versinya sendiri ditulis dengan hanya mengubah baris versinya, dicocokkan secara literal, dan isi file-nya diganti di tempat sehingga pemilik dan mode-nya tetap: cari-ganti sebelumnya memperlakukan titik pada 1.0.0 sebagai wildcard, cocok dengan satu nomor port, lalu mengubahnya menjadi 1.1.0, yang belakangan gagal sebagai port tak valid. Nama modul yang tak dikenal toolkit ditolak, bukan diam-diam tak mem-build apa pun, dan pesan penutupnya mengingatkan bahwa setiap modul lain tetap di versinya sendiri.

Arsip diberi label versi, dan publikasi tetap langkah terpisah. Menamai tiap arsip menurut tag-nya membuat dua versi dari satu modul tak pernah saling menimpa, dan folder-nya langsung memperlihatkan versi mana saja yang tersimpan. Build berhenti begitu image ada di mesin lokal. Push ke registry sengaja dikerjakan manual, karena tag yang di-push adalah tag yang akan ditarik setiap environment sesudahnya, dan momen itu layak mendapat perhatian manusia.

Spesifikasi

MasukanSatu modul, atau semua modul secara eksplisit, dan versi baru; untuk arsip, opsional satu modul atau environment lain sebagai sumber
KeluaranImage bertag versi tiap modul, entri versi yang diperbarui, dan satu arsip terkompresi per image dan tag
KeamananVersi yang sudah ada tak ditimpa tanpa flag; compile yang gagal menghentikan build; modul tak dikenal ditolak; tak ada yang di-push otomatis
PrasyaratDocker beserta Compose; Cargo untuk modul Rust; source modul tersedia di disk. Script-script ini mencari lokasinya sendiri, jadi bisa dijalankan dari working directory mana pun
Masukan, keluaran, dan jaminan toolkit ini.

Terkait

Prosedur rilis yang langkah pertamanya mem-build image dengan toolkit ini.

Perintah Docker pendek yang dipakai build dan arsip image.

Tool cari-ganti yang saya pakai untuk mengganti nama di seluruh project; perintah build sengaja berhenti memakainya untuk nomor versi.

Setiap script mengikuti bentuk yang saya berikan pada setiap tool kecil, dalam varian Bash-nya.

Istilah

Tag image
Label sesudah titik dua pada nama image, di sini dipakai sebagai versi yang ditarik environment.
Registry
Server yang menyimpan image yang dipublikasikan, tempat staging dan production menariknya.
Modul
Satu service di dalam stack, dengan source, image, dan versinya sendiri.
Rebuild
Mem-build image lagi di bawah versi yang sudah dimilikinya, hanya diizinkan bila disengaja.
Pencocokan literal
Mencocokkan teks persis seperti tertulis, jadi titik berarti titik, bukan karakter apa pun.
Arsip image
Image yang disimpan ke file terkompresi, yang bisa dimuat di mesin lain dengan tag-nya tetap utuh.

Technologies covered

  • Bash
  • Rust
  • Docker
  • Docker Compose

About the author

Photo of Romi Fadli

Romi Fadli, S.Kom.

Solution Architect · Backend Engineer · Embedded Systems

In my day job I work as a solution architect. I design the system, lead the team that builds it — quality assurance, backend developers, a UI developer, DevOps and DevSecOps — and write the most critical modules myself, such as a certificate authority, a long-term PDF signer, and the core API of a personnel system.

I work across the whole stack that a running system actually needs. On the hardware side that means PCB design, microcontrollers, and embedded firmware — including RISC-V boards running FreeRTOS and Embassy, speaking MQTT over mutually authenticated TLS on a microcontroller with 64 KB of SRAM.

Most of my day-to-day work is software: Rust backends and API modules built on Clean Architecture, an OAuth2/OpenID Connect authorization server written from scratch, PAdES document signing, and certificate authorities — root CAs, timestamping authorities, and OCSP responders. I also build the frontends that sit on top of them.

Running all of that means infrastructure: Docker Compose stacks, networking, Mikrotik and RADIUS, observability with OpenTelemetry, and a steady habit of writing command-line tools and utilities for Linux when the existing ones do not fit.

Share

Enjoyed this?

Get an email when a new article is published.

Referenced by

A purple root circle linked to a blue and an orange intermediate circle, which lead to a signed document with a green seal and to a clock.

Aurograf

DevOps

Platform tanda tangan digital Pemerintah Kota Tangerang Selatan: penanda tangan membuktikan identitasnya, menandatangani PDF hingga PAdES B-LTA dengan sertifikat dari otoritas milik platform sendiri, dan siapa pun bisa memverifikasinya — versi 2, yang saya rancang, bangun, dan operasikan.

10 min read Read more →

Related Articles

A stack of Markdown documents and an orange arrow leading to a browser page with a side menu, a heading, paragraphs, a dark code panel, and a table of contents with its active entry highlighted

Satu script yang mengubah dokumentasi Markdown satu project menjadi situs statis yang terbuka dari folder tanpa server maupun internet: menu, daftar isi yang mengikuti pembaca, tabel yang tak pernah terpotong, kode dengan tombol salin, dan tautan yang tetap berfungsi.

7 min read Read more →
An old layout with a grey banner and a new structure with a green banner, each holding a blue database, a purple document store, and an orange telemetry store; three coloured paths pass through one export package marked with a green check

Empat perintah yang memindahkan stack dari layout lama ke struktur baru melintasi versi mayor: export tanpa mengubah data sumber, import tiap store sesuai cara yang diizinkan versinya, verifikasi apa yang benar-benar tiba, dan rename modul sambil memindahkan datanya.

11 min read Read more →
Four identical grey keys on the left each become a key of its own colour on the right, every new key marked with a green check; below, a purple key stays behind a red bar

Satu perintah yang merotasi kredensial internal satu environment kunci demi kunci: dry run sebagai default, backup lebih dulu, nilai unik untuk tiap kunci, login sungguhan untuk membuktikan tiap kredensial yang bisa dipakai login, dan rollback bagi yang gagal.

8 min read Read more →