Ortam değişkenlerini Docker kapsayıcılarına nasıl geçiririm?


829

Docker'da yeniyim ve bir kapsayıcıdan harici bir veritabanına nasıl erişileceği belirsiz. Bağlantı dizesinde sabit kodlamanın en iyi yolu nedir?

# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string

Yanıtlar:


1243

Ortam değişkenlerini -ebayraklı kaplarınıza iletebilirsiniz .

Bir başlangıç ​​komut dosyasından bir örnek:

sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \ 
-e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \
-e POSTGRES_ENV_POSTGRES_USER='bar' \
-e POSTGRES_ENV_DB_NAME='mysite_staging' \
-e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \
-e SITE_URL='staging.mysite.com' \
-p 80:80 \
--link redis:redis \  
--name container_name dockerhub_id/image_name

Veya, psvb. Tarafından görüntüleneceği komut satırında değere sahip olmak istemiyorsanız, değeri -eyalnızca şu olmadan verirseniz geçerli ortamdan alabilir =:

sudo PASSWORD='foo' docker run  [...] -e PASSWORD [...]

Birçok ortam değişkeniniz varsa ve özellikle bunların gizli olması gerekiyorsa, bir env dosyası kullanabilirsiniz :

$ docker run --env-file ./env.list ubuntu bash

--Env dosyası bayrağı, bir dosya adını bağımsız değişken olarak alır ve her satırın VAR = VAL biçiminde olmasını bekler ve --env öğesine iletilen bağımsız değişkeni taklit eder. Yorum satırlarının başına yalnızca # işareti konmalıdır


Bunu yapmanın daha kolay bir yolu var mı? Kapsayıcıyı her seferinde farklı değişkenlerle yeniden oluşturmak zorunda kalmak gerçekten rahatsız edici. Belki bir dosyada saklar?
Jason Axelson

29
Docker çalıştırma komutlarını kabuk komut dosyalarında (./start_staging.sh vb.) Saklıyorum, sonra Ansible kullanarak uzaktan yürütüyorum.
errata

1
İkinci versiyonu çalıştırmakta güçlük çekiyorum; PASSWORD = foo'yu ortamda ayarladım, sonra --env PASSWORD'i geçtim ve kabın config.json'unda sadece "PASSWORD" kelimesi görünüyor; diğer tüm ortam değişkenlerinin bir anahtarı ve değeri vardır. Docker 1.12.1 kullanıyorum.
Kevin Burke

@KevinBurke: Mevcut kabuk ortamından okuyorsanız -e PASSWORD = $ PASSWORD istediğinizi düşünüyorum
errata

8
@KevinBurke: Bunun export PASSWORD=fooyerine yapın ve değişken docker runbir ortam değişkeni olarak geçerek docker run -e PASSWORDiş yapar.
qerub

93

Burada ve @errata tarafından belirtildiği gibi komutla -eparametreleri kullanarak geçebilirsiniz. Ancak, bu yaklaşımın olası dezavantajı, kimlik bilgilerinizin çalıştırdığınız işlem listesinde görüntülenmesidir. Daha güvenli hale getirmek için, bir yapılandırma dosyasında kimlik bilgilerinizi yazmak ve yapabilirler ile belirtildiği gibi burada . Ardından, bu makineye erişimi olan diğer kişilerin kimlik bilgilerinizi görmemesi için bu yapılandırma dosyasının erişimini denetleyebilirsiniz.docker run ..

docker run--env-file


2
Bu sorunu gidermek için @ errata'nın yanıtına başka bir yol ekledim.
Bryan

21
Dikkat edin, --env-filekullandığınız --envenv değerleriniz kullandığınız kabuğun standart semantiği ile alıntılanacak / kaçacaktır, ancak --env-filedeğerleri kullanırken kabınızın içine gireceğiniz farklı olacaktır. Docker run komutu sadece dosyayı okur, çok temel ayrıştırma yapar ve değerleri kaba aktarır, kabuğunuzun davranış biçimine eşdeğer değildir. Sadece bir grup --envgirişi bir --env-file.
16'da

5
Shorn cevabını detaylandırmak için, env dosyasını kullanırken çok uzun bir ortam değişkeninin değerini tek bir satıra koymak zorunda kaldım, çünkü içine satır sonu koymak veya bölmek için herhangi bir yol görünmüyor gibi birden fazla satır: $ MY_VAR = stuff $ MY_VAR = $ MY_VAR daha fazla stuff
Jason White

53

Kapsayıcılarınızı döndürme yöntemi olarak 'docker-compose' yöntemini kullanıyorsanız, sunucunuzda tanımlı bir ortam değişkenini Docker kapsayıcısına geçirmenin kullanışlı bir yolu vardır.

Senin içinde docker-compose.ymldosyanın, en temel bir hapi-js kabı ve kod görünüyor gibi dönerken diyelim:

hapi_server:
  container_name: hapi_server
  image: node_image
  expose:
    - "3000"

Docker projenizin bulunduğu yerel sunucunun hapi-js kabınıza iletmek istediğiniz 'NODE_DB_CONNECT' adlı bir ortam değişkenine sahip olduğunu ve yeni adının 'HAPI_DB_CONNECT' olmasını istediğinizi varsayalım. Sonra docker-compose.ymldosyada, yerel ortam değişkenini kapsayıcıya geçirir ve şöyle adlandırırsınız:

hapi_server:
  container_name: hapi_server
  image: node_image
  environment:
    - HAPI_DB_CONNECT=${NODE_DB_CONNECT}
  expose:
    - "3000"

Bu kapsayıcı herhangi bir dosyada bir veritabanı bağlantı dizesi sabit kodlama önlemek için yardımcı olacağını umuyoruz!


6
Bu işe yaramaz. Bu değişkenler kaba aktarılmaz.
Frondor

@Frondor gerçekten mi? Bu belgelere göre olması gerektiği gibi görünüyor.
darda

1
Bu yaklaşımla ilgili sorun, docker-compose.yml dosyasındaki ortam değişkenlerini gitmemeniz gereken git deposuna uygulamanızdır. Bunu nasıl başaracaksın? ideal olarak gitignored ve Dockerfile veya docker-compose.yml içine alabilir / yükleyebilirsiniz ayrı bir env dosyanız olurdu
Khaled Osman

35

Kullanarak docker-compose, docker-compose.yml dosyasında env değişkenlerini ve daha sonra docker-composegörüntüleri oluşturmak için çağrılan tüm Docker dosya (lar) ını devralabilirsiniz . Dockerfile RUNKomutun ortama özgü komutları yürütmesi gerektiğinde yararlıdır .

(kabuğunuz RAILS_ENV=developmentçevrede zaten var)

docker-compose.yml :

version: '3.1'
services:
  my-service: 
    build:
      #$RAILS_ENV is referencing the shell environment RAILS_ENV variable
      #and passing it to the Dockerfile ARG RAILS_ENV
      #the syntax below ensures that the RAILS_ENV arg will default to 
      #production if empty.
      #note that is dockerfile: is not specified it assumes file name: Dockerfile
      context: .
      args:
        - RAILS_ENV=${RAILS_ENV:-production}
    environment: 
      - RAILS_ENV=${RAILS_ENV:-production}

Dockerfile :

FROM ruby:2.3.4

#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production

#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV

#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi

Ben dosyaları veya çevre değişkenleri belirtme ihtiyacını yok Bu şekilde docker-compose build/ upkomutlar:

docker-compose build
docker-compose up

Aynı isim olmalılar mı? Biraz kafa karıştırıcı görünüyor .. Ve bunun yerine geliştirme çalıştırmak istersem argümanları nasıl geçersiz kılabilirim?
CyberMew

@CyberMew Evet, ortamınız, docker-compose ve Dockerfile arasında aynı ad olmalıdır. Bunun yerine geliştirmeyi çalıştırmak istiyorsanız, docker-compose derlemesini çalıştırmadan önce, ortam değişkenini ayarlamak için terminalinizde RAILS_ENV = development komutunu çalıştırın, bu şekilde docker-compose ve Dockerfile bu değeri ortamınızdan devralır.
Joshweir

30

-eOrtam değişkenlerini ayarlamak için veya --env değerini kullanın (varsayılan []).

Bir başlangıç ​​komut dosyasından bir örnek:

 docker run  -e myhost='localhost' -it busybox sh

Komut satırından birden çok ortam kullanmak istiyorsanız, her ortam değişkeninden önce -ebayrağı kullanın .

Misal:

 sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh

Not: Kapsayıcı adını bundan önce değil, ortam değişkeninden sonra koyduğunuzdan emin olun.

Çok sayıda değişken ayarlamanız gerekiyorsa, --env-filebayrağı kullanın

Örneğin,

 $ docker run --env-file ./my_env ubuntu bash

Diğer yardımlar için Docker yardımına bakın:

 $ docker run --help

Resmi belgeler: https://docs.docker.com/compose/environment-variables/


2
Neden ihtiyacımız var ubuntu bash? Ubuntu ile oluşturulan resimler için temel resim olarak mı yoksa her resim için mi geçerli?
Reyansh Kharga

Keşke -eçağlar öncesindeki argümanlardan sonra konteyner ismini koymakla ilgili biraz okudum ! Bunu neden gerekli hale getirdiklerini anlamaya bile başlayamıyorum ...
ironchicken

13

Ana makine ortam değişkenlerini bir docker kapsayıcısına nasıl bağlayacağınız güzel bir kesmek var:

env > env_file && docker run --env-file env_file image_name

Çünkü, çok dikkatli bu tekniği kullanın env > env_filedökümü TÜM ev sahipliği makinesi ENV değişkenleri env_fileve koşu kapta erişilebilir hale.



5

Başka bir yol da güçlerini kullanmaktır /usr/bin/env:

docker run ubuntu env DEBUG=1 path/to/script.sh

2

Ortam değişkenleri env.shyerel olarak varsa ve kapsayıcı başladığında ayarlamak istiyorsanız, deneyebilirsiniz

COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]

Bu komut, bir bash kabuğu ( sourcebash komutu olduğundan bash kabuğu istiyorum env.sh) ile kaplamayı başlatır, dosyayı (ortam değişkenlerini ayarlar ) kaynaklar ve jar dosyasını yürütür.

Öyle env.shgörünüyor,

#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"

printenvKomutu sadece gerçek kaynak komutunun çalıştığını test etmek için ekledim . Source komutunun iyi çalıştığını veya ortam değişkenlerinin docker günlüklerinizde görüneceğini onayladığınızda, muhtemelen kaldırmanız gerekir.


2
Bu yaklaşımla, farklı / değiştirilmiş env setini her geçmek istediğinizde docker görüntüsünü yeniden oluşturmanız gerekecektir. "Docker --run --env-dosyası ./somefile.txt" sırasında envleri geçirmek üstün / dinamik bir yaklaşımdır.
Dmitry Shevkoplyas

2
@DmitryShevkoplyas Kabul ediyorum. Benim kullanım durumum --env-filebir arg için bir docker runkomut belirtme seçeneği yoktur . Örneğin, Google uygulama motorunu kullanarak bir uygulama dağıtıyorsanız ve kapsayıcı içinde çalışan uygulama, docker kapsayıcısında ayarlanmış ortam değişkenlerine ihtiyaç duyuyorsa, docker runkomut üzerinde denetiminiz olmadığından ortam değişkenlerini ayarlamak için doğrudan bir yaklaşımınız yoktur. . Böyle bir durumda, say, KMS kullanarak env değişkenlerinin şifresini çözen ve bunları env.shenv değişkenlerini ayarlamak için kaynaklanabilecek bir komut dosyasına sahip olabilirsiniz.
akilesh raj

bunun yerine .normalde bulunan POSIX (nokta) komutunu kullanabilirsiniz . ( aynıdır )shsourcesource.
go2null

1

Jv kullanarak env JSON dönüştürmek için:

env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>

bu jq sürüm 1.6 veya daha yenisini gerektirir

bu ana env json olarak, aslında Dockerfile'de olduğu gibi:

ENV HOST_ENV  (all env from the host as json)

Bu hat sizin için nasıl çalışıyor docker run -e HOST_ENV="$env_as_json" <image>? : ? Benim durumumda Docker, docker argümanları olarak iletildiğinde değişkenleri veya alt kabukları ( ${}veya $()) çözüyor gibi görünmüyor . Örneğin: A=123 docker run --rm -it -e HE="$A" ubuntuo kabın içinde: root@947c89c79397:/# echo $HE root@947c89c79397:/# .... HEDeğişken bunu yapmaz.
Perplexabot

0

-e bayrağı ve $ kullanarak makine ortamı değişkenini de barındırabiliriz:

Çalıştırmadan önce yerel env değişkenini ve dosyasını dışa aktarmanız (ayarlamanız anlamına gelir) veya kullanmadan hemen önce

docker run -it -e MG_HOST=$MG_HOST -e MG_USER=$MG_USER -e MG_PASS=$MG_PASS -e MG_AUTH=$MG_AUTH -e MG_DB=$MG_DB -t image_tag_name_and_version 

Bu yöntemi kullanarak benim durumumda env değişkenini sizin adınızla otomatik olarak ayarlayın (MG_HOST, MG_USER)

Ek:

Python kullanıyorsanız, dock içindeki bu ortam değişkenine

import os
host,username,password,auth,database=os.environ.get('MG_HOST'),os.environ.get('MG_USER'),os.environ.get('MG_PASS'),os.environ.get('MG_AUTH'),os.environ.get('MG_DB')

0

docker run --rm -it --env-file <(bash -c 'env | grep <your env data>') İçinde saklanan verileri grep etmenin .envve güvenli olmayan bir şekilde saklanmadan Docker'a iletmenin bir yoludur (böylece sadece docker historyanahtarlara bakamazsınız.

Senin gibi bir sürü AWS malzeme var diyelim .env:

AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx

`` docker run --rm -it --env-file <(bash -c 'env | grep AWS_') ile çalışan docker, hepsini kapacak ve konteynerden erişilebilir olması için güvenli bir şekilde geçirecektir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.