[{"data":1,"prerenderedAt":1308},["ShallowReactive",2],{"post-document:\u002Fdevops\u002Fdocker\u002F2026\u002F08\u002F17\u002Fdocker-10-compose-basics-and-build\u002F":3},{"id":4,"title":5,"body":6,"categories":1287,"date":1290,"description":1291,"extension":1292,"image":1293,"key_concepts":1293,"last_modified_at":1293,"legacyPath":1294,"meta":1295,"navigation":535,"part":1297,"path":1298,"published":535,"robots":1293,"seo":1299,"series":1300,"stem":1301,"strengths":1293,"summary":1293,"tags":1302,"tradeoffs":1293,"__hash__":1307},"posts\u002Fposts\u002FCI-CD-Docker\u002FDocker\u002F2026-08-17-docker-10-compose-basics-and-build.md","Docker 기초 10편: Compose 기본 구조와 이미지 빌드",{"type":7,"value":8,"toc":1269},"minimark",[9,13,67,76,79,82,87,92,181,185,188,196,203,227,230,255,259,267,292,317,320,322,326,329,447,460,464,658,665,669,713,716,722,733,735,739,742,845,862,866,872,899,904,988,994,1034,1062,1065,1074,1077,1092,1103,1152,1166,1221,1260,1263,1265],[10,11,12],"p",{},"Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 하나의 YAML 파일로 정의하고, 한 번의 명령으로 함께 실행,중지,관리하는 도구.",[14,15,20],"pre",{"className":16,"code":17,"language":18,"meta":19,"style":19},"language-mermaid shiki shiki-themes github-light github-dark","flowchart LR\n    Y[\"compose.yaml\u003Cbr\u002F>애플리케이션 구성도\"] -->|docker compose up| D[\"Docker Engine\"]\n    D --> F[\"frontend container\"]\n    D --> B[\"backend container\"]\n    D --> DB[\"database container\"]\n    D --> N[\"network\"]\n    D --> V[\"volume\"]\n","mermaid","",[21,22,23,31,37,43,49,55,61],"code",{"__ignoreMap":19},[24,25,28],"span",{"class":26,"line":27},"line",1,[24,29,30],{},"flowchart LR\n",[24,32,34],{"class":26,"line":33},2,[24,35,36],{},"    Y[\"compose.yaml\u003Cbr\u002F>애플리케이션 구성도\"] -->|docker compose up| D[\"Docker Engine\"]\n",[24,38,40],{"class":26,"line":39},3,[24,41,42],{},"    D --> F[\"frontend container\"]\n",[24,44,46],{"class":26,"line":45},4,[24,47,48],{},"    D --> B[\"backend container\"]\n",[24,50,52],{"class":26,"line":51},5,[24,53,54],{},"    D --> DB[\"database container\"]\n",[24,56,58],{"class":26,"line":57},6,[24,59,60],{},"    D --> N[\"network\"]\n",[24,62,64],{"class":26,"line":63},7,[24,65,66],{},"    D --> V[\"volume\"]\n",[68,69,70],"blockquote",{},[10,71,72,75],{},[21,73,74],{},"docker run","이 가전제품을 하나씩 직접 설치하는 일이라면, Docker Compose는 집 전체의 가전제품,배선,수도 연결을 설계도 한 장으로 한꺼번에 설치하는 작업.",[10,77,78],{},"Compose는 여러 컨테이너를 편리하게 조율하지만, Kubernetes처럼 여러 노드에 컨테이너를 스케줄링하고 장애 시 자동으로 재배치하는 완전한 클러스터 오케스트레이터는 아니고. 로컬 개발, 교육, 통합 테스트, 단일 Docker 호스트 애플리케이션에 특히 적합하다.",[80,81],"hr",{},[83,84,86],"h2",{"id":85},"_1-docker-compose-핵심-개념","1. Docker Compose 핵심 개념",[88,89,91],"h3",{"id":90},"먼저-알아둘-단어","먼저 알아둘 단어",[93,94,95,111],"table",{},[96,97,98],"thead",{},[99,100,101,105,108],"tr",{},[102,103,104],"th",{},"단어",[102,106,107],{},"뜻",[102,109,110],{},"쉬운 비유",[112,113,114,126,137,148,159,170],"tbody",{},[99,115,116,120,123],{},[117,118,119],"td",{},"Compose file",[117,121,122],{},"서비스,네트워크,볼륨 구성을 선언한 YAML 파일",[117,124,125],{},"건물 설계도",[99,127,128,131,134],{},[117,129,130],{},"Service",[117,132,133],{},"동일한 설정으로 실행할 컨테이너의 논리적 정의",[117,135,136],{},"식당의 주방,홀,창고 역할",[99,138,139,142,145],{},[117,140,141],{},"Project",[117,143,144],{},"하나의 Compose 애플리케이션에 속한 리소스 묶음",[117,146,147],{},"건물 단지 이름",[99,149,150,153,156],{},[117,151,152],{},"Network",[117,154,155],{},"서비스끼리 통신하는 가상 네트워크",[117,157,158],{},"건물 내부 통로",[99,160,161,164,167],{},[117,162,163],{},"Volume",[117,165,166],{},"컨테이너가 사라져도 데이터를 보존하는 저장소",[117,168,169],{},"별도 창고",[99,171,172,175,178],{},[117,173,174],{},"Declarative",[117,176,177],{},"원하는 최종 상태를 파일에 선언하는 방식",[117,179,180],{},"작업 순서 대신 완성 도면 전달",[88,182,184],{"id":183},"_11-compose가-필요한-이유","1.1 Compose가 필요한 이유",[10,186,187],{},"Compose 없이 세 개의 컨테이너를 실행하려면 네트워크와 볼륨을 만들고, 각 컨테이너에 환경 변수와 포트를 반복해서 지정해야 한다.",[14,189,194],{"className":190,"code":192,"language":193,"meta":19},[191],"language-text","docker network create ...\ndocker volume create ...\ndocker run ... database\ndocker run ... backend\ndocker run ... frontend\n","text",[21,195,192],{"__ignoreMap":19},[10,197,198,199,202],{},"Compose에서는 이 구성을 ",[21,200,201],{},"compose.yaml","에 저장한 뒤 다음 명령으로 실행한다.",[14,204,208],{"className":205,"code":206,"language":207,"meta":19,"style":19},"language-bash shiki shiki-themes github-light github-dark","docker compose up -d\n","bash",[21,209,210],{"__ignoreMap":19},[24,211,212,216,220,223],{"class":26,"line":27},[24,213,215],{"class":214},"sScJk","docker",[24,217,219],{"class":218},"sZZnC"," compose",[24,221,222],{"class":218}," up",[24,224,226],{"class":225},"sj4cs"," -d\n",[10,228,229],{},"Compose가 관리하는 대표 항목은 다음과 같다.",[231,232,233,237,240,243,246,249,252],"ul",{},[234,235,236],"li",{},"컨테이너 이미지 또는 빌드 방법",[234,238,239],{},"환경 변수와 Secret",[234,241,242],{},"서비스 간 네트워크",[234,244,245],{},"호스트에 공개할 포트",[234,247,248],{},"Volume과 Bind Mount",[234,250,251],{},"시작 의존 관계와 Healthcheck",[234,253,254],{},"재시작 정책",[88,256,258],{"id":257},"_12-서비스와-컨테이너의-관계","1.2 서비스와 컨테이너의 관계",[10,260,261,262,266],{},"서비스는 ",[263,264,265],"strong",{},"컨테이너 그 자체가 아니라 컨테이너 실행 설정","이다. 기본적으로 서비스당 컨테이너 하나가 만들어지지만, 필요하면 같은 서비스의 컨테이너 수를 늘릴 수 있다.",[14,268,270],{"className":205,"code":269,"language":207,"meta":19,"style":19},"docker compose up -d --scale worker=3\n",[21,271,272],{"__ignoreMap":19},[24,273,274,276,278,280,283,286,289],{"class":26,"line":27},[24,275,215],{"class":214},[24,277,219],{"class":218},[24,279,222],{"class":218},[24,281,282],{"class":225}," -d",[24,284,285],{"class":225}," --scale",[24,287,288],{"class":218}," worker=",[24,290,291],{"class":225},"3\n",[14,293,295],{"className":16,"code":294,"language":18,"meta":19,"style":19},"flowchart TD\n    S[\"worker service\u003Cbr\u002F>공통 실행 설정\"] --> C1[\"worker container 1\"]\n    S --> C2[\"worker container 2\"]\n    S --> C3[\"worker container 3\"]\n",[21,296,297,302,307,312],{"__ignoreMap":19},[24,298,299],{"class":26,"line":27},[24,300,301],{},"flowchart TD\n",[24,303,304],{"class":26,"line":33},[24,305,306],{},"    S[\"worker service\u003Cbr\u002F>공통 실행 설정\"] --> C1[\"worker container 1\"]\n",[24,308,309],{"class":26,"line":39},[24,310,311],{},"    S --> C2[\"worker container 2\"]\n",[24,313,314],{"class":26,"line":45},[24,315,316],{},"    S --> C3[\"worker container 3\"]\n",[10,318,319],{},"고정된 호스트 포트를 사용하는 서비스를 여러 개로 확장하면 포트 충돌이 발생할 수 있다. 여러 복제본 앞에는 별도의 프록시나 로드 밸런서가 필요할 수 있다.",[80,321],{},[83,323,325],{"id":324},"_2-composeyaml-구조","2. compose.yaml 구조",[88,327,91],{"id":328},"먼저-알아둘-단어-1",[93,330,331,341],{},[96,332,333],{},[99,334,335,337,339],{},[102,336,104],{},[102,338,107],{},[102,340,110],{},[112,342,343,356,369,382,395,408,421,434],{},[99,344,345,350,353],{},[117,346,347],{},[21,348,349],{},"services",[117,351,352],{},"실행할 서비스 정의",[117,354,355],{},"입주 업체 목록",[99,357,358,363,366],{},[117,359,360],{},[21,361,362],{},"image",[117,364,365],{},"컨테이너를 만들 이미지",[117,367,368],{},"완제품 주문",[99,370,371,376,379],{},[117,372,373],{},[21,374,375],{},"build",[117,377,378],{},"이미지를 직접 만드는 방법",[117,380,381],{},"현장에서 제품 제작",[99,383,384,389,392],{},[117,385,386],{},[21,387,388],{},"ports",[117,390,391],{},"호스트 포트와 컨테이너 포트 연결",[117,393,394],{},"대표번호를 내선에 연결",[99,396,397,402,405],{},[117,398,399],{},[21,400,401],{},"environment",[117,403,404],{},"컨테이너 프로세스에 전달할 환경 변수",[117,406,407],{},"작업자에게 전달하는 업무 메모",[99,409,410,415,418],{},[117,411,412],{},[21,413,414],{},"volumes",[117,416,417],{},"데이터 또는 파일 마운트",[117,419,420],{},"외부 창고 연결",[99,422,423,428,431],{},[117,424,425],{},[21,426,427],{},"networks",[117,429,430],{},"서비스가 참여할 네트워크",[117,432,433],{},"출입 가능한 통로 지정",[99,435,436,441,444],{},[117,437,438],{},[21,439,440],{},"depends_on",[117,442,443],{},"서비스 생성,시작 의존 관계",[117,445,446],{},"선행 작업 확인표",[68,448,449],{},[10,450,451,452,454,455,454,457,459],{},"쉬운 비유: 최상위 ",[21,453,349],{},", ",[21,456,427],{},[21,458,414],{},"는 각각 입주자, 도로, 창고를 정의하는 설계도 영역.",[88,461,463],{"id":462},"_21-최소-예제","2.1 최소 예제",[14,465,469],{"className":466,"code":467,"language":468,"meta":19,"style":19},"language-yaml shiki shiki-themes github-light github-dark","services:\n  db:\n    image: postgres:15\n    environment:\n      POSTGRES_PASSWORD: postgres\n    volumes:\n      - db-data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n\n  backend:\n    image: my-backend:1.0\n    environment:\n      DB_HOST: db\n      DB_PORT: \"5432\"\n    depends_on:\n      - db\n\n  frontend:\n    image: my-frontend:1.0\n    ports:\n      - \"8080:80\"\n\nvolumes:\n  db-data:\n","yaml",[21,470,471,480,487,498,505,515,522,530,537,545,555,562,573,584,592,599,604,612,622,630,638,643,650],{"__ignoreMap":19},[24,472,473,476],{"class":26,"line":27},[24,474,349],{"class":475},"s9eBZ",[24,477,479],{"class":478},"sVt8B",":\n",[24,481,482,485],{"class":26,"line":33},[24,483,484],{"class":475},"  db",[24,486,479],{"class":478},[24,488,489,492,495],{"class":26,"line":39},[24,490,491],{"class":475},"    image",[24,493,494],{"class":478},": ",[24,496,497],{"class":218},"postgres:15\n",[24,499,500,503],{"class":26,"line":45},[24,501,502],{"class":475},"    environment",[24,504,479],{"class":478},[24,506,507,510,512],{"class":26,"line":51},[24,508,509],{"class":475},"      POSTGRES_PASSWORD",[24,511,494],{"class":478},[24,513,514],{"class":218},"postgres\n",[24,516,517,520],{"class":26,"line":57},[24,518,519],{"class":475},"    volumes",[24,521,479],{"class":478},[24,523,524,527],{"class":26,"line":63},[24,525,526],{"class":478},"      - ",[24,528,529],{"class":218},"db-data:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\n",[24,531,533],{"class":26,"line":532},8,[24,534,536],{"emptyLinePlaceholder":535},true,"\n",[24,538,540,543],{"class":26,"line":539},9,[24,541,542],{"class":475},"  backend",[24,544,479],{"class":478},[24,546,548,550,552],{"class":26,"line":547},10,[24,549,491],{"class":475},[24,551,494],{"class":478},[24,553,554],{"class":218},"my-backend:1.0\n",[24,556,558,560],{"class":26,"line":557},11,[24,559,502],{"class":475},[24,561,479],{"class":478},[24,563,565,568,570],{"class":26,"line":564},12,[24,566,567],{"class":475},"      DB_HOST",[24,569,494],{"class":478},[24,571,572],{"class":218},"db\n",[24,574,576,579,581],{"class":26,"line":575},13,[24,577,578],{"class":475},"      DB_PORT",[24,580,494],{"class":478},[24,582,583],{"class":218},"\"5432\"\n",[24,585,587,590],{"class":26,"line":586},14,[24,588,589],{"class":475},"    depends_on",[24,591,479],{"class":478},[24,593,595,597],{"class":26,"line":594},15,[24,596,526],{"class":478},[24,598,572],{"class":218},[24,600,602],{"class":26,"line":601},16,[24,603,536],{"emptyLinePlaceholder":535},[24,605,607,610],{"class":26,"line":606},17,[24,608,609],{"class":475},"  frontend",[24,611,479],{"class":478},[24,613,615,617,619],{"class":26,"line":614},18,[24,616,491],{"class":475},[24,618,494],{"class":478},[24,620,621],{"class":218},"my-frontend:1.0\n",[24,623,625,628],{"class":26,"line":624},19,[24,626,627],{"class":475},"    ports",[24,629,479],{"class":478},[24,631,633,635],{"class":26,"line":632},20,[24,634,526],{"class":478},[24,636,637],{"class":218},"\"8080:80\"\n",[24,639,641],{"class":26,"line":640},21,[24,642,536],{"emptyLinePlaceholder":535},[24,644,646,648],{"class":26,"line":645},22,[24,647,414],{"class":475},[24,649,479],{"class":478},[24,651,653,656],{"class":26,"line":652},23,[24,654,655],{"class":475},"  db-data",[24,657,479],{"class":478},[10,659,660,661,664],{},"들여쓰기가 구조를 결정하므로 Tab 대신 공백을 사용해야 한다. 최신 Compose Specification에서는 최상위 ",[21,662,663],{},"version"," 필드가 필요하지 않다.",[88,666,668],{"id":667},"_22-전체-구조","2.2 전체 구조",[14,670,672],{"className":16,"code":671,"language":18,"meta":19,"style":19},"flowchart TD\n    C[\"Compose Project\"] --> S[\"services\"]\n    C --> N[\"networks\"]\n    C --> V[\"volumes\"]\n    C --> SEC[\"secrets\"]\n    S --> DB[\"db\"]\n    S --> API[\"backend\"]\n    S --> WEB[\"frontend\"]\n",[21,673,674,678,683,688,693,698,703,708],{"__ignoreMap":19},[24,675,676],{"class":26,"line":27},[24,677,301],{},[24,679,680],{"class":26,"line":33},[24,681,682],{},"    C[\"Compose Project\"] --> S[\"services\"]\n",[24,684,685],{"class":26,"line":39},[24,686,687],{},"    C --> N[\"networks\"]\n",[24,689,690],{"class":26,"line":45},[24,691,692],{},"    C --> V[\"volumes\"]\n",[24,694,695],{"class":26,"line":51},[24,696,697],{},"    C --> SEC[\"secrets\"]\n",[24,699,700],{"class":26,"line":57},[24,701,702],{},"    S --> DB[\"db\"]\n",[24,704,705],{"class":26,"line":63},[24,706,707],{},"    S --> API[\"backend\"]\n",[24,709,710],{"class":26,"line":532},[24,711,712],{},"    S --> WEB[\"frontend\"]\n",[10,714,715],{},"Compose는 별도로 지정하지 않으면 현재 디렉터리 이름을 프로젝트 이름으로 사용한다. 생성되는 리소스에는 일반적으로 프로젝트 이름이 접두사로 붙는다.",[14,717,720],{"className":718,"code":719,"language":193,"meta":19},[191],"myapp_default\nmyapp-db-1\nmyapp_db-data\n",[21,721,719],{"__ignoreMap":19},[10,723,724,725,728,729,732],{},"실제 이름은 Compose 버전, 설정한 ",[21,726,727],{},"container_name",", 리소스 종류에 따라 달라질 수 있다. 서비스 검색에는 컨테이너 이름보다 ",[263,730,731],{},"서비스 이름","을 사용하는 것이 좋다.",[80,734],{},[83,736,738],{"id":737},"_3-이미지-빌드와-실행-명령","3. 이미지 빌드와 실행 명령",[88,740,91],{"id":741},"먼저-알아둘-단어-2",[93,743,744,754],{},[96,745,746],{},[99,747,748,750,752],{},[102,749,104],{},[102,751,107],{},[102,753,110],{},[112,755,756,767,778,789,802,815,831],{},[99,757,758,761,764],{},[117,759,760],{},"Build Context",[117,762,763],{},"이미지 빌더에 전달할 파일 범위",[117,765,766],{},"공장에 보내는 재료 상자",[99,768,769,772,775],{},[117,770,771],{},"Dockerfile",[117,773,774],{},"이미지를 만드는 절차",[117,776,777],{},"제품 조립 설명서",[99,779,780,783,786],{},[117,781,782],{},"Build Argument",[117,784,785],{},"이미지 빌드 중에만 사용하는 값",[117,787,788],{},"제조 공정용 임시 지시사항",[99,790,791,796,799],{},[117,792,793],{},[21,794,795],{},"ENTRYPOINT",[117,797,798],{},"컨테이너의 기본 실행 프로그램",[117,800,801],{},"반드시 실행할 본체",[99,803,804,809,812],{},[117,805,806],{},[21,807,808],{},"CMD",[117,810,811],{},"기본 명령 또는 기본 인자",[117,813,814],{},"본체에 전달하는 기본 옵션",[99,816,817,822,828],{},[117,818,819],{},[21,820,821],{},"command",[117,823,824,825,827],{},"Compose에서 이미지의 ",[21,826,808],{},"를 대체하는 값",[117,829,830],{},"기본 옵션 교체",[99,832,833,838,842],{},[117,834,835],{},[21,836,837],{},"entrypoint",[117,839,824,840,827],{},[21,841,795],{},[117,843,844],{},"실행 본체 교체",[68,846,847],{},[10,848,849,850,852,853,855,856,858,859,861],{},"쉬운 비유: ",[21,851,795],{},"가 커피 머신이라면 ",[21,854,808],{},"는 기본 메뉴인 아메리카노. ",[21,857,821],{},"는 메뉴를 라테로 바꾸고, ",[21,860,837],{},"는 커피 머신 자체를 다른 기계로 교체한다.",[88,863,865],{"id":864},"_31-기존-이미지-사용과-직접-빌드","3.1 기존 이미지 사용과 직접 빌드",[10,867,868,869,871],{},"Registry의 이미지를 그대로 사용할 때는 ",[21,870,362],{},"를 지정한다.",[14,873,875],{"className":466,"code":874,"language":468,"meta":19,"style":19},"services:\n  web:\n    image: nginx:alpine\n",[21,876,877,883,890],{"__ignoreMap":19},[24,878,879,881],{"class":26,"line":27},[24,880,349],{"class":475},[24,882,479],{"class":478},[24,884,885,888],{"class":26,"line":33},[24,886,887],{"class":475},"  web",[24,889,479],{"class":478},[24,891,892,894,896],{"class":26,"line":39},[24,893,491],{"class":475},[24,895,494],{"class":478},[24,897,898],{"class":218},"nginx:alpine\n",[10,900,901,902,871],{},"로컬 Dockerfile로 이미지를 만들 때는 ",[21,903,375],{},[14,905,907],{"className":466,"code":906,"language":468,"meta":19,"style":19},"services:\n  app:\n    build:\n      context: .\u002Fapp\n      dockerfile: Dockerfile.prod\n      args:\n        APP_ENV: production\n    image: myapp:1.0\n    ports:\n      - \"8080:8080\"\n",[21,908,909,915,922,929,939,949,956,966,975,981],{"__ignoreMap":19},[24,910,911,913],{"class":26,"line":27},[24,912,349],{"class":475},[24,914,479],{"class":478},[24,916,917,920],{"class":26,"line":33},[24,918,919],{"class":475},"  app",[24,921,479],{"class":478},[24,923,924,927],{"class":26,"line":39},[24,925,926],{"class":475},"    build",[24,928,479],{"class":478},[24,930,931,934,936],{"class":26,"line":45},[24,932,933],{"class":475},"      context",[24,935,494],{"class":478},[24,937,938],{"class":218},".\u002Fapp\n",[24,940,941,944,946],{"class":26,"line":51},[24,942,943],{"class":475},"      dockerfile",[24,945,494],{"class":478},[24,947,948],{"class":218},"Dockerfile.prod\n",[24,950,951,954],{"class":26,"line":57},[24,952,953],{"class":475},"      args",[24,955,479],{"class":478},[24,957,958,961,963],{"class":26,"line":63},[24,959,960],{"class":475},"        APP_ENV",[24,962,494],{"class":478},[24,964,965],{"class":218},"production\n",[24,967,968,970,972],{"class":26,"line":532},[24,969,491],{"class":475},[24,971,494],{"class":478},[24,973,974],{"class":218},"myapp:1.0\n",[24,976,977,979],{"class":26,"line":539},[24,978,627],{"class":475},[24,980,479],{"class":478},[24,982,983,985],{"class":26,"line":547},[24,984,526],{"class":478},[24,986,987],{"class":218},"\"8080:8080\"\n",[14,989,992],{"className":990,"code":991,"language":193,"meta":19},[191],"project\u002F\n├── compose.yaml\n└── app\u002F\n    ├── Dockerfile.prod\n    └── app.jar\n",[21,993,991],{"__ignoreMap":19},[14,995,999],{"className":996,"code":997,"language":998,"meta":19,"style":19},"language-dockerfile shiki shiki-themes github-light github-dark","FROM eclipse-temurin:17-jre\n\nARG APP_ENV\nENV APP_ENV=${APP_ENV}\n\nCOPY app.jar \u002Fapp\u002Fapp.jar\nENTRYPOINT [\"java\", \"-jar\", \"\u002Fapp\u002Fapp.jar\"]\n","dockerfile",[21,1000,1001,1006,1010,1015,1020,1024,1029],{"__ignoreMap":19},[24,1002,1003],{"class":26,"line":27},[24,1004,1005],{},"FROM eclipse-temurin:17-jre\n",[24,1007,1008],{"class":26,"line":33},[24,1009,536],{"emptyLinePlaceholder":535},[24,1011,1012],{"class":26,"line":39},[24,1013,1014],{},"ARG APP_ENV\n",[24,1016,1017],{"class":26,"line":45},[24,1018,1019],{},"ENV APP_ENV=${APP_ENV}\n",[24,1021,1022],{"class":26,"line":51},[24,1023,536],{"emptyLinePlaceholder":535},[24,1025,1026],{"class":26,"line":57},[24,1027,1028],{},"COPY app.jar \u002Fapp\u002Fapp.jar\n",[24,1030,1031],{"class":26,"line":63},[24,1032,1033],{},"ENTRYPOINT [\"java\", \"-jar\", \"\u002Fapp\u002Fapp.jar\"]\n",[231,1035,1036,1042,1047,1057],{},[234,1037,1038,1041],{},[21,1039,1040],{},"context: .\u002Fapp",": 빌더에 전달할 디렉터리.",[234,1043,1044,1046],{},[21,1045,998],{},": Context를 기준으로 사용할 Dockerfile 경로.",[234,1048,1049,1052,1053,1056],{},[21,1050,1051],{},"args",": Dockerfile의 ",[21,1054,1055],{},"ARG","에 전달할 빌드 시점 값.",[234,1058,1059,1061],{},[21,1060,362],{},": 빌드 결과에 붙일 이미지 이름과 태그.",[10,1063,1064],{},"Build Argument는 비밀값 전달 수단이 아니다. 이미지 이력이나 빌드 캐시에 남을 수 있으므로 비밀번호와 토큰을 넣지 않아야 한다.",[88,1066,1068,1069,1071,1072],{"id":1067},"_32-command와-entrypoint","3.2 ",[21,1070,821],{},"와 ",[21,1073,837],{},[10,1075,1076],{},"이미지에 다음 설정이 있다고 가정합니다.",[14,1078,1080],{"className":996,"code":1079,"language":998,"meta":19,"style":19},"ENTRYPOINT [\"docker-entrypoint.sh\"]\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n",[21,1081,1082,1087],{"__ignoreMap":19},[24,1083,1084],{"class":26,"line":27},[24,1085,1086],{},"ENTRYPOINT [\"docker-entrypoint.sh\"]\n",[24,1088,1089],{"class":26,"line":33},[24,1090,1091],{},"CMD [\"nginx\", \"-g\", \"daemon off;\"]\n",[10,1093,1094,1096,1097,1099,1100,1102],{},[21,1095,821],{},"만 지정하면 이미지의 ",[21,1098,808],{},"를 대체하고 ",[21,1101,795],{},"는 유지한다.",[14,1104,1106],{"className":466,"code":1105,"language":468,"meta":19,"style":19},"services:\n  web:\n    image: nginx:alpine\n    command: [\"nginx\", \"-g\", \"daemon off;\"]\n",[21,1107,1108,1114,1120,1128],{"__ignoreMap":19},[24,1109,1110,1112],{"class":26,"line":27},[24,1111,349],{"class":475},[24,1113,479],{"class":478},[24,1115,1116,1118],{"class":26,"line":33},[24,1117,887],{"class":475},[24,1119,479],{"class":478},[24,1121,1122,1124,1126],{"class":26,"line":39},[24,1123,491],{"class":475},[24,1125,494],{"class":478},[24,1127,898],{"class":218},[24,1129,1130,1133,1136,1139,1141,1144,1146,1149],{"class":26,"line":45},[24,1131,1132],{"class":475},"    command",[24,1134,1135],{"class":478},": [",[24,1137,1138],{"class":218},"\"nginx\"",[24,1140,454],{"class":478},[24,1142,1143],{"class":218},"\"-g\"",[24,1145,454],{"class":478},[24,1147,1148],{"class":218},"\"daemon off;\"",[24,1150,1151],{"class":478},"]\n",[10,1153,1154,1156,1157,1159,1160,1162,1163,1165],{},[21,1155,837],{},"를 지정하면 이미지의 ",[21,1158,795],{},"를 대체한다. Compose에서는 이미지의 기본 ",[21,1161,808],{},"도 무시되므로 필요한 인자를 ",[21,1164,821],{},"로 명시해야 한다.",[14,1167,1169],{"className":466,"code":1168,"language":468,"meta":19,"style":19},"services:\n  web:\n    image: nginx:alpine\n    entrypoint: [\"\u002Fcustom-entrypoint.sh\"]\n    command: [\"nginx\", \"-g\", \"daemon off;\"]\n",[21,1170,1171,1177,1183,1191,1203],{"__ignoreMap":19},[24,1172,1173,1175],{"class":26,"line":27},[24,1174,349],{"class":475},[24,1176,479],{"class":478},[24,1178,1179,1181],{"class":26,"line":33},[24,1180,887],{"class":475},[24,1182,479],{"class":478},[24,1184,1185,1187,1189],{"class":26,"line":39},[24,1186,491],{"class":475},[24,1188,494],{"class":478},[24,1190,898],{"class":218},[24,1192,1193,1196,1198,1201],{"class":26,"line":45},[24,1194,1195],{"class":475},"    entrypoint",[24,1197,1135],{"class":478},[24,1199,1200],{"class":218},"\"\u002Fcustom-entrypoint.sh\"",[24,1202,1151],{"class":478},[24,1204,1205,1207,1209,1211,1213,1215,1217,1219],{"class":26,"line":51},[24,1206,1132],{"class":475},[24,1208,1135],{"class":478},[24,1210,1138],{"class":218},[24,1212,454],{"class":478},[24,1214,1143],{"class":218},[24,1216,454],{"class":478},[24,1218,1148],{"class":218},[24,1220,1151],{"class":478},[14,1222,1224],{"className":16,"code":1223,"language":18,"meta":19,"style":19},"flowchart LR\n    I[\"Image 설정\"] --> EP[\"ENTRYPOINT\u003Cbr\u002F>실행 파일\"]\n    I --> CMD[\"CMD\u003Cbr\u002F>기본 명령,인자\"]\n    CE[\"Compose entrypoint\"] -. 대체 .-> EP\n    CC[\"Compose command\"] -. 대체 .-> CMD\n    EP --> RUN[\"최종 실행 명령\"]\n    CMD --> RUN\n",[21,1225,1226,1230,1235,1240,1245,1250,1255],{"__ignoreMap":19},[24,1227,1228],{"class":26,"line":27},[24,1229,30],{},[24,1231,1232],{"class":26,"line":33},[24,1233,1234],{},"    I[\"Image 설정\"] --> EP[\"ENTRYPOINT\u003Cbr\u002F>실행 파일\"]\n",[24,1236,1237],{"class":26,"line":39},[24,1238,1239],{},"    I --> CMD[\"CMD\u003Cbr\u002F>기본 명령,인자\"]\n",[24,1241,1242],{"class":26,"line":45},[24,1243,1244],{},"    CE[\"Compose entrypoint\"] -. 대체 .-> EP\n",[24,1246,1247],{"class":26,"line":51},[24,1248,1249],{},"    CC[\"Compose command\"] -. 대체 .-> CMD\n",[24,1251,1252],{"class":26,"line":57},[24,1253,1254],{},"    EP --> RUN[\"최종 실행 명령\"]\n",[24,1256,1257],{"class":26,"line":63},[24,1258,1259],{},"    CMD --> RUN\n",[10,1261,1262],{},"배열 형태는 Shell의 문자열 해석 차이를 줄여 주므로 실행 파일과 인자가 명확할 때 유용하다.",[80,1264],{},[1266,1267,1268],"style",{},"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}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":19,"searchDepth":33,"depth":33,"links":1270},[1271,1276,1281],{"id":85,"depth":33,"text":86,"children":1272},[1273,1274,1275],{"id":90,"depth":39,"text":91},{"id":183,"depth":39,"text":184},{"id":257,"depth":39,"text":258},{"id":324,"depth":33,"text":325,"children":1277},[1278,1279,1280],{"id":328,"depth":39,"text":91},{"id":462,"depth":39,"text":463},{"id":667,"depth":39,"text":668},{"id":737,"depth":33,"text":738,"children":1282},[1283,1284,1285],{"id":741,"depth":39,"text":91},{"id":864,"depth":39,"text":865},{"id":1067,"depth":39,"text":1286},"3.2 command와 entrypoint",[1288,1289],"DevOps","Docker","2026-08-17 12:45:00 +0900","Docker Compose의 핵심 개념, compose.yaml 구조, 이미지 빌드와 command 및 entrypoint를 정리한다.","md",null,"\u002Fdevops\u002Fdocker\u002F2026\u002F08\u002F17\u002Fdocker-10-compose-basics-and-build\u002F",{"layout":1296},"post","10","\u002Fposts\u002Fci-cd-docker\u002Fdocker\u002F2026-08-17-docker-10-compose-basics-and-build",{"title":5,"description":1291},"Docker 기초","posts\u002FCI-CD-Docker\u002FDocker\u002F2026-08-17-docker-10-compose-basics-and-build",[1289,1303,130,1304,1305,1306],"Docker Compose","YAML","Build","Entrypoint","DtlUNHwjyeOnakwOy6Ko9nD8JavW5DptJByFha2L-JQ",1788744787872]