# Deploy your application

Take a Java application from source to a public deliberate. deployment.

Canonical: https://docs.deliberate.space/start/application/

Take a Spring Boot repository from source code to a public HTTPS URL. You will
package it as a container, push the image, describe the runtime, and apply it to
production.

## Before you start

You need:

- a deliberate. account, Team, and authenticated CLI—complete [Install and
  sign in](/start/install/) first;
- Docker, Podman, or nerdctl; and
- a Java application that listens on a known HTTP port.

The example uses Java 21, Maven Wrapper, port `8080`, and Spring Boot Actuator's
`/actuator/health` endpoint. Change those details to match your application.

## 1. Package the Java application

Add a `Dockerfile` at the repository root:

```dockerfile
FROM eclipse-temurin:21-jdk AS build
WORKDIR /src
COPY . .
RUN ./mvnw -DskipTests package \
 && cp "$(find target -maxdepth 1 -name '*.jar' ! -name '*-plain.jar' | head -1)" /app.jar

FROM eclipse-temurin:21-jre
RUN useradd --system --uid 10001 app
COPY --from=build --chown=10001:10001 /app.jar /app.jar
USER 10001
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
```

For Gradle, replace the Maven build command with `./gradlew bootJar` and copy
the resulting application JAR from `build/libs/`.

## 2. Confirm the active Team

```sh
deliberate team show
```

If this is not the Team that should own the application, switch it with
`deliberate team use <team-slug>` before minting registry credentials.

## 3. Push the image to the deliberate. registry

Let the CLI mint a short-lived push credential and log your local container
runtime in:

```sh
deliberate registry login
```

Docker is auto-detected first; use `--runtime podman` or `--runtime nerdctl` to
choose another runtime. The command prints the registry and Team-scoped image
prefix. Tag and push an immutable version:

```sh
docker build -t registry.deliberate.cloud/<team-slug>/hello-java:1.0.0 .
docker push registry.deliberate.cloud/<team-slug>/hello-java:1.0.0
```

Your Team's workloads receive pull access to its private registry namespace
automatically.

## 4. Describe the deployment

Create `.deliberate/project.yaml`:

```yaml
team: <team-slug>
project: hello-java
flow: default
```

Create `.deliberate/app.yaml`:

<!-- schema-example:start -->
```yaml
resource: component
name: app
image: registry.deliberate.cloud/acme/hello-java:1.0.0
cpu: 1
memory: 2Gi
ports:
  - port: 8080
    protocol: http
healthcheck:
  path: /actuator/health
  port: 8080
  initialDelay: 30s

---
resource: route
host: hello-java
visibility: public
rules:
  - path: /
    to: app
open:
  - label: Open hello-java
    path: /
    description: Open the deployed application.
```
<!-- schema-example:end -->

Replace `acme` with your Team slug. The Component declares maximum runtime
headroom: CPU is throttled at its boundary, while exceeding memory may restart
the Component. On the default `standard` class this is not reserved capacity;
measured consumption determines usage and the values protect against runaway
processes and spending. The platform uses `1` vCPU and `2Gi` when these fields
are omitted.
The declared port is internal until the separate route exposes it publicly.
If your app has no Actuator endpoint, point `healthcheck.path` at another
endpoint that returns HTTP 2xx when the process is ready.

Applications commonly need environment variables, secrets, databases, object
storage, volumes, or a custom/private route. [Project
configuration](/build/configuration/) shows how those resources are granted and
wired without adding platform-specific configuration to your application.

## 5. Apply and open

Run these commands from the directory containing `.deliberate/`:

```sh
deliberate apply --env production
deliberate open --env production
```

`apply` validates the complete tree and streams progress until the application
is ready. `open` opens the public route declared above.

## 6. Deploy and test a change

Before changing production, deploy the complete Project into a temporary
Environment. Change the image tag in `.deliberate/app.yaml`, then apply to any
name matching the default Flow's `preview-*` stage:

```sh
deliberate apply --env preview-new-greeting
deliberate open --env preview-new-greeting
```

There is no separate create step. On its first apply, deliberate. recognises
the `preview-*` name and forks the current production Environment according to
the Flow's clone policy. Components, configuration, routes, secrets, and
supported data resources come across together; the changed `.deliberate/` tree
is then reconciled on top. The preview receives its own generated routes, so it
can be exercised without replacing production.

When the change is accepted, keep the same desired state and apply it to
production:

```sh
deliberate apply --env production
```

Then remove the temporary Environment and everything it stood up:

```sh
deliberate envs delete preview-new-greeting
```

Environment deletion is idempotent, making the same cleanup command suitable
for a local workflow or CI.

## 7. If it does not become ready

```sh
deliberate components list --env production
deliberate deployments list --env production
deliberate logs --env production --component app
```

The usual first-deploy failures are a wrong image path, the process listening on
a different port, or a health endpoint that is absent or not ready yet. The
Environment canvas in the console shows the same component, route, rollout, and
health state. Continue with [Observe and recover](/operate/observe-and-recover/)
for the recovery loop and the boundary between deployment rollback and data
restore.

## Next steps

- [Prepare the application for production use](/operate/prepare-for-production/)
- [Add variables, secrets, dependencies, or routes](/build/configuration/)
- [Test the next revision in a preview Environment](/deploy/environments/)
- [Attach your own hostname](/deploy/custom-domains/)
