레이블이 colima인 게시물을 표시합니다. 모든 게시물 표시
레이블이 colima인 게시물을 표시합니다. 모든 게시물 표시

docker virtiofs volume mount symlink creation failure

## 증상
macOS Docker 에서 bind mount(-v) 된 경로에서 tar 압축 해제 시 symlink 포함 파일이 Permission denied 로 실패한다.
tar: re2-2025-11-05/python/LICENSE: Cannot open: Permission denied
tar: Exiting with failure status due to previous errors

ls 로 확인하면 symlink 대신 퍼미션 ---------- 인 0바이트 파일이 생성되어 있다.
---------- 1 root root 0 Aug 17 23:47 LICENSE

## 원인

Docker for Mac 은 호스트와 컨테이너 간 파일 공유에 VirtioFS 드라이버를 사용한다.

VirtioFS 는 호스트와 가상머신(VM) 간 파일 공유를 위한 파일시스템 프로토콜이다.
QEMU/KVM 의 virtio 가상화 프레임워크 위에서 동작하며, FUSE 프로토콜을 기반으로 호스트 파일시스템을 VM 내부에 마운트한다.
Docker for Mac 은 Linux VM 위에서 컨테이너를 실행하는데, -v bind mount 시 macOS 호스트 파일을 이 Linux VM 에 공유해야 한다.
이전에는 gRPC-FUSE 를 사용했으나, 성능 개선을 위해 VirtioFS 가 기본 파일 공유 드라이버로 채택되었다.
macOS (호스트) ←→ VirtioFS ←→ Linux VM ←→ 컨테이너

VirtioFS 는 gRPC-FUSE 대비 파일 I/O 성능이 크게 향상되지만, 일부 POSIX 파일시스템 동작(퍼미션 000 파일 생성, symlink 등)에서 호환성 문제가 있다.

tar 가 symlink 를 풀 때 내부적으로 다음 순서로 동작한다.
1. openat("dst", O_CREAT|O_EXCL, 000)  ← placeholder 파일 생성 (퍼미션 000)
2. 실제 타겟 파일 생성
3. unlinkat("dst")                       ← placeholder 삭제
4. symlinkat("../src", "dst")            ← symlink 생성

VirtioFS 는 퍼미션 000 으로 파일을 생성하는 openat() 호출을 Permission denied 로 거부한다.
1단계에서 실패하므로 symlink 가 만들어지지 않고 깨진 0바이트 파일만 남게 된다.
이 문제는 같은 디렉토리 내 symlink 에서는 발생하지 않고, 다른 디렉토리를 가리키는 symlink(예: python/LICENSE → ../LICENSE) 에서만 발생한다.

컨테이너 내부 경로(/tmp등)에서는 Linux 네이티브 파일시스템(overlay2)을 사용하므로 정상 동작한다.
./openat ./mounted/demo   → Permission denied (VirtioFS)
./openat /tmp/demo         → OK (overlay2)

## 해결 방법
1. named volume 사용 (권장)

bind mount 대신 Docker named volume 을 사용하면 Docker VM 내부 파일시스템이 사용되어 symlink 가 정상 동작한다.

# named volume 생성해서 마운트
docker volume create my_source_vol
docker run -dit \
    -v my_source_vol:/workspace/source \
    my_image

# 호스트 소스를 named volume 으로 복사
docker cp ./source/. "container_name:/workspace/source"

2. 컨테이너 내부 경로에서 빌드

소스를 컨테이너 내부 경로(`/tmp` 등)로 복사한 후 빌드한다.

docker exec -it my_container /bin/bash -c "
    cp -a /mounted/source /tmp/source &&
    cd /tmp/source &&
    ./build.sh /mounted/output"

3. VirtioFS 대신 다른 마운트 방식 사용
VirtioFS 를 사용하지 않으면 symlink 가 정상 생성된다. 다만 파일 I/O 성능이 저하될 수 있다.

# Docker Desktop 사용 시
Docker Desktop → Settings → General → "VirtioFS" 체크 해제

# Colima 사용 시
Colima 는 vmType 에 따라 사용 가능한 마운트 방식이 다르다.

vmType 종류
vz: macOS 자체 가상화 프레임워크(Virtualization.Framework) 사용. 네이티브라 빠르지만 macOS 13+ 필요
qemu: 오픈소스 하드웨어 에뮬레이터. CPU, 메모리, 디스크 등을 소프트웨어로 에뮬레이션한다. vz 보다 느리지만 다양한 마운트 타입 지원

mountType 종류:
virtiofs: macOS Virtualization.Framework 기반, 가장 빠름 (vmType vz 전용)
sshfs: SSH 기반 파일 전송, virtiofs 보다 느리지만 안정적 (vmType qemu 전용)
9p: Plan 9 프로토콜 기반, 가장 안정적 (vmType qemu 전용)

vmType vz 를 사용하는 경우 virtiofs 만 지원되므로 마운트 타입 변경으로는 해결할 수 없다.
이 경우 해결 방법 1(named volume) 또는 2(컨테이너 내부 경로에서 빌드)를 사용해야 한다.

현재 마운트 타입 확인:

# json 출력에서 mount_type, driver(vmType) 확인
colima status --json | jq '{mount_type, driver}'

# 또는 설정 파일 직접 확인
# colima.yaml 위치: ~/.config/colima/default/colima.yaml
grep -E 'mountType|vmType' ~/.config/colima/default/colima.yaml

vmType qemu 로 변경하면 sshfs 또는 9p 를 사용할 수 있지만 비추천한다.
macOS 에서 QEMU 바이너리에 com.apple.security.hypervisor entitlement 서명이 필요한데, 서명 에러가 발생하는 경우가 많고 vz 대비 성능도 떨어진다.

# qemu 시작 시 서명 에러 예시
"QEMU binary does not seem properly signed with the com.apple.security.hypervisor entitlement"

또한 mountType 은 VM 생성 후 변경 불가하므로 삭제 후 재생성해야 한다.

# colima start --mount-type 만으로는 변경되지 않는다
WARN[0001] 'volume mount type' cannot be updated after initial setup, discarded

qemu 로 변경 시도 후 다시 vz 로 되돌리려면 VM 을 삭제하고 재생성해야 한다.

# 기존 VM 삭제
colima delete --force

# vz + virtiofs 로 재생성 (기존 옵션에 맞게 조정)
colima start --vm-type vz --mount-type virtiofs --cpu 10 --memory 4 --disk 100

결론: Colima + vz 환경에서는 마운트 타입 변경이 현실적이지 않으므로 해결 방법 1(named volume) 또는 2(컨테이너 내부 경로에서 빌드)를 사용하자.

colima, podman

맥북에선 docker desktop(docker client/command-tools과 별개로 docker desktop은 UI를 지원하는 데몬(dockerd)으로 동작)을 사용했는데 유료라 무료 대체제를 알아보자.

참고로
linux 라면 podman 이 좋을것 같고
mac 에선 vm 시작이 좀 더 빠르고 기존 docker client 를 계속 사용할 수 있고 k8s 환경 구성도 쉬워 colima 가 좋은것 같다.

#####

colima + docker client
colima(https://github.com/abiosoft/colima)는 docker desktop 을 대신하는 데몬이다.
VM + container runtime(docker/containerd/incus) + docker api 를 제공한다.

# 설치
brew install colima

# (임시) 설정 파일 수정
# ~/.config/colima/default/colima.yaml 로 저장해서 디폴트 설정으로 사용하자.
colima template

# 4cpu, 4GiB 메모리 VM 생성
colima start --cpu 4 --memory 4

# colima 를 stop 하지 않고 맥을 종료했다면 다음번 colima start 할때 다음과 같은 에러가 발생할 수 있다.
# FATA[0002] error starting vm: error at 'starting': exit status 1
# 이 경우 강제 종료하고 다시 시작하면 된다.
colima stop --force

# docker 명령(client)을 그대로 사용하면 된다.
# nginx 이미지 다운로드
docker pull nginx:latest

# nginx container 실행
docker run -d -p 8080:80 --name colima_nginx nginx:latest

# nginx container 리소스 모니터링
docker stats colima_nginx

# nginx container log 모니터링
docker logs -f colima_nginx

# ab(ApacheBench)로 -t 60 초로 부하를 줬을때 리소스 현황

# k8s 환경으로 띄우기
# cpu, mem 변경시 colima stop 후 다시 cpu, mem 변경해서 시작한다.
colima stop
colima start --cpu 4 --memory 8 --kubernetes

# 상태 정보
colima status

# instance 리스트(status, arch, cpus, memory, disk 등 파악)
colima list

# kubernetes cluster 재설정(초기화, 설치된 리소스들은 모두 지워진다)
colima k8s reset

# kubectl config 정보 확인시
colima ssh -- cat /etc/rancher/k3s/k3s.yaml

# ingress nginx controller 설치
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

# 이제 kubectl 로 일반 k8s 처럼 사용할 수 있다.

# colima 삭제(k8s 설정등 지우고 새로 시작할때)
colima delete

#####

podman machine + podman
podman(https://github.com/containers/podman)는 docker 데몬,client 사용없이 별개의 환경이으로 구성할 수 있다.
docker 데몬 같은게 없는 daemonless 구조이고 로 호스트에서 root 권한없이 일반 사용자 계정으로 컨테이너를 실행하는 rootless container 방식 시스템 전체에 영향을 주지 않아 보안성이 좋다고 한다.

# 설치
brew install podman

# 실행중인 vm list 파악
podman machine list

# podman machine(vm) 시작
podman machine init --cpus=4 --memory=4096
podman machine start

# vm 삭제시
# mac 에서 이름이 podman-machine-default 하나로 고정되어 있다.
podman machine rm podman-machine-default

# nginx 이미지 다운로드(docker client 가 아니라 이미지 주소가 다르다.)
podman pull docker.io/library/nginx:latest

# nginx container 실행
podman run -d -p 8081:80 --name podman_nginx nginx:latest

# nginx container log 모니터링
podman logs -f podman_nginx

# ab(ApacheBench)로 -t 60 초로 부하를 줬을때 리소스 현황

# vm 접속해 k3s 등을 직접 설치하는 등 kubernetes 환경 구성이 복잡하다.

Prev