Deploying apps
A deployment takes your code, builds an image, starts it as a container, checks that it is healthy, and moves the traffic over to it. Each deployment is a numbered release with its own log, and you can look at, and roll back to, the recent ones.
Where the code comes from
- A Git repository. Any
https://or SSH Git address. Public repositories need nothing more; private ones use a deploy key, an access token or the GitHub connection. Only the branch you choose is cloned, with no history. - An upload. A
.zipor.tar.gzof the project. You can replace it later on the app's page and deploy again. Archives are unpacked with strict limits (no path tricks, links or special files; 64 MB packed, 500 MB unpacked and 20,000 files by default, see Configuration).
How the stack is detected
CommyPanel looks at your repository in this order, and uses the first match:
- A
Dockerfilein the root of the repository. It always wins, and is used as it is. This is how you run any language, and how you choose exactly what runs. - .NET: a
.csprojor.slnfile. There must be exactly one web project (SDKMicrosoft.NET.Sdk.Web) targeting .NET 6 or newer. With several, add a Dockerfile to choose one. - Go: a
go.modfile. Themainpackage is found in the repository root or in acmd/<name>folder; with several programs, add a Dockerfile to choose one. - Node.js: a
package.jsonfile with astartscript or amainfile.
You can also choose the type by hand when you create the app. If it does not match what is in the repository, the deployment fails with a clear message rather than guessing.
What is generated
For .NET, Go and Node, CommyPanel writes a multi-stage Dockerfile (build stage, then a slim runtime stage that runs as a non-root user). You see its notes at the top of the deployment log.
| Stack | Build | Runtime |
|---|---|---|
| .NET | dotnet publish with the SDK image for your target framework | the ASP.NET runtime image; listens on http://+:PORT; runs as the image's app user from .NET 8 |
| Go | go build with the Go version in your go.mod, without cgo | a distroless static image running as non-root; the binary is /app |
| Node.js | npm ci (or pnpm or yarn, detected from your lockfile or packageManager), then build if your package.json has that script, then production dependencies only | node:<major>-slim where the major version comes from engines.node or .nvmrc (24 by default, 18 at least); NODE_ENV=production; runs as the node user; starts with your start script, or node <main> |
Your app must listen on the port CommyPanel gives it, which it passes as the PORT environment variable. The app port setting tells CommyPanel which port to publish; the app should read PORT.
What a deployment does
- Get the code: clone the branch, or unpack the upload.
- Build the image: one build at a time on the server, with CPU and memory limits.
- Release command (optional): run once in a fresh container, for example migrations. See Release command.
- Start: the new container starts next to the old one.
- Health check: CommyPanel asks your health check path until the app answers (anything below 500 counts), for up to 60 seconds.
- Go live: nginx is pointed at the new container and reloaded gracefully. The old container then stays for a few minutes while CommyPanel watches the new release and rolls back by itself if it is clearly worse, and then stops. With a gradual rollout turned on, only a share of the visitors gets the new release at first.
If any step fails, the old version keeps serving and the deployment is marked failed with the reason. See Zero-downtime deployments for the details.
Older images are kept so that Roll back is instant: the last 3 per app by default (DEPLOY_KEEP_IMAGES). A rollback starts a container from an older image without building anything. It does not undo changes to volumes or databases.
Settings
On the app page, Settings holds the branch, the app port, the health check path, memory and CPU limits and the release command. Changes apply from the next deployment. Environment variables, volumes and links have their own tabs, and take effect when you apply the changes.
By default an app gets 512 MB of memory and one CPU core; set limits to change that.
Who can do what
Creating apps needs apps.create, changing settings apps.update, and deploying and rolling back apps.deploy. See Permissions.