Dockerfile에서 'COPY'와 'ADD'명령의 차이점은 무엇입니까?


2196

Dockerfile에서 COPYADD명령 의 차이점은 무엇 이며 언제 다른 것을 사용할 것입니까?

COPY <src> <dest>

COPY 명령어는 새 파일 <src>을 경로의 컨테이너 파일 시스템에 복사 하여 추가합니다.<dest>

ADD <src> <dest>

ADD 명령어는 새 파일 <src>을 path의 컨테이너 파일 시스템에 복사 하여 추가합니다 <dest>.



9
2018 년 6 월 기준으로 ADD는 이미지 (예 : 정적 파일)에 추가하고 COPY는 컨테이너 (예 : 이미지의 런타임 인스턴스)에 추가합니다. 분명히 이것은 이미지가 Docker를 실행할 때마다 COPY가 실행된다는 것을 의미합니다. 또는 어쩌면 이것이 일관성이없는 용어의 경우입니까?
크리스 로빈슨

14
일관성이없는 용어라고 생각합니다.
Daniel Stevens

6
@ChrisRobinson은 콘텐츠를 가져 오기 COPY위해 원래 컨텍스트에 액세스 할 필요가 없기 때문에 실행될 때마다 실행 하는 것이 불가능 합니다.
Ken Williams

답변:


2166

동작에 대한 자세한 설명은 ADDCOPY설명서를 확인해야 하지만 간단히 말해서 다음과 같은 여러 가지 ADD작업을 수행 할 수 있습니다 COPY.

  • ADD<src>URL이 될 수 있습니다
  • 다음은 주석을 참조하여 ADD 설명서에 다음과 같이 명시되어 있습니다.

    인식 된 압축 형식 (ID, gzip, bzip2 또는 xz)의 로컬 tar 아카이브 인 경우 디렉토리로 압축이 풀립니다. 원격 URL의 리소스는 압축 해제되지 않습니다.

Dockerfile을 작성 하는 모범 사례COPY 는 마법이 ADD필요하지 않은 위치를 사용 하도록 제안 합니다. 그렇지 않으면 ( 이 답변을 찾아야했기 때문에 ) keep_this_archive_intact.tar.gz컨테이너 에 복사하려고 할 때 언젠가 놀랄 것입니다. 대신 파일 시스템에 내용을 뿌립니다.


65
.tar.gz에 대한 URL과 함께 ADD를 사용하면 파일 시스템으로 아카이브를 추출하지 않습니다 (지금 확인하고 확인하기 위해 두 번 확인했습니다)
Cecile

42
이것은 필수 정보이며 공식 Dockerfile 참조가 이러한 방식으로 차이점을 명확하게 밝히지 않는 것은 범죄입니다.
Cheeso 2019

1
이미지와 이미지가 다른 경우 확실하지 않습니다. zip 파일에는 busybox 이미지와 ADD를 사용했습니다. 압축을 풀지 않고 대상 디렉토리에 단순히 나타납니다. 나는 tarball에 대해서만 추출이 발생한다고 가정하지만 지금은 확인하지 않았습니다.
Santosh Kumar Arjunan

4
@SantoshKumarArjunan : Docker 문서는 ADD 및 자동 타르 추출에 대해 다음과 같이 설명합니다. If <src> is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory. Resources from remote URLs are not decompressed. Docker ADD
hmacias

1
COPY는 --from = <name | index>를 허용합니다. 여기서 ADD에 대한 동일한 지원을 찾을 수 없습니다
Brandon

474

COPY 이다

'ADD'와 동일하지만 tar 및 원격 URL 처리가 없습니다.

소스 코드에서 직접 참조 하십시오 .


15
나는 상황을 제대로 볼 수 있나요 : ADD또한 존재하지 않는 디렉토리를 생성합니다 . 그것은 어떻게 든이 전체 스레드에서 낙심하고 있지만 그래서, 그것은이 이점 을 통해 COPY실행할 수 없기 때문에 mkdir일부 입력 저장
엘리

3
COPY도 그렇게합니다
@eli

지금까지 가장 좋은 설명. 왜 대답이 맞지 않습니까?
xdevx32

141

그 시점에서 공식 문서가 있습니다 : Dockerfile 작성을위한 모범 사례

이미지 크기가 중요하기 때문에 ADD원격 URL에서 패키지를 가져 오는 데 사용 하지 않는 것이 좋습니다. curl또는 wget대신 사용해야 합니다. 그렇게하면 더 이상 필요없는 파일을 추출한 후 삭제할 수 있으며 이미지에 다른 레이어를 추가 할 필요가 없습니다.

RUN mkdir -p /usr/src/things \
  && curl -SL http://example.com/big.tar.gz \
    | tar -xJC /usr/src/things \
  && make -C /usr/src/things all

ADDtar 자동 추출 기능이 필요하지 않은 다른 항목 (파일, 디렉토리)의 경우 항상을 사용해야 COPY합니다.



18
Docker는 COPY더 투명하기 때문에 선호한다고 말합니다 . 로부터 도커 파일 모범 사례 : (2014년 12월 15일) Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features that are not immediately obvious.
schemar

115

Docker 문서에서 :

추가 또는 복사

ADD와 COPY는 기능적으로 비슷하지만 일반적으로 COPY가 바람직합니다. ADD보다 투명하기 때문입니다. COPY는 로컬 파일을 컨테이너로 복사하는 기본 기능 만 지원하는 반면 ADD에는 로컬 전용 tar 추출 및 원격 URL 지원과 같은 일부 기능이 즉시 눈에 띄지 않습니다. 결과적으로 ADD를 가장 잘 사용하는 것은 ADD rootfs.tar.xz /에서와 같이 이미지에 로컬 tar 파일 자동 추출입니다.

더보기 : Dockerfile 작성을위한 모범 사례


46

/usr/local컨테이너에 xx.tar.gz를 추가하려면 압축을 풀고 쓸모없는 압축 패키지를 제거하십시오.

복사의 경우 :

COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local
RUN rm /tmp/jdk-7u79-linux-x64.tar.gz

ADD의 경우 :

ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/

ADD는 로컬 전용 tar 추출을 지원합니다. 그 외에도 COPY는 3 개의 레이어를 사용하지만 ADD는 1 개의 레이어 만 사용합니다.


3
왜 두 개의 레이어가 아닌가? RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz
Stephen C

25

COPY 호스트에서 이미지로 파일 / 디렉토리를 복사합니다.

ADD 호스트에서 이미지로 파일 / 디렉토리를 복사하지만 원격 URL을 가져오고 TAR 파일을 추출 할 수도 있습니다 ...

COPY파일 및 / 또는 디렉토리를 빌드 컨텍스트로 간단히 복사하는 데 사용하십시오 .

사용 ADD등, 원격 리소스를 다운로드 TAR 파일을 추출하기위한 ..


5
나 같은 멍청한 놈에 대한 완벽한 설명
uneq95

17

Docker 문서에서 : https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

"ADD와 COPY는 기능적으로 비슷하지만 일반적으로 COPY가 선호됩니다. ADD보다 투명하기 때문입니다. COPY는 로컬 파일을 컨테이너로 복사하는 기본 기능 만 지원하지만 ADD에는 로컬 전용 tar 추출 및 ADD rootfs.tar.xz /에서와 같이 ADD를 가장 잘 사용하는 것은 이미지에 로컬 tar 파일을 자동 추출하는 것입니다.

컨텍스트와 다른 파일을 사용하는 여러 Dockerfile 단계가있는 경우 한 번에 하나씩이 아니라 개별적으로 복사하십시오. 이렇게하면 특별히 필요한 파일이 변경 될 경우 각 단계의 빌드 캐시가 무효화됩니다 (단계를 다시 실행해야 함).

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

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/

COPY를 넣을 때보 다 RUN 단계에 대한 캐시 무효화가 줄어 듭니다. 그 전에 / tmp /.

이미지 크기가 중요하기 때문에 ADD를 사용하여 원격 URL에서 패키지를 가져 오는 것은 권장하지 않습니다. 대신 curl 또는 wget을 사용해야합니다. 그렇게하면 더 이상 필요없는 파일을 추출한 후 삭제할 수 있으며 이미지에 다른 레이어를 추가 할 필요가 없습니다. 예를 들어 다음과 같은 일을 피해야합니다.

 ADD http://example.com/big.tar.xz /usr/src/things/
 RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
 RUN make -C /usr/src/things all

대신 다음과 같은 작업을 수행하십시오.

 RUN mkdir -p /usr/src/things \
     && curl -SL htt,p://example.com/big.tar.xz \
     | tar -xJC /usr/src/things \
     && make -C /usr/src/things all

ADD의 tar 자동 추출 기능이 필요하지 않은 다른 항목 (파일, 디렉토리)의 경우 항상 COPY를 사용해야합니다. "


7

출처 : https://nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile :

COPY 및 ADD는 모두 유사한 목적을 수행하는 Dockerfile 명령어입니다. 특정 위치에서 Docker 이미지로 파일을 복사 할 수 있습니다.

COPY는 src와 대상을받습니다. 호스트 (Docker 이미지를 생성하는 머신)에서 Docker 이미지 자체로 로컬 파일 또는 디렉토리로 복사 할 수 있습니다.

ADD를 사용하면 그렇게 할 수 있지만 2 개의 다른 소스도 지원합니다. 먼저 로컬 파일 / 디렉토리 대신 URL을 사용할 수 있습니다. 둘째, 소스에서 대상으로 직접 tar 파일을 추출 할 수 있습니다

ADD의 유효한 유스 케이스는 로컬 tar 파일을 Docker 이미지의 특정 디렉토리로 추출하려는 경우입니다.

로컬 파일을 Docker 이미지로 복사하는 경우 더 명확하므로 항상 COPY를 사용하십시오.


7

Dockerfile을 작성할 때 파일 / 디렉토리를 복사하는 데 사용할 수있는 두 가지 명령이 있습니다ADDCOPY. 기능 범위에 약간의 차이가 있지만 본질적으로 동일한 작업을 수행합니다.

그렇다면 왜 우리는 두 가지 명령을 가지고 있으며, 언제 하나를 사용할지 어떻게 알 수 있습니까?

의사 ADD명령

ADD명령이보다 오래 되었다는 점에 주목하여 시작하겠습니다 COPY. Docker 플랫폼이 시작된 이후 ADD명령은 명령 목록의 일부였습니다.

이 명령은 파일 / 디렉토리를 지정된 컨테이너의 파일 시스템으로 복사합니다.

ADD명령 의 기본 구문 은 다음과 같습니다.

ADD <src> … <dest>

복사 할 소스 ( <src>)와 저장하려는 대상 ( <dest>)이 포함됩니다. 소스가 디렉토리 인 경우 ADD파일 시스템 메타 데이터를 포함하여 내부의 모든 것을 복사합니다.

예를 들어, 파일이 로컬에서 사용 가능하고 이미지의 디렉토리에 추가하려는 경우 다음을 입력하십시오.

ADD /source/file/path  /destination/path

ADDURL에서 파일을 복사 할 수도 있습니다. 외부 파일을 다운로드하여 원하는 대상으로 복사 할 수 있습니다. 예를 들면 다음과 같습니다.

ADD http://source.file/url  /destination/path

추가 기능은 압축 파일을 복사하여 지정된 대상에서 컨텐츠를 자동으로 추출한다는 것입니다. 이 기능은 로컬로 저장된 압축 파일 / 디렉토리에만 적용됩니다.

ADD source.file.tar.gz /temp

URL에서 압축 파일 / 디렉토리를 다운로드하고 추출 할 수는 없습니다. 이 명령은 외부 패키지를 로컬 파일 시스템에 복사 할 때 외부 패키지의 압축을 풀지 않습니다.

의사 COPY명령

일부 기능 문제로 인해 Docker는 콘텐츠 복제를위한 추가 명령을 도입해야했습니다 COPY.

밀접하게 관련된 ADD명령 과 달리 COPY할당 된 기능은 하나만 있습니다. 그 역할은 지정된 형식으로 파일 / 디렉토리를 기존 형식으로 복제하는 것입니다. 이는 압축 파일 추출을 처리하지 않고 그대로 복사하는 것을 의미합니다.

이 명령은 로컬로 저장된 파일에만 사용할 수 있습니다. 따라서 URL과 함께 사용하여 외부 파일을 컨테이너에 복사 할 수 없습니다.

COPY명령 을 사용하려면 기본 명령 형식을 따르십시오.

소스를 입력하고 명령이 다음과 같이 컨텐츠를 추출 할 위치를 입력하십시오.

COPY <src> … <dest> 

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

COPY /source/file/path  /destination/path 

어떤 명령을 사용해야합니까? (모범 사례)

COPY명령이 도입 된 상황을 고려할 때 , 유지 ADD는 필수적인 문제임 이 분명합니다 . Docker는 Dockerfile 작성에 대한 모범 사례를 설명하는 공식 문서를 발표했으며 ADD명령 사용에 대해 명시 적으로 조언합니다 .

Docker의 공식 문서 메모 COPY는보다 투명하므로 항상 안내해야합니다 ADD.

로컬 빌드 컨텍스트에서 컨테이너로 복사해야하는 경우를 사용하십시오 COPY.

Docker 팀 ADD은 URL에서 패키지를 다운로드하고 복사하는 데 사용하지 않는 것이 좋습니다 . 대신 RUN명령 내에서 wget 또는 curl을 사용하는 것이 더 안전하고 효율적 입니다. 이렇게하면 추가 이미지 레이어를 만들지 않고 공간을 절약 할 수 있습니다.


4

중요 사항

COPY도커 이미지에서 Java 패키지를 풀고 untar 해야했습니다 . ADD를 사용하여 만든 도커 이미지 크기를 비교할 때 COPY, tar -xzf * .tar.gz 및 rm * .tar.gz를 사용하여 만든 도커 이미지보다 180MB가 큽니다.

이는 ADD가 tar 파일을 제거하더라도 여전히 어딘가에 유지됨을 의미합니다. 그리고 그것은 이미지를 더 크게 만듭니다 !!


최신 버전의 Docker에도 여전히 적용됩니까?
Navin

3

Docker 17.05 COPY다단계 빌드--from 에서 플래그 와 함께 사용되어 이전 빌드 단계에서 현재 빌드 단계로 아티팩트를 복사합니다.

로부터 문서

선택적으로 COPY는 --from=<name|index>소스 위치를 사용자가 보낸 빌드 컨텍스트 대신 사용되는 이전 빌드 단계 (FROM .. AS로 작성)로 설정하는 데 사용할 수 있는 플래그 를 승인합니다 .


0
docker build -t {image name} -v {host directory}:{temp build directory} .

파일에 이미지를 복사하는 또 다른 방법입니다. -v 옵션은 빌드 과정에서 사용한 볼륨을 임시로 만듭니다.

빌드 전용 호스트 디렉토리를 마운트하기 때문에 다른 볼륨과 다릅니다. 표준 cp 명령을 사용하여 파일을 복사 할 수 있습니다.

또한 curl 및 wget과 같이 이미지 스택을 곱하지 않고 명령 스택 (단일 컨테이너에서 실행)에서 실행할 수 있습니다. ADD 및 COPY는 독립형 컨테이너에서 실행되므로 추가 컨테이너에서 실행되는 파일의 후속 명령에 이미지 크기가 곱해지기 때문에 스택 할 수 없습니다.

옵션이 설정되어 있으면 :

-v /opt/mysql-staging:/tvol

하나의 컨테이너에서 다음이 실행됩니다.

RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \
    mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \

    mkdir /u1/mysql/mysql-files && \
    mkdir /u1/mysql/innodb && \
    mkdir /u1/mysql/innodb/libdata && \
    mkdir /u1/mysql/innodb/innologs && \
    mkdir /u1/mysql/tmp && \

    chmod 750 /u1/mysql/mysql-files && \
    chown -R mysql /u1/mysql && \
    chgrp -R mysql /u1/mysql

1
해당 옵션이 표시되는 도커 버전은 무엇입니까? 1.12.1 클라이언트에서 문서화 되지 않았으며 작동하지 않습니다.
BMitch

2
실제로이 기능은 아직 주 릴리스에 포함되지 않았으며 주제에 대해 여전히 많은 논의가 있기 때문에 오랜 시간이 지나기 전에는 예상하지 말아야합니다 ... 자세한 내용은 버그 보고서를 참조하십시오 : github.com/ docker / docker / issues / 14080 .
jwatkins

1
예, 그러한 옵션은 없습니다 (최신 버전 17.06에서 확인). 이 답변은 잘못된 것입니다. unknown shorthand flag: 'v' in -v
커비

오해의 소지가있는 의견
Guido van Steen

도커 볼륨은 대답에서 여기에 아무런 관련이 없었습니다. 직접적인 질문에 대답 할 수 있다면 제발 : 쉽게 downvote 답변입니다.
Majid Ali Khan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.