Satu Dockerfile sering kali perlu digunakan untuk beberapa konfigurasi, misalnya port yang berbeda antara lingkungan pengujian dan produksi. Docker menyediakan dua mekanisme untuk keperluan itu, yaitu ARG untuk nilai yang terbaca saat build dan ENV untuk nilai yang terbaca saat container berjalan. Topik ini membahas cara menetapkan dan mengisi keduanya, tabel perbedaannya, serta jebakan yang menyertainya. Contoh yang digunakan kembali adalah image aplikasi catatan, yang membaca port dari variabel lingkungan APP_PORT.
ARG, konfigurasi saat build#
ARG mendeklarasikan variabel yang dapat diisi saat build melalui opsi --build-arg. Nilai ARG terbaca mulai baris deklarasinya hingga akhir tahap build, sehingga instruksi yang berada di atas deklarasi belum dapat menggunakannya. Apabila tidak diisi, nilai default pada deklarasi yang digunakan.
ARG APP_PORT=8000
RUN echo "membangun untuk port ${APP_PORT}"# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# mengisi ARG saat build dengan --build-arg
docker build --build-arg APP_PORT=9000 -t aplikasi-catatan .Nilai yang diisi lewat --build-arg hanya berlaku selama build. Nilai tersebut tidak tersimpan pada konfigurasi image, sehingga proses yang berjalan di dalam container tidak pernah melihatnya. Karena itu, ARG cocok untuk hal yang hanya diperlukan saat membangun, misalnya versi paket atau varian image.
ENV, konfigurasi saat berjalan#
ENV menetapkan variabel lingkungan yang tersimpan pada konfigurasi image dan diwarisi setiap proses di dalam container. Nilainya dapat diisi ulang per container melalui opsi -e pada docker run tanpa membangun ulang image. Untuk aplikasi Python, ENV juga lazim digunakan untuk mengatur perilaku pustaka, misalnya PYTHONDONTWRITEBYTECODE=1 yang mencegah Python menulis berkas .pyc saat berjalan.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# mengisi ulang ENV saat container berjalan dengan opsi -e
docker run --rm -e APP_PORT=9100 -p 9100:9100 aplikasi-catatanKonfigurasi yang perlu terbaca saat build sekaligus saat berjalan ditangani dengan menyalin nilai ARG ke ENV, sebagaimana Dockerfile berikut.
# Image dasar: Python 3.12 varian slim berbasis Debian
FROM python:3.12-slim
# ARG terbaca saat build dan diisi lewat --build-arg
ARG APP_PORT=8000
# Nilai ARG disalin ke ENV agar terbaca saat container berjalan
ENV APP_PORT=${APP_PORT}
ENV PYTHONDONTWRITEBYTECODE=1
WORKDIR /aplikasi
COPY app.py .
CMD ["python3", "app.py"]ARG APP_PORT=8000 terbaca saat build dan dapat diisi ulang lewat --build-arg, sedangkan ENV APP_PORT=${APP_PORT} menyalin nilai yang sudah terisi ke konfigurasi image. Aplikasi membaca APP_PORT saat menyala, sehingga port dapat ditentukan saat build dan diganti lagi saat container berjalan.
Pembacaan variabel lingkungan oleh aplikasi dapat diperagakan langsung tanpa Docker. Dua eksekusi berikut memanggil logika yang sama dengan app.py, satu dengan variabel terisi dan satu tanpa variabel.
# variabel lingkungan terbaca oleh proses aplikasi saat berjalan
APP_PORT=9100 python3 -c "import os; print(int(os.environ.get('APP_PORT', '8000')))"
# tanpa variabel lingkungan, nilai default digunakan
python3 -c "import os; print(int(os.environ.get('APP_PORT', '8000')))"9100
8000Proses pertama membaca APP_PORT bernilai 9100 dari lingkungannya, sedangkan proses kedua menggunakan nilai default 8000. Inilah cara ENV berperan dari sudut pandang aplikasi, yaitu sebagai variabel lingkungan biasa yang dibaca saat proses menyala.
Perbedaan ARG dan ENV#
Tabel berikut merangkum perbedaan keduanya.
| Aspek | ARG | ENV |
|---|---|---|
| Saat terbaca | Selama build | Saat container berjalan |
| Cara mengisi | Opsi --build-arg pada docker build | Deklarasi pada Dockerfile, diisi ulang dengan opsi -e |
| Tersimpan pada konfigurasi image | Tidak | Ya |
| Terbaca oleh proses aplikasi | Tidak | Ya |
| Kegunaan lazim | Versi paket, varian image, opsi saat build | Port, mode aplikasi, perilaku pustaka |
Keduanya saling melengkapi. ARG mengatur pembangunan, sedangkan ENV membawa konfigurasi ke dalam container. Pola ARG diikuti ENV menjembatani keduanya apabila satu nilai diperlukan pada dua sisi, sebagaimana pola APP_PORT pada Dockerfile di atas.
Karena jejak tersebut, rahasia tidak pernah ditampung pada saat build maupun pada ENV image. Konfigurasi sensitif disuntikkan saat container berjalan dari penyimpanan yang dikelola khusus, dan pembahasannya lebih jauh ada pada modul Keamanan dan CI.
ARG pada build multi-stage#
Cakupan ARG berakhir di batas tahap pada build multi-stage, yaitu Dockerfile dengan beberapa instruksi FROM. Variabel yang dideklarasikan pada tahap pertama tidak otomatis terbaca pada tahap berikutnya, sehingga nilai yang dibutuhkan lintas tahap dideklarasikan ulang di masing-masing tahap.
FROM python:3.12-slim AS build
ARG APP_PORT=8000
RUN echo "tahap build memakai port ${APP_PORT}"
FROM python:3.12-slim
# deklarasi ulang diperlukan, baik tanpa nilai default maupun dengan nilai
ARG APP_PORT=8000
ENV APP_PORT=${APP_PORT}
COPY app.py .
CMD ["python3", "app.py"]Deklarasi ulang tanpa nilai default juga sah, yaitu ARG APP_PORT tanpa tanda sama dengan. Bentuk ini menyalin nilai yang diisi lewat --build-arg dari tahap sebelumnya, sedangkan bentuk dengan nilai default akan menimpanya. Tanpa deklarasi ulang, ${APP_PORT} pada tahap kedua bernilai string kosong, sehingga ENV APP_PORT= menyimpan nilai kosong dan aplikasi menggunakan nilai defaultnya sendiri. Perilaku ini mudah disalahpahami saat pertama ditemui, padahal sumbernya hanyalah batas cakupan variabel.
Kesalahan umum#
- Mengharapkan ARG terbaca oleh aplikasi di dalam container. ARG hanya berlaku saat build, sehingga proses yang berjalan menerima string kosong atau tidak menerima variabelnya sama sekali. Perbaikannya adalah menyalin nilai ke ENV dengan pola
ARG APP_PORT=8000diikutiENV APP_PORT=${APP_PORT}. - Menggunakan variabel sebelum deklarasinya. Instruksi yang memakai
${APP_PORT}di atas barisARG APP_PORTmenghasilkan string kosong tanpa pesan error apa pun. Deklarasi selalu diletakkan di atas penggunaan pertamanya. - Menampung kredensial pada ARG karena terasa sementara. Nilai itu tetap terbaca pada
docker historydan sering ikut tersalin ke cache build, sehingga jebakannya sama dengan ENV. Bagian Penanganan Secret pada modul Keamanan dan CI membahas jalur yang benar.
Ringkasan#
- ARG diisi saat build lewat
--build-argdan hanya terbaca mulai deklarasinya hingga akhir tahap build, tanpa melewati batas FROM. - ENV tersimpan pada konfigurasi image, diwarisi proses di dalam container, dan dapat diisi ulang per container dengan opsi
-e. - Pola ARG diikuti ENV menjembatani konfigurasi saat build dan saat berjalan, sedangkan rahasia tidak pernah ditampung pada keduanya.
Referensi#
- Build variables — Docker Docs — Menjelaskan ARG dan ENV, cakupan masing-masing, serta perbedaannya.
- Dockerfile reference — Docker Docs — Menetapkan sintaks ARG, nilai default, dan cakupannya pada Dockerfile.
- Dockerfile reference — Docker Docs — Menetapkan sintaks ENV dan cara nilai diwariskan ke container.