Compose: Interpolasi variabel lingkungan di docker-compose.yml

Dibuat pada 30 Apr 2015  ·  109Komentar  ·  Sumber: docker/compose

(Saya membuat masalah baru untuk ini karena yang lama telah mengumpulkan cukup banyak bagasi.)

Dimungkinkan untuk meneruskan variabel lingkungan ke nilai entri konfigurasi apa pun * di docker-compose.yml . Banyak orang ingin melakukannya, ini bagus untuk portabilitas dan saya puas itu tidak akan menyebabkan kekacauan.

Saya punya beberapa perhitungan.

Variabel yang diperlukan dan default opsional

Sangat berguna untuk dapat menetapkan bahwa variabel yang _must_ ada di lingkungan, yaitu Compose akan menolak untuk dijalankan jika tidak. Namun, ini akan merepotkan ketika Anda memiliki banyak dari mereka, jadi itu harus menjadi sesuatu yang Anda aktifkan secara eksplisit, atau mungkin untuk menentukan nilai default.

Implementasi MVP tidak perlu memiliki salah satu fitur, tetapi harus ada jalur yang jelas untuk mengimplementasikan keduanya dengan cara yang kompatibel dengan versi sebelumnya.

Sintaksis

Ada alasan kuat untuk menerapkan standar yang ditetapkan, selama itu tidak kelas berat - persyaratan fungsionalitas kami minimal.

  • Perluasan parameter POSIX tidak masalah. Ini memiliki terlalu banyak fitur, tetapi kami dapat menerapkan subset di antaranya:

    • ${VARIABLE} - mengeluarkan string kosong jika VARIABLE tidak disetel

    • ${VARIABLE-default} - keluaran default jika VARIABLE tidak disetel

    • ${VARIABLE?} - kesalahan muncul jika VARIABLE tidak disetel

https://github.com/docker/compose/pull/845 menerapkan sintaks ${VARIABLE:default} gaya Bash, yang mirip dengan perluasan parameter POSIX tetapi sedikit berbeda.

  • Sintaks format Python akan sepele untuk diterapkan, tetapi terkait dengan bahasa Python, dan memiliki terlalu banyak fitur.

Penerapan

Fungsi Python os.path.expandvars mengimplementasikan kasus paling dasar dari ekspansi parameter POSIX:

>>> from os.path import expandvars
>>> expandvars('${HOME}')
'/Users/aanand'

Namun, ada setidaknya 2 masalah:

  1. Variabel yang tidak disetel tidak meluas menjadi string kosong - sebaliknya, tidak menghasilkan perluasan:

``

expandvars ('$ {UNSET}')
'$ {UNSET}'
``

  1. Sintaks yang rusak tidak salah - sebagai gantinya, itu juga menghasilkan tidak ada perluasan:

``

expandvars ('$ {HOME')
'$ {HOME'
``

Sejauh ini, https://github.com/docker/compose/pull/845 adalah yang paling dekat yang kami miliki, tetapi saya pada dasarnya waspada terhadap penerapan yang mengandalkan ekspresi reguler. Membuat template adalah pekerjaan yang tidak sepele, dan orang-orang akan memasukkan semua jenis hal yang rusak, jadi kami membutuhkan sesuatu yang kuat, ketat, dan kesalahan dengan pesan yang membantu. Dua persyaratan penting:

  • Jika seseorang memasukkan sesuatu dalam format yang salah, Tulis tidak akan berjalan.
  • Dimungkinkan untuk melepaskan salah satu karakter khusus yang digunakan dalam sintaks template.

Mungkin sudah ada implementasi Python yang bagus dari interpolasi variabel mirip-Bash di luar sana - jika tidak, membuat sesuatu yang berdiri sendiri akan jauh lebih disukai daripada membengkak basis kode Compose.

* Sebenarnya, apakah ada kunci konfigurasi yang _shouldn't_ kami izinkan untuk interpolasi?

kinenhancement kinfeature

Komentar yang paling membantu

Kasus penggunaan saya adalah mengizinkan $PWD dalam volumes , sehingga setiap pengembang dalam tim dapat mengkloning repo ke mana pun dan jalur masih dapat dipasang dengan benar.

elasticsearch:
  image: zinvoice/elasticsearch
  volumes:
    - $PWD:/app

Semua 109 komentar

Seberapa jauh Anda ingin melangkah dengan standar UNIX yang sudah mapan ini? (FWIW, ini bukan standar defacto, ini standar sebenarnya.)

Sebagai seseorang yang secara tidak sengaja mencoba menggunakan perluasan parameter POSIX di Dockerfiles, jika semuanya didukung di docker-compose.yml, itu akan membuat saya menjadi kemping yang bahagia.

@kojiromike Hmm, jadi ekspansi parameter POSIX sebenarnya adalah tujuan saya, tetapi membaca dokumen sepertinya saya salah mengingat sintaks / semantik.

Edit: Saya telah memperbarui pemikiran saya tentang sintaks dalam deskripsi.

Saya telah mengikuti utas lama dan kami sangat ingin memiliki fitur ini. Akhirnya rasa sakitnya terlalu besar dan kami membuat skrip bahs preprocessor yaml untuk menggantikan variabel dalam gaya POSIX. itu berfungsi dengan baik tetapi akhirnya kami berhenti menggunakannya, karena ada satu masalah. Anda harus menjalankan preprocessor terlebih dahulu dan mengatur semua parameter sebelum Anda mendapatkan solusi akhir. Sekarang kita menggunakan fitur docker yaml extends. Karena memungkinkan kita untuk check in konfigurasi sebenarnya dan hanya menjalankannya pada target. Kami lebih tahu apa yang akan terjadi.

Meskipun saya adalah pendukung variabel passing yang dibuat oleh buruh pelabuhan, saya sekarang tidak begitu yakin.

Sebagai solusi yang ideal, saya lebih suka melihat pekerja pelabuhan melakukan perluasan dengan benar. Dalam arti itu akan menjadi solusi yang cocok untuk keduanya. Lantas apa yang rusak pada buruh pelabuhan meluas? Ini pada dasarnya adalah fakta bahwa Anda harus menulis semua entri di file yang diwariskan. Ini bukan gabungan di mana Anda hanya memasukkan apa yang ingin Anda timpa.

Lihatlah contoh aktual dan seberapa panjangnya itu. Hanya ada dua baris yang penting.

#Common 
elasticsearch:
  image: zinvoice/elasticsearch
  hostname: elasticsearch
  restart: always
  dns: 172.17.42.1
  ports:
    - "9200:9200"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro
    - /data/elasticsearch:/opt/elasticsearch/data/elasticsearch

logstash:
  image: zinvoice/logstash
  hostname: logstash
  dns: 172.17.42.1
  restart: always
  ports:
    - "5000:5000"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro

kibana:
  image: zinvoice/kibana
  hostname: kibana
  dns: 172.17.42.1
  restart: always
  ports:
    - "5601:5601"
  volumes:
    - /etc/localtime:/etc/localtime:ro
    - /etc/timezone:/etc/timezone:ro

logspout:
  image: zinvoice/logspout
  hostname: logspout
  command: logstash://logstash.docker:5000
  restart: always
  dns: 172.17.42.1
  ports:
    - "8003:8000"
  volumes:
    - /var/run/docker.sock:/tmp/docker.sock

doorman:
  image: zinvoice/doorman
  hostname: doorman
  restart:  always
  dns: 172.17.42.1
  ports:
    - "8085:8085"
# inherited
elasticsearch:
  extends:
    file: ../common.yml
    service: elasticsearch

logstash:
  extends:
    file: ../common.yml
    service: logstash

kibana:
  extends:
    file: ../common.yml
    service: kibana

logspout:
  extends:
    file: ../common.yml
    service: logspout

doorman:
  environment:
    - DOORMAN_GITHUB_APPID=xxxxxxxx
    - DOORMAN_GITHUB_APPSECRET=xxxxxx
  links:
    - nginxtrusted
  extends:
    file: ../common.yml
    service: doorman

Jadi rekomendasi saya memperbaiki buruh pelabuhan memperluas dan membuatnya kurang bertele-tele. Anda bahkan tidak perlu menulis kode sebanyak itu karena YAML menyediakan semua fungsionalitas yang Anda butuhkan. Jika Anda tetap menggunakan YAML standar, file dapat dianalisis atau dibuat oleh alat dan UI lain.

Lihatlah "jangkar node" YAML dan "penggabungan file" YAML, ini mungkin solusi yang tepat.

FYI: diskusi ini berlanjut sekarang di # 1380

@ Vad1mo Saya setuju bahwa extends gagal dalam kasus Anda. Ada banyak hal yang dapat kami lakukan untuk meningkatkan pengalaman tersebut - dapatkah Anda membuka masalah tersendiri untuk itu, agar kami tidak tersimpangkan di sini?

Tentu saja! Saya hanya ingin menekankan bahwa ini bisa menjadi alternatif yang mudah dan elegan.
Jika compose extends membuat Anda setengah jalan untuk passing variabel, maka compose-extends yang ditingkatkan akan membuat passing variabel menjadi usang. Memiliki lebih sedikit konsep untuk dipahami membuat lebih mudah bagi pengguna.

Kasus penggunaan saya adalah mengizinkan $PWD dalam volumes , sehingga setiap pengembang dalam tim dapat mengkloning repo ke mana pun dan jalur masih dapat dipasang dengan benar.

elasticsearch:
  image: zinvoice/elasticsearch
  volumes:
    - $PWD:/app

@mattes Saya yakin itu sudah didukung, saya rasa .:/app juga didukung

@aanand Sebagai PoC saya melakukan hackup kotor dari POSIX PE dengan Python . Untuk hari Sabtu.

@kojirike Tampak hebat. Beri tahu saya jika Anda berencana untuk melanjutkannya.

@aandan saya berniat, tetapi pasti ada beberapa bug sekarang (dan saya pikir mungkin ide yang buruk untuk menggunakan shlex ). Laporan bug dan PR tentu saja diterima.

@dnephin bagaimana dengan $HOME / ~ ?

@nafg Keduanya didukung untuk jalur host volume

@dnephin menarik, b / c entah bagaimana saya berakhir dengan direktori bernama '$ HOME' ...

@aanand Seperti VARIABLE: default }", dengan global_extends (atau "import") ini akan menjadi lebih efektif.

T: Apakah ini memungkinkan untuk menentukan nomor port yang diekspos ke host? seperti - "$ {WEB_ PORT: 80 }: 80"?
Kasus penggunaan adalah untuk dapat dengan mudah menjalankan beberapa contoh aplikasi pada mesin / cluster yang sama, biasanya mendengarkan port yang berbeda atau ditetapkan ke nama domain lokal yang berbeda.

Ya, Anda pasti bisa melakukannya.

Saya ingin menggunakan vars dalam volume bersama dengan docker-compose scale my_app=3 . Saya memiliki docker-compose.yml

server:
  image: alexanderilyin/docker-teamcity-server
  ports:
   - "8111:8111"
  volumes:
    - .TeamCity:/root/.BuildServer
  links:
   - mysql
mysql:
  image: alexanderilyin/docker-mysql
  volumes:
    - .MySQL:/var/lib/mysql
  environment:
    MYSQL_DATABASE: teamcity
    MYSQL_USER: teamcity
    MYSQL_PASSWORD: teamcity
    MYSQL_ALLOW_EMPTY_PASSWORD: yes
agent:
  image: alexanderilyin/docker-teamcity-agent
  links:
   - server

Dan saya ingin dapat menggunakan scale untuk agen dan menggunakan volume dinamis bagi mereka untuk menyimpan data di antara peluncuran, misalnya:

agent:
  image: alexanderilyin/docker-teamcity-agent
  volumes:
    - .agent_{$AGENT_INSTANCE_ID}:/opt/buildAgent
  links:
   - server

Saya berharap variabel interpolasi dapat dilakukan sebagai bagian dari nama gambar juga
Kami menggunakan https://github.com/openshift/source-to-image untuk membangun container lokal di CI untuk setiap cabang dan kemudian menjalankan pengujian di atasnya menggunakan docker-compose.
Menjalankan pengujian dengan gambar dinamis cukup rumit dengan docker-compose dan memerlukan rendering template manual ..: -1:

Tetapi Anda dapat mengatur COMPOSE_PROJECT_NAME untuk mengontrol awalan per proses agar dapat melakukannya, bukan? Jika demikian, tidak perlu memiliki logika yang rumit dan file yml yang tidak dapat dibaca di sekitar nama.

@andrerer jangan ikuti. Menurut dokumen yang mengontrol Sets the project name, which is prepended to the name of every container started by Compose saat kami mencoba menyetel properti gambar:

web:
  image: <I_AM_DYNAMIC>

ah, kesalahanku.

Pikir yang Anda maksud

<I_AM_DYNAMIC>:
  image: nginx

Referensi gambar dinamis (dan build) memang akan sangat masuk akal. Misalnya beralih antara debug dan non debug base container untuk bahasa pemrograman Anda misalnya akan menjadi kasus penggunaan yang baik untuk ini.

Kasus penggunaan tambahan _ (yang mungkin ada dalam pikiran @ Maxim-Filimonov) _: Mampu mengganti tag mana yang akan digunakan gambar, sehingga Anda dapat menggunakan: terbaru secara default, tetapi ubah untuk dengan mudah menguji sesuatu yang lain tanpa mengubah yml file _ (pada dasarnya diperlukan untuk kasus penggunaan CI) _.

@andrerom itulah kasus penggunaan kami: +1:

Apakah ini juga akan berhasil untuk hal-hal seperti ??

web:
  environment:
    - FOO=${whoami}

@ k0377 Saya rasa mereka tidak akan melakukannya, karena itu benar-benar sesuatu yang ditangani oleh shell, tetapi Anda dapat menambahkan hasilnya dalam variabel lingkungan dan menggunakannya.

Dalam kasus khusus ini, variabel lingkungan $USER mungkin akan memberi Anda hal yang sama.

@aanand Mengapa tidak menggunakan mesin template yang sudah ada? Jinja2 ada di sana dan berfungsi dengan baik.

Seperti yang disebutkan sebelumnya - mengimplementasikan template kita sendiri adalah tugas yang tidak sepele (dan regexps tidak terlalu keren) sehingga kita harus menggunakan yang sudah ada, yang terbukti solid.

Alternatifnya, kami mungkin menggunakan nenek moyang dan referensi YAML https://gist.github.com/bowsersenior/979804

Tapi kemudian kami dibatasi pada penggunaan variabel (menyuntikkan nama variabel ke tengah konten).

1 untuk Jinja2: itu pasti cocok dengan cetakan dan memungkinkan untuk menggunakannya
persis kasus penggunaan itu (membuat template dalam file yml)

Pada Selasa, 26 Mei 2015 pukul 13.25, tonnzor [email protected] menulis:

@aanand https://github.com/aanand Mengapa tidak menggunakan template yang ada
mesin yang sudah ada? Jinja2 ada di sana dan berfungsi dengan baik.

Seperti yang disebutkan sebelumnya - menerapkan template kita sendiri adalah tugas yang tidak sepele
(dan regexps tidak terlalu keren) sehingga kita harus menggunakan yang sudah ada,
yang terbukti solid.

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105493447.

Jinja2 melakukan _lot_ lebih dari yang kami butuhkan:

  • bersyarat
  • perulangan
  • ekstensi / warisan
  • komentar
  • filter

Kami tidak menambahkan semua itu ke Tulis. Jika Jinja2 dapat dikonfigurasi untuk hanya menginterpolasi variabel, maka itu mungkin saja kandidat.

Sebenarnya perulangan mungkin menarik.

Asumsikan Anda memiliki daftar pelanggan yang Anda inginkan untuk memulai penampung
di mana Anda menempatkan beberapa variabel khusus pelanggan ke dalam lingkungan.

Extension / Inheritance mungkin menarik untuk meningkatkan arus
mekanisme ekstensi yang belum sempurna.

Filter bisa sangat bagus untuk melakukan sesuatu dengan variabel yang ada.

Pada hari Selasa, 26 Mei 2015 pukul 13.56, Aanand Prasad [email protected]
menulis:

Jinja2 melakukan _lot_ lebih dari yang kami butuhkan:

  • bersyarat
  • perulangan
  • ekstensi / warisan
  • komentar
  • filter

Kami tidak menambahkan semua itu ke Tulis. Jika Jinja2 dapat dikonfigurasi
untuk hanya menginterpolasi variabel, maka itu mungkin saja kandidat.

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105498909.

Mereka _might_ menjadi fitur yang menarik, tetapi mereka datang dengan jauh lebih kompleks daripada yang saya nyaman perkenalkan ke Compose dan format file, dan kami akan mengikat keduanya ke bahasa template tertentu dengan (sejauh yang saya tahu) implementasi tunggal dan tidak ada spesifikasi. Itu sama sekali tidak mungkin.

@aanand Beberapa catatan di sini:

  1. Jinja2 solid dan butuh beberapa menit untuk melakukan pra-pemrosesan YAML dengannya:

dari Templat impor jinja2
template = Template ('Halo {{name}}!')
template.render (name = "Aanand")
Halo Aanand!

Jika Anda menginginkan keamanan lebih - Anda dapat menggunakan sandbox yang tidak dapat diubah:

dari jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Halo {{name}}!')
template.render (name = "Aanand")
Halo Aanand!

Dalam kasus kami, itu akan menjadi:

impor os
dari jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Halo {{name}}!')
template.render (** os.environ)

  1. Bukankah kita menginginkan filter? Dengan filter Anda dapat menentukan nilai default dengan mudah ({{value | default ("default")}})
  2. Apakah kita benar-benar perlu peduli dengan pengguna yang menggunakan fitur Jinja yang diperluas untuk menyekrup file YAML? Dengan cara yang sama, pengguna dapat menghasilkan file YAML yang tidak valid secara manual. Saya pikir kita harus membuatnya tetap sederhana - coba proses yang diberikan template Jinja dan kembalikan kesalahan jika ada kesalahan atau YAML yang dihasilkan tidak valid (sama seperti yang Anda lakukan sekarang).
  3. Jika Anda tidak melihat Jinja2 sebagai solusi - akan lebih baik setidaknya menggunakan {{variable}} sebagai sintaks.
  4. Django menggunakan regexp untuk mengurai dan menghasilkan cetakan. Ini adalah kelas produksi untuk waktu yang lama dan hidup dengan baik dengannya.

impor os
impor kembali
template = "Halo {{name}}!"
re.sub ("{{\ s _ ([a-zA-Z0-9 _] +?) \ s_}}", lambda m: os.environ.get (m.group (1), ''), template)

Bagaimanapun - kami harus menjalankan fitur ini, apa pun solusi yang kami ambil.

Saya +1 dalam menggunakan solusi template generik jika template dipertimbangkan. Misalnya http://mustache.github.io , yang tersedia dalam banyak bahasa. Ini hanya sebuah contoh, mesin template lainnya dapat dianggap sama

@aanand saya sangat mengerti maksud Anda. Saya juga menyukai kesederhanaan dan
kesederhanaan penulisan dsl.

Mungkin ini harus dilakukan sebagai proyek eksternal, katakanlah meta-composer. Itu
mengambil compose.tpl.yml dan variable.yml, membuat docker-compose.yml
dan pergilah.
Seperti yang ditunjukkan @tonnzor, t dapat dilakukan dengan sepotong kecil kode python.

Ini akan memberikan templating yang kuat bagi mereka yang tidak membutuhkannya
memperkenalkan kompleksitas untuk tugas-tugas sederhana.

Pada hari Selasa, 26 Mei 2015 jam 16.52, Sebastiaan van Stijn <
[email protected]> menulis:

Saya +1 dalam menggunakan solusi template _generic_ jika template-nya
dipertimbangkan. Misalnya http://mustache.github.io , yang tersedia di banyak tempat
bahasa. Ini hanyalah sebuah contoh, mesin template lainnya bisa
dianggap sama

-
Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Hmm… Jadi sekarang proposal untuk menggunakan bahasa template di dalam compose.yml (yang merupakan bahasa deskriptif untuk membuat container Docker), untuk hal-hal seperti command dan entrypoint , yang sudah menerima exec dan sh -c gaya nilai? Ini bisa membingungkan, karena setelah template merender, perintah shell yang dihasilkan mungkin masih akan ditafsirkan, jadi jika sebuah variabel berkembang menjadi * itu selanjutnya akan diperluas secara global. Urutan pelarian dalam satu bahasa atau lainnya menjadi rumit ketika Anda memiliki banyak lapisan interpretasi fall-through.

@kojiromike Saya tidak yakin mesin templating diinginkan, tetapi jika itu akan digunakan! lebih baik gunakan sesuatu yang terkenal. Pertanyaan dasarnya adalah; harus buruh pelabuhan-menulis menulis substitusi dari awal, atau menggunakan sesuatu yang sudah ada.

Pada Sel, 26 Mei 2015, 11.02 Christoph Witzany [email protected]
menulis:

@aanand saya sangat mengerti maksud Anda. Saya juga menyukai kesederhanaan dan
kesederhanaan penulisan dsl.

Mungkin ini harus dilakukan sebagai proyek eksternal, katakanlah meta-composer. Itu
mengambil compose.tpl.yml dan variable.yml, membuat docker-compose.yml
dan pergilah.

Anda dapat melakukannya hari ini tanpa proyek baru. Saya yakin jinja bisa
dipanggil dari baris perintah entah bagaimana. Secara pribadi saya hanya menggunakan envsubst
perintah.

Apa yang akan sangat membantu adalah jika compose dapat membaca file dari stdin.
Itu akan menghilangkan kebutuhan akan file perantara.

Seperti yang ditunjukkan @tonnzor, t dapat dilakukan dengan sepotong kecil kode python.

Ini akan memberikan templating yang kuat bagi mereka yang tidak membutuhkannya
memperkenalkan kompleksitas untuk tugas-tugas sederhana.

Pada hari Selasa, 26 Mei 2015 jam 16.52, Sebastiaan van Stijn <
[email protected]> menulis:

Saya +1 dalam menggunakan solusi template _generic_ jika template-nya
dipertimbangkan. Misalnya http://mustache.github.io , yang tersedia di banyak tempat
bahasa. Ini hanyalah sebuah contoh, mesin template lainnya bisa
dianggap sama

Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.

Balas email ini secara langsung atau lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105554730. src = "
https://ci6.googleusercontent.com/proxy/iSBXyl7D8PwFM4p1mGPHCR7bQctunieGbhyGkvo0QIMIjmAYE3I0Mt96yl1fGrqcuOzxV4APP8ZRIw-5_qd6nzps9Mpr6jTAydCC4xs8JDgqm93aIbWvN1eMlxykrz7iwYooyAQdqL4RFJokeEbnBkZm5mhgKg=s0-d-e1-ft#https://github.com/notifications/beacon/AAGAUO8xqz29B2SUoG7QFPUy848_JJW9ks5oNIJlgaJpZM4EMysO.gif
">

1 untuk membaca file dari stdin. Saya tidak punya masalah dengan menggunakan solusi template eksternal tetapi tidak memiliki file antara akan menyenangkan.

Kedengarannya seperti langkah pertama yang bagus, dan fitur umum dari banyak alat Cli. Ayo lakukan itu

: +1:

Jadi contohnya

envsubst compose.tmpl.yml | docker-compose -f - up -d

wfm. : +1:

Baru saja memperhatikan bahwa buruh pelabuhan / distribusi menangani nilai pengganti dalam file yml melalui variabel lingkungan, tetapi menggunakan pendekatan yang berbeda https://github.com/docker/distribution/blob/master/docs/configuration.md#override -configuration-options

^^ @aanand

@thaJeztah itu akan berhasil untuk kita juga. Kita bisa menggunakan variabel lingkungan untuk mengganti perintah

DOCKER_COMPOSE_IMAGE_NAME='my_image:is_dynamic'

Pendekatan yang menarik, tapi saya bukan penggemar - nama variabel lingkungan verbose, banyak duplikasi jika Anda ingin menggunakan satu nilai di banyak tempat, semuanya implisit, tidak ada interpolasi dalam string.

@aanand tidak benar-benar menjual pendekatan itu juga, tetapi ingin menunjukkannya karena ini adalah proyek lain dalam organisasi "Docker".

Baru saja tersandung di https://github.com/kelseyhightower/confd yang mungkin menarik. Ini menggunakan http://golang.org/pkg/text/template/#pkg -overview

@olalonde sayangnya, docker-compose ditulis dengan Python, jadi Go-templates tidak berfungsi.

@aanand I'm +20 pada proposal asli Anda, dengan perubahan bahwa bahkan gambar dan terutama tag dapat dimasukkan. Lakukan saja, akan menghemat banyak pembungkus dan penanganan konfigurasi yang tidak diperlukan;)

Saya menulis paket python kecil yang membantu saya dengan itu. Rencananya adalah untuk menyalurkan semua perintah melalui penulisan buruh pelabuhan sehingga Anda dapat menggunakannya secara setara.
Lihat di https://github.com/webcrofting/meta-compose/

meta-compose terlihat sangat bagus. Ini harus diintegrasikan ke docker-compose!

+1 Besar di sini - Saya tidak senang dengan prapemrosesan template, tetapi menarik variabel lingkungan dengan satu atau lain cara akan sangat bagus. Ekspansi POSIX mungkin lebih bersih dari Jinja2, tapi bagaimanapun juga tidak masalah.

+1 besar dari sini juga. Kasus penggunaan saya lebih untuk menambahkan dukungan ID iklan dinamis untuk wadah kafka yang sangat penting bagi produsen data (yang bisa berupa wadah lain).

Saya juga senang dengan fitur ini.

Ekspansi POSIX mungkin lebih bersih dari Jinja2, tapi bagaimanapun juga tidak masalah.

Saya pikir argumen lain yang mendukung ekspansi POSIX adalah bahwa ini tanpa logika. Jinja2 mendukung beberapa tingkat logika bersyarat / loop (seperti yang dilakukan kebanyakan mesin template, bahkan yang mengklaim sebagai "tanpa logika"). Mencampur logika template dan YAML cukup aneh menurut pengalaman saya. Bisakah seseorang memikirkan kasus penggunaan untuk logika seperti itu? Jika tidak, sebaiknya hindari dukungan untuk saat ini.

Alangkah baiknya memiliki jawaban yang jelas dari pengembang tentang fitur ini. Membaca berbagai isu dan PR, tidak jelas apakah Anda benar-benar ingin menerapkannya atau tidak.

Jika ya, dengan mekanisme seperti apa? Jika tidak, orang dapat mulai membuat beberapa alat pihak ketiga untuk mengelola fitur tersebut.

Terima kasih !

Oke, saya baru saja melihat https://github.com/docker/compose/pull/76. Saya kira jawabannya ada di sana ...

Berjalan beberapa siklus atas masalah / PR terkait.

AFAIK, komunitas nginx menolak untuk mengadopsi mesin templat apa pun untuk file konfigurasi, bahkan untuk substitusi variabel sederhana. Mengapa? Mungkin, mereka masih memilih mesin template yang ideal: smile :

@tokopedia

Membaca berbagai isu dan PR, tidak jelas apakah Anda benar-benar ingin menerapkannya atau tidak.

Masalah ini seharusnya memberikan jawaban pasti untuk pertanyaan itu, jadi maaf saya gagal menjelaskan: ya, kami ingin menerapkannya, dan dengan sintaks gaya POSIX.

terima kasih @aanand !

Terima kasih, @aanand.

1 untuk saya. Saya perlu meneruskan --dns = (alamat bridge docker0), dan saya memerlukannya untuk berfungsi jika itu pernah berubah dalam versi docker yang akan datang, jadi variabel lingkungan dan / atau shell sempurna. meta-compose tidak berfungsi untuk saya, karena seharusnya mendukung DOCKER_HOST jarak jauh dan misalnya melalui docker-swarm, tidak hanya secara lokal.

: +1: Ini akan sangat menyenangkan. Saat ini saya entah akhirnya menghasilkan file .yml melalui skrip lain, atau hanya tidak menggunakan docker-compose sama sekali, dan secara manual --link-ing buruh pelabuhan.

:jempolan:

Saya pikir interpolasi variabel lingkungan dasar akan sangat berguna untuk hal-hal sederhana.

Beberapa kasus penggunaan sederhana:

  • Mampu menentukan secara dinamis tag gambar yang akan ditarik dari repositori jarak jauh.
  • Mampu mengatur pemetaan port untuk sebuah kontainer.

Alat seperti Ansible sudah dapat membuat template dengan sangat baik, jadi saya tidak yakin bahwa mesin template lengkap diperlukan. Tetapi tidak dapat memiliki konten dinamis dalam file comose.yml sangat membatasi.

Mengenai gabungan PR # 1488, saya sangat tertarik untuk memasukkan file konfigurasi ke docker-compose . Saya tidak mengerti mengapa docker-compose tidak dapat diambil dari proses node.

var spawn = require('child_process').spawn;

var compose = spawn('docker-compose', ['--file' + '-' + 'up']);

compose.stdin.setEncoding = 'utf-8';

compose.stdout.on('data', function (data) {
    console.log('"docker-compose --file - up" stdout: "%s".', data);
});

compose.stderr.on('data', function (data) {
    console.log('"docker-compose --file - up" returned an error: "%s".', data);
});

compose.on('close', function (code) {
    if (code !== 0) {
        console.log('"docker-compose --file - up" existed with an erroneous code: "%s".', code);
    } else {
        console.log('"docker-compose --file - up" existed with code: "%s". SUCCESS!', code);
    }
});

compose.stdin.write("redis: {\"image\": \"redis\"}\n");
compose.stdin.end();

Ada contoh tentang cara menyalurkan data dari Node.js?

Hal lain yang saya temukan adalah bahwa docker-compose 1.4.0-RC1 mengirim beberapa pesan yang tampaknya normal seperti Starting... atau Attaching... ke stderr alih-alih stdout .

@ Kadishmal Bisakah Anda membuka masalah terpisah untuk ini?

Kandidat sintaks / implementasi lainnya: template string Python, seperti yang ditentukan dalam PEP 0292 dan diimplementasikan dalam string.Template .

Ini sangat mirip dengan perluasan parameter POSIX:

  • $foo berkembang menjadi nilai foo
  • ${foo} berkembang menjadi nilai foo
  • $ , ${ , $} , ${} , ${foo , $ {foo} , ${ foo} , ${foo } adalah kesalahan

Kekurangan:

  • Tidak ada nilai default atau sintaks "nilai yang diperlukan". Namun, kita bisa memutuskan nanti apakah kita ingin mereka cukup pantas menulis kode template kita sendiri.
  • Pesan kesalahan tidak mengekspos informasi yang dapat dibaca mesin tentang di mana kesalahan sintaks berada (tanpa melakukan pencocokan ekspresi reguler pada string kesalahan, yaitu).
  • Sintaks melarikan diri berbeda dari POSIX: $$ bukan \$ .

Ini mungkin sebenarnya adalah berkah tersembunyi: YAML tidak menyukai \$ , dan mengharuskan Anda untuk melarikan diri dua kali. Saya tidak berpikir memberitahu orang untuk mengetik \\$ hanya untuk mendapatkan tanda dolar akan berhasil.

Saya telah meningkatkan implementasi di # 1765.

+1

Saya tidak yakin apakah ini tempat yang tepat untuk ini, atau apakah saya harus membuat masalah baru.

Saya pikir prioritas env harus sebaliknya, yaitu variabel dari shell yang memanggil docker-compose harus menimpa variabel apa pun dalam docker-compose.yml, yang pada gilirannya harus menimpa variabel apa pun yang ditentukan oleh container.

Inilah yang saat ini terjadi ketika saya mencobanya:

docker-compose.yml:

test:
    image: ubuntu
    environment:
        - FOO="from compose"

dan kemudian jalankan dengan perintah env :

docker-compose run test env | grep FOO

memberikan FOO="from compose" , seperti yang diharapkan. Tapi kemudian:

FOO="from shell" docker-compose run test env | grep FOO

juga memberikan FOO="from compose" , tetapi di sini saya mengharapkan FOO="from shell" .

Beberapa orang mungkin masih memerlukan interpolasi variabel untuk kasus penggunaan lain, tetapi mengubahnya akan memenuhi kasus "default" - secara efektif definisi / nilai environment: di docker-compose.yml adalah defaultnya, dan dapat diganti pada waktu proses jika diperlukan, tanpa memerlukan sintaks YAML tambahan.

@fazy Anda tidak memperhitungkan bahwa env perintah dieksekusi di mengisolasi test wadah di mana FOO 's nilai adalah from compose (hanya sebagaimana mestinya dan seperti yang telah dikonfigurasi dalam file docker-compose ). Tetapi di luar wadah itu jika proses docker-compose memiliki semacam fungsi cetak untuk variabel lingkungan yang Anda atur sebelum perintah itu akan dicetak 'dari shell' karena itu adalah nilai untuk host (serta untuk proses docker-compose ) tempat Anda menjalankannya. Mungkin Anda mengharapkan nilai FOO menjadi from shell dalam kasus ini tetapi secara pribadi saya akan sangat terkejut jika itu terjadi. (Saya harap meskipun bahasa Inggris saya, Anda akan mengerti maksud saya).

@smileart terima kasih, saya rasa saya mengerti apa yang Anda katakan.

Namun, container test tidak sepenuhnya terisolasi, ia mendapatkan lingkungannya dari docker-compose (atau setidaknya, docker-compose dapat mengatur variabel lingkungan ke dalam container yang diluncurkan), dan docker-compose sendiri dapat melihat variabel lingkungan "luar".

Anda dapat melihat dengan docker-compose.yml ini:

test:
    image: ubuntu
    environment:
        - FOO

Lalu perintahnya:

FOO="from shell" docker-compose run test env | grep FOO

memang memberikan hasil "dari shell".

Jadi pertanyaan saya adalah tentang prioritas. Dengan hanya menentukan nama variabel di sini, - FOO , saya dapat memasukkan variabel dari luar. Tetapi jika saya menentukan - FOO=something _and_ menyuntikkan variabel dari luar, mana yang harus diutamakan? IMHO variabel yang ditentukan pada baris perintah harus didahulukan dari file konfigurasi.

@fazy Oh, maaf, saya belum mencoba FOO="from shell" docker-compose run test env | grep FOO tanpa menentukan nilainya di docker-compose.yml dan saya tidak tahu ini memberi kita nilai host FOO . Jadi bukan hanya itu sudah aneh bagi saya: smiley: Saya pikir menyiapkan variabel lingkungan sebelum docker-compose akan memengaruhi docker-compose dan docker-compose HANYA tanpa membuangnya ke wadah. Sekarang saya mengerti apa yang Anda maksud.

Saya baru saja menemukan kelemahan melarikan diri $ disebutkan di https://github.com/docker/compose/issues/1377#issuecomment -124571722. Pertama saya melakukan hanya FOO=ba$e lalu FOO='ba$e' (lupa bahwa itu diambil "telanjang"), lalu FOO=ba\$e , lalu FOO=ba\\$e , lalu saya menyerah dan pergi ke dokumen, hanya untuk terkejut menemukan bahwa " $ adalah karakter melarikan diri untuk $ ". Bagi saya, ini bukan "yang paling mengejutkan".

Namun, saya tidak tahu apa solusi yang bagus.

@ ct-clearhaus Compose bukan satu-satunya program yang menggunakan $ untuk meng-escape $ . Anda juga akan menemukannya di makefiles. Jadi bagi sebagian orang idiom ini cukup familiar.

Saya suka implementasi substitusi variabel yang ada. Namun saya benar-benar dapat menggunakan kemampuan untuk menyetel default, sesuai proposal asli @aanand . Menurut saya sintaks POSIX sempurna:

${ENV-default}

Penggunaan khusus saya adalah saya ingin dapat menentukan port host tempat layanan dijalankan:

PORT=8123 docker-compose up

Dengan menambahkan ini ke docker-compose.yml :

web:
  ports:
    - "${PORT-8000}:5000"

Apakah fitur ini masih dalam rencana dan sedang dalam proses?

Saya mencoba memecahkan masalah saya dengan extends , tetapi ternyata cukup berantakan. Saya tidak hanya harus menduplikasi hampir semua docker-compose.yml hanya untuk mengubah satu pengaturan, juga tidak ada cara untuk _mengubah_ pengaturan port yang terekspos, Anda hanya dapat add to daftar port yang terbuka, yang mana tidak ideal untukku.

Mengapa docker-compose tidak gagal saat variabel lingkungan tidak disetel? Itu hanya mencatat peringatan dan melanjutkan. Tidak hanya kembali dan kesalahan menjadi pendekatan yang lebih baik ...
WARNING: The FOO variable is not set. Defaulting to a blank string.

1 untuk sintaks POSIX untuk mendeklarasikan nilai default

Mungkin saya kehilangan sesuatu yang jelas, tetapi saya ingin dapat menggunakan variabel lingkungan dari env_file untuk menetapkan nilai variabel lingkungan, misalnya:

docker-compose.env:

DB_PASSWORD=test

buruh pelabuhan-menulis.yaml:

...
service:
    database:
        env_file:
            - ./docker-compose.env
        environment:
            - MYSQL_PASSWORD=${DB_PASSWORD}
    webserver:
        env_file:
            - ./docker-compose.env
        environment:
            - WORDPRESS_DB_PASSWORD=${DB_PASSWORD}

Bisakah itu dicapai dengan cara lain? Saya tidak ingin memiliki file template yaml yang perlu disalurkan melalui envsubst.

Mengapa tidak memasukkan nilai ini langsung ke env_file seperti yang Anda inginkan?

2636 akan mendukung file env untuk nilai default

Itu berarti memiliki variabel yang harus memiliki nilai yang sama di dua tempat, membuatnya lebih mudah jika Anda hanya perlu mengubah satu. # 2636 terlihat menjanjikan.

Sekarang sangat membutuhkan mekanisme untuk mendukung variabel default, karena keterbatasan yang ada memaksa kami untuk menggunakan skrip pembungkus untuk membantu penulisan dok. Saya perlu barang-barang seperti NODE_ENV=${NODE_ENV:-dev} untuk bekerja, dan demi kenyamanan, alangkah baiknya memiliki SOME_NUMBER=$((96*60)) untuk bekerja. Apakah ini dijadwalkan untuk versi yang akan datang?

1 untuk nilai default

1 untuk nilai default. ini menjadi penting bagi kami.

Saya setuju @ darkn3rd - Saya perlu mendapatkan id pengguna dan id grup pengguna untuk menyiapkannya dalam wadah. Satu-satunya cara yang saya temukan adalah memaksa tim saya untuk mengekspor 2 vars ... atau menggunakan makefile yang saya buat untuk mengekspor set.

Kalau saja saya bisa melakukan:

    user: $((id -u)):$((id -g))

itu akan menyelesaikan seluruh masalah saya

@mgor Kedengarannya Anda bisa melewati envsubst ?

env $(cat docker-compose.env | xargs) envsubst < docker-compose.tmpl > docker-compose.yml

harus melakukannya (tanpa mencemari lingkungan yang ada), saya pikir.

@OJFord @mgor Tidak ada niat untuk melakukan highjack pada utas tetapi saya membuat beberapa alat CLI untuk memiliki alur kerja yang lebih bersih; envset dan slv .

envset development -- slv docker-compose.tpl > docker-compose.yml

envset akan memuat variabel dari file env ke sesi shell saat ini, slv tidak mengganti template menggunakan variabel lingkungan.

Saya setuju @OJFord tetapi bukan itu yang saya butuhkan ...
Biar saya jelaskan: kami adalah tim yang terdiri dari 40 pengembang yang menggunakan tumpukan penulisan buruh pelabuhan yang berbeda. Kami menggunakan git untuk mendapatkan kode.

Jika saya meminta mereka untuk memodifikasi docker-compose.yml yang dikirimkan oleh git kami, jadi saya yakin seseorang akan mendorong file docker-compose.yml yang dimodifikasi ... Percayalah, itu yang akan terjadi.

Saya dapat "menghasilkan file komposer dasar" yang diabaikan oleh git dan diperpanjang oleh docker-compose.yml, tetapi untuk membuatnya, saya perlu memberikan Makefile atau bashscript ... Harinya akan tiba ketika "basis file docker "akan diperlukan perubahan, dan tim tidak akan menyadari bahwa mereka perlu menjalankan ulang pembuatan.

Sama untuk file "env", itu sangat bagus, tetapi tidak berfungsi dengan "build" dan saya perlu meminta tim saya untuk membuat file ini.

Sungguh, jika docker-compose bisa mendapatkan nilai dari bash (atau solusi lain yang mengembalikan sesuatu yang lain yang merupakan var ENV) di file yaml akan menyelesaikan banyak kebutuhan.

Contoh saya dalam perintah saya sebelumnya adalah yang sempurna: Saya perlu mendapatkan id pengguna dan gid dan nilai-nilai itu tidak ditetapkan oleh ENV vars. Jadi saya perlu meminta tim saya untuk menulis ID mereka dalam file .env ... Sederhana untuk saya dan Anda, tidak untuk semua.

Tepatnya: Saya perlu memberikan file docker-compose yang tidak boleh diubah oleh tim, karena ada di repositori git.

Permintaan tarik ini adalah contoh sederhana yang cocok untuk saya. Mungkin Anda bisa membantu saya menjadi lebih baik.

Saya mencoba dengan lingkungan dan arahan pengguna dari file docker-compose.yml. Bekerja dengan baik untuk saat ini.

Nilai default harus ada di sana ... Sangat berguna ... Pengembang dan OPS menggunakan log galangan kapal atau syslog ... Jadi, mereka biasanya harus membuat LOG_FORMAT default yang ditunjukkan di bawah ini ... Kita bisa saja memiliki nilai default dan hanya menggunakannya saat beralih ke syslog ...

default:
  extends:
    file: base.yml
    service: base-${LOG_FORMAT:docker}
  labels:
    - "net.company.npmjs.datacenter=${DATA_CENTER}"
    - "net.company.npmjs.env=${ENV}"
    - "net.company.npmjs.hostname=${HOSTNAME}"
    - "net.company.npmjs.role=${NPMO_ROLE}"
    - "net.company.npmjs.log=${LOG_FORMAT}"

base-syslog:
  log_driver: syslog
  log_opt:
    tag: "{{.ImageName}}/{{.Name}}/{{.ID}}"

base-docker:
  log_driver: json-file
  log_opt:
    max-size: "128m"
    max-file: "4"

Kapan ini akan tersedia? Saya menggunakan Compose 1.7.0 dan ini masih belum ada :(

Tolong tolong beri kami nilai default!

@marcellodesales : Mungkin Anda dapat memanfaatkan file docker-compose.override.yml dengan cara tertentu. Periksa fitur itu.

Juga +1 di env vars. Ini adalah titik sakit utama kami dengan docker-compose saat ini.

Saya akan bersikeras pada PR # 3367 saya untuk bisa mendapatkan nilai tertentu dari host. :)

@pataquets Saya rasa saya tidak ingin membuat file override lainnya ... file base.yml , seperti yang ditunjukkan di atas, menunjukkan semua hal yang didukung dalam hal driver logger, dll ... Saya hanya ingin beralih dan memiliki nilai default. Saya akan berpikir bahwa kita perlu mempertahankan lebih banyak file yml. Tapi saya akan mengingatnya untuk berjaga-jaga.

+1

+1

+1

+1

Adakah pemberitahuan tentang penggunaan variabel lingkungan di docker-compose?

+1

+1

FYI: Variabel lingkungan untuk docker-compose berfungsi mulai 1.7.0. Anda juga dapat menyetel variabel default penulisan-buruh pelabuhan di .env dalam direktori yang sama dengan file root docker-compose.yml . Hal ini tidak menjadi bingung dengan envfiles mesin buruh pelabuhan, karena itu adalah hal yang berbeda.

Apakah ada cara untuk menyetel nama layanan sebagai variabel?

Daripada menulis ini

services:
   site_db:
     image: mysql:5.7

Kami bisa menulis

services:
   ${CONTAINER_NAME}:
     image: mysql:5.7

Tujuan saya adalah menyimpan docker-compose.yml di beberapa situs, dan hanya mengubah file .env . Saat ini, saya masih perlu mengubah nama penampung karena saya menjalankan beberapa aplikasi di host yang sama. Dan saya ingin setiap layanan memiliki nama sendiri untuk kejelasan.

@LouWii dapat Anda gunakan

services:
    site_db:
      container_name: "${CONTAINER_NAME}"
      image: mysql:5.7

atau (buat format file 2.1 dan lebih tinggi)

services:
    site_db:
      container_name: "${CONTAINER_NAME:-defaultname}"
      image: mysql:5.7

Tetapi mengapa tidak menetapkan nama proyek? Nama proyek adalah _intended_ untuk itu, karena itu memberi awalan / namespaces nama-wadah yang dibuat untuk mencegah konflik dengan proyek lain di host yang sama. Lihat https://docs.docker.com/compose/reference/envvars/#/composeprojectname

@thaJeztah Terima kasih! Saya masih mempelajari cara kerja Docker dan buruh pelabuhan. Menetapkan nama proyek tampaknya menjadi opsi yang lebih baik, sangat masuk akal dalam penggunaan saya.

Apakah ada cara untuk membuat skrip di dalam tanda kurung kurawal? Misalnya ${HOST_PORT + 1} .

Anda bisa menyalurkan file melalui Jinja atau sesuatu ...

Pada Sel, 24 Jan 2017, 05.36 Sam A. Horvath-Hunt [email protected]
menulis:

Apakah ada cara untuk membuat skrip di dalam tanda kurung kurawal? Misalnya $ {HOST_PORT

  • 1}.

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/docker/compose/issues/1377#issuecomment-274767368 ,
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AAGAUN5ZrU39dnVVVASwIHr5mGqJFxh3ks5rVdRIgaJpZM4EMysO
.

Apakah saya bisa lolos dari $ ?

environment:
   PATH: "$PATH:/home/appuser/.bundler/bin"

Saat ini, hal ini menyebabkan variabel PATH host diinterpolasi dan bukan penampungnya

apakah file docker-compose.yml hanya satu yang ditemukan?
bagaimana cara menambah atau memodifikasinya?
Terima kasih sebelumnya

@logicminds meskipun saya tidak dapat menemukannya didokumentasikan di mana pun, saya menemukan $$ interpolates ke escaped $ .

environment:
   PATH: "$$PATH:/home/appuser/.bundler/bin"

@elquimista memiliki solusi yang menurut saya berguna https://github.com/mhart/alpine-node/issues/48#issuecomment -430902787

Apakah halaman ini membantu?
0 / 5 - 0 peringkat