Docker 컨테이너에 환경 변수를 어떻게 전달합니까?


828

Docker를 처음 접했고 컨테이너에서 외부 데이터베이스에 액세스하는 방법이 확실하지 않습니다. 연결 문자열을 하드 코딩하는 가장 좋은 방법입니까?

# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string

답변:


1241

-e플래그 를 사용하여 환경 변수를 컨테이너에 전달할 수 있습니다 .

시작 스크립트의 예 :

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

또는 명령 줄에 값 ps등을 표시하지 않으려는 -e경우 =: 없이 값을 지정하면 현재 환경에서 값을 가져올 수 있습니다 .

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

많은 환경 변수가 있고 특히 비밀 변수 인 경우 env 파일을 사용할있습니다 .

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

--env-file 플래그는 파일 이름을 인수로 사용하고 각 행이 VAR = VAL 형식으로되어 --env에 전달 된 인수를 모방합니다. 주석 줄 앞에는 # 만 있으면됩니다.


더 쉬운 방법이 있습니까? 매번 다른 변수로 컨테이너를 다시 만들어야한다는 것은 정말 짜증납니다. 파일로 저장 하시겠습니까?
Jason Axelson

29
도커 실행 명령을 쉘 스크립트 (./start_staging.sh 등)에 저장 한 다음 Ansible을 사용하여 원격으로 실행합니다.
정오표

1
두 번째 버전이 작동하는 데 문제가 있습니다. 환경에서 PASSWORD = foo를 설정 한 다음 --env PASSWORD를 전달하면 컨테이너의 config.json에 "PASSWORD"라는 단어 만 나타납니다. 다른 모든 환경 변수에는 키와 값이 있습니다. Docker 1.12.1을 사용하고 있습니다.
케빈 버크

@KevinBurke : 나는 당신이 -e PASSWORD를 원한다고 생각 = 현재 쉘 환경에서 읽고 있다면 $ PASSWORD
에라타

8
@KevinBurke : export PASSWORD=foo대신 수행하면 변수가 docker run환경 변수로 전달 되어 docker run -e PASSWORD작동합니다.
qerub

93

여기에 언급되고 @errata에 언급 된대로 명령에 -e매개 변수를 사용하여 전달할 수 있습니다 . 그러나이 방법의 가능한 단점은 자격 증명이 실행되는 프로세스 목록에 자격 증명이 표시된다는 것입니다. 더 안전하게 보호하려면 구성 파일에 자격 증명을 작성하고 수행 할 수 있습니다 에 언급 한 바와 같이 여기 . 그런 다음 해당 시스템에 액세스 할 수있는 다른 사용자가 자격 증명을 볼 수 없도록 해당 구성 파일의 액세스를 제어 할 수 있습니다.docker run ..

docker run--env-file


2
@errata의 답변 에이 문제를 해결하는 또 다른 방법을 추가했습니다.
Bryan

21
의주의 --env-file를 사용할 때, --env당신의 ENV 값이 인용 될 것입니다 / 당신이 사용하고있는 쉘 어떤 표준 의미로 이스케이프 만 사용하는 경우 --env-file값을 서로 다른 것 컨테이너 내부에 얻을 것이다. docker run 명령은 파일을 읽고 매우 기본적인 구문 분석을 수행하고 값을 컨테이너로 전달합니다. 이는 쉘의 동작 방식과 동일하지 않습니다. 많은 --env항목을 로 변환하는 경우 알아야 할 작은 정보 --env-file입니다.
Shorn

5
Shorn 답변을 자세히 설명하기 위해 env 파일을 사용할 때 줄 바꿈을 넣거나 분할 할 수있는 방법이 없기 때문에 매우 긴 환경 변수 값을 한 줄에 모두 넣어야했습니다. $ MY_VAR = stuff $ MY_VAR = $ MY_VAR 더 많은 것들
Jason White

53

컨테이너를 스핀 업하는 방법으로 'docker-compose'를 사용하는 경우 실제로 서버에 정의 된 환경 변수를 Docker 컨테이너로 전달하는 유용한 방법이 있습니다.

당신의에서 docker-compose.yml파일의 당신이 기본 게요!-JS 컨테이너와 코드를 보이는 등을 회전하는 가정 해 봅시다 :

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

도커 프로젝트가있는 로컬 서버에 hapi-js 컨테이너에 전달하려는 환경 변수 'NODE_DB_CONNECT'가 있고 새 이름을 'HAPI_DB_CONNECT'로 지정한다고 가정 해 봅시다. 그런 다음 docker-compose.yml파일에서 로컬 환경 변수를 컨테이너에 전달하고 다음과 같이 이름을 바꿉니다.

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

컨테이너의 모든 파일에서 데이터베이스 연결 문자열을 하드 코딩하는 것을 피하는 데 도움이되기를 바랍니다.


6
작동하지 않습니다. 이러한 변수는 컨테이너로 전달되지 않습니다.
Frondor

@ 프론 도르 정말? 이 문서 에 따르면 그것은 해야하는 것처럼 보입니다.
darda

1
이 접근법의 문제점은 docker-compose.yml 파일의 환경 변수를 git 저장소에 커밋하지 않아야한다는 것입니다. 이 문제를 어떻게 해결합니까? 이상적으로는 gitignored되는 별도의 ENV 파일이 것하고 Dockerfile 또는 고정 표시기 - compose.yml로 / 부하를 가져올 수 있습니다
칼레드 오스만

35

을 사용하면 docker-composedocker-compose.yml 및 이후에 docker-compose이미지를 빌드하기 위해 호출 된 모든 Dockerfile에서 env 변수를 상속 할 수 있습니다. 이것은 Dockerfile RUN명령이 환경에 특정한 명령을 실행해야 할 때 유용 합니다.

(쉘은 RAILS_ENV=development이미 환경에 존재합니다)

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}

도커 파일 :

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

이 방법으로 파일이나 docker-compose build/ up명령 에서 환경 변수를 지정할 필요가 없습니다 .

docker-compose build
docker-compose up

그들은 같은 이름이어야합니까? 다소 혼란스러운 것 같습니다. 대신 개발을 실행하려면 인수를 어떻게 재정의합니까?
CyberMew

@CyberMew 예, 환경, docker-compose 및 Dockerfile간에 동일한 이름이어야합니다. 대신 docker-compose build를 실행하기 전에 개발을 실행하려면 터미널에서 RAILS_ENV = development를 실행하여 환경 변수를 설정하십시오. 그런 식으로 docker-compose와 Dockerfile이 환경에서 해당 값을 상속합니다.
joshweir

30

-e환경 변수를 설정 하려면 또는 --env 값을 사용하십시오 (기본값 []).

시작 스크립트의 예 :

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

명령 행에서 여러 환경을 사용하려면 모든 환경 변수 전에 -e플래그를 사용하십시오 .

예:

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

참고 : 컨테이너 이름은 환경 변수가 아닌 환경 변수 뒤에 있어야합니다.

많은 변수를 설정해야하는 경우 --env-file플래그를 사용하십시오.

예를 들어

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

다른 도움이 필요하면 Docker 도움말을 살펴보십시오.

 $ docker run --help

공식 문서 : https://docs.docker.com/compose/environment-variables/


2
왜 우리는 필요 ubuntu bash합니까? 우분투로 만든 이미지를 기본 이미지 또는 모든 이미지에 적용합니까?
Reyansh Kharga

나는 -e오래 전 논쟁 후에 컨테이너 이름을 넣는 것에 대해 조금 읽었 으면 좋겠다 . 그들이이 필요했다 왜 난 ... 이해하기 시작할 수 없습니다
ironchicken

13

호스트 머신 환경 변수를 도커 컨테이너에 파이프하는 방법에 대한 좋은 해킹이 있습니다.

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

모든 호스트 시스템 ENV 변수를 env > env_file덤프 하여 실행중인 컨테이너에서 액세스 할 수 있으므로이 기술을 매우 신중하게 사용하십시오 .env_file



5

다른 방법은 다음과 같은 기능을 사용하는 것입니다 /usr/bin/env.

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

2

env.sh로컬에 환경 변수가 있고 컨테이너가 시작될 때 환경 변수 를 설정하려는 경우 시도 할 수 있습니다

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

이 명령은 bash 쉘 ( sourcebash 명령 이므로 bash 쉘을 원합니다)로 컨테이너를 시작하고 env.sh파일을 환경 변수를 설정하고 jar 파일을 실행합니다.

env.sh같은 외모,

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

printenv실제 소스 명령이 작동하는지 테스트하기 위해 명령을 추가했습니다 . source 명령이 제대로 작동하는지 확인하거나 환경 변수가 docker logs에 나타날 때이를 제거해야합니다.


2
이 방법을 사용하면 다른 / 수정 된 env 세트를 전달할 때마다 docker 이미지를 다시 작성해야합니다. "docker --run --env-file ./somefile.txt"중에 envs를 전달하는 것이 우수 / 동적 접근 방식입니다.
Dmitry Shevkoplyas

2
@DmitryShevkoplyas 동의합니다. 내 유스 케이스는 명령에 --env-filearg를 지정하는 옵션이없는 곳 docker run입니다. 예를 들어 Google 앱 엔진을 사용하여 애플리케이션을 배포하고 컨테이너 내에서 실행되는 앱에 도커 컨테이너 내에 설정된 환경 변수가 필요한 경우 docker run명령 을 제어 할 수 없으므로 환경 변수를 설정하는 직접적인 방법이 없습니다. . 이 경우 KMS를 사용하여 env 변수를 해독하고 env 변수 env.sh를 설정하기 위해 소스에 추가 할 수있는 스크립트를 만들 수 있습니다.
akilesh raj

대신 .정기적으로 sh사용 가능한 POSIX (도트) 명령을 사용할 수 있습니다 source. ( source것과 동일 .)
go2null

1

jq를 사용하여 env를 JSON으로 변환 :

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

여기에는 jq 버전 1.6 이상 이 필요합니다

이것은 본질적으로 Dockerfile에서와 같이 호스트 env를 json으로 설정합니다.

ENV HOST_ENV  (all env from the host as json)

그 라인은 어떻게 작동 docker run -e HOST_ENV="$env_as_json" <image>합니까? : ? 필자의 경우 Docker는 docker args로 전달 될 때 변수 또는 하위 셸 ( ${}또는 $())을 해결하지 않는 것 같습니다 . 예를 들면 A=123 docker run --rm -it -e HE="$A" ubuntu다음과 같습니다 root@947c89c79397:/# echo $HE root@947c89c79397:/# . 그 컨테이너 안에서 : .... HE변수가 만들지 않습니다.
Perplexabot

0

-e 플래그와 $를 사용하여 머신 환경 변수를 호스팅 할 수도 있습니다.

실행하기 전에 로컬 환경 변수 및 파일을 내보내거나 (설정을 의미) 사용해야합니다.

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 

이 방법을 사용하면 내 경우에 주어진 이름으로 env 변수를 자동으로 설정합니다 (MG_HOST, MG_USER)

추가 :

파이썬을 사용하는 경우 도커 내에서 이러한 envment 변수에 액세스 할 수 있습니다

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>') a에 저장된 데이터를 grep하여 .envDocker에 전달 하는 방법은 안전하지 않은 상태로 저장되지 않으므로 docker history키를 보거나 잡을 수 없습니다 .

다음 .env과 같이 AWS에 많은 것들이 있다고 가정 해보십시오 .

AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx

```docker run --rm -it --env-file <(bash -c 'env | grep AWS_')으로 docker를 실행하면 모든 것을 가져 와서 컨테이너 내에서 액세스 할 수 있도록 안전하게 전달합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.