[Diposting-silang dan diedit dari https://stackoverflow.com/questions/21933955 karena dianggap terlalu sysadmin untuk StackOverflow.]
Saya memiliki wadah buruh pelabuhan yang menjalankan Nginx, yang menghubungkan ke wadah buruh pelabuhan lainnya. Nama host dan alamat IP wadah kedua dimuat ke wadah Nginx sebagai variabel lingkungan saat startup, tetapi tidak tahu sebelumnya (dinamis). Saya ingin saya nginx.conf
menggunakan nilai-nilai ini - misalnya
upstream gunicorn {
server $APP_HOST_NAME:$APP_HOST_PORT;
}
Bagaimana saya bisa memasukkan variabel lingkungan ke dalam konfigurasi Nginx saat startup?
EDIT 1
Ini adalah seluruh file, setelah jawaban yang disarankan di bawah ini:
env APP_WEB_1_PORT_5000_TCP_ADDR;
# Nginx host configuration for django_app
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location /static/ {
alias /app/static/;
}
location /media/ {
alias /app/media/;
}
location / {
proxy_pass http://gunicorn;
}
}
Muat ulang nginx lalu galat:
$ nginx -s reload
nginx: [emerg] unknown directive "env" in /etc/nginx/sites-enabled/default:1
EDIT 2: lebih detail
Variabel lingkungan saat ini
root@87ede56e0b11:/# env | grep APP_WEB_1
APP_WEB_1_NAME=/furious_turing/app_web_1
APP_WEB_1_PORT=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP=tcp://172.17.0.63:5000
APP_WEB_1_PORT_5000_TCP_PROTO=tcp
APP_WEB_1_PORT_5000_TCP_PORT=5000
APP_WEB_1_PORT_5000_TCP_ADDR=172.17.0.63
Rooting nginx.conf:
root@87ede56e0b11:/# head /etc/nginx/nginx.conf
user www-data;
worker_processes 4;
pid /var/run/nginx.pid;
env APP_WEB_1_PORT_5000_TCP_ADDR;
Konfigurasi nginx situs:
root@87ede56e0b11:/# head /etc/nginx/sites-available/default
# Django app is served by Gunicorn, running under port 5000 (via Foreman)
upstream gunicorn {
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
}
server {
listen 80;
Muat ulang konfigurasi nginx:
root@87ede56e0b11:/# nginx -s reload
nginx: [emerg] directive "server" is not terminated by ";" in /etc/nginx/sites-enabled/default:3
server $ENV{"APP_WEB_1_PORT_5000_TCP_ADDR"}:5000;
denganserver app_web_1:5000;
app_web_1
me- restart itu akan mendapatkan alamat IP baru, jadi Anda perlu me-restart wadah nginx Anda juga. Docker akan memulai ulang dengan yang diperbarui/etc/hosts
sehingga Anda tidak perlu mengubah file konfigurasi nginx.Jawaban:
Dari file docker Nginx resmi:
Memperbarui:
Tapi Anda tahu ini disebabkan oleh variabel Nginx-nya seperti ini:
rusak untuk:
Jadi, untuk mencegahnya, saya menggunakan trik ini:
Saya memiliki skrip untuk menjalankan Nginx, yang digunakan pada
docker-compose
file sebagai opsi perintah untuk server Nginx, saya menamainyarun_nginx.sh
:Dan karena ditentukannya
DOLLAR
variabel baru padarun_nginx.sh
skrip, sekarang kontennginx.conf.template
file saya untuk variabel Nginx itu sendiri adalah seperti ini:Dan untuk variabel yang saya tetapkan adalah seperti ini:
Juga di sini , ada kasus penggunaan nyata saya untuk itu.
sumber
proxy_set_header Host $http_host;
command: /bin/bash -c "envsubst '$VAR1 $VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
berfungsi untuk saya b / c Saya tahu apa itu namanya ...$
, haruscommand: /bin/bash -c "envsubst '\$VAR1 \$VAR2' < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
CMD ["/bin/sh","-c", "if [ -n \"${SOME_ENV}\" ]; then echo envsubst '${SOME_ENV}' with ${SOME_ENV} && envsubst '${SOME_ENV}' < /etc/nginx/conf.d/default.template > /etc/nginx/conf.d/default.conf; fi ; nginx -g 'daemon off;'"]
Melakukan ini dengan Lua jauh lebih mudah daripada kedengarannya:
Saya menemukan itu di sini:
https://docs.apitools.com/blog/2014/07/02/using-environment-variables-in-nginx-conf.html
Sunting:
Rupanya ini membutuhkan pemasangan modul lua: https://github.com/openresty/lua-nginx-module
Edit 2:
Perhatikan bahwa dengan pendekatan ini Anda harus mendefinisikan
env
variabel dalam Nginx:Anda harus melakukan ini dalam konteks tingkat atas
nginx.conf
atau tidak akan berhasil! Tidak di blok server atau dalam konfigurasi beberapa situs di/etc/nginx/sites-available
, karena dimasukkan olehnginx.conf
dalamhttp
konteks (yang bukan konteks tingkat atas).Perhatikan juga bahwa dengan pendekatan ini jika Anda mencoba membuat pengalihan misalnya:
itu tidak akan berfungsi juga:
Dan jika Anda memberikan nama variabel yang terpisah untuk itu:
nginx tidak akan menafsirkannya dan akan mengarahkan Anda ke
https://%24server_name_from_env/
.sumber
env NGINX_SERVERNAME
suatu tempat di nginx.conf Anda.set_by_lua
variabel di file config yang disertakan, sedangkanenv MY_VAR
deklarasi ada di nginx.conf utama, seperti yang disarankan. Sayang sekali, ini akan menjadi solusi terbersih!envsubst
? Saya kira pro adalah Anda tidak perlu menjalankanenvsubstr
perintah sebelum memulai server dan con adalah bahwa Anda perlu menginstal modul lua? Saya ingin tahu apakah ada implikasi keamanan pada kedua pendekatan tersebut?envsubst
dan yang tidak boleh digunakan dalam kasus sayaSaya menulis sesuatu yang mungkin atau mungkin tidak membantu: https://github.com/yawn/envplate
Ini inline mengedit file konfigurasi dengan referensi $ {key} ke variabel lingkungan, secara opsional membuat backup / mencatat apa yang dilakukannya. Ini ditulis dalam Go dan biner statis yang dihasilkan dapat dengan mudah diunduh dari tab rilis untuk Linux dan MacOS.
Itu juga dapat mengeksekusi () proses, mengganti default, log dan memiliki semantik kegagalan yang masuk akal.
sumber
Gambar nginx resmi merekomendasikan penggunaan
envsubst
, tetapi seperti yang ditunjukkan oleh orang lain itu akan menggantikan juga$host
dan variabel lain, yang tidak diinginkan. Tapi untungnyaenvsubst
bisa mengambil sebagai parameter nama variabel untuk diganti .Untuk menghindari parameter perintah yang sangat kompleks ke wadah (seperti dalam contoh yang ditautkan), Anda dapat menulis skrip entri titik Docker yang akan mengisi variabel lingkungan sebelum menjalankan perintah. Script entrypoint juga merupakan tempat yang baik untuk memvalidasi parameter dan menetapkan nilai default.
Berikut adalah contoh wadah nginx yang menerima
API_HOST
danAPI_PORT
parameter sebagai variabel lingkungan.nginx-default.conf.template
docker-entrypoint.sh
Dockerfile
sumber
Apa yang saya lakukan adalah menggunakan erb !
--Setelah menggunakan erb
Ini digunakan dalam Cloudfoundry staticfile-buildpack
Contoh konfigurasi nginx: https://github.com/cloudfoundry/staticfile-buildpack/blob/master/conf/nginx.conf
Dalam kasus Anda
menjadi
sumber
Mengacu pada jawaban tentang menggunakan erb, itu bisa dilakukan seperti di bawah ini.
Tulis file konfigurasi NGINX sebagai file erb yang berisi variabel lingkungan, dan evaluasi dengan menggunakan perintah erb ke file konfigurasi normal.
Di dalam blok server dari file nginx.conf.erb mungkin ada
sumber
erb
melakukan substitusi variabel ... setelah wadah dimulai, kan?) -erb
apakah ini benar-benar Ruby: stuartellis.name/articles/erbSaya tahu ini adalah pertanyaan lama, tetapi untuk berjaga-jaga seandainya seseorang menemukan ini (seperti yang saya miliki sekarang), ada cara yang jauh lebih baik untuk melakukan ini. Karena buruh pelabuhan memasukkan alias penampung yang tertaut di / etc / hosts, Anda bisa melakukannya
dengan asumsi perintah buruh pelabuhan Anda adalah sesuatu seperti
docker run --link othercontainer:docker_link_alias nginx_container
.sumber
Pilihan lain ... Saya baru saja menemukan alat ini hari ini: https://github.com/kreuzwerker/envplate ... Ditulis dalam Go, ini dapat diinstal dengan sangat mudah. Menggunakannya cukup sederhana. Meskipun Anda perlu menempatkan variabel template di nginx.conf Anda.
Misalnya
${SOME_ENV_VAR}
akan diganti ketikaep
perintah envplate dipanggil pada file. Jadi seandainya Dockerfile Anda gagal mendapatkan biner itu atau seandainya itu tidak berjalan karena suatu alasan, itu akan membuat konfigurasi Anda tidak valid. Hanya sedikit catatan dibandingkan dengan solusi lain seperti menggunakan ekstensi perl atau lua.Saya sangat suka bagaimana Anda dapat mengatur nilai default juga ketika variabel lingkungan tidak diatur. Ex.
${SOME_ENV_VAR:default-value}
(dan Anda dapat menghindari nilai). Sekali lagi, envplate harus tetap berhasil dijalankan.Salah satu manfaat menggunakan pendekatan seperti ini adalah Anda tidak berakhir dengan gambar Docker yang lebih besar dari yang diperlukan karena Anda menginstal semua jenis modul tambahan yang tidak Anda perlukan. Mungkin juga lebih mudah daripada menggunakan sed jika segala sesuatu mulai menjadi kompleks dan itu berisi fungsionalitas nilai default itu.
sumber
Saya menyelesaikan ini menggunakan skrip shell.
Ini template nginx:
Dan skrip untuk mengganti variabel lingkungan ada di sini:
sumber
Kemungkinan lain adalah dengan menggunakan perintah 'sed' dengan ekspresi reguler, maka Anda tidak perlu mengacaukan file konfigurasi Anda sama sekali! Dengan begitu Anda dapat menggunakan file konfigurasi Anda secara normal, tetapi ketika Anda menjalankan buruh pelabuhan, itu akan menukar nilai-nilai dengan variabel env. Tidak satu pun dari ini "tambahkan string teks ke file konfigurasi Anda yang Anda cari dan gantikan dengan."
Anda dapat membuat file run.sh dengan nilai penggantian menggunakan variabel lingkungan Anda.
Untuk mengubah "7s" pada baris ini:
Sed Perintah menggunakan client_body_timeout sebagai baris pencarian dan $ client_body_timeout sebagai variabel env pengganti:
Salin / rekatkan baris ini untuk setiap parameter yang ingin Anda atur dan ubah client_body_timeout dengan opsi konfigurasi dan $ client_body_timeout dengan variabel env yang dikaitkan dengannya. Gunakan dengan file konfigurasi yang ada dan itu hanya akan berfungsi.
sumber
Berikut adalah contoh penggunaan
sed
pendekatan, tidak selalu lebih baik tetapi mungkin bermanfaat bagi sebagian orang. Pertama, tambahkan kata kunci khusus untuk diganti dalam file conf. Kedua, buat dockerfile yang mendeklarasikanENV
variabel dan kemudianCMD
yang digunakansed
untuk mengedit konfigurasi sebelum menjalankan nginx secara eksplisit.Jadi misalkan default.conf Anda berisi ini dengan kata kunci
docker_host
:Dan tulis Dockerfile Anda mirip dengan:
Kemudian bangun gambar dan jalankan wadah menggunakan
sumber
Cara yang tepat untuk melakukan ini dengan lua, karena jawaban di atas basi:
sumber
Anda harus dapat melakukan apa yang Anda inginkan dengan templat Dockerize .
sumber