PageSourceSearch

https://caprover.com/assets/js/bc52432b.c261b225.js

js caprover.com collected 2026-10-03 19:24:24 UTC 6,714 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkcaprover_docs_site=self.webpackChunkcaprover_docs_site||[]).push([["7157"],{6176(e,n,i){i.r(n),i.d(n,{metadata:()=>o,default:()=>p,frontMatter:()=>r,contentTitle:()=>s,toc:()=>l,assets:()=>c});var o=JSON.parse('{"id":"captain-definition-file","title":"Captain Definition File","description":"Basics","source":"@site/../content/en/docs/captain-definition-file.md","sourceDirName":".","slug":"/captain-definition-file","permalink":"/docs/captain-definition-file","draft":false,"unlisted":false,"editUrl":"https://github.com/caprover/caprover-website/edit/master/content/en/docs/captain-definition-file.md","tags":[],"version":"current","frontMatter":{"id":"captain-definition-file","title":"Captain Definition File","sidebar_label":"Captain Definition File"},"sidebar":"docs","previous":{"title":"CaptainDuckDuck Upgrade","permalink":"/docs/cdd-migration"},"next":{"title":"Deployment Methods","permalink":"/docs/deployment-methods"}}'),t=i(4848),a=i(8453);let r={id:"captain-definition-file",title:"Captain Definition File",sidebar_label:"Captain Definition File"},s,c={},l=[{value:"Basics",id:"basics",level:2},{value:"Use a Dockerfile",id:"use-a-dockerfile",level:2},{value:"Use an image name",id:"use-an-image-name",level:2},{value:"Monorepos",id:"monorepos",level:2},{value:"Choosing runtime versions",id:"choosing-runtime-versions",level:2}];function d(e){let n={a:"a",code:"code",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h2,{id:"basics",children:"Basics"}),"\n",(0,t.jsxs)(n.p,{children:["A ",(0,t.jsx)(n.code,{children:"captain-definition"})," file at the root of a project tells CapRover how to build or deploy it. The file uses JSON and requires ",(0,t.jsx)(n.code,{children:"schemaVersion: 2"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"For a Node.js app:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n  "schemaVersion": 2,\n  "templateId": "node/24"\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"templateId"})," uses the ",(0,t.jsx)(n.code,{children:"LANGUAGE/VERSION"})," format. The built-in templates are ",(0,t.jsx)(n.code,{children:"node"}),", ",(0,t.jsx)(n.code,{children:"php"}),", ",(0,t.jsx)(n.code,{children:"python-django"}),", and ",(0,t.jsx)(n.code,{children:"ruby-rack"}),". CapRover resolves the version from the corresponding official container image at build time."]}),"\n",(0,t.jsx)(n.p,{children:"For new production applications, a repository-owned Dockerfile usually provides the clearest and most reproducible build. It also supports any language or runtime."}),"\n",(0,t.jsx)(n.h2,{id:"use-a-dockerfile",children:"Use a Dockerfile"}),"\n",(0,t.jsx)(n.p,{children:"Reference a Dockerfile in the repository:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n  "schemaVersion": 2,\n  "dockerfilePath": "./Dockerfile"\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"The Docker build context is the root of the uploaded project, even when the Dockerfile is in a subdirectory."}),"\n",(0,t.jsx)(n.p,{children:"You can also define the Dockerfile inline:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n  "schemaVersion": 2,\n  "dockerfileLines": [\n    "FROM node:24-alpine",\n    "WORKDIR /usr/src/app",\n    "COPY package*.json ./",\n    "RUN npm install --omit=dev && npm cache clean --force",\n    "COPY . .",\n    "ENV NODE_ENV=production",\n    "ENV PORT=80",\n    "EXPOSE 80",\n    "CMD [\\"npm\\", \\"start\\"]"\n  ]\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["See Docker's ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/reference/dockerfile/",children:"Dockerfile reference"})," and ",(0,t.jsx)(n.a,{href:"https://docs.docker.com/build/building/best-practices/",children:"build best practices"})," for more options."]}),"\n",(0,t.jsx)(n.h2,{id:"use-an-image-name",children:"Use an image name"}),"\n",(0,t.jsx)(n.p,{children:"To deploy a prebuilt image from a registry:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n  "schemaVersion": 2,\n  "imageName": "nginxdemos/hello"\
1n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can paste an image-only definition into the app's ",(0,t.jsx)(n.strong,{children:"Deployment"})," tab. The CLI also accepts a prebuilt image through ",(0,t.jsx)(n.code,{children:"caprover deploy --imageName IMAGE"}),"."]}),"\n",(0,t.jsx)(n.h2,{id:"monorepos",children:"Monorepos"}),"\n",(0,t.jsx)(n.p,{children:"A repository can contain a separate definition for each app:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-text",children:"/project\n  /frontend\n    package.json\n  /backend\n    package.json\n  captain-definition-backend\n  captain-definition-frontend\n"})}),"\n",(0,t.jsxs)(n.p,{children:["In each app's ",(0,t.jsx)(n.strong,{children:"Deployment"})," tab, set the Captain Definition Path to the relevant file, such as ",(0,t.jsx)(n.code,{children:"./captain-definition-backend"}),". Dockerfile ",(0,t.jsx)(n.code,{children:"COPY"})," paths remain relative to the project root because the root is the build context."]}),"\n",(0,t.jsx)(n.h2,{id:"choosing-runtime-versions",children:"Choosing runtime versions"}),"\n",(0,t.jsx)(n.p,{children:"Use an actively supported runtime release and pin it to the level of reproducibility your application requires. Available template versions follow the tags published by the official images:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://hub.docker.com/_/node",children:"Node.js image tags"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://hub.docker.com/_/php",children:"PHP image tags"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://hub.docker.com/_/python",children:"Python image tags"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://hub.docker.com/_/ruby",children:"Ruby image tags"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Changing a floating tag can change the runtime used by a later build. Pin an exact tag or digest when repeatable builds are required."})]})}function p(e={}){let{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453(e,n,i){i.d(n,{R:()=>r,x:()=>s});var o=i(6540);let t={},a=o.createContext(t);function r(e){let n=o.useContext(a);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.