it-swarm.dev

빌드 중에 호스트 볼륨을 Dockerfile의 도커 컨테이너에 마운트하는 방법

원래 질문 : Dockerfile에서 VOLUME 명령어를 사용하는 방법은 무엇입니까?

제가 해결하고자하는 실제 질문은 빌드 과정에서 Dockerfile의 도커 컨테이너에 호스트 볼륨을 마운트하는 방법입니다. 즉, docker run -v /export:/export 중에 docker build 기능을 사용하는 방법입니다.

그 뒤에있는 이유는 Docker에 물건을 만들 때, 나는 그 (apt-get install) 캐시를 한 개의 독에서 고정시키지 않고 공유/재사용하기를 원합니다. 그것이 제가이 질문에 대해 묻는 주된 이유입니다.

최신 업데이트 :

Docker v18.09 이전에 정답은 다음으로 시작해야합니다.

빌드 중에 볼륨을 마운트하는 방법이 있지만 Dockerfiles는 포함되지 않습니다.

그러나 그것은 잘못 설명되고 조직되고 지원되는 대답이었습니다. 내 독 마커를 다시 설치할 때 다음과 같은 기사가 우연히 발견되었습니다.

apt-cacher-ng 서비스를 도킹합니다.
https://docs.docker.com/engine/examples/apt-cacher-ng/

그것은 바로/간접적 인 것이 아니라 내 질문에 대한 도커의 해결책입니다. 그것은 도커가 우리에게 제안한 정통적인 방식입니다. 그리고 제가 여기서 물어 보려고했던 것보다 더 낫다고 인정합니다.

또 다른 방법은 v18.09의 Buildkit과 같이 새로 승인 된 응답 입니다.

당신에게 맞는 것을 선택하십시오.


was :Docker가 아닌 솔루션 로커가 있었지만 이제는 로커가 중단되었으므로 답을 되돌릴 수 없습니다 "불가능합니다" 다시.


이전 업데이트 :대답은 "불가능"입니다. 문제가 광범위하게 https://github.com/docker/docker/issues/3156 에서 논의 된 것을 알기 때문에 대답으로 받아 들일 수 있습니다. . 도커 개발자는 이식성이 가장 중요한 문제임을 이해할 수 있습니다. 그러나 도커 사용자로서이 누락 된 기능에 대해 매우 실망한다고 말해야합니다. " Gentoo를 기본 이미지로 사용하고 싶지만 포티지 트리 데이터가 1GB가되기를 바란다면 이미지의 어떤 레이어 에라도 있어야합니다. 설치 도중 이미지에 거대한 포티지 트리가 나타나지 않는 경우 소형 컨테이너를 사용할 수 있습니다. "예, wget 또는 curl을 사용하여 다운로드 할 수 있습니다. 하지만 이제는 단지 이식성에 대한 고려만으로도 Gentoo 기본 ​​이미지를 만들 때마다 1GB 이상의 Portage 트리지를 다운로드해야한다는 사실은 효율적이지 않고 사용하기 쉽지 않습니다. 더 나아가 패키지 저장소는 언제나/usr/portage에있을 것이므로 항상 Gentoo에서 포팅 할 수 있습니다. 다시 말하지만, 나는 그 결정을 존중하지만, 저의 실망을 표현할 수있게 해주시기 바랍니다. 감사.


원본 질문세부 정보 :

에서

볼륨을 통해 디렉토리 공유
http://docker.readthedocs.org/en/v0.7.3/use/working_with_volumes/

데이터 볼륨 기능은 "Docker Remote API 버전 1부터 사용할 수 있습니다."라고 말합니다. 내 도커는 1.2.0 버전이지만 위의 기사에서 제공하는 예제가 작동하지 않는다는 것을 알았습니다.

# BUILD-USING:        docker build -t data .
# RUN-USING:          docker run -name DATA data
FROM          busybox
VOLUME        ["/var/volume1", "/var/volume2"]
CMD           ["/usr/bin/true"]

Dockerfile에서 호스트 마운트 볼륨을 VOLUME 명령을 통해 고정 컨테이너에 마운트하는 적절한 방법은 무엇입니까?

$ apt-cache policy lxc-docker
lxc-docker:
  Installed: 1.2.0
  Candidate: 1.2.0
  Version table:
 *** 1.2.0 0
        500 https://get.docker.io/ubuntu/ docker/main AMD64 Packages
        100 /var/lib/dpkg/status

$ cat Dockerfile 
FROM          debian:sid

VOLUME        ["/export"]
RUN ls -l /export
CMD ls -l /export

$ docker build -t data .
Sending build context to Docker daemon  2.56 kB
Sending build context to Docker daemon 
Step 0 : FROM          debian:sid
 ---> 77e97a48ce6a
Step 1 : VOLUME        ["/export"]
 ---> Using cache
 ---> 59b69b65a074
Step 2 : RUN ls -l /export
 ---> Running in df43c78d74be
total 0
 ---> 9d29a6eb263f
Removing intermediate container df43c78d74be
Step 3 : CMD ls -l /export
 ---> Running in 8e4916d3e390
 ---> d6e7e1c52551
Removing intermediate container 8e4916d3e390
Successfully built d6e7e1c52551

$ docker run data
total 0

$ ls -l /export | wc 
     20     162    1131

$ docker -v
Docker version 1.2.0, build fa7b24f
194
xpt

먼저, "왜 VOLUME 작동하지 않습니까?" Dockerfile에서 VOLUME을 정의하면 볼륨의 원본이 아닌 대상 만 정의 할 수 있습니다. 빌드하는 동안 익명의 볼륨 만 얻을 수 있습니다. 익명의 볼륨은 모든 RUN 명령에 마운트되고 이미지 내용이 미리 채워지며 RUN 명령이 끝날 때 무시됩니다. 볼륨에 대한 변경 사항이 아닌 컨테이너에 대한 변경 사항 만 저장됩니다.


이 질문이 제기 되었기 때문에 도움이 될 수있는 몇 가지 기능이 발표되었습니다. 첫 번째는 다단계 빌드로 디스크 공간을 비효율적 인 첫 번째 단계로 만들고 필요한 출력 만 최종 단계로 복사 할 수 있습니다. 두 번째 기능은 이미지 빌드 방식과 새로운 기능을 빌드에 크게 추가하는 Buildkit입니다.

다단계 빌드의 경우 FROM 행이 여러 개있을 것이며 각 행마다 별도의 이미지 생성을 시작합니다. 기본적으로 마지막 이미지에만 태그가 지정되지만 이전 스테이지의 파일을 복사 할 수 있습니다. 표준 사용법은 바이너리 또는 기타 애플리케이션 아티팩트를 빌드하는 컴파일러 환경과 해당 아티팩트를 복사하는 두 번째 단계 인 런타임 환경을 갖는 것이다. 당신은 가질 수 있습니다 :

FROM debian:sid as builder
COPY export /export
RUN compile command here >/result.bin

FROM debian:sid
COPY --from=builder /result.bin /result.bin
CMD ["/result.bin"]

결과로 전체/내보내기 디렉토리가 아닌 결과 바이너리 만 포함 된 빌드가 생성됩니다.


Buildkit은 18.09에 실험 중입니다. 프론트 엔드 파서를 변경하는 기능을 포함하여 빌드 프로세스를 완전히 재 설계했습니다. 이러한 파서 변경 중 하나는 실행 명령에 대한 캐시 디렉토리를 마운트 할 수있는 RUN --mount 옵션을 구현했습니다. 예 : 다음은 데비안 디렉토리 중 일부를 마운트하는 방법입니다 (데비안 이미지를 재구성하면 패키지를 다시 설치할 수 있습니다).

# syntax = docker/dockerfile:experimental
FROM debian:latest
RUN --mount=target=/var/lib/apt/lists,type=cache \
    --mount=target=/var/cache/apt,type=cache \
    apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
      git

보유한 응용 프로그램 캐시의 캐시 디렉토리를 조정할 수 있습니다 (예 : maven의 경우 $ HOME/.m2, golang의 경우 /root/cache.


TL : DR : 응답 : RUN --mount 구문을 사용하면 빌드 컨텍스트에서 읽기 전용 디렉토리를 마운트 할 수 있습니다. 폴더는 빌드 컨텍스트에 있어야하며 호스트 또는 빌드 클라이언트에 다시 매핑되지 않습니다.

# syntax = docker/dockerfile:experimental
FROM debian:latest
RUN --mount=target=/export,type=bind,source=export \
    process export directory here...

디렉토리는 컨텍스트에서 마운트되기 때문에 읽기 전용으로도 마운트되며 변경 사항을 호스트 또는 클라이언트로 다시 푸시 할 수 없습니다. 빌드 할 때 18.09 이상의 설치가 필요하고 export DOCKER_BUILDKIT=1로 빌드 키트를 사용할 수 있습니다.

16
BMitch

VOLUME 명령어를 사용하여 고정 표시 에 탑재 할 대상 을 알리는 것은 불가능합니다. 그것은 휴대 성을 심각하게 깨뜨릴 것입니다. 이 명령은 해당 디렉토리의 내용이 이미지에 포함되지 않으며 --volumes-from 명령 줄 매개 변수를 사용하여 다른 컨테이너에서 액세스 할 수 있음을 도커에게 알려줍니다. 호스트에서 디렉토리에 액세스하려면 -v /path/on/Host:/path/in/container를 사용하여 컨테이너를 실행해야합니다.

마운트 중에 호스트 볼륨을 마운트 할 수 없습니다. 특권있는 빌드가없고 호스트를 마운트하는 것도 이식성을 심각하게 저하시킵니다. wget이나 curl을 사용하여 빌드에 필요한 것을 다운로드하여 제자리에 넣을 수 있습니다.

107
Andreas Steffan

업데이트 : 누군가는 단지 대답으로 받아들이지 않을 것이며, 나는 특히,이 특별한 질문에 대해 매우 좋아한다.

좋은 소식, 지금 방법이 있습니다 -

해결 방법은 Rocker입니다. https://github.com/grammarly/rocker

John Yani ,"IMO, Dockerfile의 모든 약점을 해결하여 개발에 적합하도록했습니다."

흔들리는 것

https://github.com/grammarly/rocker

새로운 명령을 도입함으로써 Rocker는 일반 Docker로 인해 고통을 겪고있는 다음 사용 사례를 해결하는 것을 목표로합니다.

  1. 빌드 단계에서 재사용 가능한 볼륨을 마운트하십시오. 따라서 종속성 관리 도구는 빌드간에 캐시를 사용할 수 있습니다.
  2. Ssh 키를 build와 공유하고 (개인 레포즈를 당기기 등) 결과 이미지에 남겨 두지 않습니다.
  3. 서로 다른 이미지에서 응용 프로그램을 빌드하고 실행하고, 하나의 이미지에서 다른 이미지로 쉽게 이질적으로 전달할 수 있어야하며, 이상적으로 단일 Dockerfile에이 논리를 포함하십시오.
  4. Dockerfiles에서 바로 태그/푸시 이미지.
  5. 쉘 빌드 명령에서 변수를 전달하여 Dockerfile로 대체 할 수 있습니다.

그리고 더. 이것들은 Grammarly에서 Docker의 채택을 막고있는 가장 중요한 문제입니다.

업데이트 : Rocker는 Github의 공식 프로젝트 레포 당 생산이 중단되었습니다.

2018 년 초 현재 컨테이너 생태계는이 프로젝트가 시작된 3 년 전보다 훨씬 성숙한 상태입니다. 이제 로커의 중요하고 뛰어난 기능 중 일부는 도커 빌드 또는 기타 잘 지원되는 도구로 쉽게 처리 할 수 ​​있지만 일부 기능은 로커에 고유합니다. 자세한 내용은 https://github.com/grammarly/rocker/issues/199 를 참조하십시오.

61
xpt

빌드 중에 볼륨을 마운트하는 방법이 있지만 Dockerfiles는 포함되지 않습니다.

이 기술은 사용하고자하는베이스 (-v 옵션을 사용하여 컨테이너에 볼륨을 마운트)에서 container 를 만들고, 쉘 스크립트를 실행하여 이미지 구축 작업을 수행합니다. , 완료되면 컨테이너로 이미지를 커밋하십시오.

이렇게하면 원하지 않는 초과 파일을 제거 할뿐만 아니라 SSH 파일과 같은 보안 파일에도 좋을뿐만 아니라 단일 이미지를 만듭니다. 단점이 있습니다. 커밋 명령은 모든 Dockerfile 지침을 지원하지 않으며 빌드 스크립트를 편집해야 할 경우 중단 할 때 다시 시작할 수 없습니다.

최신 정보:

예를 들어,

CONTAINER_ID=$(docker run -dit ubuntu:16.04)
docker cp build.sh $CONTAINER_ID:/build.sh
docker exec -t $CONTAINER_ID /bin/sh -c '/bin/sh /build.sh'
docker commit $CONTAINER_ID $REPO:$TAG
docker stop $CONTAINER_ID
12
Keith Mason

컨테이너를 실행하면 호스트의 디렉토리가 작성되어 컨테이너에 마운트됩니다. 어떤 디렉토리인지 알 수 있습니다.

$ docker inspect --format "{{ .Volumes }}" <ID>
map[/export:/var/lib/docker/vfs/dir/<VOLUME ID...>]

컨테이너에서 호스트의 디렉토리를 마운트하려면 -v 매개 변수를 사용하고 디렉토리를 지정해야합니다. 귀하의 경우에는 다음과 같습니다 :

docker run -v /export:/export data

그래서 컨테이너 안의 hosts 폴더를 사용하게됩니다.

5
Behe

도커 컨테이너 내부에서 실행되는 도커 명령을 통해 빌드를 실행하여 원하는 작업을 수행 할 수 있다고 생각합니다. 참조 이제 Docker가 Docker | Docker 블로그 . 이와 같은 기술이지만 실제로 컨테이너에서 외부 도커에 액세스하는 방법이 사용되었습니다. 예를 들어, 가능한 가장 작은 Docker 컨테이너 생성 방법을 탐색하는 동안 Xebia 블로그 .

또 다른 관련 기사는 도커 이미지 최적화 | CenturyLink Labs 는 빌드 중에 물건을 다운로드하면 결국 다운로드, 다운로드 및 삭제를 한 번에 모두 수행하여 최종 이미지에서 낭비되는 것을 피할 수 있다고 설명합니다.

4
nealmcb

못 생겼어.하지만 나는 이렇게 닮았다.

Dockerfile :

FROM foo
COPY ./m2/ /root/.m2
RUN stuff

imageBuild.sh :

docker build . -t barImage
container="$(docker run -d barImage)"
rm -rf ./m2
docker cp "$container:/root/.m2" ./m2
docker rm -f "$container"

나는 /root/.m2에 우주를 다운로드하는 Java 빌드를 가지고 매 시간마다 그렇게했습니다 . imageBuild.sh는 빌드 후 해당 폴더의 내용을 호스트에 복사하고 Dockerfile은 다음 빌드를 위해 이미지로 다시 복사합니다.

이는 볼륨이 작동하는 방식 (예 : 빌드간에 유지됨)과 같습니다.

3

다음은 Shell 스크립트없이 빌드 및 커밋을 사용하는 단순화 된 2 단계 접근 방식입니다. 여기에는 다음이 포함됩니다.

  1. 이미지를 부분적으로 빌드 볼륨없이
  2. 컨테이너 볼륨 포함을 실행하고 변경 한 다음 결과를 커밋하여 원래 이미지 이름을 바꿉니다.

비교적 약간의 변경으로 추가 단계는 빌드 시간에 몇 초만 추가됩니다.

원래:

docker build -t image-name . # your normal docker build

# Now run a command in a throwaway container that uses volumes and makes changes:
docker run -v /some:/volume --name temp-container image-name /some/post-configure/command

# Replace the original image with the result:
# (reverting CMD to whatever it was, otherwise it will be set to /some/post-configure/command)   
docker commit --change="CMD bash" temp-container image-name 

# Delete the temporary container:
docker rm temp-container

유스 케이스에서 maven toolchains.xml 파일을 미리 생성하려고하지만 많은 JDK 설치가 런타임까지 사용할 수없는 볼륨에 있습니다. 일부 이미지는 모든 JDKS와 호환되지 않으므로 빌드시 호환성을 테스트하고 toolchains.xml을 조건부로 채워야합니다. 휴대용 이미지가 필요하지 않으며 Docker Hub에 게시하지 않습니다.

0
Akom