Chapter Config dan Secret ditutup dengan satu janji yang sengaja digantung: Compose secrets di luar Swarm tidak mengenkripsi apa pun, dan keputusan arsitektur yang benar untuk produksi akan dibahas pada chapter ini. Sekarang saatnya menunaikan janji itu secara utuh. Password database, token API, kunci privat — sepanjang course ini semuanya berpindah tangan sebagai teks polos rahasia123 di environment variable, dan itu memang cukup untuk latihan; tetapi setiap tingkat kematangan infrastruktur menuntut perlakuan yang berbeda terhadap barang berbahaya ini. Chapter ini menyusun enam tingkat penyimpanan rahasia sebagai tangga — dari hardcode yang harus tidak pernah dilakukan sampai secret manager produksi — lalu menutupnya dengan dua keterampilan yang sering terlupakan: rotasi terjadwal dan pemburuan rahasia yang lolos ke dalam image.
Tangga Enam Tingkat Penyimpanan Rahasia #
| Tingkat | Contoh bentuknya | Nilai keamanan |
|---|---|---|
| 1 — Hardcode di Dockerfile | ENV POSTGRES_PASSWORD=rahasia123 | tidak ada: tertanam permanen di layer image |
| 2 — Environment variable runtime | docker run -e POSTGRES_PASSWORD=... | rendah: terbaca docker inspect |
3 — Berkas .env + interpolasi | ${POSTGRES_PASSWORD} di compose.yaml | sedang: nilai keluar dari repository, tetap teks polos di disk |
| 4 — Compose secrets | POSTGRES_PASSWORD_FILE=/run/secrets/db_password | baik untuk development: berkas, per-service, read-only |
| 5 — Secret saat build | docker build --secret id=token_npm,env=TOKEN_NPM | baik untuk CI: hangus setelah build |
| 6 — Secret manager | Vault, SOPS, sidecar penyuntik | produksi: terpusat, terenkripsi, diaudit, bisa dirotasi |
Enam baris tabel itu bukan pilihan yang setara — tabelnya adalah tangga yang dinaiki sesuai kematangan lingkungan, dan tiga tingkat pertama punya cacat yang perlu kita buktikan supaya alasan menaikinya bukan dogma.
Tingkat 1 — Hardcode di Dockerfile #
Tingkat paling bawah sekaligus paling berbahaya: menuliskan rahasia langsung di Dockerfile, baik lewat ENV maupun ARG. Kita sudah menyaksikan nasibnya pada Chapter Secret dan SSH Mount: docker history menampilkan setiap instruksi build secara terbuka termasuk nilai ARG dan ENV — token npm rahasia123 terpampang sebagai baris riwayat tersendiri. Layer image bersifat permanen: meski baris berikutnya menghapus berkasnya, layer yang memuat nilai rahasia tetap ada dan bisa diekstrak siapa pun yang memegang image — bahkan setelah image didorong ke registry.
Tingkat 2 — Environment Variable Saat Runtime #
Naik satu anak tangga: nilai tidak lagi tertanam di image, melainkan disuntikkan saat container diciptakan lewat -e. Masalahnya, nilai itu menempel pada konfigurasi container — dan konfigurasi container terbaca siapa pun yang memiliki akses Docker. Kita buktikan dengan container db yang menyala dengan password polos:
$ docker run -d --name db \
-e POSTGRES_USER=katalog -e POSTGRES_PASSWORD=rahasia123 -e POSTGRES_DB=katalog \
postgres:18-alpineOutput yang Dihasilkan:
3f9c1e7a2b84d5c06e8f1a3b7d9c2e4f5a6b8d0c2e4f6a8b1d3c5e7f9a0b2d4c$ docker inspect db --format '{{range .Config.Env}}{{println .}}{{end}}'Output yang Dihasilkan:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PGDATA=/var/lib/postgresql/data
POSTGRES_USER=katalog
POSTGRES_PASSWORD=rahasia123
POSTGRES_DB=katalogMari kita telaah kebocoran di dalam output tersebut:
- Format template mengiterasi
.Config.Env—rangemenyusuri daftar environment container danprintlnmencetak satu entri per baris; tanpa satu pun enkripsi, karena memang tidak ada yang bisa dienkripsi di sini. POSTGRES_PASSWORD=rahasia123terpampang polos — siapa pun yang bisa menjalankandocker inspectmembaca password dalam sekejap; dan mengingat keanggotaan grup docker setara root host pada Chapter Mengatur Akses Docker, “siapa pun” berarti semua orang yang layak kita curigai.- Environment diwariskan ke seluruh proses turunan — skrip diagnostik, tool pihak ketiga, sampai crash dump ikut membawa nilai itu; environment variable adalah medium yang paling mudah bocor secara tidak sengaja.
Container uji ini kita bersihkan dengan docker rm -f db — penelitiannya selesai, tidak ada alasan membiarkannya menyala.
Tingkat 3 — Berkas .env dan Interpolasi Compose #
Tangga berikutnya memindahkan nilai keluar dari perintah dan berkas project: nilai hidup di berkas .env, dan compose.yaml hanya memuat interpolasi ${POSTGRES_PASSWORD} — mekanisme yang sudah kita bedah tuntas pada Chapter Environment dan env File. Nilai tidak pernah tertulis di repository, dan berbagi konfigurasi antar anggota tim menjadi soal berbagi satu berkas kecil. Cacatnya tetap sama: isi .env masih teks polos di disk, dan justru karena itu berkas ini mesti dijaga ketat.
Tingkat 4 — Compose Secrets #
Mekanisme secrets Compose mengubah pembawa rahasia dari string environment menjadi berkas read-only di /run/secrets/<nama> — pola yang sudah kita bangun pada Chapter Config dan Secret. Bentuk panjang deklarasinya membuka tiga pengencangan tambahan:
services:
db:
image: postgres:18-alpine
environment:
POSTGRES_USER: katalog
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
POSTGRES_DB: katalog
secrets:
- source: db_password
target: db_password
mode: 0400
secrets:
db_password:
file: ./db_password.txtMari kita telaah tiga pengencangan tersebut:
POSTGRES_PASSWORD_FILE— pola*_FILEpada image resmi postgres: entry point membaca isi berkas sebagai password, sehingga string polos tidak pernah menempel pada environment container dan lolos daridocker inspectseperti demo tingkat dua.mode: 0400— bit izin pemasangan: hanya pemilik berkas yang boleh membaca; tanpa kunci ini mode bawaan lebih longgar dan seluruh proses di dalam container bisa membacanya.- Hanya service yang mendeklarasikan —
webyang tidak memuat bloksecretstidak akan pernah melihat/run/secrets/db_password; rahasia berhenti menyebar ke service yang tidak membutuhkannya, tidak seperti.envyang cenderung dibaca semua service.
Tingkat 5 — Secret yang Hangus Setelah Build #
Rahasia bertipe lain muncul saat build: token npm untuk registry privat, kunci SSH untuk repositori privat. Solusinya adalah --mount=type=secret yang sudah kita praktikkan pada Chapter Secret dan SSH Mount: nilai dikirim dari mesin build ke instruksi RUN tertentu sebagai berkas sementara, tidak pernah meninggalkan jejak di layer maupun docker history, dan hangus begitu instruksi selesai. Pola docker build --secret id=token_npm,env=TOKEN_NPM inilah standar untuk CI: token hidup sebagai environment variable rahasia di runner, bukan di image hasilnya.
Tingkat 6 — Secret Manager untuk Produksi #
Tingkat teratas menyerahkan penyimpanan sepenuhnya ke sistem yang memang dibangun untuk itu: Vault menyimpan rahasia terpusat dengan enkripsi, kebijakan akses, dan audit log; SOPS mengenkripsi berkas rahasia langsung di repository sehingga aman di-commit; sidecar atau init container menyuntikkan nilai ke aplikasi tepat sebelum menyala. Pola yang sama menyelesaikan dua masalah yang tingkat di bawahnya tidak sanggup: siapa yang mengakses rahasia menjadi tercatat, dan rotasi menjadi operasi satu titik, bukan suntingan berkas di lusinan mesin.
docker secret di Swarm #
Docker sendiri membawa mekanisme tingkat enam lahirnya: pada cluster Swarm, objek docker secret disimpan terenkripsi di log Raft para manajer, didistribusikan hanya ke node yang menjalankan service penerimanya, dan dipasang sebagai berkas di /run/secrets/<nama>:
$ docker secret create db_password db_password.txtOutput yang Dihasilkan:
2e48e91c2d8169d71aff774c97636d428aa7313d0077fe9a832db39f37cc04eeOutput tersebut adalah ID secret yang baru diciptakan — satu-satunya jejak yang terlihat di terminal, karena isinya memang tidak pernah ditampilkan lagi. Service kemudian menerima secret itu lewat flag --secret pada docker service create. Seluruh upacara orchestration-nya — Raft, node manajer, service — adalah wilayah Chapter Docker Swarm di Section Orchestration dan Ekosistem.
Rotasi Rahasia #
Rahasia yang tidak pernah berganti adalah kredensial yang bocor diam-diam bertahun-tahun. Rotasi yang sehat punya jadwal — misalnya setiap 90 hari, dan seketika setelah indikasi kebocoran — dengan prosedur tiga langkah. Pertama, nilai baru disiapkan di sumbernya: berkas db_password.txt ditulis ulang, atau versi baru dibuat di secret manager. Kedua, container diciptakan ulang agar secret terpasang ulang:
$ docker compose up -d dbOutput yang Dihasilkan (dipotong):
[+] Running 1/1
✔ Container katalog-db-1 Recreated
...Ketiga, database diajak berganti kata sandinya sendiri, karena password yang tersimpan di cluster tidak ikut terganti hanya karena berkas secret berganti:
$ docker compose exec db psql -U katalog -c "ALTER ROLE katalog WITH PASSWORD 'rahasia456';"Output yang Dihasilkan:
ALTER ROLEPadanan untuk cluster yang memakai superuser bawaan adalah ALTER ROLE postgres WITH PASSWORD '...'; — mekanismanya identik, hanya nama perannya yang berbeda.
Blast radius rotasi perlu dipikirkan sebelum tombol ditekan, bukan sesudahnya. Ketika ALTER ROLE dijalankan, aplikasi yang masih memegang password lama langsung gagal autentikasi — dan bila yang dirotasi adalah token yang dipakai lima service, lima service jatuh bersamaan. Karena itu rotasi produksi dilakukan bertahap: ganti satu service dalam satu waktu, dan pastikan alarm kegagalan autentikasi menyala sebelum pelanggan melakukannya. docker compose up -d db pada contoh kita hanya menciptakan ulang satu container, dan justru itu intinya: desain yang baik membuat rotasi menyinggung permukaan sekecil mungkin.
Memburu Rahasia yang Lolos #
Tangga di atas mengatur rahasia yang kita ketahui; musuh yang sebenarnya adalah yang lolos tanpa sepengetahuan kita — image lama kolega, layer warisan, token di log build tahun lalu. Kebiasaan auditnya dua lapis: docker history image:tag dibaca teliti untuk nilai yang mencurigakan pada baris ENV dan ARG, dan pemindai seperti Trivy atau Docker Scout — bahasan penuh chapter berikutnya — memeriksa image secara otomatis.
Rekomendasi per Lingkungan #
| Lingkungan | Tingkat yang layak | Catatan |
|---|---|---|
| Latihan pribadi | 2-3 | nyaman, tanpa data nyata |
| Development tim | 3-4 | .env dijaga gitignore, secret per-service |
| Build CI | 5 | token hidup sebagai environment rahasia runner |
| Staging | 4, menyiapkan 6 | perlakuan mendekati produksi |
| Produksi | 6 + rotasi terjadwal | audit log dan blast radius menjadi wajib |
Rahasia kini tertata di seluruh daur hidupnya: tidak tertanam di image, tidak terpampang di environment, dan berganti secara terjadwal. Namun isi image itu sendiri belum pernah kita periksa. Image katalog-web:2.0 yang kita bangun dari node:22-alpine membawa ratusan paket, dan sebagian dari mereka mungkin membawa cacat yang sudah dikenal dunia dengan nomor dan tingkat keparahannya. Chapter Image Scanning memperkenalkan CVE, SBOM, dan cara Docker Scout membaca isi image sebelum image itu menyentuh server produksi.
Referensi #
- Docker secrets di Swarm — mekanisme secret terenkripsi Raft dan distribusinya ke node.
- Build Secrets
— pola
--secretdengan sumber environment dan berkas. - Secrets — Compose File Reference
— deklarasi teratas
secrets, kuncifile,mode, dan path bawaan.