Docker 파일에서 “ADD”명령을 사용하여 Docker의 빌드 컨텍스트 외부의 파일을 어떻게 포함시킬 수 있습니까?
Docker 설명서에서 :
경로는 빌드 컨텍스트 내에 있어야합니다. 도커 빌드의 첫 번째 단계는 컨텍스트 디렉토리 (및 서브 디렉토리)를 도커 디먼에 보내는 것이므로 ../something/something을 추가 할 수 없습니다.
이 문제에 Docker를 수용하기 위해 전체 프로젝트를 재구성하고 싶지 않습니다. 모든 Docker 파일을 동일한 하위 디렉토리에 유지하고 싶습니다.
또한 Docker가 아직 심볼릭 링크를 지원하지 않는 것으로 보입니다. Dockerfile ADD 명령은 호스트 # 1676의 심볼릭 링크를 따르지 않습니다.
내가 생각할 수있는 유일한 다른 것은 파일을 Docker 빌드 컨텍스트에 복사하는 사전 빌드 단계를 포함시키는 것입니다 (그리고 해당 파일을 무시하도록 버전 컨트롤을 구성하십시오). 그보다 더 나은 해결 방법이 있습니까?
답변
이 문제를 해결하는 가장 좋은 방법은 -f를 사용하여 빌드 컨텍스트와 독립적으로 Dockerfile을 지정하는 것입니다.
예를 들어이 명령은 ADD 명령에 현재 디렉토리의 모든 항목에 대한 액세스 권한을 부여합니다.
docker build -f docker-files/Dockerfile .
업데이트 : Docker는 이제 Dockerfile을 빌드 컨텍스트 외부에 허용합니다 (18.03.0-ce, https://github.com/docker/cli/pull/886에 고정 ). 그래서 당신은 또한 같은 것을 할 수 있습니다
docker build -f ../Dockerfile .
답변
나는 종종 --build-arg
이 목적을 위해 옵션을 사용하고 있다고 생각합니다 . 예를 들어 Dockerfile에 다음을 넣은 후 :
ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
당신은 할 수 있습니다 :
docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .
그러나 Docker 설명서 에서 다음 경고에 유의하십시오 .
경고 : github 키, 사용자 자격 증명 등과 같은 비밀을 전달하기 위해 빌드 시간 변수를 사용하지 않는 것이 좋습니다. 빌드 시간 변수 값은 docker history 명령으로 이미지의 모든 사용자에게 표시됩니다.
답변
Linux에서는 다른 디렉토리를 심볼릭 링크하는 대신 마운트 할 수 있습니다
mount --bind olddir newdir
자세한 내용은 /superuser/842642 를 참조하십시오.
다른 OS에서 비슷한 것을 사용할 수 있는지 모르겠습니다. 또한 Samba를 사용하여 폴더를 공유하고 폴더를 Docker 컨텍스트에 다시 마운트하려고 시도했습니다.
답변
나는 좋은 패턴을 알아 내기 위해이 시간을 보냈다. 설명하는 가장 좋은 방법은 다음과 같습니다.
- Dockerfile : 자체 상대 경로에서 파일 만 볼 수 있습니다
- 컨텍스트 : 공유하려는 파일과 Dockerfile이 복사 될 “공간”의 위치
그래서, 말했듯이, 여기에 파일을 재사용 해야하는 Dockerfile의 예가 있습니다. start.sh
도커 파일
그것은 ALWAYS
로 자신의 현재 디렉토리를 가진, 상대 경로에서로드됩니다 local
사용자가 지정한 경로에 대한 참조입니다.
COPY start.sh /runtime/start.sh
파일
이 아이디어를 고려하면 Dockerfiles에 특정 항목을 빌드하기 위해 여러 개의 사본이 있다고 생각할 수 있지만 모두에 액세스해야합니다 start.sh
.
./all-services/
/start.sh
/service-X/Dockerfile
/service-Y/Dockerfile
/service-Z/Dockerfile
./docker-compose.yaml
이 구조와 위의 파일을 고려하면 docker-compose.yml이 있습니다.
docker-compose.yaml
- 이 예에서
shared
컨텍스트 디렉토리는runtime
디렉토리입니다.- 여기 동일한 정신 모델로,이 디렉토리 아래의 모든 파일이 소위로 이동한다고 생각하십시오
context
. - 마찬가지로 동일한 디렉토리에 복사하려는 Dockerfile을 지정하십시오. 을 사용하여 지정할 수 있습니다
dockerfile
.
- 여기 동일한 정신 모델로,이 디렉토리 아래의 모든 파일이 소위로 이동한다고 생각하십시오
- 기본 컨텐츠가있는 디렉토리는 설정할 실제 컨텍스트입니다.
은 docker-compose.yml
다음과 같습니다
version: "3.3"
services:
service-A
build:
context: ./all-service
dockerfile: ./service-A/Dockerfile
service-B
build:
context: ./all-service
dockerfile: ./service-B/Dockerfile
service-C
build:
context: ./all-service
dockerfile: ./service-C/Dockerfile
all-service
는 컨텍스트로 설정되고 공유 파일start.sh
은 각로 지정된 Dockerfile과 함께 복사됩니다dockerfile
.- 시작 파일을 공유하여 각자 고유의 방식으로 빌드됩니다!
건배!
답변
문제 2745 의 토론을 읽으면 docker는 심볼릭 링크를 지원하지 않을뿐만 아니라 컨텍스트 외부의 파일 추가를 지원하지 않을 수도 있습니다. docker 빌드에 들어가는 파일은 명시 적으로 컨텍스트의 일부이거나 고정 버전으로도 배포 된 URL에서 가져와야하므로 잘 알려진 URL 또는 파일과 함께 제공되는 파일로 빌드를 반복 할 수있는 디자인 철학 인 것 같습니다. 도커 컨테이너.
나는 버전 제어 소스 (예 : docker build -t stuff http://my.git.org/repo) 에서 빌드하는 것을 선호합니다. 그렇지 않으면 임의의 파일로 임의의 장소에서 빌드하고 있습니다.
근본적으로, …..-SvenDowideit, Docker Inc
내 의견이지만 코드와 도커 리포지토리를 분리하려면 재구성해야한다고 생각합니다. 이렇게하면 컨테이너가 일반적이며 빌드 타임이 아닌 런타임에 모든 버전의 코드를 가져올 수 있습니다.
또는 docker를 기본 코드 배포 아티팩트로 사용하고 dockerfile을 코드 리포지토리의 루트에 넣습니다. 이 경로를 사용하는 경우 더 일반적인 시스템 수준 세부 정보를위한 부모 도커 컨테이너와 코드와 관련된 설정을위한 자식 컨테이너를 갖는 것이 좋습니다.
답변
더 간단한 해결 방법은 ‘컨텍스트’자체를 변경하는 것입니다.
예를 들어, 대신 다음을 제공하십시오.
docker build -t hello-demo-app .
현재 디렉토리를 컨텍스트로 설정합니다. 부모 디렉토리를 컨텍스트로 원한다고 가정 해 봅시다.
docker build -t hello-demo-app ..
답변
먼저 이미지에 필요한 타르볼을 만들어이를 컨텍스트로 사용할 수도 있습니다.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts