[{"data":1,"prerenderedAt":675},["ShallowReactive",2],{"post-document:\u002Fdevops\u002Fdocker\u002F2026\u002F08\u002F24\u002Foci-container-standard\u002F":3},{"id":4,"title":5,"body":6,"categories":656,"date":659,"description":660,"extension":661,"image":662,"key_concepts":662,"last_modified_at":662,"legacyPath":663,"meta":664,"navigation":666,"part":662,"path":667,"published":666,"robots":662,"seo":668,"series":662,"stem":669,"strengths":662,"summary":662,"tags":670,"tradeoffs":662,"__hash__":674},"posts\u002Fposts\u002FCI-CD-Docker\u002FDocker\u002F2026-08-24-oci-container-standard.md","OCI: 컨테이너 이미지와 런타임의 공통 표준",{"type":7,"value":8,"toc":649},"minimark",[9,14,21,24,29,32,43,46,52,55,58,63,66,70,75,78,84,87,93,97,100,106,109,113,116,119,122,128,131,137,140,146,149,155,159,162,167,170,173,176,182,185,191,194,200,203,209,212,215,220,223,312,315,318,323,327,330,349,352,358,361,365,368,373,376,381,384,388,391,394,397,416,419,425,428,431,435,438,443,450,456,461,465,470,475,481,485,488,491,494,496,517,520,526,529,533,536,539,544,546,560,566,569,572,575,578,581,584,587,591,594,600,603,606,609,615,618,624,627,630,636,639,645],[10,11,13],"h2",{"id":12},"ociopen-container-initiative란","OCI(Open Container Initiative)란?",[15,16,17],"blockquote",{},[18,19,20],"p",{},"OCI는 \"컨테이너 이미지와 컨테이너 실행 방식에 대한 국제 공통 규격\"",[18,22,23],{},"Docker가 만든 이미지를 Docker에서만 실행하는 게 아니라, containerd, CRI-O, Kubernetes, Podman 같은 다른 생태계에서도 동일하게 사용할 수 있게 해주는 표준",[25,26,28],"h1",{"id":27},"_1-oci는-왜-등장했는가","1. OCI는 왜 등장했는가?",[18,30,31],{},"초창기 컨테이너 시장 -> Docker가 거의 표준처럼 쓰임",[33,34,40],"pre",{"className":35,"code":37,"language":38,"meta":39},[36],"language-text","Docker Image\n    ↓\nDocker Engine\n    ↓\nContainer\n","text","",[41,42,37],"code",{"__ignoreMap":39},[18,44,45],{},"문제는 이러면 Docker라는 특정 회사와 구현체에 생태계가 강하게 종속될 수 있다는 것",[33,47,50],{"className":48,"code":49,"language":38,"meta":39},[36],"Docker Image\n    ↓\nDocker에서만 실행 가능\n\nA회사 Image\n    ↓\nA회사 Runtime에서만 실행 가능\n\nB회사 Image\n    ↓\nB회사 Runtime에서만 실행 가능\n",[41,51,49],{"__ignoreMap":39},[18,53,54],{},"따라서 Docker, Google, Red Hat, IBM, Microsoft 등 여러 기업이 참여해서 만든 표준화 프로젝트가 OCI(Open Container Initiative)",[18,56,57],{},"이와 같이 모인 목적은",[15,59,60],{},[18,61,62],{},"컨테이너를 어떤 형식으로 만들고, 어떻게 실행하면 좋을까하는 공통 규격을 만들자.",[18,64,65],{},"라는 일념하에 힘을 합치게 된다.",[25,67,69],{"id":68},"_2-oci는-프로그램이-아니다","2. OCI는 프로그램이 아니다.",[15,71,72],{},[18,73,74],{},"OCI는 설계도 \u002F 규격이고 runc 같은 프로그램이 그 규격을 구현",[18,76,77],{},"OCI 자체는 Docker나 containerd처럼 실행되는 프로그램이 아니다.",[33,79,82],{"className":80,"code":81,"language":38,"meta":39},[36],"Docker      → 프로그램\ncontainerd  → 프로그램\nrunc        → 프로그램\n\nOCI         → 표준 Specification\n",[41,83,81],{"__ignoreMap":39},[18,85,86],{},"비유를 해보자면",[33,88,91],{"className":89,"code":90,"language":38,"meta":39},[36],"HTTP   = 웹 통신 규칙\nChrome = HTTP를 사용하는 프로그램\n\nOCI    = 컨테이너 규칙\nrunc   = OCI 규칙을 구현한 프로그램\n",[41,92,90],{"__ignoreMap":39},[25,94,96],{"id":95},"_3-oci의-핵심-3가지-표준","3. OCI의 핵심 3가지 표준",[18,98,99],{},"OCI에서는 크게 세 가지를 정의",[33,101,104],{"className":102,"code":103,"language":38,"meta":39},[36],"OCI\n├── Image Specification\n├── Runtime Specification\n└── Distribution Specification\n",[41,105,103],{"__ignoreMap":39},[18,107,108],{},"각각이 약간씩 다르므로 아래서 좀 설명을 해보려 한다.",[25,110,112],{"id":111},"_4-oci-image-specification","4. OCI Image Specification",[18,114,115],{},"컨테이너 이미지를 어떤 구조로 저장할 것인가를 정의",[18,117,118],{},"Docker 이미지를 생각하면 된다.",[18,120,121],{},"예를 들어",[33,123,126],{"className":124,"code":125,"language":38,"meta":39},[36],"nginx image\n├── Layer 4  nginx 설정\n├── Layer 3  nginx 설치\n├── Layer 2  라이브러리\n└── Layer 1  Ubuntu filesystem\n",[41,127,125],{"__ignoreMap":39},[18,129,130],{},"OCI Image Spec은 다음과 같은 것을 정의",[33,132,135],{"className":133,"code":134,"language":38,"meta":39},[36],"Image\n├── Manifest\n├── Config\n└── Layers\n",[41,136,134],{"__ignoreMap":39},[18,138,139],{},"예를 들면",[33,141,144],{"className":142,"code":143,"language":38,"meta":39},[36],"Manifest\n    ↓\n어떤 Config와 Layer를 사용하는지 기록\n\nConfig\n    ├── 환경변수\n    ├── 실행 명령어\n    ├── Working Directory\n    └── Architecture\n\nLayers\n    ↓\n실제 파일 시스템 데이터\n",[41,145,143],{"__ignoreMap":39},[18,147,148],{},"이런 식으로 규격을 표준화했기 때문에, 덕분에 Docker에서 만든 이미지도 다른 OCI 호환 프로그램에서 사용할 수 있다. (오우? 굉장히 좋다고 할 수 있다.)",[33,150,153],{"className":151,"code":152,"language":38,"meta":39},[36],"Docker build\n    ↓\nOCI Image\n    ├── Docker\n    ├── Podman\n    └── containerd\n",[41,154,152],{"__ignoreMap":39},[25,156,158],{"id":157},"_5-oci-runtime-specification","5. OCI Runtime Specification",[18,160,161],{},"Runtime Spec은:",[15,163,164],{},[18,165,166],{},"\"컨테이너를 실제 Linux 프로세스로 어떻게 실행할 것인가?\"",[18,168,169],{},"를 정의",[18,171,172],{},"예를 들어 컨테이너 실행하려면 이런 정보가 필요하다",[18,174,175],{},"어떤 프로그램을 실행할 것인가?",[33,177,180],{"className":178,"code":179,"language":38,"meta":39},[36],"nginx\n",[41,181,179],{"__ignoreMap":39},[18,183,184],{},"어떤 환경변수를 사용할 것인가?",[33,186,189],{"className":187,"code":188,"language":38,"meta":39},[36],"PORT=80\n",[41,190,188],{"__ignoreMap":39},[18,192,193],{},"어떤 namespace를 만들 것인가?",[33,195,198],{"className":196,"code":197,"language":38,"meta":39},[36],"PID Namespace\nNetwork Namespace\nMount Namespace\n",[41,199,197],{"__ignoreMap":39},[18,201,202],{},"어떤 resource 제한을 적용할 것인가?",[33,204,207],{"className":205,"code":206,"language":38,"meta":39},[36],"CPU\nMemory\n",[41,208,206],{"__ignoreMap":39},[18,210,211],{},"이런 실행 정보를 OCI Runtime Spec에서 규정",[18,213,214],{},"대표적인 설정 파일이",[18,216,217],{},[41,218,219],{},"config.json",[18,221,222],{},"개념적으로",[33,224,228],{"className":225,"code":226,"language":227,"meta":39,"style":39},"language-json shiki shiki-themes github-light github-dark","{\n  \"process\": {\n    \"args\": [\"nginx\"]\n  },\n  \"linux\": {\n    \"namespaces\": [\n      \"...\"\n    ]\n  }\n}\n","json",[41,229,230,239,249,265,271,279,288,294,300,306],{"__ignoreMap":39},[231,232,235],"span",{"class":233,"line":234},"line",1,[231,236,238],{"class":237},"sVt8B","{\n",[231,240,242,246],{"class":233,"line":241},2,[231,243,245],{"class":244},"sj4cs","  \"process\"",[231,247,248],{"class":237},": {\n",[231,250,252,255,258,262],{"class":233,"line":251},3,[231,253,254],{"class":244},"    \"args\"",[231,256,257],{"class":237},": [",[231,259,261],{"class":260},"sZZnC","\"nginx\"",[231,263,264],{"class":237},"]\n",[231,266,268],{"class":233,"line":267},4,[231,269,270],{"class":237},"  },\n",[231,272,274,277],{"class":233,"line":273},5,[231,275,276],{"class":244},"  \"linux\"",[231,278,248],{"class":237},[231,280,282,285],{"class":233,"line":281},6,[231,283,284],{"class":244},"    \"namespaces\"",[231,286,287],{"class":237},": [\n",[231,289,291],{"class":233,"line":290},7,[231,292,293],{"class":260},"      \"...\"\n",[231,295,297],{"class":233,"line":296},8,[231,298,299],{"class":237},"    ]\n",[231,301,303],{"class":233,"line":302},9,[231,304,305],{"class":237},"  }\n",[231,307,309],{"class":233,"line":308},10,[231,310,311],{"class":237},"}\n",[18,313,314],{},"이런 정보를 Runtime이 읽는다.",[18,316,317],{},"대표적인 OCI Runtime 구현체가",[18,319,320],{},[41,321,322],{},"runc",[10,324,326],{"id":325},"runc가-중요한-이유","runc가 중요한 이유",[18,328,329],{},"Docker에서",[33,331,335],{"className":332,"code":333,"language":334,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark","docker run nginx\n","bash",[41,336,337],{"__ignoreMap":39},[231,338,339,343,346],{"class":233,"line":234},[231,340,342],{"class":341},"sScJk","docker",[231,344,345],{"class":260}," run",[231,347,348],{"class":260}," nginx\n",[18,350,351],{},"를 실행한다고, Docker가 직접 Linux Namespace와 cgroup을 전부 만드는 구조는 아니다.",[33,353,356],{"className":354,"code":355,"language":38,"meta":39},[36],"사용자\n    │\n    │ docker run nginx\n    ▼\nDocker CLI\n    │\n    ▼\ndockerd\n    │\n    ▼\ncontainerd\n    │\n    ▼\nrunc\n    │\n    ▼\nLinux Kernel\n    ├── Namespace\n    ├── cgroup\n    ├── capabilities\n    └── filesystem\n    │\n    ▼\nnginx process\n",[41,357,355],{"__ignoreMap":39},[18,359,360],{},"여기서",[18,362,363],{},[41,364,322],{},[18,366,367],{},"가 OCI Runtime Specification을 구현한 프로그램이다.",[15,369,370],{},[18,371,372],{},"Docker가 최종적으로 컨테이너라는 특별한 VM을 만드는 것이 아니라, runc를 통해 Linux Kernel 기능을 이용해서 격리된 프로세스를 만들어낸다.",[18,374,375],{},"결국은",[15,377,378],{},[18,379,380],{},"\"컨테이너의 실체는 결국 Linux에서 실행되는 프로세스다\"",[18,382,383],{},"라는 개념을 구현하는 것은 OCI Runtime",[25,385,387],{"id":386},"_6-kubernetes에서도-oci가-사용된다","6. Kubernetes에서도 OCI가 사용된다",[18,389,390],{},"OCI가 중요한 이유는 Docker만의 이야기가 아니기 때문.",[18,392,393],{},"Kubernetes에서 사용되기 때문이다.",[18,395,396],{},"에를 들어 Kubernetes에서 Pod를 생성",[33,398,400],{"className":332,"code":399,"language":334,"meta":39,"style":39},"kubectl apply -f nginx.yaml\n",[41,401,402],{"__ignoreMap":39},[231,403,404,407,410,413],{"class":233,"line":234},[231,405,406],{"class":341},"kubectl",[231,408,409],{"class":260}," apply",[231,411,412],{"class":244}," -f",[231,414,415],{"class":260}," nginx.yaml\n",[18,417,418],{},"라고 하면",[33,420,423],{"className":421,"code":422,"language":38,"meta":39},[36],"kubectl\n    │\n    ▼\nKubernetes API Server\n    │\n    ▼\nkubelet\n    │\n    ▼\nCRI\n    │\n    ▼\ncontainerd\n    │\n    ▼\nOCI Runtime\n    │\n    ▼\nrunc\n    │\n    ▼\nLinux Kernel\n    │\n    ▼\nnginx process\n",[41,424,422],{"__ignoreMap":39},[18,426,427],{},"라고 하면서,",[18,429,430],{},"OCI Runtime을 사용하게 된다.",[25,432,434],{"id":433},"_7-cri와-oci는-다른-것","7. CRI와 OCI는 다른 것",[18,436,437],{},"CRI\nOCI",[439,440,442],"h3",{"id":441},"cri","CRI",[444,445,446],"ul",{},[447,448,449],"li",{},"Container Runtime Interface",[33,451,454],{"className":452,"code":453,"language":38,"meta":39},[36],"Kubernetes\n    ↕\ncontainerd \u002F CRI-O\n",[41,455,453],{"__ignoreMap":39},[15,457,458],{},[18,459,460],{},"Kubernetes와 Container Runtime 사이의 API 규격",[439,462,464],{"id":463},"oci","OCI",[444,466,467],{},[447,468,469],{},"Open Container Initiative",[15,471,472],{},[18,473,474],{},"컨테이너 이미지와 실제 실행 규격",[33,476,479],{"className":477,"code":478,"language":38,"meta":39},[36],"Kubernetes\n    │\n    ▼\nkubelet\n    │ CRI\n    ▼\ncontainerd\n    │ OCI\n    ▼\nrunc\n    │\n    ▼\nLinux Kernel\n",[41,480,478],{"__ignoreMap":39},[25,482,484],{"id":483},"_8-oci가-실제로-어디에-응용","8. OCI가 실제로 어디에 응용?",[18,486,487],{},"OCI 표준 덕분에 다양한 컨테이너 기술이 서로 호환",[18,489,490],{},"Docker\nPodman\ncontainerd\nCRI-0\nKubernetes\nAWS ECS \u002F EKS\nGoogle GKE\nAzure AKS\nGithub Actions\nCI\u002FCD 시스템",[18,492,493],{},"등이 컨테이너 이미지를 다룰 수 있음",[18,495,121],{},[33,497,499],{"className":332,"code":498,"language":334,"meta":39,"style":39},"docker build -t myapp .\n",[41,500,501],{"__ignoreMap":39},[231,502,503,505,508,511,514],{"class":233,"line":234},[231,504,342],{"class":341},[231,506,507],{"class":260}," build",[231,509,510],{"class":244}," -t",[231,512,513],{"class":260}," myapp",[231,515,516],{"class":260}," .\n",[18,518,519],{},"해서 이미지를 만들고 Registry에 올리면",[33,521,524],{"className":522,"code":523,"language":38,"meta":39},[36],"Developer Laptop\n    │ docker build\n    ▼\nOCI Image\n    │\n    ▼\nContainer Registry\n    ├── Docker\n    ├── Kubernetes\n    ├── AWS ECS\n    ├── GKE\n    └── Azure AKS\n",[41,525,523],{"__ignoreMap":39},[18,527,528],{},"어디에서 실행하든 OCI 규격을 이해하기 때문에 동일한 이미지를 사용할 수 있다.",[25,530,532],{"id":531},"_9-docker-registry에서도-oci가-응용","9. Docker Registry에서도 OCI가 응용",[18,534,535],{},"OCI에는 Distribution Specification도 있다.",[18,537,538],{},"이건",[15,540,541],{},[18,542,543],{},"\"컨테이너 이미지를 Registry와 어떻게 주고받을 것인가\"",[18,545,169],{},[33,547,549],{"className":332,"code":548,"language":334,"meta":39,"style":39},"docker pull nginx\n",[41,550,551],{"__ignoreMap":39},[231,552,553,555,558],{"class":233,"line":234},[231,554,342],{"class":341},[231,556,557],{"class":260}," pull",[231,559,348],{"class":260},[33,561,564],{"className":562,"code":563,"language":38,"meta":39},[36],"Docker\n    │ Registry API\n    ▼\nDocker Hub\n    ├── Manifest\n    ├── Config\n    └── Layers\n",[41,565,563],{"__ignoreMap":39},[18,567,568],{},"그래서 다음과 같은 Registry들이 서로 비슷한 방식으로 OCI 이미지를 저장",[18,570,571],{},"Docker Hub",[18,573,574],{},"GitHub Container Registry",[18,576,577],{},"Amazon ECR",[18,579,580],{},"Google Artifact Registry",[18,582,583],{},"Azure Container Registry",[18,585,586],{},"Harbor",[25,588,590],{"id":589},"_10-oci-때문에-docker가-없어도-된다","10. OCI 때문에 Docker가 없어도 된다.",[18,592,593],{},"OCI 표준이 있기 때문에",[33,595,598],{"className":596,"code":597,"language":38,"meta":39},[36],"Docker Build\n    ↓\nOCI Image\n    ├── Podman\n    ├── containerd\n    └── Kubernetes\n",[41,599,597],{"__ignoreMap":39},[18,601,602],{},"처럼 사용할 수 있다.",[18,604,605],{},"이는 Vendor Lock-in을 줄이는 역할을 한다.",[25,607,608],{"id":608},"결론",[33,610,613],{"className":611,"code":612,"language":38,"meta":39},[36],"Docker CLI\n    │\n    ▼\ndockerd\n    │\n    ▼\ncontainerd\n    │ OCI Runtime Specification\n    ▼\nrunc\n    │\n    ▼\nLinux Kernel\n    ├── Namespace\n    ├── cgroup\n    └── capability\n    │\n    ▼\nContainer\n(= isolated process)\n",[41,614,612],{"__ignoreMap":39},[18,616,617],{},"이미지는",[33,619,622],{"className":620,"code":621,"language":38,"meta":39},[36],"Dockerfile\n    │\n    ▼\ndocker build\n    │\n    ▼\nOCI Image\n    ├── Manifest\n    ├── Config\n    └── Layers\n    │\n    ▼\nContainer Registry\n    │\n    ▼\ncontainerd\n    │\n    ▼\nrunc\n    │\n    ▼\nLinux Process\n",[41,623,621],{"__ignoreMap":39},[18,625,626],{},"면접에서 나온다면 ...",[18,628,629],{},"OCI는 Open Container Initiative로, 컨테이너 이미지 형식과 컨테이너 실행 방식 등을 표준화한 규격입니다. 대표적으로 OCI Image Spec, Runtime Spec, Distribution Spec이 있습니다. Docker나 Kubernetes 생태계에서 서로 다른 Runtime과 Registry가 동일한 컨테이너 이미지를 호환해서 사용할 수 있도록 해줍니다. 대표적인 OCI Runtime 구현체가 runc입니다.",[33,631,634],{"className":632,"code":633,"language":38,"meta":39},[36],"Docker       = 컨테이너를 사용하는 플랫폼\ncontainerd   = 컨테이너 생명주기 관리자\nOCI          = 컨테이너 표준 규격\nrunc         = OCI Runtime 규격 구현체\nLinux Kernel = 실제 격리를 수행하는 주체\nContainer    = 결국 격리된 Linux Process\n",[41,635,633],{"__ignoreMap":39},[18,637,638],{},"여기까지 연결하면",[33,640,643],{"className":641,"code":642,"language":38,"meta":39},[36],"Kubernetes\n    ↓\nCRI\n    ↓\ncontainerd\n    ↓\nOCI\n    ↓\nrunc\n    ↓\nLinux Kernel\n    ↓\nProcess\n",[41,644,642],{"__ignoreMap":39},[646,647,648],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":39,"searchDepth":241,"depth":241,"links":650},[651,652],{"id":12,"depth":241,"text":13},{"id":325,"depth":241,"text":326,"children":653},[654,655],{"id":441,"depth":251,"text":442},{"id":463,"depth":251,"text":464},[657,658],"DevOps","Docker","2026-08-24 00:50:00 +0900","OCI가 등장한 배경과 Image, Runtime, Distribution Specification의 역할, Docker와 Kubernetes에서 OCI가 사용되는 흐름을 정리한다.","md",null,"\u002Fdevops\u002Fdocker\u002F2026\u002F08\u002F24\u002Foci-container-standard\u002F",{"layout":665},"post",true,"\u002Fposts\u002Fci-cd-docker\u002Fdocker\u002F2026-08-24-oci-container-standard",{"title":5,"description":660},"posts\u002FCI-CD-Docker\u002FDocker\u002F2026-08-24-oci-container-standard",[464,658,671,672,322,673],"Container","containerd","Kubernetes","GD04k44V_tB5aaBoBZIQft2M7VdUcfGSFCHnQxmR9ck",1788744788004]