Dapatkan nilai variabel lingkungan di Dockerfile

254

Saya sedang membangun wadah untuk aplikasi ruby. Konfigurasi aplikasi saya terkandung dalam variabel lingkungan (dimuat di dalam aplikasi dengan dotenv ).

Salah satu variabel konfigurasi tersebut adalah ip publik aplikasi, yang digunakan secara internal untuk membuat tautan. Saya perlu menambahkan entri dnsmasq yang menunjuk ip ini ke 127.0.0.1 di dalam wadah, sehingga ia dapat mengambil tautan aplikasi seolah-olah itu tidak di kemas.

Karena itu saya mencoba untuk mengatur ENVdi Dockerfile saya yang akan mengirimkan variabel lingkungan ke wadah.

Saya mencoba beberapa hal.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

Semuanya melewati string "REQUEST_DOMAIN" alih-alih nilai variabel lingkungan. Apakah ada cara untuk meneruskan nilai variabel lingkungan dari mesin host ke wadah?

Damien MATHIEU
sumber

Jawaban:

392

Anda harus menggunakan ARGarahan di Dockerfile Anda yang dimaksudkan untuk tujuan ini.

The ARGinstruksi mendefinisikan variabel yang pengguna dapat lulus pada build-waktu untuk pembangun dengan perintah buruh pelabuhan membangun menggunakan --build-arg <varname>=<value>bendera.

Jadi Dockerfile Anda akan memiliki baris ini:

ARG request_domain

atau jika Anda lebih suka nilai default:

ARG request_domain=127.0.0.1

Sekarang Anda dapat mereferensikan variabel ini di dalam Dockerfile Anda:

ENV request_domain=$request_domain

maka Anda akan membangun wadah Anda seperti ini:

$ docker build --build-arg request_domain=mydomain Dockerfile


Catatan 1: Gambar Anda tidak akan dibuat jika Anda telah mereferensikannya ARGdi Dockerfile Anda tetapi mengecualikannya di --build-arg.

Catatan 2: Jika pengguna menentukan argumen build yang tidak didefinisikan di Dockerfile, build mengeluarkan peringatan:

[Peringatan] Satu atau lebih build-args [foo] tidak dikonsumsi.

Daniel van Flymen
sumber
12
ARG tersedia mulai dari docker v1.9 dan seterusnya.
Synesso
Apakah ini didukung untuk dibangun dari jarak jauh di docker repo?
James Lin
4
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argAnda salah. Anda dapat membangun gambar dengan referensi bahkan tanpa --build-arg. Selain itu Anda dapat menetapkan nilai default untuk build arg.
ALex_hha
1
Apa tujuan dari jalur ENV? Bagi saya --build-arg + ARG sudah cukup.
Phil
3
ARG mendefinisikan variabel yang akan digunakan di dalam dockerfile dalam perintah selanjutnya. ENV mendefinisikan variabel lingkungan yang diteruskan ke wadah.
Herm
56

Jadi kamu bisa melakukan: cat Dockerfile | envsubst | docker build -t my-target -

Kemudian miliki Dockerfile dengan sesuatu seperti:

ENV MY_ENV_VAR $MY_ENV_VAR

Saya kira mungkin ada masalah dengan beberapa karakter khusus, tetapi setidaknya ini berfungsi untuk sebagian besar kasus.

jonasfj
sumber
13
Ini sepertinya tidak berfungsi jika Anda perlu MENAMBAH file dari direktori yang berisi Dockerfile.
Tom Hennen
2
Solusi yang sangat bagus! Di Mac Anda bisa mendapatkan envsubstsebagai bagian dari brew install gettext. Tetapi karena kemungkinan konflik dengan sistem pembangunan BSD itu adalah "keg-only" dan tidak ada symlnks yang dibuat. Namun, aman ln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/untuk menambahkan satu perintah itu ke PATH Anda. (Ini benar-benar libs yang perhatian.) Atau Anda dapat menggunakannya dalam nya /usr/local/Cellar/gettext/*/bin/envsubstlokasi
Bruno Bronosky
1
Untuk memperjelas komentar @ TomHennen, mengirim Dockerfile ke docker build -, khususnya, tidak berfungsi ketika Anda mereferensikan jalur relatif dari Dockerfile Anda, terlepas dari substitusi env var.
superEb
4
Re @ komentar TomHennen ini, jika Anda tidak ingin menggunakan perintah tergantung pada konteks seperti COPY di Dockerfile Anda Anda selalu bisa mengarahkan output dari envsubst ke file sementara dan kemudian makan yang menjadi docker buildgantinya. Contoh cat Dockerfile | envsubst > DockerfileWithEnvVarsdocker build -t my-target -f DockerfileWithEnvVars .rm DockerfileWithEnvVars
:,
Atau Anda dapat menggunakan spons dari paket envsubst < Dockerfile | sponge Dockerfile
moreutils
19

Alternatif menggunakan envsubsttanpa kehilangan kemampuan untuk menggunakan perintah seperti COPYatau ADD, dan tanpa menggunakan file perantara adalah dengan menggunakan Substitusi Proses Bash :

docker build -f <(envsubst < Dockerfile) -t my-target .
L. Alberto Giménez
sumber
3
sayangnya itu sepertinya tidak berhasil (Docker 17.09), saya mendapatkan kesalahanunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Alexander Klimetschek
11

Memuat variabel lingkungan dari file yang Anda buat saat runtime.

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF

... lalu di Dockerfile

ADD build /build
RUN /build/test.sh

di mana test.sh memuat MYVAR dari env.sh

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
Dan C
sumber
4

Jika Anda hanya ingin menemukan dan mengganti semua variabel lingkungan ($ ExampleEnvVar) di Dockerfile kemudian membangunnya, ini akan berhasil:

envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -

Snassr
sumber
Jawaban terbaik di sini, dan berdasarkan itu, mampu melakukan: di envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -mana FROMgaris menggunakan variabel lingkungan.
mikequentel
-6

tambahkan -ekunci untuk meneruskan variabel lingkungan ke wadah. contoh:

$ MYSQLHOSTIP=$(sudo docker inspect -format="{{ .NetworkSettings.IPAddress }}" $MYSQL_CONRAINER_ID)
$ sudo docker run -e DBIP=$MYSQLHOSTIP -i -t myimage /bin/bash

root@87f235949a13:/# echo $DBIP
172.17.0.2
Valentin Kantor
sumber
6
Damien ingin membangun sebuah gambar. -e bekerja dengan menjalankan perintah sebagai gantinya.
Andres Restrepo