최근 수정 시각 : 2026-08-08 15:08:49

runc

runc
개발 Docker → OCI
최초 출시 2015년 7월(v0.0.1)
최신 버전 1.3.x 계열[1]
개발 언어 Go
라이선스 Apache-2.0
운영체제 리눅스
종류 OCI 런타임 명세 표준 구현체
링크 GitHub

1. 개요2. 역사3. 동작 방식4. 보안 취약점5. 다른 컨테이너 런타임과의 관계6. 관련 문서


1. 개요

runc는 OCI(Open Container Initiative) 런타임 명세(runtime-spec)의 표준 참조 구현체로, 리눅스에서 파일시스템 격리, 네임스페이스, cgroups 등의 커널 기능을 조합해 실제로 컨테이너 프로세스를 생성하고 실행하는 저수준(low-level) 명령줄 도구다. Docker, containerd, CRI-O 같은 상위 도구들이 이미지 처리나 네트워크 구성 같은 복잡한 작업을 담당하는 동안, 실제로 격리된 프로세스를 만들어 내는 핵심 작업은 대부분 runc가 도맡는다. 이 때문에 "Docker의 심장부"라고 표현되기도 한다.

2. 역사

2013년 등장한 초기 Docker는 리눅스 컨테이너를 만들 때 이미 존재하던 LXC 도구를 기반으로 삼았다. Docker는 여기에 컨테이너 이미지라는 "패키징" 개념과, 서로 다른 머신 사이에서도 이미지를 그대로 옮겨 실행할 수 있는 "이식성" 개념을 더했다.

2014년 Docker 팀은 별도의 외부 프로그램을 호출하는 대신 Go 언어로 직접 컨테이너를 생성·관리할 수 있는 라이브러리인 libcontainer를 개발하며 LXC 의존에서 벗어났다. 같은 해 열린 DockerCon에서 Kubernetes가 발표되었고, 이를 계기로 컨테이너 생태계 전반에 걸쳐 통일된 표준이 필요하다는 공감대가 확산되었다.

2015년 6월, Docker와 CoreOS를 비롯한 여러 업계 주요 기업들이 Linux Foundation 산하 프로젝트로 OCI(Open Container Initiative)를 설립했다. 이는 특정 회사(Docker) 중심으로 흘러가던 컨테이너 표준을, 여러 업체가 함께 참여하는 중립적인 개방형 거버넌스로 전환하려는 시도였다. Docker는 자사가 개발해 온 컨테이너 포맷과 런타임을 OCI에 기증했고, libcontainer 역시 OCI 산하로 넘어가면서 이를 기반으로 runtime-spec의 최초 표준 구현체가 만들어졌다. 이렇게 탄생한 도구가 바로 runc이며, 2015년 7월 v0.0.1 버전으로 첫 출시되었다.

이후 runc는 오랜 개발을 거쳐 2021년 6월 22일 1.0.0 버전에 도달했다. 이후로도 지속적으로 마이너 버전이 이어지고 있으며, 프로젝트 측은 매년 4월 말과 10월 말, 약 6개월 주기로 새 마이너 버전을 릴리스하는 정책을 공식화한 바 있다.

3. 동작 방식

runc는 OCI 런타임 명세를 따르는 "파일시스템 번들"을 입력으로 받아 동작한다. 이 번들은 크게 컨테이너의 루트 파일시스템과, 실행할 명령·환경 변수·마운트할 경로·적용할 자원 제한 등을 정의한 `config.json` 설정 파일로 구성된다. runc는 이 설정을 읽어, 리눅스 커널의 네임스페이스로 프로세스·네트워크·마운트 등을 격리하고, cgroups로 CPU·메모리 등의 자원 사용량을 제한하는 방식으로 실제 컨테이너 프로세스를 만들어 실행한다.

상위 도구가 이미지를 내려받아 이 번들 형태로 풀어 놓기만 하면, 그 이후의 "실제로 격리된 프로세스를 띄우는" 작업은 runc가 전담하는 구조다. 이런 역할 분담 덕분에, Docker 외에도 containerd나 CRI-O처럼 서로 다른 상위 도구들이 동일한 runc를 공통의 저수준 실행 엔진으로 공유할 수 있다.

4. 보안 취약점

runc는 컨테이너 격리의 가장 밑단을 담당하는 만큼, 여기서 발견되는 취약점은 종종 "컨테이너 탈출(container escape)" — 즉 컨테이너 안에 있어야 할 프로세스가 호스트 시스템에 대한 권한을 획득하는 사고로 이어진다는 점에서 특히 심각하게 다뤄진다.
  • CVE-2016-9962: runc의 init 프로세스가 호스트로부터 물려받은 파일 디스크립터를 그대로 들고 있어서, 공격자가 이를 이용해 호스트 파일시스템을 순회하며 컨테이너를 탈출할 수 있었던 취약점이다.
  • CVE-2019-5736: 2019년 2월 공개된 이 취약점은 컨테이너 안에서 root(UID 0)로 실행 중인 프로세스가, `docker exec` 등으로 컨테이너에 진입하는 시점을 노려 호스트의 runc 바이너리 자체를 자신이 조작한 내용으로 덮어써 실행시키는 방식으로, 호스트에서 root 권한을 획득할 수 있게 하는 심각한 결함이었다. 폴란드의 보안 연구팀 Dragon Sector 소속 Adam Iwaniuk와 Borys Poplawski가 발견했으며, LXC에도 유사한 근본적 결함이 존재한다는 사실이 함께 밝혀지기도 했다.
  • CVE-2024-21626 (Leaky Vessels): 내부 파일 디스크립터가 새는 결함으로 인해, Dockerfile의 `WORKDIR` 지시어를 조작하는 방식으로 컨테이너 프로세스가 호스트 디렉터리에 대한 파일 디스크립터를 계속 쥐고 있을 수 있었던 취약점이다. 이를 이용하면 호스트 파일시스템을 읽거나 쓸 수 있었다.
  • 2025년 공개된 일련의 취약점들(CVE-2025-31133 등): `/dev/null`이나 `/dev/console`을 특정 경로에 바인드 마운트해서 민감한 호스트 경로를 가리는(masking) runc의 처리 방식을 노린 사례들이다. 공격자가 경쟁 조건(race condition)이나 심볼릭 링크 치환을 이용해 이 바인드 마운트 대상을 조작하면, 보안 보호 장치가 완전히 적용되기 전에 `/proc` 등 민감한 경로에 쓰기 접근 권한을 얻어 컨테이너를 탈출할 수 있는 구조였다.

이런 사고가 반복되면서, 컨테이너를 root 권한이 아닌 일반 사용자로 실행하거나 SELinux 같은 강제적 접근 통제(MAC)를 함께 적용하는 것이 중요한 완화책으로 꾸준히 권장되고 있다.

5. 다른 컨테이너 런타임과의 관계

runc는 OCI runtime-spec의 참조 구현체이지만, 유일한 구현체는 아니다. C로 작성되어 더 가볍고 빠른 것을 지향하는 crun이나, 가상머신 수준의 격리를 제공하는 Kata Containers(runV 계열) 등 같은 명세를 따르는 다른 런타임들도 존재한다. OCI가 명세 자체를 개방형 표준으로 관리하는 덕분에, Docker나 Kubernetes 같은 상위 도구들은 이런 여러 런타임 구현체를 상황에 따라 교체해서 사용할 수 있다.

한편 runc 자체는 매번 새로운 프로세스로 실행되고 종료되는 방식이라, Docker나 Kubernetes 환경에서는 runc를 직접 호출하는 대신 containerd 같은 상주형(데몬) 관리 계층을 하나 더 두어, 컨테이너의 생명주기를 지속적으로 관리하고 runc는 그때그때 필요한 순간에만 호출하는 구조를 흔히 사용한다.

6. 관련 문서


[1] 2026년 8월 기준. 1.4, 1.5 계열도 병행 개발 중

분류