Lima(Linux Machines)는 리눅스 VM을 쉽게 만들어 쓸 수 있게 해 주는 오픈소스 도구이다. 자동 파일 공유와 포트 포워딩을 갖춘 리눅스 VM을 실행해 주고, 공식 사이트는 윈도우의 WSL2와 비슷하다고 소개한다.1 VM 이미지를 직접 받아 가상화 프로그램에 설치하는 대신 limactl 명령으로 배포판 템플릿을 고르고 CPU, 메모리, 디스크 같은 사양만 정하면 VM이 만들어지며, 컨테이너 런타임인 containerd와 nerdctl도 기본으로 함께 설치된다.
Lima는 2021년에 시작해 2022년 CNCF Sandbox에 들어갔고 2025년에 Incubating 단계로 올라간 CNCF 프로젝트이다.2 Rancher Desktop, Colima, Finch, Podman Desktop 같은 도구가 사용 사례로 소개된다.1
이 글은 맥에서 Lima로 VM을 만들고 그 안에서 컨테이너를 실행해 보기 위해, 설치부터 bridged 네트워크 구성과 VM 관리까지 정리한다.
목차
1. 개요
Lima는 Linux 같은 macOS 외 호스트도 지원하지만,3 이 글은 macOS 기준이다. Lima를 설치하고, limactl로 Ubuntu 22.04 VM을 만들어 시작, 접속, 수정, 중지, 삭제하는 과정을 실제 실행 결과와 함께 따라 해 본다. VM 안에서 nerdctl로 nginx를 띄워 접속하는 것까지 확인한다.
또한 VM을 만들 때 정해야 하는 항목 중 하나가 네트워크이다. 기본 NAT로는 VM이 맥 안의 대역에만 있어서 같은 LAN의 다른 기기에서 접근하기 어렵기 때문에, k3s 노드 간 통신이나 MetalLB의 LoadBalancer IP처럼 내부 네트워크 대역의 IP가 필요하면 bridged 네트워크를 지정한다. 이 모드는 socket_vmnet을 root로 실행해야 해서 brew install만으로는 동작하지 않으므로, 이 글은 그 사전 준비와 동작 구조도 함께 다룬다.
| 항목 | 내용 |
|---|---|
| macOS | 26.6.2 (arm64) |
| Lima | 2.2.1 |
| socket_vmnet | v1.2.2 (소스 빌드) |
| VM 이미지 | Ubuntu 22.04 (aarch64) |
| VM 타입 | vz |
2. Lima 설치
Homebrew로 설치한다.
brew install lima
limactl --version
limactl version 2.2.1
3. bridged 네트워크 준비
VM의 네트워크는 --network 옵션으로 모드를 골라 지정한다.
| 모드 | 지정 방법 | socket_vmnet, sudoers | VM이 받는 IP |
|---|---|---|---|
| 기본 NAT | 옵션 없음 | 불필요 | 192.168.5.x (VM마다 같은 주소) |
vzNAT | --network vzNAT | 불필요 | Apple NAT 대역 |
shared | --network lima:shared | 필요 | networks.yaml의 대역 (기본 192.168.105.x) |
bridged | --network lima:bridged | 필요 | DHCP로 받는 내부 네트워크 대역 (이 글은 192.168.0.x) |
- 이 글에서 직접 테스트한 모드는
bridged뿐이며, 나머지는 설정 파일과 Lima 문서를 기준으로 정리함 shared,bridged의lima:뒤 이름은networks.yaml의networks:아래 키와 일치해야 함- 맥 안에서만 쓸 거라면 sudo 설정이 필요 없는
vzNAT나 기본 NAT로도 충분함
이 글은 내부 네트워크 대역의 IP가 필요한 경우를 위해 bridged를 쓴다. 관련 용어는 다음과 같다.
- vmnet: macOS의 가상 네트워크 프레임워크. 호출하려면 root 권한이 필요함4
- socket_vmnet: vmnet 호출을 root로 대신 수행하고 Unix 소켓으로 VM과 연결하는 데몬. VM 자체는 일반 사용자 권한으로 실행됨
아래 준비는 최초 1회만 하면 되고, 이후 VM을 몇 대 만들어도 다시 할 필요가 없다. 3-1과 3-3은 sudo가 필요하다.
3-1. socket_vmnet 설치
brew install socket_vmnet은 하지 않는다. Homebrew 설치본은 사용자 소유라서 Lima가 거부하고, 문서도 Homebrew 설치를 권장하지 않는다.5 테스트에서는 Homebrew로 socket_vmnet을 설치한 상태였고, 이때 limactl sudoers가 아래 오류로 실패했다.
networks.yaml field `paths.socketVMNet` error: file `/opt/homebrew/Cellar/socket_vmnet/1.2.2/bin/socket_vmnet` is not owned by `root` (uid: 0), but by uid 501
Lima는 root로 실행될 socket_vmnet이 사용자가 바꿔칠 수 없는 위치에 있는지 검사하며, 이 검사는 Lima 1.0.0부터 엄격해졌다. 바이너리와 상위 디렉터리가 모두 root 소유여야 하고, 기본 경로는 /opt/socket_vmnet/bin/socket_vmnet이다.5 소스를 받아 빌드하고 root 소유로 설치한다.
git clone https://github.com/lima-vm/socket_vmnet
cd socket_vmnet
git checkout v1.2.2 # 최신 릴리스 태그로 바꿔도 됨
make
sudo make PREFIX=/opt/socket_vmnet install.bin
ls -l /opt/socket_vmnet/bin/
/opt/socket_vmnet/bin/socket_vmnet --version
-rwxr-xr-x@ 1 root wheel 39040 socket_vmnet
-rwxr-xr-x@ 1 root wheel 34080 socket_vmnet_client
v1.2.2
PREFIX=/opt/socket_vmnet을 주면install.bin이bin디렉터리를 만들고socket_vmnet과socket_vmnet_client를 설치하므로mkdir은 필요 없음socket_vmnet은 root로 도는 데몬이고,socket_vmnet_client는 qemu 타입에서 쓰는 도우미임. 이 글의vz타입은socket_vmnet만 사용함
3-2. networks.yaml 확인
~/.lima/_config/networks.yaml은 직접 만들지 않는다. limactl이 처음 필요할 때 기본값으로 생성한다.
grep -A3 '^paths:' ~/.lima/_config/networks.yaml
grep -A3 '^ bridged:' ~/.lima/_config/networks.yaml
paths:
socketVMNet: "/opt/socket_vmnet/bin/socket_vmnet" # 3-1에서 설치한 root 소유 경로
networks:
bridged:
mode: bridged
interface: en0 # 브리지할 물리 인터페이스
bridged항목은 기본값이interface: en0이라 따로 고칠 필요가 없었음. 다른 인터페이스를 쓰려면 이 값을 바꿈socketVMNet이 Homebrew 경로(/opt/homebrew/Cellar/...)로 되어 있으면 아래 명령으로 고침
sed -i '' 's#^ socketVMNet:.*# socketVMNet: "/opt/socket_vmnet/bin/socket_vmnet"#' ~/.lima/_config/networks.yaml
3-3. sudoers 설치
VM을 시작할 때마다 비밀번호를 묻지 않고 socket_vmnet만 root로 띄울 수 있게 한다. limactl sudoers가 내용을 만들어 주므로 확인한 뒤 설치한다.
limactl sudoers > /tmp/etc_sudoers.d_lima
cat /tmp/etc_sudoers.d_lima # 내용 확인
sudo install -o root /tmp/etc_sudoers.d_lima /etc/sudoers.d/lima
sudo visudo -c -f /etc/sudoers.d/lima # 문법 검증
rm /tmp/etc_sudoers.d_lima
limactl sudoers --check
/etc/sudoers.d/lima: parsed OK
`/private/etc/sudoers.d/lima` is up-to-date (or sudo doesn't require a password)
- 허용되는 것은
admin그룹이 지정된 socket_vmnet 명령(bridged/en0, host, shared), 해당 pid 파일에 대한pkill -F,/private/var/run/lima디렉터리 생성뿐이고 다른 명령은 허용되지 않음 - 대상 그룹은 Lima 2.2부터 기본
admin이므로groups에admin이 없으면networks.yaml의group:을 본인 그룹으로 바꾸고 다시 생성함5 /etc/sudoers는 직접 편집하지 않음
4. VM 생성
VM 이름은 master-1로 예를 든다.
4-1. 템플릿과 다운로드된 이미지 확인
지원하는 템플릿은 --list-templates로 확인한다. 전체가 80여 개라 Ubuntu만 걸러 본다.
limactl create --list-templates | grep ubuntu
experimental/ubuntu-26.10
experimental/ubuntu-next
ubuntu
ubuntu-20.04
ubuntu-22.04
ubuntu-24.04
ubuntu-24.10
ubuntu-25.04
ubuntu-25.10
ubuntu-26.04
ubuntu-lts
다운로드한 이미지는 캐시에 저장되고, url 파일로 어떤 파일을 받았는지 확인할 수 있다. 아래는 이 글의 테스트를 마친 뒤의 상태이다.
awk 1 ~/Library/Caches/lima/download/by-url-sha256/*/url
https://cloud-images.ubuntu.com/releases/jammy/release-20260926/ubuntu-22.04-server-cloudimg-arm64.img
https://github.com/containerd/nerdctl/releases/download/v2.4.1/nerdctl-full-2.4.1-linux-arm64.tar.gz
- 두 번째 파일은 VM에 containerd와 nerdctl을 설치하는 번들로, Lima 기본 설정(
containerd.user: true)에 따라 함께 받아짐(7절)
캐시는 limactl prune으로 지운다.
limactl prune
level=info msg="Pruning `~/Library/Caches/lima`"
- 옵션 없이 실행하면 VM이 없을 때, 중지된 VM이 있을 때, VM이 실행 중일 때 모두 캐시가 지워지며
~/Library/Caches/lima/download폴더도 없어짐. VM을 먼저 중지하거나 삭제하지 않아도 됨 - VM 디스크는 캐시와 별개라서 실행 중인 VM은 계속 동작하고, 중지된 VM도 이미지를 다시 받지 않고 시작됨. 이후 새 VM을 만들 때는 이미지를 다시 받음
--keep-referred를 주면 VM이 있는 동안 캐시가 지워지지 않음(실행 중 1개, 중지 1개일 때 확인). VM이 없을 때의 동작은 실행해 보지 않음
4-2. master-1 생성
이 글은 ubuntu-22.04로 만든다.
limactl create template:ubuntu-22.04 \
--name master-1 \
--cpus 2 \
--memory 4 \
--disk 20 \
--vm-type vz \
--network lima:bridged \
--mount-none \
--tty=false
template:ubuntu-22.04: Ubuntu 22.04 템플릿.template://ubuntu-22.04표기는 Lima v2.0부터 경고가 나므로template:로 씀--memory 4,--disk 20: 단위 없이 GiB 숫자만 받음.--disk 30GiB는invalid syntax오류가 남--vm-type vz: Apple Virtualization 프레임워크를 쓰는 VM 타입--network lima:bridged:networks.yaml의bridged항목을 선택하며, 이 한 줄이 VM에lima0을 추가함--mount-none: 맥의 홈 디렉터리를 VM에 마운트하지 않음--tty=false: 편집기를 열지 않고 바로 생성
create는 VM 설정과 디스크만 만들고 시작하지는 않는다. 이 시점의 상태는 Stopped이고 호스트 에이전트 로그(ha.*.log)도 없다.
4-3. VM 시작
limactl start --tty=false master-1
limactl list
- 처음 한 번은 Ubuntu 클라우드 이미지(약 670MiB)를 받는다. 다운로드가 끝나야 호스트 에이전트가 뜨므로, 그동안
limactl list는Stopped로 표시됨. 정상 동작이므로 기다림 - 이미지는 캐시되어 이후 VM은 다시 받지 않음
4-4. SSH 공개키 배포
VM의 authorized_keys에는 Lima 자체 키만 들어 있다. 이 상태로 LAN IP에 접속하면 Permission denied (publickey)가 나므로 맥의 공개키를 넣어 준다.
limactl shell master-1 bash -c '
mkdir -p ~/.ssh && chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys
grep -qxF "$1" ~/.ssh/authorized_keys || echo "$1" >> ~/.ssh/authorized_keys
' _ "$(cat ~/.ssh/id_ed25519.pub)"
grep -qxF로 이미 있는 키는 중복해서 넣지 않음- VM의 사용자명은 맥 사용자명이고 hostname은
lima-<이름>
4-5. bridged IP 확인
limactl shell master-1 ip -4 -o addr show lima0 | awk '{print $4}'
192.168.0.118/24
이 주소로 바로 접속한다.
ssh lemon@192.168.0.118
4-6. worker-1 생성
VM 간 통신을 확인하기 위해 4-2와 같은 옵션으로 worker-1을 하나 더 만든다.
limactl create template:ubuntu-22.04 --name worker-1 \
--cpus 2 --memory 4 --disk 20 \
--vm-type vz --network lima:bridged --mount-none --tty=false
limactl start --tty=false worker-1
limactl shell worker-1 ip -4 -o addr show lima0 | awk '{print $4}'
192.168.0.119/24
- 공개키는 4-4와 같은 방법으로
worker-1에도 배포함
5. 네트워크 확인
VM이 켜진 상태에서 호스트와 VM의 네트워크 구성을 확인한다.
5-1. 호출 흐름
limactl start
└─ sudo socket_vmnet --vmnet-mode=bridged --vmnet-interface=en0 ... (Lima가 실행)
└─ macOS vmnet 프레임워크 호출
└─ bridge100, vmenet0 생성 (macOS가 만듦)
limactl start 로그에 Lima가 socket_vmnet을 띄우는 명령이 그대로 나온다.
Starting socket_vmnet daemon for `bridged` network
sudo --user root --group wheel --non-interactive /opt/socket_vmnet/bin/socket_vmnet --pidfile=/private/var/run/lima/bridged_socket_vmnet.pid --socket-group=admin --vmnet-mode=bridged --vmnet-interface=en0 /private/var/run/lima/socket_vmnet.bridged
- 데몬은 VM마다 뜨는 것이 아니라 bridged 네트워크당 하나이며, bridged VM들이 함께 사용함
- 마지막 bridged VM을 중지하면 Lima가
pkill -F로 데몬을 종료함
5-2. 호스트의 bridge100
bridged VM이 켜져 있는 동안 호스트에는 bridge100과 vmenet0 인터페이스가 생긴다.
ifconfig bridge100 | grep -E 'inet|member'
member: vmenet0 flags=3<LEARNING,DISCOVER>
member: en0 flags=8003<LEARNING,DISCOVER,MACNAT>
vmenet0은 VM 쪽 가상 포트,en0은 실제 NIC이고bridge100은 둘을 묶는 L2 브리지inet줄이 없으므로bridge100자체에는 IP가 없음. 맥의 LAN 주소는 계속 en0의 주소(ipconfig getifaddr en0)- 브리지가 켜져 있는 동안 en0에
PROMISC플래그가 붙음 - VM을 모두 중지하면
bridge100,vmenet0, socket_vmnet 데몬,PROMISC가 모두 사라지고, 다시 시작하면 생김(5-4)
5-3. VM의 NIC와 기본 라우트
bridged VM에는 NIC가 둘이다.
limactl shell master-1 ip -4 -o addr show | awk '{print $2, $4}'
limactl shell master-1 ip route
lo 127.0.0.1/8
eth0 192.168.5.15/24
lima0 192.168.0.118/24
# ip route (일부 줄 생략)
default via 192.168.0.1 dev lima0 proto dhcp src 192.168.0.118 metric 100
default via 192.168.5.2 dev eth0 proto dhcp src 192.168.5.15 metric 200
192.168.0.0/24 dev lima0 proto kernel scope link src 192.168.0.118 metric 100
192.168.5.0/24 dev eth0 proto kernel scope link src 192.168.5.15 metric 200
eth0은 Lima 기본 NAT이고 모든 VM이192.168.5.15로 같은 주소라서 노드 간 통신에는 쓸 수 없음. Lima가 SSH 포트 포워딩에 사용함lima0이 en0에 브리지된 NIC이며 내부 네트워크의 DHCP가 준 주소를 가짐- 기본 라우트는
lima0(metric 100)이eth0(metric 200)보다 우선하므로 외부 통신은 기본 게이트웨이(192.168.0.1)를 거침 - k3s에서는 node IP, flannel iface 등을
lima0기준으로 명시하는 편이 안전함
5-4. 연결 확인
master-1(192.168.0.118)과 worker-1(192.168.0.119) 두 VM으로 맥과 VM 사이, VM 사이, VM과 인터넷 사이의 통신을 확인했다.
ping -c 2 192.168.0.119 # 맥 → VM
ssh lemon@192.168.0.118 'ping -c 2 -I lima0 192.168.0.119' # VM ↔ VM
ssh lemon@192.168.0.119 'ping -c 2 -I lima0 192.168.0.118'
ssh lemon@192.168.0.118 'ping -c 2 -I lima0 1.1.1.1' # VM → 인터넷
| 확인 | 결과 |
|---|---|
| 맥 → VM ping | 손실 0%, 약 0.5ms |
master-1 ↔ worker-1 (lima0) | 양방향 손실 0%, 약 0.5ms |
| VM → 1.1.1.1 | 손실 0%, 약 12ms |
| SSH (비밀번호 없이) | 두 VM 모두 접속됨 |
VM을 모두 중지했다가 다시 시작해서 호스트 인터페이스의 변화도 확인했다.
limactl stop master-1; limactl stop worker-1
ifconfig | grep -E '^(bridge100|vmenet)'; pgrep -fl socket_vmnet; ifconfig en0 | grep -o PROMISC
limactl start master-1; limactl start worker-1
ifconfig bridge100 | grep member; ifconfig en0 | grep -o PROMISC
- 중지 후:
bridge100,vmenet0, socket_vmnet 데몬,PROMISC가 모두 없음 - 시작 후: 모두 다시 생겼고, 두 VM이 중지 전과 같은 IP를 받음
- 같은 LAN의 다른 기기(폰, 다른 PC)에서 VM으로 접속하는 것은 확인하지 못했고, 맥에서의 접속만 확인함
6. VM 관리
이 절은 4-2와 같은 옵션으로 만든 demo-1에서 실행했다. 출력은 시각 정보를 지우고 일부 줄을 생략했다.
6-1. VM 수정
디스크를 20GiB에서 30GiB로 늘린다. VM을 중지한 상태에서 설정을 바꾸고 다시 시작하면 Lima가 디스크 파일을 늘리고, 파티션과 파일시스템은 cloud-init이 부팅 중에 확장한다.
limactl stop demo-1
limactl edit --tty=false --disk 30 demo-1
grep '^disk:' ~/.lima/demo-1/lima.yaml
limactl start --tty=false demo-1
level=info msg="The instance demo-1 has shut down"
level=info msg="Instance `demo-1` configuration edited"
disk: 30GiB
level=info msg="Resize instance demo-1's disk from 20GiB to 30GiB"
VM 안에서 확인한다.
limactl shell demo-1 bash -c 'lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | grep vda; df -h / | tail -1; ip -4 -o addr show lima0 | awk "{print \$4}"'
vda 30G disk
├─vda1 29.9G part /
└─vda15 99M part /boot/efi
/dev/vda1 29G 2.5G 27G 9% /
192.168.0.120/24
growpart,resize2fs를 직접 실행하지 않았고, 수정 전(/20G 중 2.5G 사용)과 같은 IP와 같은 사용량이 유지됨- 디스크는 늘릴 수만 있고 줄일 수 없음. 파일은 스파스라서 실제 호스트 사용량은 쓴 만큼만 늘어남
6-2. VM 중지와 재시작
limactl stop demo-1
limactl list demo-1
limactl start --tty=false demo-1
level=info msg="The instance demo-1 has shut down"
NAME STATUS SSH VMTYPE ARCH CPUS MEMORY DISK DIR
demo-1 Stopped 127.0.0.1:49893 vz aarch64 2 4GiB 20GiB ~/.lima/demo-1
- 중지해도 디스크와 설정은 그대로 남고, 다시
start하면 이어서 부팅함 - bridged VM이 모두 중지되면
bridge100과 socket_vmnet 데몬이 사라짐(5-2)
6-3. VM 삭제
limactl stop demo-1
limactl delete demo-1
limactl list
level=info msg="The instance demo-1 has shut down"
level=info msg="Removing *.pid *.sock *.tmp under `~/.lima/demo-1`"
level=info msg="Deleted `demo-1` (`~/.lima/demo-1`)"
NAME STATUS
master-1 Running
worker-1 Running
- 삭제하면
~/.lima/demo-1디렉터리가 통째로 없어지므로 디스크 내용은 복구할 수 없음 - 다른 VM(master-1, worker-1)이 켜져 있으면
bridge100은 그대로 유지됨. 이 글에서 삭제 후에도 두 멤버(vmenet0,en0)가 남아 있는 것을 확인함
7. containerd로 nginx 실행
Lima의 기본 설정(containerd.user: true)에 따라 VM에는 rootless containerd와 nerdctl이 함께 설치된다. 이 절은 6-3에서 삭제한 뒤 4-2와 같은 옵션으로 다시 만든 demo-1(lima0 192.168.0.120)에서 실행했다.
limactl shell demo-1 bash -c 'command -v nerdctl containerd; systemctl --user is-active containerd'
/usr/local/bin/nerdctl
/usr/local/bin/containerd
active
nginx를 8080 포트로 실행하고 맥에서 lima0 IP로 접속한다.
limactl shell demo-1 nerdctl run -d --name nginx -p 8080:80 nginx:alpine
limactl shell demo-1 nerdctl ps
curl -sI http://192.168.0.120:8080 | head -2
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dfcf6941a710 docker.io/library/nginx:alpine "/docker-entrypoint.…" 16 seconds ago Up 0.0.0.0:8080->80/tcp nginx
HTTP/1.1 200 OK
Server: nginx/1.31.8
-p 8080:80은 VM의 모든 주소에서 8080을 열어서, VM 안의127.0.0.1과lima0IP, 맥에서 모두 200 응답을 받음-p 192.168.0.120:8080:80처럼lima0IP를 지정하면 포트는 열리지만 curl이 응답 없이 타임아웃됨. 원인은 확인하지 못했으므로 IP 지정 없이 포트만 연결함- 정리는
nerdctl rm -f nginx
8. 결론
Lima는 설치 후 limactl 명령만으로 VM 생성부터 삭제, 기본 containerd를 이용한 컨테이너 실행까지 다룰 수 있었다. VM에 내부 네트워크 대역의 IP가 필요하면 bridged 네트워크를 쓰되, socket_vmnet을 root 소유로 설치하는 사전 준비가 필요하다.
같은 LAN의 다른 기기에서의 접속, vzNAT와 shared 모드, 다른 Ubuntu 버전, CPU와 메모리 수정은 직접 실행하지 않았다. VM의 IP는 DHCP가 정하므로 고정이 필요하면 DHCP 서버에서 IP를 예약해야 한다.
9. 참고문헌
Lima, Lima — Lima 소개(자동 파일 공유와 포트 포워딩을 갖춘 리눅스 VM, WSL2와 유사), CNCF incubating 프로젝트 표기, Rancher Desktop·Colima·Finch·Podman Desktop 사용 사례 ↩︎ ↩︎
CNCF, Lima becomes a CNCF incubating project — 2021년 시작, 2022년 9월 Sandbox 편입, Incubating 승격 ↩︎
Lima, Lima documentation — macOS 외 호스트(Linux 등) 지원 ↩︎
lima-vm/socket_vmnet, socket_vmnet — vmnet 호출을 root로 수행하는 데몬의 소스와 빌드 방법 ↩︎
Lima, VMNet networks — socket_vmnet의 root 소유 요구, Homebrew 설치 비권장, 기본 경로
/opt/socket_vmnet/bin/socket_vmnet, 소스 빌드와limactl sudoers설치 절차, Lima 2.2의 sudoers 그룹 기본값 ↩︎ ↩︎ ↩︎