programing

도커가 컨텍스트 외부의 심볼릭 링크를 따릅니다.

linuxpc 2023. 7. 30. 17:26
반응형

도커가 컨텍스트 외부의 심볼릭 링크를 따릅니다.

또 다른 도커 심볼릭 질문입니다.내 모든 도커 빌드에 복사할 파일이 많이 있습니다.내 dir 구조는 다음과 같습니다.

parent_dir
    - common_files
        - file.txt
    - dir1
        - Dockerfile  
        - symlink -> ../common_files

위의 예에서는 파일을 원합니다.dir1 내부 빌드를 도커할 때 복사할 txt.그러나 여러 개의 파일 복사본을 유지 관리하고 싶지 않습니다.txt. 도커 버전 0.10 기준으로 이 링크에 따라 도커 빌드는

ADD 빌드 지침은 컨테이너 루트 내부의 심볼 링크를 따릅니다.

그러나 Docker 파일에서 다음 행 중 하나를 사용하여 빌드하면 해당 파일이나 디렉터리가 표시되지 않습니다.

ADD symlink /path/dirname또는ADD symlink/file.txt /path/file.txt

마운트 옵션으로는 해결되지 않습니다(크로스 플랫폼...).나는 노력했다.tar -czh . | docker build -t성공하지 못한

도커가 심볼릭 링크를 따르고 common_files/file을 복사하도록 하는 방법이 있습니까?구축된 컨테이너에 txt를 넣으시겠습니까?

그것은 불가능하며 실행되지 않을 것입니다.github 이슈 #1676에 대한 논의를 살펴보시기 바랍니다.

반복할 수 없기 때문에 허용하지 않습니다.당신의 컴퓨터의 심볼릭 링크는 제 컴퓨터와 같지 않으며 같은 도커 파일은 두 가지 다른 결과를 생성합니다.또한 /etc/passwd에 대한 심볼 링크가 있으면 로컬 파일이 아닌 호스트 파일이 연결되기 때문에 문제가 발생합니다.

아직도 이 문제가 있는 사람이 있다면 superuser.com 에서 아주 좋은 해결책을 찾았습니다.

https://superuser.com/questions/842642/how-to-make-a-symlinked-folder-appear-as-a-normal-folder

기본적으로 tar를 사용하여 심볼 링크의 참조를 취소하고 결과를 도커 빌드에 제공할 것을 제안합니다.

$ tar -czh . | docker build -

한 가지 방법은 다음과 같은 방법으로 상위 디렉토리에서 빌드를 실행하는 것입니다.

$ docker build [tags...] -f dir1/Dockerfile .

(또는 동등하게 하위 디렉터리에서)

$ docker build  [tags...] -f Dockerfile ..

적절한 경로로 복사/추가를 수행하도록 도커 파일을 구성해야 합니다.▁a▁want다▁depending있니▁might습▁you를 원할 수도 있습니다..dockerignore부모님께선 문맥 속에 넣고 싶지 않은 것들을 생략할 수 있습니다.

도커 빌드의 이식성을 깨뜨린다는 것은 알지만 심볼릭 대신 하드 링크를 사용할 수 있습니다.

ln /some/file ./hardlink

저도 같은 맥락에서 이 문제를 해결해야 했습니다.내 해결책은 계층적 도커 빌드를 사용하는 것입니다.즉, 다음과 같습니다.

parent_dir
  - common_files
    - Dockerfile
    - file.txt

- dir1
    - Dockerfile (FROM common_files:latest)

단점은 dir1 이전에 common_files를 빌드해야 한다는 것입니다.여러 개의 종속 이미지가 있는 경우 공통 레이어를 사용하기 때문에 이미지 크기가 모두 약간 작아지는 것이 장점입니다.

작은 노드를 만들 정도로 좌절했습니다.이를 지원하는 JS 유틸리티: 파일 동기화

기존 디렉토리 구조를 고려할 때:

parent_dir
    - common_files
        - file.txt
    - my-app
        - Dockerfile
        - common_files -> symlink to ../common_files

기본 사용:

cd parent_dir

// starts live-sync of files under "common_files" to "my-app/HardLinked/common_files"
npx file-syncer --from common_files --to my-app/HardLinked

당신의 럼그당의에서.Dockerfile:

[regular commands here...]

# have docker copy/overlay the HardLinked folder's contents (common_files) into my-app itself
COPY HardLinked /

질의응답

  • 어떻게 이것이 단순히 복사하는 것보다 더 나은가요?parent_dir/common_filesparent_dir/my-app/common_files도커가 달리기 전에?

이는 심볼 링크가 유용하고 대부분의 도구에서 잘 작동하기 때문에 일반 심볼 링크를 포기한다는 것을 의미합니다.예를 들어 소스 파일을 보거나 편집할 수 없습니다.common_files몇 가지 단점이 있는 내 앱 복사본에서.(아래 참조)

  • 이 복사하는 더 ?parent_dir/common-filesparent_dir/my-app/common_files_Copy실행되기 을 도가실 기도전커그가합니다로 .parent_dir/my-app/common_files제조 시간에?

두 가지 이점이 있습니다.

  1. file-syncer는 일반적인 의미에서 파일을 "복사"하지 않습니다.원본 폴더의 파일에서 하드 링크를 만듭니다.이것은 만약 당신이 아래의 파일들을 편집한다면,parent_dir/my-app/HardLinked/common_files아에있파들에 있는 parent_dir/common_files는아파일한/ (이는 디버깅 과 교차 이 될 수 [가 활성 편집]),(특히 동기화 중인 폴더가 현재 편집 중인 노드 동기화된 경우) 디버깅 및 프로젝트 간 편집에 도움이 될 수 있으며 파일 버전이 항상 원본 파일에 동기화/동기화되도록 보장합니다.
  2. ㅠㅠfile-syncer변경되는 정확한 파일에 대한 하드 링크 파일만 업데이트합니다. Tilt 또는 Scaffold같은 파일 감시 도구는 최소한의 파일 집합에 대한 변경을 감지합니다. 이는 기본적인 "파일 변경 시 전체 폴더 복사" 도구보다 라이브 업데이트 푸시 시간이 더 빠르다는 것을 의미합니다.
  • 이것이 동기화와 같은 일반 파일 동기화 도구보다 어떻게 더 낫습니까?

이러한 도구 중 일부는 사용할 수 있지만 대부분은 한 가지 또는 다른 종류의 문제가 있습니다.가장 일반적인 방법은 기존 파일의 하드 링크를 생성할 수 없거나 이미 하드 링크된 파일에 대해 "업데이트 푸시"를 수행할 수 없다는 것입니다(하드 링크된 파일은 편집된 파일과 감시된 파일 경로가 다를 경우 파일 감시자에게 변경 사항을 자동으로 통지하지 않기 때문).는 이러한 중 수가빌드 에는 또이이동도즉대러응인예기구위각설않답제도빌을해지쉽구에서사드되계게한경틸수것용:없플실있하할록는도는다다래행니그의트가입)--asyncfile-syncer에서 사용할 수 있습니다.local(...)의 젝트시작의의 .Tiltfile)

도커가 수락하는 방식으로 디렉터리를 "연결"할 수 있는 한 가지 도구는 도커 자체입니다.

필요한 모든 파일/디렉토리가 적절한 경로에 마운트된 상태에서 임시 도커 컨테이너를 실행하고 이러한 컨테이너 내에서 이미지를 빌드할 수 있습니다.예:

docker run -it \
    --rm \
    -v /var/run/docker.sock:/var/run/docker.sock \
    --mount "type=bind,source=$ImageRoot/Dockerfile,destination=/Image/Dockerfile,readonly" \
    --mount "type=bind,source=$ImageRoot/.dockerignore,destination=/Image/.dockerignore,readonly" \
    --mount "type=bind,source=$ReposRoot/project1,destination=/Image/project1,readonly" \
    --mount "type=bind,source=$ReposRoot/project2,destination=/Image/project2,readonly" \
    --env DOCKER_BUILDKIT=1 \
    docker:latest \
        docker build "/Image" --tag "my_tag"

위의 예에서 변수를 가정합니다.$ImageRoot그리고.$ReposRoot설정되었습니다.

simlinks를 사용하는 대신 simlinks를 복사하거나 만드는 대신 sites_available_enable_enable_enable 파일을 sites에서 sites로 이동하는 것만으로 관리적으로 문제를 해결할 수 있습니다.

따라서 사이트 구성이 중지된 경우 site_available 폴더에만 한 복사본이 있고 사용해야 하는 경우 site_available 폴더에 무언가가 있거나 site_enabled 폴더에 있습니다.

작은 래퍼 스크립트를 사용하여 필요한 dir를 도커 파일의 위치에 복사합니다.

  • build.sh;

.

#!/bin/bash
[ -e bin ] && rm -rf bin
cp -r ../../bin .
docker build -t "sometag" .

일반적으로 빌드 명령어를 하위 폴더에 격리하므로 응용 프로그램 및 논리 수준이 더 높은 위치에 배치됩니다.

.
├── app
│   ├── package.json
│   ├── modules
│   └── logic
├── deploy
│   ├── back
│   │   ├── nginx
│   │   │   └── Chart.yaml
│   │   ├── Containerfile
│   │   ├── skaffold.yaml
│   │   └── .applift -> ../../app
│   ├── front
│   │   ├── Containerfile
│   │   ├── skaffold.yaml
│   │   └── .applift -> ../../app
│   └── skaffold.yaml
└── .......

저는 그 심볼릭 링크들에 대해 ".applift"라는 이름을 사용합니다. applift -> ../../app.

이제 경로 깊이에 구애받지 않고 실제 경로를 통해 심볼릭 링크를 추적할 수 있습니다.

dir/deploy/front$ docker build -f Containerfile --tag="build" `realpath .applift`

또는 func에서 짐을 싸라.

dir/deploy$ docker_build () { docker build -f "$1"/Containerfile --tag="$2" `realpath "$1/.applift"`; }
dir/deploy$ docker_build ./back "front_builder"

그렇게

COPY app/logic/ ./app/

컨테이너에서 파일이 작동합니다.

예, 이 경우 다른 도면층에 대한 컨텍스트가 늘어납니다.그러나 일반적으로 빌드 디렉토리에는 다른 컨텍스트 파일이 없습니다.

parent_dir에 common_files/의 공통 라이브러리와 common docker/Docker file이 포함되어 있는 상황이 있었습니다. dir1/에는 다른 코드 저장소의 내용이 포함되어 있었지만 해당 저장소가 이러한 부모 코드 저장소 폴더에 액세스할 수 있기를 원했습니다.다음과 같이 심볼릭 링크를 사용하지 않고 해결했습니다.

parent_dir
    - common_files
        - file.txt
    - docker
        - Dockerfile
    - dir1
        - docker-compose.yml --> ../common_files
                             --> ../docker/Dockerfile

그래서 저는 docker-compose.yml 파일을 만들었습니다. 여기서 파일이 실행될 docker-compose.yml에 대한 파일 위치를 지정했습니다.두 에 변경을 또두리리에서모사도용파한다변최니위노습기했해력소하화경을일커의두를 했습니다.DIR실행할 하위 디렉터리를 지정하는 인수:

version: "3.8"

services:
  dev:
    container_name: template
    build:
      context: "../"
      dockerfile: ./docker/Dockerfile
      args:
        - DIR=${DIR}
    volumes:
      - ./dir1:/app
      - ./common_files:/common_files

dir1/ 폴더 내에서 다음을 실행했고 성공적으로 실행되었습니다.

export DIR=./dir1 && docker compose -f docker-compose.yml build

다음은 원본 도커 파일입니다.

...
WORKDIR /app
COPY . /app

RUN my_executable
...

다음은 도커 파일에 대한 변경 사항이 포함된 내용은 다음과 같습니다.

...
ARG DIR=${DIR}
WORKDIR /app
COPY . /app
RUN cd ${DIR} && my_executable && cd /app
...

파일을 도커 할 수 .DIR상위 리포지토리에서 호출한 경우 이후의 인수DIR빈 문자열일 것이고 이전처럼 동작할 것입니다.

common그리고 나서.COPY --from=common file1 .그 파일을 어디에 사용하시겠습니까?

예:

common
  fileA
  fileB
  Dockerfile
app1
  Dockerfile
app2
  Dockerfile

common/Dockerfile

FROM scratch
WORKDIR /common
ADD . .

app1/Dockerfile

FROM alpine
COPY --from=common /common/fileA .
COPY --from=common /common/fileB .

app2/Dockerfile

FROM alpine
COPY --from=common /common/fileB .

이러한 방식으로 많은 공유 파일을 패키지화하고 앱에서 필요한 파일을 선택할 수 있습니다.버전을 사용할 수도 있습니다.common컨테이너.

그고물론리.common파일이 변경될 때마다 먼저 빌드해야 합니다.

방금 포드맨에서 certbot ssl을 사용하여 node.js 웹 서버를 구축했습니다. 제가 "no directory"에했을 때 file or directory" 했습니다./etc/letsencrypt/live/my_domain/privkey.pem.

조사를 하는 동안, 저는 그 파일들이 실제로 다음의 심볼릭 링크라는 것을 알게 되었습니다./etc/letsencrypt/archive/my_domain/심볼릭 링크만 컨테이너에 복사합니다.이 은 호스트의 만 하면 ./etc/letsencrypt/etc/letsencrypt결과적으로, 내 노드는 심볼릭 링크를 통해 실제 소스 파일에 성공적으로 액세스할 수 있습니다.

TL;DR: 도커/포드맨이 심볼릭 링크의 내용을 호스트에서 컨테이너로 복사하기를 기대할 수 없습니다.따라서 원본 파일도 컨테이너에 투영되거나 복사되는지 확인하십시오.소스도 존재하므로 컨테이너 내에서 심볼 링크를 사용하여 액세스해도 됩니다.

잘 부탁드립니다, 에드윈 루

언급URL : https://stackoverflow.com/questions/31881904/docker-follow-symlink-outside-context

반응형