트러블슈팅

macOS에서 만든 tar 빌드 컨텍스트가 Linux Docker에서 풀리지 않는 이유

개개발 노하우 노트2026년 11월 9일 · 3분 읽기

macOS에서 tar로 묶은 빌드 컨텍스트를 원격 Linux Docker 데몬에 직접 넘겼다가, 이미지 빌드가 시작도 못 하고 컨텍스트 해제 단계에서 실패한 경험을 정리한 글이다. 원인은 macOS 파일에 붙어 있는 확장 속성(xattr)이었고, 아카이브를 만들 때 이 속성을 빼는 것으로 해결했다.

상황

개인 블로그 프로젝트를 자체 호스팅한 Linux 서버에 배포하는 중이었다. 개발은 macOS 노트북에서 하고, 이미지 빌드는 서버의 Docker 데몬이 맡는 구조였다. 서버 쪽 빌드 환경 사정으로 BuildKit 대신 레거시 빌더를 써야 했고, 소스 디렉터리를 tar 스트림으로 묶어 표준 입력으로 넘기는 방식을 골랐다. Docker는 tarball을 표준 입력으로 받으면 그 내용을 그대로 빌드 컨텍스트로 쓴다.

증상

빌드 명령을 실행하자 Dockerfile의 첫 단계도 돌기 전에 오류가 났다. 데몬이 받은 컨텍스트를 풀다가 확장 속성을 적용하지 못했다는 내용이었고, 문제의 속성은 macOS가 내려받은 파일이나 앱이 만든 파일에 붙이는 출처(provenance) 정보였다. 같은 소스를 서버에서 직접 받아 빌드하면 문제가 없었기 때문에, 처음에는 Dockerfile이나 서버 권한 문제로 오해하기 쉬웠다.

원인

macOS 기본 tar는 libarchive 기반의 bsdtar다. bsdtar는 macOS에서 아카이브를 만들 때 파일의 확장 속성과 ACL 같은 메타데이터를 함께 담는다. 경우에 따라 AppleDouble 형식의 `._파일명` 항목이 따로 들어가기도 한다.

macOS끼리 주고받을 때는 이 정보가 쓸모 있지만, 받는 쪽이 Linux 파일시스템이면 사정이 다르다. Linux가 모르는 이름공간의 속성은 적용할 수 없고, 레거시 빌더는 컨텍스트를 풀다가 이 실패를 그대로 오류로 처리한다. 결국 빌드 실패는 소스나 Dockerfile 문제가 아니라 "아카이브에 실려 간 macOS 전용 메타데이터" 문제였다.

해결

아카이브를 만들 때 확장 속성을 아예 빼도록 두 가지를 같이 적용했다.

  • 환경 변수 `COPYFILE_DISABLE=1`: macOS tar가 copyfile 기능으로 AppleDouble 메타데이터를 만드는 동작을 끈다.
  • bsdtar 옵션 `--no-xattrs`: 확장 속성을 아카이브에 넣지 않는다. 필요하면 `--no-mac-metadata`도 함께 쓴다.

```bash

COPYFILE_DISABLE=1 tar --no-xattrs --no-mac-metadata \

--exclude=node_modules --exclude=.git \

-czf - . \

| docker -H "$REMOTE_DOCKER_HOST" build -t my-app:latest -

```

이렇게 만든 스트림은 순수한 파일 내용과 기본 권한만 담기 때문에 Linux 데몬이 문제없이 풀었고, 빌드도 정상으로 진행됐다. tar로 직접 컨텍스트를 만들면 `.dockerignore`가 적용되지 않으므로 무거운 디렉터리는 `--exclude`로 따로 빼는 편이 좋다.

다시 겪지 않으려면

  • macOS에서 만든 tar를 Linux 쪽에서 풀 계획이면 처음부터 `COPYFILE_DISABLE=1`과 `--no-xattrs`를 붙인다.
  • 배포 스크립트에 이 옵션을 고정해 두고, 사람이 손으로 tar 명령을 치지 않게 한다.
  • 아카이브 안에 `._`로 시작하는 항목이 있는지 `tar -tzf`로 한 번 확인한다.
  • 가능하면 레거시 빌더보다 BuildKit 기반 빌드를 쓴다. 컨텍스트 전송 방식이 달라 이런 문제를 덜 만난다.
  • 빌드가 컨텍스트 단계에서 실패하면 Dockerfile보다 먼저 "무엇이 아카이브에 실려 갔는가"를 의심한다.

참고 자료