> ## Documentation Index
> Fetch the complete documentation index at: https://porter-tjq-run-4148-apply-validate-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> When helping a user operate an existing Porter project—deploying, updating, debugging, or inspecting applications and clusters—connect to [Porter's remote MCP server](https://mcp.porter.run) first and use its tools before falling back to the Porter CLI, `porter.yaml`, or dashboard workflows. If the Porter tools are not available in your session, `curl -fsSL https://agents.porter.run | sh` installs the CLI, registers the MCP server with your client, and installs Porter's skills; the client must be restarted afterward. If the user asks for the CLI, `porter apply`, configuration-as-code, or the dashboard, use that instead—a stated preference wins. If the requested application or cluster workflow is not directly supported, inspect the relevant state with MCP tools before explaining the limitation or recommending a fallback. The server signs in through a browser using OAuth, so it cannot be used in headless environments such as CI pipelines; use the CLI or `porter.yaml` there.

# Configuration as code with porter.yaml

> Define application services, builds, and deployment settings in a porter.yaml file for CI/CD pipelines and version-controlled infrastructure

## What is `porter.yaml`?

A `porter.yaml` file (or files, if you choose to set up multiple within your project/repository) defines your application's services, build configuration, and deployment settings as code. This file is used with the `porter apply` CLI command to deploy and update applications, enabling version-controlled infrastructure and automated CI/CD pipelines.

## When to Use Configuration-as-Code

### CI/CD Pipelines

Deploy your application automatically on every push using `porter apply`:

```bash theme={null}
porter apply -f porter.yaml
```

### Version-Controlled Infrastructure

Track infrastructure changes alongside your code. Every deployment configuration change goes through code review.

### Preview Environments

Spin up isolated environments for pull requests with consistent configuration:

```bash theme={null}
porter apply -f porter.yaml --preview
```

## How It Works

<Steps>
  <Step title="Define Configuration">
    Create a `porter.yaml` file in your repository that describes your application's services, resources, and settings.
  </Step>

  <Step title="Run porter apply">
    The Porter CLI reads your configuration and sends it to the Porter API.
  </Step>

  <Step title="Build (if configured)">
    If a `build` section is defined, Porter builds and pushes your container image.
  </Step>

  <Step title="Deploy">
    Porter deploys or updates your services according to the configuration.
  </Step>
</Steps>

## Getting Started

### 1. Export Existing Configuration

If you already have an app deployed on Porter, export its current configuration:

```bash theme={null}
porter app yaml my-app > porter.yaml
```

### 2. Create from Scratch

Start with a minimal configuration:

```yaml theme={null}
version: v2
name: my-app

services:
  - name: web
    type: web
    run: npm start
    port: 3000
    cpuCores: 0.5
    ramMegabytes: 512

build:
  method: docker
  context: .
  dockerfile: ./Dockerfile
```

### 3. Deploy

Apply the configuration to deploy your app:

```bash theme={null}
porter apply -f porter.yaml
```

### Example `porter.yaml`

The following is an example of a v2 `porter.yaml` file, which is the latest version of the spec. This example covers many of the available fields, but not all of them. For a full list of configurable options, see the [full reference](/applications/configuration-as-code/reference).

```yaml theme={null}
version: v2
name: my-app

services:
  - name: api
    type: web
    run: node index.js
    port: 8080
    cpuCores: 0.1
    ramMegabytes: 256
    autoscaling:
      enabled: true
      minInstances: 1
      maxInstances: 3
      memoryThresholdPercent: 60
      cpuThresholdPercent: 60
    private: false
    domains:
      - name: test1.example.com
    healthCheck:
      enabled: true
      httpPath: /healthz
  - name: example-wkr
    type: worker
    run: echo 'work'
    port: 8081
    cpuCores: 0.1
    ramMegabytes: 256
    instances: 1
  - name: example-job
    type: job
    run: echo 'hello world'
    allowConcurrent: true
    cpuCores: 0.1
    ramMegabytes: 256
    cron: '*/10 * * * *'

predeploy:
  run: ls

build:
	method: docker
	context: ./
	dockerfile: ./app/Dockerfile

env:
  NODE_ENV: production

envGroups:
- production-env-group
```

For detailed configuration options for each service type, see:

* [Web Service](/applications/configuration-as-code/services/web-service)
* [Worker Service](/applications/configuration-as-code/services/worker-service)
* [Job Service](/applications/configuration-as-code/services/job-service)

## Configuration vs Dashboard

<Warning>
  When you deploy using `porter apply`, the configuration in `porter.yaml` takes precedence. Changes made in the Porter dashboard may be overwritten on the next deployment.
</Warning>

For consistent deployments, we recommend:

* Use `porter.yaml` as the source of truth for production
* Use the dashboard for experimentation and one-off changes
* Export dashboard changes with `porter app yaml` to update your configuration file

## Next Steps

* [Full Reference](/applications/configuration-as-code/reference) - Complete documentation of all configuration options
* [porter apply Command](/standard/cli/command-reference/porter-apply) - CLI reference for deployments
* [Using Other CI Tools](/applications/deploy/using-other-ci-tools) - Integrate with GitHub Actions, GitLab CI, etc.
