> ## 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.

# porter apply

> Deploy applications using porter.yaml with the porter apply command, supporting container builds, image updates, and preview environments

<Info>
  This command is the recommended way to deploy applications in CI/CD pipelines and for version-controlled infrastructure.
</Info>

`porter apply` is the primary command for deploying applications using configuration-as-code. It reads a `porter.yaml` file, **builds a new container image**, and **deploys your application** to the cluster.

By default, `porter apply` performs a full build and deploy cycle. Use `--no-build` to skip building and deploy with an existing image.

<Info>
  You can run `porter apply` without a `porter.yaml` file to deploy using the existing application configuration. This is useful for triggering a new build and deploy without changing any settings.
</Info>

## Usage

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

## Prerequisites

* You've logged in to the Porter CLI after running [porter auth login](/standard/cli/command-reference/porter-auth)
* You're connected to the correct project by running [porter config set-project](/standard/cli/command-reference/porter-config)
* You're connected to the correct cluster by running [porter config set-cluster](/standard/cli/command-reference/porter-config)

## Options

### Deployment Options

| Flag        | Short | Description                                                                   |
| ----------- | ----- | ----------------------------------------------------------------------------- |
| `--file`    | `-f`  | Path to the `porter.yaml` configuration file (optional if app already exists) |
| `--app`     |       | Override the app name specified in `porter.yaml`                              |
| `--target`  | `-x`  | Specify a deployment target (name or ID)                                      |
| `--wait`    | `-w`  | Wait for the deployment to complete before exiting                            |
| `--preview` | `-p`  | Deploy to a preview environment based on current git branch                   |

<Warning>
  **Use `--exact` with caution.** When set, this flag disables config merging with existing app configuration—any settings not explicitly defined in your `porter.yaml` will be overwritten. Most users should avoid this flag unless they need to completely replace the application configuration.
</Warning>

| Flag      | Description                                            |
| --------- | ------------------------------------------------------ |
| `--exact` | Disable config merging with existing app configuration |

### Build Options

| Flag                  | Description                                                 |
| --------------------- | ----------------------------------------------------------- |
| `--no-build`          | Skip building a new image and deploy with an existing image |
| `--no-pull`           | Don't pull the previous image before building               |
| `--tag`               | Specify a custom image tag (overrides value in porter.yaml) |
| `--image-repository`  | Set the image repository to use                             |
| `--build-context`     | Override the build context directory                        |
| `--build-method`      | Set build method: `docker` or `pack`                        |
| `--dockerfile`        | Override the Dockerfile path (for docker builds)            |
| `--builder`           | Set the builder to use (for pack builds)                    |
| `--attach-buildpacks` | Attach buildpacks to use (for pack builds)                  |
| `--verbose`           | Show verbose output during build                            |

### Environment Options

You can pass environment variables and secrets directly via command-line flags without modifying your `porter.yaml`.

| Flag          | Description                                                          |
| ------------- | -------------------------------------------------------------------- |
| `--variables` | Set environment variables as key=value pairs (overrides porter.yaml) |
| `--secrets`   | Set secrets as key=value pairs (overrides porter.yaml)               |

### Validation Options

| Flag        | Description                                                                                   |
| ----------- | --------------------------------------------------------------------------------------------- |
| `--dry-run` | Perform server-side validation to confirm the configuration is valid without applying changes |

To check a `porter.yaml` locally without building or deploying, use the [`porter apply validate`](#porter-apply-validate) subcommand.

### Advanced Options

| Flag                    | Short | Description                                          |
| ----------------------- | ----- | ---------------------------------------------------- |
| `--helm-overrides-file` | `-v`  | Path to a file containing Helm value overrides       |
| `--attach-env-groups`   |       | Comma-separated list of environment groups to attach |

## Environment Variables

You can also configure `porter apply` using environment variables. These are automatically set in the GitHub workflow that Porter generates for your application.

| Variable                      | Description                               |
| ----------------------------- | ----------------------------------------- |
| `PORTER_TOKEN`                | Authentication token (required for CI/CD) |
| `PORTER_HOST`                 | Porter API host URL                       |
| `PORTER_PROJECT`              | Target project ID                         |
| `PORTER_CLUSTER`              | Target cluster ID                         |
| `PORTER_APP_NAME`             | App name (alternative to `--app`)         |
| `PORTER_DEPLOYMENT_TARGET_ID` | Deployment target ID                      |
| `PORTER_TAG`                  | Image tag to deploy                       |

## Examples

<CodeGroup>
  ```bash Basic Deployment theme={null}
  # Deploy using porter.yaml in the current directory
  porter apply -f porter.yaml
  ```

  ```bash Wait for Completion theme={null}
  # Deploy and wait for the deployment to complete
  porter apply -f porter.yaml --wait
  ```

  ```bash Preview Environment theme={null}
  # Deploy to a preview environment
  porter apply -f porter.yaml --preview
  ```

  ```bash Validate Locally theme={null}
  # Check porter.yaml against the schema without building or deploying
  porter apply validate -f porter.yaml
  ```

  ```bash Dry Run theme={null}
  # Validate the full configuration server-side without deploying
  porter apply -f porter.yaml --dry-run
  ```

  ```bash CI/CD Pipeline theme={null}
  # Deploy in a CI/CD pipeline with explicit configuration
  PORTER_TOKEN=$PORTER_DEPLOY_TOKEN \
  PORTER_PROJECT=$PROJECT_ID \
  PORTER_CLUSTER=$CLUSTER_ID \
  porter apply -f porter.yaml
  ```

  ```bash Skip Build theme={null}
  # Deploy using an existing image (skip build step)
  porter apply -f porter.yaml --no-build --tag v1.2.3
  ```

  ```bash With Environment Variables theme={null}
  # Deploy with runtime environment variables and secrets
  porter apply -f porter.yaml --variables LOG_LEVEL=debug,NODE_ENV=production --secrets API_KEY=secret123
  ```
</CodeGroup>

## `porter apply validate`

Validate a `porter.yaml` file against the schema locally. This command does not build, push, or deploy, and does not contact the Porter API.

**Usage:**

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

**Options:**

| Flag     | Short | Description                                                                         |
| -------- | ----- | ----------------------------------------------------------------------------------- |
| `--file` | `-f`  | Path to the `porter.yaml` file (defaults to `porter.yaml` in the current directory) |

On success the command prints `✓ porter.yaml is valid`. On failure it prints the validation error and exits non-zero. For server-side validation of the full configuration against your project, use `porter apply --dry-run`.

## Workflow

When you run `porter apply`, the following steps occur:

<Steps>
  <Step title="Parse Configuration">
    Porter reads and validates your `porter.yaml` file (if provided)
  </Step>

  <Step title="Build Image">
    Porter builds and pushes a new container image (unless `--no-build` is specified)
  </Step>

  <Step title="Deploy Services">
    Porter deploys or updates all services defined in the configuration
  </Step>

  <Step title="Wait for Rollout (if --wait)">
    If `--wait` is specified, Porter waits for all services to become healthy
  </Step>
</Steps>

## Configuration File

The `porter apply` command expects a `porter.yaml` file. For detailed documentation on all available configuration options, see the [porter.yaml Reference](/applications/configuration-as-code/reference).

### Minimal Example

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

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

## CI/CD Integration

Most users deploy with `porter apply` through GitHub Actions. Porter automatically generates a GitHub workflow for your application that handles authentication and deployment.

<Info>
  The workflow below is similar to what Porter automatically creates when you connect your GitHub repository. You can find it in your repository at `.github/workflows/porter_<app-name>.yml`.
</Info>

### GitHub Actions Workflow

```yaml theme={null}
name: Deploy to my-app

on:
  push:
    branches:
      - main

jobs:
  porter-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set Github tag
        id: vars
        run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

      - name: Setup porter
        uses: porter-dev/setup-porter@v0.2.0

      - name: Deploy stack
        run: porter apply
        timeout-minutes: 30
        env:
          PORTER_CLUSTER: "1"
          PORTER_HOST: https://dashboard.porter.run
          PORTER_PROJECT: "1"
          PORTER_TOKEN: ${{ secrets.PORTER_TOKEN }}
          PORTER_TAG: ${{ steps.vars.outputs.sha_short }}
          PORTER_APP_NAME: my-app
          PORTER_DEPLOYMENT_TARGET_ID: your-deployment-target-id
```

## Related Commands

* [porter app update](/standard/cli/command-reference/porter-app#porter-update) - Update an app without building
* [porter app yaml](/standard/cli/command-reference/porter-app#porter-yaml) - Export the current app configuration as YAML
