CloudBro 커뮤니티의 첫 주간 오픈소스 추천 글로 Colima를 소개해드리려 합니다.
많은 백엔드·풀스택 개발자와 DevOps 업무를 하시는 분들은 Docker에 친숙하실 것 같습니다. 로컬에서 Docker를 돌리는 것부터 실제 서비스에 컨테이너를 배포하고, 더 나아가 Kubernetes를 관리하기까지 컨테이너는 우리 개발자의 일상에서 자주 쓰는 도구입니다. 그만큼 컨테이너와는 애증의 관계라고도 할 수 있겠습니다.
그런 Docker를 개발자 컴퓨터에서 쉽게 다루기 위해 많은 분들이 Docker Desktop을 이용하실 것 같습니다. 그런데 회사의 규모가 커져 무료 사용 조건을 벗어나면, 유료 구독을 검토해야 할 때가 옵니다.
물론 직원 250명 미만이면서 연 매출 1,000만 달러 미만인 소규모 기업에는 무료 사용 조건이 적용됩니다. 단 이러한 조건에 해당되지 않는 규모가 큰 팀이라면 Docker Desktop을 계속 구독할지, 대안을 찾을지 선택의 기로에 놓입니다.
Colima를 살펴볼 이유가 구독료에만 있는 것은 아닙니다. 2026년 6월에는 Apple의 container 1.0도 나왔지만, 이 도구는 자체 API를 사용하며 Docker API를 기본으로 제공하지 않습니다. 같은 컨테이너 이미지를 쓴다고 해서 docker 명령까지 그대로 쓸 수 있는 것은 아닌 셈입니다. OrbStack은 개인 용도로는 무료이지만 업무용 라이선스는 유료이고 소스가 공개된 제품도 아닙니다. 기존 Docker 도구를 이어서 쓰면서, 업무에도 무료로 사용하고 소스도 살펴볼 수 있는 환경을 원한다면 MIT 라이선스로 공개된 Colima가 좋은 선택지 중 하나가 됩니다.
그러한 연유로 Colima를 소개해드리려 하고, 아래 단락부터는 설치하고 사용하는 방법과 함께, Docker 요청과 파일, 포트가 Mac과 Linux VM 사이에서 어떻게 연결되는지 살펴보겠습니다.
1. Mac에서 Linux VM이 필요한 이유
Colima는 Mac 안에 Linux VM을 만들고, 그 안에서 Docker Engine을 실행합니다. Docker Desktop을 사용할 때도 Linux 컨테이너는 VM 안에서 실행됩니다. 터미널에서 Docker 명령만 입력하다 보면 이 VM을 직접 다룰 일은 많지 않습니다.
Linux 컨테이너는 자신만의 커널을 부팅하지 않고, 실행 중인 머신의 Linux 커널을 함께 사용합니다. 이미지에는 프로그램과 라이브러리 등이 들어 있으며, 프로세스가 볼 수 있는 자원은 Linux의 namespaces가 분리합니다. CPU·메모리 사용량은 cgroups가 관리합니다.
macOS가 사용하는 커널은 XNU이므로, 일반적인 Linux 컨테이너를 실행하려면 Linux 커널을 사용할 환경이 따로 필요합니다. 그래서 Colima가 Mac에서 VM을 만들고 VM에 엔진을 얹는 것이라고 할 수 있습니다.
아래 단락에서는 실제로 Colima를 설치하여 docker 명령어를 사용하는 예시를 설명하겠습니다.
2. Colima를 설치하고 컨테이너 실행하기
설치부터 hello-world까지
Homebrew가 설치된 Mac이라면 아래 명령으로 Colima와 Docker CLI를 설치하고 바로 이용할 수 있습니다. 이 때 사용간 VM의 자원과 실행 환경 설정은 프로필로 묶어 관리하는데, 여기서는 이름을 따로 지정하지 않은 기본 프로필과 Docker 런타임을 사용합니다.
brew install colima docker
colima start
docker run --rm hello-world
위의 터미널 명령은 Colima와 Docker CLI를 설치하고 간단하게 hello world 컨테이너를 띄워보는 명령어입니다. 정말 간단하게 설치 및 이용할 수 있고 평소 docker compose나 docker buildx를 쓰고 계셨다면 Colima 설치 문서에 따라 해당 플러그인도 별도로 설치하여 이용하실수 있습니다.
colima start가 준비하는 것
이제 좀 더 깊이 들여다 보겠습니다. Lima는 VM의 생성·실행과 Mac과 VM 사이의 파일 공유·포트 전달을 제공하는 도구입니다. colima start를 실행하면 Colima가 CPU·메모리·마운트 등의 프로필 설정을 Lima 구성으로 바꾸어 VM을 시작하고, 이어서 Docker를 준비합니다.
그림 아래의 QEMU·VZ·krunkit은 VM을 실행/제어하는 백엔드입니다. 이 중 VZ는 Apple의 Virtualization.framework를 뜻합니다.
Colima의 app/app.go에서도 이 순서를 확인할 수 있습니다. 주요 호출만 추리면 다음과 같습니다.
guest.Start() → cont.Provision() → cont.Start()
VM 시작 런타임 준비 런타임 시작
이어지는 cont.Provision()은 Docker Engine의 설정과 Mac의 연결 정보를 준비하는 단계입니다. cont.Start()에서는 VM의 docker.service를 시작한 뒤, VM 안에서 docker info의 응답을 확인합니다.
환경 준비를 마치면 docker run의 요청은 그림의 회색 선을 따라 VM의 dockerd로 흐릅니다. dockerd는 컨테이너와 이미지를 관리하는 Docker Engine의 백그라운드 서비스, 즉 데몬입니다. Docker CLI가 이 데몬에 API 요청을 보내므로, Docker 명령을 실행할 때 Colima CLI를 다시 호출하지는 않습니다.
3. Docker 명령이 접속할 주소 확인하기
Docker Desktop과 Colima가 모두 설치된 Mac에서 docker ps를 입력하면 어느 쪽의 컨테이너가 보일까요? Docker CLI는 선택한 Docker context의 연결 정보를 사용합니다. context에는 이름과 Docker Engine의 접속 주소 등이 들어있으므로, Colima가 등록한 context를 아래 명령어를 통해 확인하실 수 있습니다.
docker context ls
docker context inspect colima --format '{{.Endpoints.docker.Host}}'
설정을 바꾸지 않은 기본 프로필이라면 아래 형태의 Docker socket 경로를 따릅니다.
unix:///Users/<UserProfile>/.colima/default/docker.sock
unix://는 같은 운영체제 안의 프로세스끼리 데이터를 주고받는 Unix 소켓으로 접속한다는 뜻입니다. 위 주소를 사용하는 Docker CLI는 Mac의 docker.sock에 연결합니다.
Colima는 setupContext()에서 context의 존재 여부를 확인하고, 없으면 소켓 주소를 넣어 새로 만듭니다. 자동 활성화 설정이 켜져 있으면 docker context use로 Colima를 선택합니다. 기존 context의 주소는 다시 등록하지 않으므로, 실제 접속 주소는 앞의 inspect 결과로 확인합니다.
접속 대상은 DOCKER_HOST, DOCKER_CONTEXT 환경변수나 명령행 옵션으로도 지정할 수 있습니다. 이 글처럼 --context colima를 붙이면 현재 선택을 바꾸지 않고 해당 명령만 Colima로 보냅니다. 실제로 서버가 응답하는지 보려면 아래 명령을 이용하여 확인하실 수 있습니다.
docker --context colima version
위 명령의 출력에서 Server 정보를 확인하셨다면 서버의 응답을 받은 것으로 확인할 수 있습니다.
4. Mac의 docker.sock에서 VM까지 요청 전달하기
방금 확인한 접속 주소는 Mac의 경로인데, 실제 동작을 위한 Docker Engine은 VM 안에 있습니다. 이 두 곳을 연결하기 위해 Colima는 Lima 구성에 소켓 전달 규칙을 추가합니다. Mac에서 연결을 받을 경로가 HostSocket, VM에서 요청을 보낼 경로가 GuestSocket입니다.
HostSocket: /Users/<UserProfile>/.colima/default/docker.sock
GuestSocket: /var/run/docker.sock
Lima의 호스트 에이전트는 Mac에서 VM 연결을 관리하는 프로세스입니다. 이 프로세스가 forwardSSH()를 호출하면 OpenSSH에 -O forward와 -L <호스트 소켓>:<게스트 소켓> 옵션이 전달됩니다. 설정을 받은 OpenSSH는 Mac 소켓의 연결을 SSH(Secure Shell)를 통해 VM으로 보내고, VM의 /var/run/docker.sock에 연결합니다.
Mac의 Docker CLI
→ ~/.colima/default/docker.sock
→ SSH 연결의 소켓 전달
→ Linux VM의 /var/run/docker.sock
→ dockerd
Lima는 ControlMaster=auto와 ControlPersist=yes로 SSH 연결을 유지하므로 Docker 명령마다 연결을 새로 맺지 않아도 됩니다. -O forward는 유지 중인 SSH 프로세스에 전달 규칙을 추가할 때 쓰며, 이 요청은 ControlPath가 지정한 제어 소켓으로 보냅니다. Docker CLI의 API 요청은 앞서 확인한 docker.sock으로 들어갑니다. docker.sock은 Mac과 VM에 각각 있으므로, 디렉터리를 공유하는 것만으로 두 운영체제의 소켓 통신이 이어지지는 않습니다. 앞서 살펴본 OpenSSH의 전달 규칙이 두 소켓을 연결합니다.
이 연결은 curl로도 확인할 수 있습니다. Docker Engine API가 HTTP를 사용하므로, context에 저장된 소켓으로 아래의 명령어처럼 /_ping 요청을 보내어 확인할 수 있습니다.
colima_endpoint="$(docker context inspect colima --format '{{.Endpoints.docker.Host}}')"
curl --fail --max-time 5 \
--unix-socket "${colima_endpoint#unix://}" \
http://localhost/_ping
첫 줄에서 읽은 주소에는 unix://가 붙어 있으므로 ${colima_endpoint#unix://}로 이 접두사를 떼어 냅니다. curl은 남은 경로를 --unix-socket으로 받아 연결합니다. 이 요청에 OK가 돌아오면 Mac의 소켓부터 VM의 Docker API까지 응답을 주고받은 것입니다.
5. Mac에서 만든 파일을 컨테이너에 연결하기
Docker의 bind mount는 데몬이 실행되는 머신의 디렉터리를 컨테이너 경로에 연결합니다. Colima에서는 Docker Engine이 VM 안에 있으므로, Mac의 소스 코드를 연결하려면 먼저 그 디렉터리가 VM에도 공유돼 있어야 합니다.
예시를 위해 Mac의 홈 디렉터리에 HTML을 만들고 Nginx를 만들어서 읽어 보겠습니다. 홈 디렉터리가 VM의 같은 경로로 공유되고 자동 포트 전달이 켜진 기본 프로필을 기준으로, 아래 명령을 Mac의 터미널에 입력합니다.
mkdir -p "$HOME/colima-demo"
printf '<h1>Hello from macOS</h1>\n' > "$HOME/colima-demo/index.html"
docker --context colima run --rm -d \
--name colima-demo \
-p 127.0.0.1:8080:80 \
--mount "type=bind,src=$HOME/colima-demo,dst=/usr/share/nginx/html,readonly" \
nginx:alpine
Mac의 셸이 $HOME을 홈 디렉터리로 바꾸면 VM의 Docker Engine은 src 경로를 찾아 컨테이너의 dst에 연결합니다. Nginx는 /usr/share/nginx/html에서 readonly로 파일을 읽어냅니다.
여기서 --mount 파라미터 자체가 Mac의 디렉터리를 VM에 공유하지는 않습니다. VM에서 원본 경로가 보이지 않으면 명령이 실패합니다. VZ·virtiofs 구성에서 파일이 연결되는 순서는 다음과 같습니다.
Mac의 /Users/<사용자>/colima-demo
→ virtiofs로 VM에 공유
→ VM의 /Users/<사용자>/colima-demo
→ Docker의 bind mount
→ 컨테이너의 /usr/share/nginx/html
첫 단계의 virtiofs는 호스트의 디렉터리를 게스트에 공유하는 방식입니다. 이 구성에서 Nginx가 공유 파일을 읽으면, 호스트 처리가 필요한 파일 요청을 Linux 커널의 virtiofs 드라이버가 가상 장치로 보냅니다. Mac 쪽 디렉터리 공유는 Apple의 Virtualization.framework가 제공합니다. 컨테이너를 준비할 때 Docker API로 보내는 것은 --mount에 지정한 경로입니다. 이후 Nginx가 파일을 읽을 때는 virtiofs와 bind mount를 사용하며, Docker API용 SSH 연결로 파일 내용이 전송되지 않습니다.
Docker가 관리하는 데이터의 저장 위치
이미지나 컨테이너 데이터에는 VM 내부의 저장 공간도 사용합니다. Colima는 /var/lib/docker와 /var/lib/containerd 등의 데이터를 ext4 파일시스템을 사용하는 런타임 데이터 디스크에 저장하도록 구성합니다. Docker가 이름을 붙여 관리하는 named volume도 기본 로컬 드라이버를 사용하면 데몬 측 저장소에 놓입니다. 파일 작업이 느릴 때는 저장 위치부터 확인하면 좋겠습니다. 이 예시의 HTML은 Mac의 공유 디렉터리에, named volume의 데이터는 VM 안에 있으므로 파일을 읽고 쓰는 경로가 다릅니다.
6. Mac의 localhost로 Nginx에 접속하기
-p 127.0.0.1:8080:80은 Docker 호스트인 VM의 8080번 포트를 컨테이너의 80번 포트에 연결합니다. Mac의 브라우저에서 접속하려면 Mac의 8080번 포트에서 VM의 8080번 포트로 이어지는 연결도 필요합니다.
이 연결 역시 Lima가 담당하고, Colima가 전달 규칙을 구성합니다. 따라서 Mac에서 Nginx에 보내는 요청은 다음 순서로 전달됩니다.
Mac에서 curl http://127.0.0.1:8080 실행
→ Lima의 포트 전달
→ Linux VM의 127.0.0.1:8080
→ Docker의 포트 공개 처리
→ 컨테이너의 80번 포트에서 기다리는 Nginx
127.0.0.1은 각 네트워크 환경 자신을 가리키는 루프백 주소여서 Mac과 VM의 접속 대상은 다릅니다. Lima가 Mac의 연결을 VM으로 보내면 Docker가 주소 변환이나 프록시로 컨테이너에 전달합니다.
Mac의 브라우저에서 http://127.0.0.1:8080을 열어 Hello from macOS를 받았다면 파일 공유와 포트 전달이 함께 잘 전달된 것을 확인할 수 있습니다.
Lima가 전달할 포트를 찾는 방법
VM의 게스트 에이전트는 열린 소켓을 조사해 포트의 추가·삭제를 Mac의 호스트 에이전트에 알립니다. 호스트 에이전트가 전달 규칙에 따라 Mac의 수신 소켓을 열거나 닫고, 접속이 들어오면 전달기가 VM으로 연결을 보냅니다. 소켓을 조사하는 데에는 Linux 커널과 정보를 주고받는 인터페이스인 Netlink를 사용합니다. 이 과정은 Docker 컨테이너에만 한정되지 않습니다. VM에서 직접 실행한 서비스도 전달 규칙에 맞으면 Mac에서 접속할 수 있습니다.
포트 전달 설정을 바꾸는 경우
UDP를 사용하는 서비스라면 포트 전달 방식도 확인해야 합니다. Lima의 SSH 전달기는 TCP를 지원하고, gRPC 전달기는 TCP와 UDP를 지원합니다. Colima에서 portForwarder를 grpc로 지정하면 LIMA_SSH_PORT_FORWARDER=false를 Lima에 전달해 gRPC 전달기를 선택합니다.
자동 포트 전달을 끄려면 portForwarder를 none으로 지정합니다. Colima가 애플리케이션 포트를 무시하는 규칙을 추가하는 설정입니다. 이 경우에도 Docker Unix 소켓의 SSH 전달 규칙은 유지되므로, Docker 명령은 사용할 수 있어도 앞의 Nginx 페이지에는 자동으로 연결되지 않을 수 있습니다.
7. 실행 결과가 예상과 다를 때 확인할 곳
Docker 명령은 되는데 웹 페이지가 열리지 않을 때
Docker API와 웹 요청은 다른 연결을 쓰므로 docker --context colima ps가 돼도 Nginx에 접속하지 못할 수 있습니다. 먼저 Mac의 터미널에서 실행 상태와 로그, 공개 포트를 확인합니다.
docker --context colima ps --filter name=colima-demo
docker --context colima logs colima-demo
docker --context colima port colima-demo 80/tcp
docker port에 127.0.0.1:8080이 나온다면 VM의 포트 공개 설정은 들어가 있습니다. 이제 VM과 Mac의 실제 응답을 비교합니다. 두 줄 모두 Mac의 터미널에 입력하지만 colima ssh가 붙은 첫 curl은 VM 안에서 실행됩니다.
# VM에서 요청
colima ssh -- curl --fail --max-time 5 http://127.0.0.1:8080
# Mac에서 요청
curl --fail --max-time 5 http://127.0.0.1:8080
VM에서는 HTML이 나오는데 Mac에서 연결을 거부하거나 시간이 초과된다면 Mac의 8080번 포트를 다른 프로그램이 쓰고 있는지, Lima의 전달 설정이 맞는지 확인합니다. VM에서도 연결되지 않는다면 Nginx의 실행 상태와 Docker의 포트 매핑을 확인합니다. 다만 curl의 파라미터인 --fail은 HTTP 4xx·5xx 응답도 실패로 처리합니다. 연결 거부나 시간 초과와 달리 HTTP 오류 응답을 받았다면 서버에는 요청이 도착한 것입니다. 이때는 응답 코드와 Nginx 로그에서 원인을 찾아볼 수 있습니다.
컨테이너에서 Mac의 파일이 보이지 않을 때
Mac의 터미널에서 아래 두 명령으로 index.html을 읽어 보겠습니다. 첫 명령은 VM의 공유 파일을, 두 번째 명령은 컨테이너의 파일을 읽습니다.
colima ssh -- cat "$HOME/colima-demo/index.html"
docker --context colima exec colima-demo cat /usr/share/nginx/html/index.html
VM에서도 파일을 찾을 수 없다면 Mac과 VM 사이의 공유 경로를 확인합니다. VM에서는 읽히는데 컨테이너에서 읽히지 않는다면 --mount에 지정한 원본 경로와 목적지가 맞는지 확인하실 수 있습니다.
파일을 수정했는데 개발 서버가 반응하지 않을 때
파일 내용은 바뀌었는데 개발 서버가 갱신되지 않는다면 파일 변경 알림과 서버의 감시 설정을 확인합니다. Colima에는 호스트의 변경을 VM에 알리는 실험적 기능이 있으며, 설정 문서의 colima start --mount-inotify로 활성화합니다.
예시 컨테이너 종료하기
확인이 끝나면 Mac의 터미널에서 Nginx를 종료합니다. 앞에서 --rm으로 시작했으므로 Docker Engine이 컨테이너도 함께 제거합니다.
docker --context colima stop colima-demo
오픈소스를 관리하는 사람들
글을 마치기 전에, 무료로 쓰는 프로그램은 누가 계속 관리할까요? Colima를 시작한 개발자 Abiola Ibrahim은 시간을 내어 오픈소스에 기여하고 있으며, 후원을 받아 전업으로 일하는 것을 목표로 한다고 밝히고 있습니다. 기반 도구인 Lima는 클라우드 네이티브 프로젝트를 지원하는 재단인 CNCF에 속한 Incubating 프로젝트로 운영되고 있습니다. 오픈소스가 이러한 선의, 혹은 비영리 재단에서 운영되는 것이 아닌 한 기업의 주도로 오픈소스 개발을 진행하다 라이센스가 변경 되었을 때 Colima 같은 대안 등을 이용하게 되는데, 이 때 이러한 개인/비영리 오픈소스는 어떻게 유지가 가능할 것인가. 여러분의 생각은 어떠하신지 궁금합니다.
마치며
Colima를 설치하는 데서 시작해, Mac의 Docker 요청과 파일, 포트가 Linux VM에 연결되는 과정까지 살펴봤습니다. 평소 쓰던 docker 명령은 같지만, Mac에서 요청을 처리하는 Docker Engine의 위치를 알고 나면 더 규모가 큰 K8S를 공부하거나, 컨테이너 등을 관리하는 사항에 있어서 도움이 되시리라 믿고 글을 마치려 합니다.

