저장소 logo 저장소

1. COPY란?

COPY는 Dockerfile에서 빌드 컨텍스트에 있는 파일이나 디렉터리를 이미지 파일 시스템으로 복사하는 명령이다. Docker 공식 Dockerfile reference에 따르면 COPY<src>의 새 파일 또는 디렉터리를 이미지의 <dest> 경로에 추가한다. [1]

여기서 중요한 점은 COPY가 파일을 이동하는 명령이 아니라는 것이다.

호스트 컴퓨터의 원본 파일은 그대로 남아 있고, Docker 이미지를 만들 때 그 파일이 이미지 안으로 복사된다.


2. 사용법

COPY의 기본 문법은 다음과 같다. [1]

COPY [호스트 컴퓨터에 있는 복사할 파일의 경로] [컨테이너에서 파일이 위치할 경로]

예를 들어 현재 디렉터리에 있는 app.txt를 이미지 안의 /app.txt로 복사하려면 다음처럼 작성한다.

COPY app.txt /app.txt

docker build -t my-server .에서 마지막의 .은 현재 디렉터리를 빌드 컨텍스트로 사용한다는 의미이다. Docker 공식 문서에 따르면 빌드 컨텍스트는 빌드가 접근할 수 있는 파일들의 집합이고, COPY 같은 Dockerfile 명령은 이 컨텍스트 안의 파일을 참조할 수 있다. [2]

따라서 위 예시에서 app.txtdocker build를 실행하는 현재 디렉터리 안에 있어야 한다.


3. 파일 하나 복사해보기

먼저 작업 디렉터리에 app.txt 파일을 만든다.

echo "hello docker" > app.txt

그 다음 같은 위치에 Dockerfile을 만든다.

FROM ubuntu

COPY app.txt /app.txt

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

이미지를 빌드하고 컨테이너를 실행한다.

docker build -t my-server .
docker run -d my-server
docker ps

실행 중인 컨테이너에 들어가서 파일을 확인한다.

docker exec -it [Container ID] bash
ls /
cat /app.txt

/app.txt가 보이면 COPY app.txt /app.txt가 정상적으로 동작한 것이다.


4. 폴더 안에 있는 파일들 복사하기

이번에는 my-app 디렉터리를 만들고, 그 안에 파일을 넣는다.

mkdir my-app
echo "hello app" > my-app/app.txt
echo "hello readme" > my-app/readme.txt

Dockerfile은 다음처럼 작성한다.

FROM ubuntu

COPY my-app /my-app/

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

이미지를 빌드하고 컨테이너를 실행한다.

docker build -t my-server .
docker run -d my-server
docker ps
docker exec -it [Container ID] bash

컨테이너 안에서 /my-app 디렉터리를 확인한다.

ls /my-app
cat /my-app/app.txt
cat /my-app/readme.txt

Docker 공식 문서에 따르면 COPY의 소스가 디렉터리인 경우, 해당 디렉터리의 내용이 대상 경로로 복사된다. 하위 디렉터리가 있으면 하위 디렉터리도 함께 복사된다. [1]


5. 와일드카드 사용해보기

COPY의 소스 경로에는 와일드카드를 사용할 수 있다. Docker 공식 문서에 따르면 로컬 파일을 복사할 때 <src>는 Go의 filepath.Match 규칙에 따라 와일드카드 매칭을 지원한다. [1]

예를 들어 app.txt, readme.txt 파일을 만든다.

echo "app" > app.txt
echo "readme" > readme.txt

Dockerfile은 다음처럼 작성한다.

FROM ubuntu

COPY *.txt /text-files/

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

이미지를 빌드하고 컨테이너를 실행한다.

docker build -t my-server .
docker run -d my-server
docker ps
docker exec -it [Container ID] bash

컨테이너 안에서 /text-files 디렉터리를 확인한다.

ls /text-files

app.txtreadme.txt가 보이면 COPY *.txt /text-files/가 정상적으로 동작한 것이다.

주의할 점은 COPY *.txt /text-files/처럼 대상 경로 끝에 /를 붙이는 것이다.

Docker 공식 문서에 따르면 여러 소스 파일을 지정하거나 와일드카드를 사용해 여러 파일이 매칭되는 경우, 대상 경로는 디렉터리여야 하며 /로 끝나야 한다. [1]

또한 대상 경로의 마지막 /는 의미가 있다. 예를 들어 COPY test.txt /abs/abs라는 파일을 만들고, COPY test.txt /abs//abs/test.txt를 만든다. [1]


6. .dockerignore 사용해보기

특정 파일이나 폴더를 이미지에 복사하고 싶지 않을 때는 .dockerignore를 사용할 수 있다.

Docker 공식 문서에 따르면 .dockerignore 파일은 빌드 컨텍스트에서 제외할 파일이나 디렉터리를 지정할 때 사용한다. 빌드 클라이언트는 컨텍스트의 루트 디렉터리에서 .dockerignore 파일을 찾고, 패턴과 일치하는 파일을 빌더로 보내기 전에 컨텍스트에서 제거한다. [2]

예를 들어 다음 파일들을 준비한다.

echo "app" > app.txt
echo "readme" > readme.txt

.dockerignore 파일을 만든다.

readme.txt

Dockerfile은 다음처럼 작성한다.

FROM ubuntu

COPY ./ /

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

이미지를 빌드하고 컨테이너를 실행한다.

docker build -t my-server .
docker run -d my-server
docker ps
docker exec -it [Container ID] bash

컨테이너 안에서 파일을 확인한다.

ls /

.dockerignorereadme.txt를 적었기 때문에 COPY ./ /를 사용해도 readme.txt는 빌드 컨텍스트에서 제외된다. 따라서 이미지 안으로 복사되지 않는다. [2]


7. 정리

COPY는 호스트 컴퓨터의 파일을 직접 실행 중인 컨테이너에 보내는 명령이 아니라, Docker 이미지를 빌드하는 과정에서 빌드 컨텍스트의 파일을 이미지 안으로 복사하는 Dockerfile 명령이다. [1][2]

자주 기억해야 할 내용은 다음과 같다.


참고자료

[1] Docker Docs, Dockerfile reference - COPY: https://docs.docker.com/reference/builder/#copy
[2] Docker Docs, Build context - .dockerignore files: https://docs.docker.com/build/building/context/#dockerignore-files


« Dockerfile FROM
Dockerfile ENTRYPOINT »