도커 및 보안 비밀번호


162

나는 최근에 Docker를 사용하여 놀 수있는 서비스를 구축하는 것을 실험 해 왔으며 계속 잔소리하는 것이 Dockerfile에 암호를 넣고 있습니다. 나는 개발자이므로 소스에 암호를 저장하면 얼굴이 펀치처럼 느껴집니다. 이것이 문제가되어야합니까? Dockerfile에서 비밀번호를 처리하는 방법에 대한 좋은 규칙이 있습니까?


7
Github에서 Docker 및 비밀에 관한 모범 사례를 요청하는 공개 문제가 있습니다. github.com/docker/docker/issues/13490
Luís Bianchin

답변:


92

확실히 걱정입니다. Dockerfile은 일반적으로 리포지토리에 체크인되어 다른 사람들과 공유됩니다. 대안은 런타임시 환경 변수로 모든 신임 정보 (사용자 이름, 비밀번호, 토큰, 민감한 것)를 제공하는 것 입니다. 이것은 -e인수 (CLI의 개별 변수의 경우) 또는 --env-file인수 (파일의 여러 변수의 경우)를 통해 가능 docker run합니다. docker-compose와 함께 환경을 사용하려면 이것을 읽으십시오 .

사용 --env-file하는 ps경우 로그 또는 로그 에 표시되는 비밀로부터 보호하기 때문에 사용하는 것이 더 안전한 옵션 set -x입니다.

그러나 환경 변수는 특히 안전하지 않습니다. 이들은를 통해 볼 수 docker inspect있으므로 docker명령 을 실행할 수있는 모든 사용자가 사용할 수 있습니다 . (물론 docker호스트에서 액세스 할 수있는 모든 사용자 어쨌든 루트가지고 있습니다.)

내가 선호하는 패턴은 래퍼 스크립트를 ENTRYPOINT또는 로 사용하는 것 CMD입니다. 랩퍼 스크립트는 먼저 런타임시 외부 위치에서 컨테이너로 비밀을 가져온 다음 애플리케이션을 실행하여 비밀을 제공 할 수 있습니다. 이것의 정확한 메커니즘은 런타임 환경에 따라 다릅니다. AWS에서는 IAM 역할, 키 관리 서비스 및 S3 의 조합을 사용하여 암호화 된 비밀을 S3 버킷에 저장할 수 있습니다. HashiCorp Vault 또는 credstash 와 같은 것이 또 다른 옵션입니다.

AFAIK는 빌드 프로세스의 일부로 중요한 데이터를 사용하기위한 최적의 패턴이 없습니다. 사실, 나는 이 주제에 대한 SO 질문 이 있습니다. docker-squash 를 사용 하여 이미지에서 레이어를 제거 할 수 있습니다 . 그러나이 목적을 위해 Docker에는 기본 기능이 없습니다.

컨테이너의 구성에 대한 수줍음 설명이 유용 할 수 있습니다.


다른 의견에서 언급했듯이 .config파일 을 포함하는 2 개의 레이어 (ADD 후 및 첫 RUN 후)가 있습니다 .
Petr Gladkikh

1
예, 환경 변수가 가장 좋은 방법 인 것 같습니다. 나는 TDDing Dockerfile 개발의 맥락에서 이것을 보았습니다.
gnoll110

5
비밀번호가 env 변수 인 경우에 나타납니다 docker inspect.
날씬한

docker (linux)의 기본 설치는 sudoer 권한이 필요합니다 docker inspect. 침입자가 이미 sudo를 할 수 있다면, docker inspect에서 암호를 빼내는 것은 아마도 잘못 될 수있는 것들의 목록에서 아마도 낮을 것입니다. 이 특정 세부 사항은 나에게 허용되는 위험처럼 보입니다.
GrandOpener 17

7
@GrandOpener 시스템을 사용하는 침입자가있는 상황에만 적용됩니다. 도커 이미지를 저장소에 푸시하고 다른 사람이 가져온 경우, 자신의 시스템에 sudo가 있는지 여부는 신경 쓰지 않지만 env에서 더 이상 존재하지 않는 비밀을 볼 수 있는지 확실히 신경 씁니다.
vee_ess 2016 년

74

Google 팀은 리포지토리에 자격 증명을 넣지 않기 때문에에 허용되지 않습니다 Dockerfile. 응용 프로그램 내에서 우리의 모범 사례는 환경 변수의 cred를 사용하는 것입니다.

우리는 이것을 사용하여 해결합니다 docker-compose.

docker-compose.yml에서 컨테이너의 환경 변수가 포함 된 파일을 지정할 수 있습니다.

 env_file:
- .env

반드시 추가 할 수 있도록 .env하기 위해 .gitignore, 다음 내 자격 증명 설정 .env등의 파일을 :

SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd

.env파일을 로컬 또는 팀의 다른 팀이 확보 할 수있는 안전한 위치에 저장하십시오 .

참조 : https://docs.docker.com/compose/environment-variables/#/the-env-file


15
원하는 경우 .env 파일없이이 작업을 수행 할 수도 있습니다. docker-compose.yml 파일에서 환경 속성 을 사용 하십시오. "키만있는 환경 변수는 작성이 실행중인 시스템의 해당 값으로 분석되므로 비밀 또는 호스트 별 값에 도움이 될 수 있습니다."
D. Visser

1
이 남자에게 쿠키를 줘! :) 그래 이것은 실제로 좋은 습관입니다. docs.docker.com/compose/env-file 이 자동으로 작동하지만 docker compose 버전 2에서는이 답변에 설명 된대로 선언해야한다고 생각합니다.
동등한 8

5
/ proc / <pid> / environ 및 docker inspect를 통해 env var를 볼 수 있으므로 환경 변수 사용은 Docker 팀 자체에서 권장하지 않습니다. 루트 액세스 권한을 얻은 공격자에 대한 자격 증명을 얻는 방법을 혼란스럽게합니다. 물론 자격 증명은 CVS에서 추적해서는 안됩니다. 루트 사용자가 신용을 얻지 못하게하는 유일한 방법은 암호화 된 파일에서 웹 응용 프로그램 내에서 자격 증명을 읽고 (프로세스 환경 파일을 업데이트하지 않음) 암호 해독 프로세스가 안전하게 암호를 요구하는 것입니다. 나는 무덤으로 시도 할 것 같아요 : github.com/dyne/Tomb
pawamoy

.gitignore그래서 것을 .env중요한 정보와 파일을 체크 인되지 않습니다 GitHub의에. 추가하면 작동하지 않을 것입니다..dockerignore
TheUtherSide

안녕하세요 @theUtherSide, 귀하의 답변에 감사드립니다. .env파일을 체크인 하지 않고 전제로 서버에 배포 할 때 질문 이 있습니다 .env. 서버에서 수동으로 파일을 다시 작성하는 것이 좋습니다 ?
opensource-developer

37

Docker now (버전 1.13 또는 17.06 이상)는 비밀 정보 관리를 지원합니다. 여기의 개요 및 자세한 설명서

비슷한 기능의 존재 는 KubernetesDCOS


위의 링크에서 유용한 명령 : docker secret create: 비밀 생성 : 비밀에 docker secret inspect대한 자세한 정보 표시 docker secret ls: 모든 비밀보기 docker secret rm: 특정 비밀 --secret플래그 제거 docker service create: 서비스 생성시 비밀 생성 --secret-add--secret-rm플래그 docker service update: 비밀 값 업데이트 또는 비밀 제거 서비스 업데이트 작업 중 Docker 비밀은 관리자 노드에서 유휴 상태로 보호되고 컨테이너 시작 중에 작업자 노드에 프로비저닝됩니다.
PJ

7
예, Docker 비밀을 사용하려면 무리를 설정해야합니다.
Heather QC

11
이것은 답변을 시작하기에 좋은 방법이지만 답변 자체에 표시되는 정보는 훨씬 더 필요합니다.
Jeff Lambert

7
무리에서만 작동하는 경우 이것이 허용되는 답변인지 확실하지 않습니다. 많은 사람들이 떼를 사용하지 않지만 여전히 비밀을 전달해야합니다.
John Y

9

이미지를 다운로드 할 수있는 사람에게 자격 증명을 브로드 캐스트하지 않는 한 컨테이너에 자격 증명을 추가해서는 안됩니다. 특히 creds 파일이 중간 파일 시스템 계층의 최종 이미지에 남아 있기 때문에 ADD credsand 이후의 작업 RUN rm creds은 안전하지 않습니다. 이미지에 액세스 할 수있는 사람이라면 누구나 쉽게 추출 할 수 있습니다.

종속성을 체크 아웃하기 위해 cred가 필요할 때 본 전형적인 솔루션은 컨테이너를 사용하여 다른 컨테이너를 만드는 것입니다. 즉, 일반적으로 기본 컨테이너에 빌드 환경이 있으며 앱 컨테이너를 빌드하려면 해당 환경을 호출해야합니다. 따라서 간단한 해결책은 앱 소스를 추가 한 다음 RUN빌드 명령 을 추가하는 것 입니다. 만약 당신이 그 안에 신념이 필요하다면 이것은 안전하지 않습니다 RUN. 대신 로컬 소스에 소스를 넣고 docker run컨테이너 에서 (와 같이 ) 로컬 소스 디렉토리를 볼륨으로 마운트하고 creds를 다른 볼륨으로 주입하거나 마운트하여 빌드 단계를 수행하십시오. 빌드 단계가 완료되면 ADD이제 빌드 된 아티팩트가 포함 된 로컬 소스 디렉토리를 간단히 보내 최종 컨테이너를 빌드하십시오 .

Docker 가이 모든 것을 단순화하기 위해 몇 가지 기능을 추가하기를 희망합니다!

업데이트 : 앞으로 메소드가 중첩 된 빌드를 갖는 것처럼 보입니다. 간단히 말해서, dockerfile은 런타임 환경을 구축하는 데 사용되는 첫 번째 컨테이너와 모든 컨테이너를 최종 컨테이너에 조립할 수있는 두 번째 중첩 컨테이너 빌드를 설명합니다. 이렇게하면 빌드 타임이 두 번째 컨테이너에 없습니다. 앱을 빌드하는 데 JDK가 필요하지만 실행을 위해 JRE 만 필요한 Java 앱입니다. https://github.com/docker/docker/issues/7115 에서 시작 하여 대체 제안에 대한 링크 중 일부를 따르는 것이 가장 좋습니다 .


7

환경 변수를 많이 사용하는 경우 혼란 스러울 수있는 환경 변수를 사용하는 대신 볼륨을 사용하여 호스트의 디렉토리를 컨테이너에서 액세스 할 수 있습니다.

모든 자격 증명을 해당 폴더에 파일로 저장하면 컨테이너가 파일을 읽고 원하는대로 사용할 수 있습니다.

예를 들면 다음과 같습니다.

$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...

In the Docker container:

# echo Password is `cat /cfg/password.txt`
Password is secret

많은 프로그램이 별도의 파일에서 자격 증명을 읽을 수 있으므로이 방법으로 프로그램을 파일 중 하나를 가리킬 수 있습니다.


5

런타임 전용 솔루션

docker-compose는 비-스웜 모드 솔루션을 제공합니다 (v1.11부터 : bind mounts를 사용하는 비밀 ).

비밀은 /run/secrets/docker-compose에 의해 아래 파일로 마운트됩니다 . 이렇게하면 빌드 타임에 /run/secrets/마운트되지 않으므로 런타임 (컨테이너 실행)에서는 문제가 해결되지만 빌드 타임 (이미지 빌드)에서는 문제 가 해결되지 않습니다. 또한이 동작은 docker-compose로 컨테이너를 실행하는 데 달려 있습니다.


예:

도커 파일

FROM alpine
RUN cat /run/secrets/password
CMD sleep inifinity

docker-compose.yml

version: '3.1'
services:
  app:
    build: .
    secrets:
      - password

secrets:
  password:
    file: password.txt

빌드하려면 다음을 실행하십시오.

docker-compose up -d

더 읽을 거리 :


2

으로 도커 v1.9 개발자 당신은 사용할 수 ARG 명령 에 이미지에 명령 라인으로 전달 된 인수 가져 빌드 작업을 . 간단히 --build-arg 플래그를 사용하십시오 . 따라서 Dockerfile에 명시 적 암호 (또는 다른 합리적인 정보)를 유지하지 않고 즉시 전달할 수 있습니다.

출처 : https://docs.docker.com/engine/reference/commandline/build/ http://docs.docker.com/engine/reference/builder/#arg

예:

도커 파일

FROM busybox
ARG user
RUN echo "user is $user"

이미지 빌드 명령

docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .

빌드하는 동안 인쇄

$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .

Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
 ---> c51f86c28340
Step 2 : ARG user
 ---> Running in 43a4aa0e421d
 ---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
 ---> Running in 4360fb10d46a
**user is capuccino**
 ---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9

그것이 도움이되기를 바랍니다! 안녕.


26
Docker의 ARG 문서 에 따르면 "github 키, 사용자 자격 증명 등의 비밀을 전달하는 데 빌드 타임 변수를 사용하지 않는 것이 좋습니다"
Lie Ryan

3
Docker --build-arg var=secret가 SSH 개인 키를 이미지에 전달하는 데 사용하지 않는 이유를 궁금해하는 이유 는 문서화되지 않았습니다. 누구나 설명 할 수 있습니까?
Henk Wiersema

2
@HenkWiersema 프로세스 정보, 로그 및 명령 기록이 안전하지 않습니다. 프로세스 정보는 공개적으로 사용 가능하며 모든 명령 행 매개 변수를 포함합니다. 종종 이러한 호출은 공개 될 수있는 로그로 끝납니다. 공격자가 실행중인 프로세스에 대한 정보를 검사하고 공개 로그 파일을 탐색하여 비밀을 확인하는 것은 드문 일이 아닙니다. 공개되지 않은 경우에도 명령 기록에 저장되어 관리자가 아닌 계정을 통해 누군가가 비밀을 쉽게 얻을 수 있습니다.
tu-Reinstate Monica-dor du du

2
빌드시 필요한 자격 증명을 제공하기 위해 권장되는 방법은 무엇입니까? 예를 들어 aws s3 액세스가 필요한 이미지는 이미지 내부에있을 큰 데이터 세트를 가져 오는가?
ely

3
권장하지 않는 이유 docker historybuild-arg/ ARG변수 가 노출 되어 있기 때문 입니다. 이미지를 가져 와서 검사하고 빌드 중에 전달 된 비밀을 build-arg/ ARG매개 변수로 볼 수 있습니다.
vee_ess 2016 년

2

내 접근 방식은 효과가있는 것 같지만 아마도 순진합니다. 왜 그런지 말해줘.

docker build 동안 설정된 ARG는 history 하위 명령에 의해 노출되므로 아무 것도 수행하지 않습니다. 그러나 컨테이너를 실행할 때 run 명령에 제공된 환경 변수는 컨테이너에서 사용할 수 있지만 이미지의 일부는 아닙니다.

따라서 Dockerfile에서 비밀 데이터가 포함되지 않은 설정을 수행하십시오. 과 같은 CMD를 설정하십시오 /root/finish.sh. run 명령에서 환경 변수를 사용하여 비밀 데이터를 컨테이너로 보냅니다. finish.sh본질적으로 변수를 사용하여 빌드 작업을 완료합니다.

비밀 데이터를보다 쉽게 ​​관리하려면 --env-file스위치를 사용하여 docker run에 의해로드 된 파일에 비밀 데이터를 저장하십시오 . 물론 파일을 비밀로 유지하십시오. .gitignore등.

나를 위해, finish.sh파이썬 프로그램을 실행합니다. 이전에 실행되지 않았는지 확인한 다음 설정을 완료합니다 (예 : 데이터베이스 이름을 Django 's에 복사 settings.py).


2

"비밀"관리를위한 새로운 docker 명령 이 있습니다 . 그러나 이것은 집단 클러스터에서만 작동합니다.

docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
microsoft/iis:nanoserver 


-2

전적으로 동의하지만 간단한 해결책은 없습니다. 단일 실패 지점이 계속 존재합니다. 도커 파일 등입니다. Apcera에는 이중 인증과 같은 계획이 있습니다. 즉, Apcera 구성 규칙이 없으면 두 컨테이너가 통신 할 수 없습니다. 데모에서 uid / pwd는 명확했으며 관리자가 연결을 구성 할 때까지 재사용 할 수 없었습니다. 그러나 이것이 작동하기 위해서는 Docker 또는 적어도 네트워크 플러그인을 패치해야합니다 (이러한 것이있는 경우).


2
질문에 대한 답이 있습니까?
Abhijit Sarkar 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.