source

Docker 빌드 컨텍스트 밖의 파일을 포함하는 방법은 무엇입니까?

nicesource 2023. 8. 17. 21:25
반응형

Docker 빌드 컨텍스트 밖의 파일을 포함하는 방법은 무엇입니까?

도커 파일의 "ADD" 명령을 사용하여 도커 빌드 컨텍스트 외부의 파일을 포함하려면 어떻게 해야 합니까?

도커 설명서에서 다음을 참조하십시오.

경로는 빌드의 컨텍스트 내에 있어야 합니다. 도커 빌드의 첫 번째 단계는 컨텍스트 디렉터리(및 하위 디렉터리)를 도커 데몬으로 보내는 것이기 때문에 ../something/something을 추가할 수 없습니다.

이 문제에 있어서 도커를 수용하기 위해 전체 프로젝트를 재구성하고 싶지 않습니다.모든 Docker 파일을 동일한 하위 디렉터리에 보관합니다.

또한 도커는 아직 심볼릭 링크를 지원하지 않는 것으로 보입니다.도커 파일 ADD 명령이 호스트 #1676의 심볼 링크를 따르지 않습니다.

제가 생각할 수 있는 유일한 방법은 Docker 빌드 컨텍스트에 파일을 복사하는 빌드 전 단계를 포함하는 것입니다(그리고 해당 파일을 무시하도록 버전 컨트롤을 구성합니다).이보다 더 나은 해결 방법이 있습니까?

이 문제를 해결하는 가장 좋은 방법은 -f를 사용하여 빌드 컨텍스트와 독립적으로 도커 파일을 지정하는 것입니다.

예를 들어, 이 명령어는 현재 디렉토리에 있는 모든 항목에 대한 ADD 명령어 액세스 권한을 부여합니다.

docker build -f docker-files/Dockerfile .

업데이트: 이제 도커는 빌드 컨텍스트 밖에서 도커 파일을 사용할 수 있습니다(18.03.0-ce에서 수정됨).그래서 당신은 또한 다음과 같은 것을 할 수 있습니다.

docker build -f ../Dockerfile .

좋은 패턴과 이 기능 지원을 통해 어떤 일이 일어나고 있는지 더 잘 설명할 수 있는 방법을 찾기 위해 많은 시간을 보냈습니다.저는 그것을 설명하는 가장 좋은 방법이 다음과 같다는 것을 깨달았습니다.

  • 도커 파일:고유한 상대 경로 아래에 있는 파일만 볼 수 있습니다.
  • 컨텍스트: 공유할 파일과 Docker 파일이 복사될 "공간"의 플레이스

여기 . 도커 파일은 도커 파일, 도커 파일, 도커 파일이라는 .start.sh

도커 파일

지정한 경로에 대한 로컬 참조로 현재 디렉터리를 사용하여 항상 상대 경로에서 로드됩니다.

COPY start.sh /runtime/start.sh

파일

이것을 빌드하는 데 의 복사본을 것을 할 수 , Docker 파일에 수 있어야 합니다.start.sh.

./all-services/
   /start.sh
   /service-X/Dockerfile
   /service-Y/Dockerfile
   /service-Z/Dockerfile
./docker-compose.yaml

이 구조와 위의 파일들을 고려해 볼 때, 여기 도커 컴포지.yml이 있습니다.

도커식의

  • 이 예에서 공유 컨텍스트 디렉토리는 런타임 디렉토리입니다.
    • 여기 있는 것과 같은 정신적 모델입니다. 이 디렉토리 아래의 모든 파일이 소위 컨텍스트로 이동한다고 생각하십시오.
    • 마찬가지로 동일한 디렉토리에 복사할 도커 파일을 지정하십시오.다음을 사용하여 지정할 수 있습니다.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는 각각의 "Docker"에서 합니다.dockerfile.
  • 각각의 시작 파일을 공유하면서 각자의 방식으로 구축됩니다!

나는 종종 내가 그것을 이용하는 것을 발견합니다.--build-arg이 목적을 위한 옵션.예를 들어 Docker 파일에 다음을 입력한 후:

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)" .

그러나 도커 설명서의 다음 경고에 유의하십시오.

경고:github 키, 사용자 자격 증명 등과 같은 암호 전달에는 빌드 시간 변수를 사용하지 않는 것이 좋습니다.빌드 시간 변수 값은 도커 히스토리 명령을 사용하여 이미지의 모든 사용자가 볼 수 있습니다.

Linux에서는 다른 디렉터리를 연결하는 대신 마운트할 수 있습니다.

mount --bind olddir newdir

자세한 내용은 https://superuser.com/questions/842642 을 참조하십시오.

다른 운영체제에서도 비슷한 것을 사용할 수 있을지 모르겠습니다.또한 Samba를 사용하여 폴더를 공유하고 Docker 컨텍스트에 다시 마운트해 보았습니다.

2745호의 논의를 읽으신다면 도커만이 심볼릭 링크를 절대 지원하지 않을 수도 있습니다. 도커는 사용자의 컨텍스트 외부에 파일을 추가하는 것을 절대 지원하지 않을 수도 있습니다.도커 빌드에 들어가는 파일은 명시적으로 컨텍스트의 일부이거나 도커 컨테이너와 함께 제공되는 잘 알려진 URL 또는 파일로 빌드를 반복할 수 있도록 고정 버전과 함께 배포되는 URL에서 온 것이어야 한다는 설계 철학인 것 같습니다.

저는 버전 제어 소스 - 즉 도커 build -t stuff http://my.git.org/repo 에서 빌드하는 것을 선호합니다. 그렇지 않으면 임의의 파일로 임의의 장소에서 빌드합니다.

근본적으로, 아니... -- 스벤 다우와이드잇, 도커 주식회사.

제 의견이지만 코드와 도커 저장소를 분리하도록 재구성해야 한다고 생각합니다.이렇게 하면 컨테이너가 일반적이고 빌드 시간이 아닌 런타임에 코드의 모든 버전을 가져올 수 있습니다.

또는 도커를 기본 코드 배포 아티팩트로 사용한 다음 도커 파일을 코드 저장소 루트에 넣습니다.이 경로로 이동하는 경우 보다 일반적인 시스템 수준 세부사항을 위한 상위 도커 컨테이너와 코드에 관련된 설정을 위한 하위 컨테이너가 있어야 합니다.

더 간단한 해결 방법은 '컨텍스트' 자체를 변경하는 것이라고 생각합니다.

예를 들어, 다음을 제공하는 대신:

docker build -t hello-demo-app .

현재 디렉터리를 컨텍스트로 설정합니다. 상위 디렉터리를 컨텍스트로 사용했다고 가정해 보겠습니다.

docker build -t hello-demo-app ..

또한 이미지에 가장 먼저 필요한 항목에 대한 tarball을 만들어 컨텍스트로 사용할 수 있습니다.

https://docs.docker.com/engine/reference/commandline/build/ #/tarball-tarball-tavor

이 동작은 컨텍스트 디렉터리에 의해 제공됩니다.docker또는podman를 사용하여 빌드 프로세스에 파일을 표시합니다.
여기서 좋은 방법은 빌드 명령 중에 컨텍스트 dir를 데몬에 노출할 디렉터리의 전체 경로로 변경하는 것입니다.예:

docker build -t imageName:tag -f /path/to/the/Dockerfile /mysrc/path

용사를 /mysrc/path.(현재 디렉터리), 이 디렉터리를 컨텍스트로 사용하여 빌드 프로세스에서 해당 디렉터리 아래의 모든 파일을 볼 수 있습니다.
이 예에서는 전체를 노출하게 됩니다./mysrc/path도커 데몬의 트리입니다.
을 을사때할용능과 함께 때.docker빌드를 트리거한 사용자 ID는 컨텍스트 dir에서 단일 디렉터리 또는 파일에 대한 재귀적 읽기 권한을 가지고 있어야 합니다.

이것은 당신이 가지고 있는 경우에 유용할 수 있습니다./home/user/myCoolProject/Dockerfile그러나 같은 디렉터리에 없는 파일을 이 컨테이너 빌드 컨텍스트로 가져오려고 합니다.

은 context dir를 입니다. 에는 context dir를 사용합니다.podmandocker.

예를 들어, 당신의 내부에 있습니다.Dockerfile a COPY또는ADD다음과 같이 프로젝트 외부의 디렉토리에서 파일을 복사하는 명령입니다.

FROM myImage:tag
...
...
COPY /opt/externalFile ./
ADD /home/user/AnotherProject/anotherExternalFile ./
...

이 이를구컨파다위에 ./home/user/myCoolProject/Dockerfile다음과 같은 작업을 수행합니다.

cd /home/user/myCoolProject
podman build -t imageName:tag -f Dockefile /

컨텍스트 dir를 변경하는 몇 가지 알려진 사용 사례는 소스 코드를 작성하기 위한 도구 체인으로 컨테이너를 사용하는 경우입니다.
예: 예:

podman build --platform linux/s390x -t myimage:mytag -f ./Dockerfile /tmp/mysrc

또는 다음과 같은 경로 상대적일 수 있습니다.

podman build --platform linux/s390x -t myimage:mytag -f ./Dockerfile ../../

이 시간을 전역 경로로 사용하는 다른 예:

FROM myImage:tag
...
...
COPY externalFile ./
ADD  AnotherProject ./
...

이전글경는로의 경로에 하십시오.COPY그리고.ADDDockerfile 명령 계층에서 생략됩니다.
이 경우에는contex dir다 파일 .externalFile그리고.AnotherProject안에 있습니다/opt에 디토리다에음.context dir건물의 경우 다음과 같아야 합니다.

podman build -t imageName:tag -f ./Dockerfile /opt

context dir를 사용하거나 사용할 때 참고:
docker데몬은 컨텍스트 디르 트리에 표시되는 모든 파일을 데몬으로 "스트리밍"하려고 시도하므로 빌드 속도가 느려질 수 있습니다.또한 사용자가 컨텍스트 dir로부터 재귀적인 권한을 가져야 합니다.이 동작은 특히 API를 통해 빌드를 사용하는 경우 비용이 더 많이 들 수 있습니다., 지만과 함께, 께함.podman 즉시 는 적인권필없즉발빌생드다니합가시재이귀요한이다니▁the발 때문입니다.podmandir를 전체컨를열트않거하으지며, 사지않습다니하용텍스를 .client/server건축도 마찬가지입니다.
이러한 경우를 위한 빌드는 사용하기에 훨씬 더 흥미로울 수 있습니다.podmandocker다른 컨텍스트 디르를 사용하여 이러한 문제에 직면할 때.

일부 참조:

이를 위해 올해 초부터 buildx에 기능이 추가된 것 같습니다.

도커 파일 1.4+ 및 buildx 0.8+가 있는 경우 다음과 같은 작업을 수행할 수 있습니다.

docker buildx build --build-context othersource= ../something/something .

그런 다음 도커 파일에서 from 명령을 사용하여 컨텍스트를 추가할 수 있습니다.

ADD –-from=othersource . /stuff

관련 게시물을 참조하십시오.

GitHub 문제에서 설명한 바와 같이 빌드는 실제로 다음에서 발생합니다./tmp/docker-12345 그서같 은상인 경적로와 같은 인 경로.../relative-add/some-file는 에상입니다적대▁to다▁relative에 상대적입니다./tmp/docker-12345그러므로 그것은 검색할 것입니다./tmp/relative-add/some-file오류 메시지에도 표시됩니다.*

빌드 디렉토리 외부의 파일을 포함할 수 없으므로 "금지된 경로" 메시지가 표시됩니다.

도커 컴포지를 사용하여 필요한 볼륨을 마운트하는 서비스를 만들고 컨테이너 이미지를 커밋하여 이를 달성했습니다.그런 다음 후속 서비스에서는 마운트된 위치에 모든 데이터가 저장된 이전에 커밋된 이미지에 의존합니다. 디렉토리가 될 때 .docker commit

이것을 달성하기 위해 도커 컴포지트를 사용할 필요는 없지만, 그것은 삶을 조금 더 편하게 만듭니다.

# docker-compose.yml

version: '3'
  services:
    stage:
      image: alpine
      volumes:
        - /host/machine/path:/tmp/container/path
      command: bash -c "cp -r /tmp/container/path /final/container/path"
    setup:
      image: stage
# setup.sh

# Start "stage" service
docker-compose up stage

# Commit changes to an image named "stage"
docker commit $(docker-compose ps -q stage) stage

# Start setup service off of stage image
docker-compose up setup

셸 " " " 를 호출합니다.docker build그런 다음 파일을 제거합니다.

여기 어디에도 언급되지 않은 간단한 해결책이 있습니다.

  • 다래스호를출니합라는 래퍼 .docker_build.sh
  • 타르볼을 만들고, 큰 파일을 현재 작업 디렉토리에 복사하도록 합니다.
  • 을 부르다docker build
  • 타르볼, 대형 파일 등을 정리합니다.

은 (키를 할 때 구멍이 때문에 좋습니다. (2.) 다른 은 SSH를 사용합니다. (1.) SSH를 사용합니다. (2.) 이 솔루션은 좋습니다.sudo bind은 루트 더. 왜냐하면 루트 권한이 필요하기 때문입니다.bind.

저는 개인적으로 몇 가지 답변에 혼란스러웠기 때문에 간단하게 설명하기로 했습니다.

이미지를 생성하려면 도커 파일에서 지정한 컨텍스트를 도커로 전달해야 합니다.

도커 파일에서 항상 프로젝트 루트를 컨텍스트로 선택합니다.

예를 들어 복사 명령사용하는 경우.

첫 번째 점(.)은 컨텍스트이고 두 번째 점(.)은 컨테이너 작업 디렉토리입니다.

컨텍스트가 프로젝트 루트, 점(.)이고 코드 구조가 다음과 같다고 가정합니다.

sample-project/
  docker/
    Dockerfile

이미지를 빌드하려는 경우

경로(도커 빌드 명령을 실행하는 경로)는 /full-path/sample-project/이며, 이 작업을 수행해야 합니다.

docker build -f docker/Dockerfile . 

경로가 /full-path/sample-project/sumplier/이면 다음 작업을 수행해야 합니다.

docker build -f Dockerfile ../ 

링크를 사용한 해결 방법:

ln path/to/file/outside/context/file_to_copy ./file_to_copy

Docker 파일에서 다음과 같이 간단히 수행합니다.

COPY file_to_copy /path/to/file

쉽게 해결할 수 있는 방법은 볼륨을 실행할 때 -v 또는 --mount 플래그를 사용하여 해당 볼륨을 컨테이너에 마운트하고 해당 방식으로 파일에 액세스하는 것입니다.

예:

docker run -v /path/to/file/on/host:/desired/path/to/file/in/container/ image_name

자세한 내용은 https://docs.docker.com/storage/volumes/ 를 참조하십시오.

저는 HIPAA의 이유로 레포 컨텍스트 내로 이동할 수 없는 프로젝트와 일부 데이터 파일에 동일한 문제가 있었습니다.저는 도커 파일 2개를 사용하게 되었습니다.하나는 컨테이너 외부에서 필요한 것 없이 메인 애플리케이션을 구축하고 내부 repo에 게시합니다.그런 다음 두 번째 도커 파일이 해당 이미지를 가져와서 데이터를 추가하고 새 이미지를 생성합니다. 이 이미지는 배포된 후 아무 곳에도 저장되지 않습니다.이상적이지는 않지만 중요한 정보를 보고서에 넣지 않는 것이 제 목적에 효과가 있었습니다.

제 경우에는 Docker 파일이 플레이스홀더를 포함하는 템플릿처럼 작성되어 구성 파일을 사용하여 실제 값으로 대체합니다.

따라서 이 파일을 직접 지정할 수는 없지만 다음과 같이 도커 빌드에 파이프로 연결합니다.

sed "s/%email_address%/$EMAIL_ADDRESS/;" ./Dockerfile | docker build -t katzda/bookings:latest . -f -;

하지만 파이프 때문에,COPY명령이 작동하지 않았습니다.하지만 위의 방법은 그것을 해결합니다.-f -(분명히 파일이 제공되지 않았다고 함).만 하기- 없이-f주의 사항인 플래그, 컨텍스트 및 도커 파일이 제공되지 않습니다.

두 Docker 파일 간에 유형 스크립트 코드를 공유하는 방법

저도 같은 문제가 있었지만, 두 종류의 스크립트 프로젝트 간에 파일을 공유하는 문제가 있었습니다.공유 코드 간의 상대적인 가져오기 경로를 보존해야 했기 때문에 다른 답변 중 일부는 효과가 없었습니다.코드를 다음과 같이 구성하여 해결했습니다.

api/
  Dockerfile
  src/
    models/
      index.ts

frontend/
  Dockerfile
  src/
    models/
      index.ts

shared/
  model1.ts
  model2.ts
  index.ts

.dockerignore

참고: 공유 코드를 해당 상위 폴더에 추출한 후에 업데이트했기 때문에 가져오기 경로를 업데이트할 필요가 없었습니다.api/models/index.ts그리고.frontend/models/index.ts (예: " 공에서내기내보예유▁(예": (::export * from '../../../shared)

빌드 컨텍스트가 이제 하나 더 높은 디렉터리이기 때문에 몇 가지 추가적인 변경을 해야 했습니다.

  1. 새 컨텍스트를 사용하도록 빌드 명령을 업데이트합니다.

    docker build -f Dockerfile .. 두 의 점) (하나대두개의점신점▁instead)개의)

  2. 일사용을 합니다..dockerignore모두를 제외한 최상위 수준에서node_modules: 예:**/node_modules/**)

  3. 앞에 .Dockerfile COPY 있는 명령api/또는frontend/

  4. 알았다.shared 하여)api/src또는frontend/src)

    WORKDIR /usr/src/app
    
    COPY api/package*.json ./     <---- Prefix with api/
    RUN npm ci
    
    COPY api/src api/ts*.json ./  <---- Prefix with api/
    COPY shared usr/src/shared    <---- ADDED
    RUN npm run build
    

이것은 두 프로젝트의 상대적인 가져오기 경로를 유지하면서 모든 것을 도커로 보낼 수 있는 가장 쉬운 방법이었습니다.까다로운(귀찮게 여기는) 부분은 빌드 컨텍스트가 하나의 디렉토리에 있기 때문에 발생하는 모든 변경/결과였습니다.

빌드 컨텍스트를 변경하는 것이 방법입니다.

.net 코어 프로젝트가 있는데 Visual Studio UI를 사용하여 프로젝트를 디버그/게시하려면 프로젝트 .csproj에 "DockerfileContext"를 추가하여 컨텍스트를 변경할 수 있습니다.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    <DockerfileContext>..\..\.</DockerfileContext>
  </PropertyGroup>

  ...

</Project>

그에 따라 도커 파일의 경로를 변경하는 것을 잊지 마십시오.

빠르고 더러운 방법 중 하나는 빌드 컨텍스트를 필요한 수준만큼 설정하는 것입니다. 그러나 이는 결과를 초래할 수 있습니다.다음과 같은 마이크로서비스 아키텍처에서 작업하는 경우:

./Code/Repo1
./Code/Repo2
...

할 수 .Code디렉터리를 지정한 다음 모든 항목에 액세스하지만 저장소 수가 많으면 빌드에 시간이 오래 걸릴 수 있습니다.

예를 들어 다른 팀이 데이터베이스 스키마를 관리할 수 있습니다.Repo1 팀의 코드는 코는당팀드의에 있습니다.Repo2이것에 달려 있습니다.스키마 변경이나 다른 팀의 저장소 오염에 대해 걱정하지 않고 자신의 시드 데이터와 함께 이 종속성을 강화하고 싶은 경우(변경 내용에 따라 시드 데이터 스크립트를 계속 변경해야 할 수도 있음)두 번째 접근 방식은 구식이지만 긴 빌드 문제를 해결합니다.

또는 ps1)에 sh( 를 만듭니다../Code/Repo2필요한 파일을 복사하고 원하는 도커 명령을 호출하려면 다음과 같이 하십시오.

#!/bin/bash
rm -r ./db/schema
mkdir ./db/schema

cp  -r ../Repo1/db/schema ./db/schema

docker-compose -f docker-compose.yml down
docker container prune -f
docker-compose -f docker-compose.yml up --build

를 도커합파일컨텍를다트음같설다정니합으로 만 하면 됩니다.Repo2의내을 합니다../db/schema경로에 대한 걱정 없이 도커 파일의 디렉터리.실수로 이 디렉터리를 소스 제어에 커밋할 위험이 있지만 정리 작업을 스크립팅하는 것은 매우 쉽습니다.

언급URL : https://stackoverflow.com/questions/27068596/how-to-include-files-outside-of-dockers-build-context

반응형