# Dockerfile Requirements (/docs/dockerfile-requirements)



Rock8Cloud deploys any application that has a valid Dockerfile. Here's what you need.

## Requirements [#requirements]

Your Dockerfile must:

1. **Build successfully** - `docker build .` works without errors
2. **Expose a port** - Use `EXPOSE <port>` instruction
3. **Start automatically** - Use `CMD` or `ENTRYPOINT`

***

## Example [#example]

Here's a real-world example from [astro-rocketship](https://github.com/ProRocketeers/astro-rocketship):

```dockerfile
# Build stage
FROM oven/bun:1.3.4-alpine AS builder
WORKDIR /app

COPY package.json bun.lock ./
RUN bun install --frozen-lockfile

COPY . .
RUN bun run build

# Production stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

This multi-stage build:

* Builds the app with Bun
* Serves static files with nginx
* Results in a small, production-ready image

***

## Port Configuration [#port-configuration]

The port in your Dockerfile must match what you configure in Rock8Cloud:

**Dockerfile:**

```dockerfile
EXPOSE 3000
```

**Rock8Cloud service settings:**

* Port: `3000`

If they don't match, health checks will fail.

***

## Let Rock8Cloud Write It [#let-rock8cloud-write-it]

If your repository has no Dockerfile, tick **Generate Dockerfile** when you create the service and
an agent writes one for you.

It does not guess once and hope. The agent reads your repository, writes a Dockerfile, and pushes
it to a pull request. Rock8Cloud then builds that Dockerfile and deploys it to a preview
environment, and the agent watches the result. If the build fails it reads the build logs. If the
container starts but the app never comes up it reads the runtime logs. Either way it fixes the
Dockerfile and pushes again, up to five attempts, and it keeps going until your app is genuinely
running - unless it runs out of attempts, or stops to ask you for something it cannot set from
inside an image.

You can watch the whole thing under **Agents**, where each attempt appears as a message with the
logs the agent acted on. When the app comes up, Rock8Cloud fills in the Dockerfile path, build
context and port in your build settings to match what it wrote, and you merge the pull request to
deploy it for real.

It stops and hands back if your app needs configuration that is not there yet, such as a database
URL or an API key. Those live on the environment rather than in the image, so the agent will not
invent one. It tells you which values are missing, and the service page shows what it is waiting
on. Set them, then send the session a message and it picks up where it left off.

If it runs out of attempts instead, the session still stays open with everything it learned. Send
it a message to keep going, or take over the pull request yourself.

<Callout type="info">
  The agent is instructed to only touch Dockerfiles, `.dockerignore` and container config files,
  and not to change your application code or dependencies to make a build pass. Every change
  still arrives as a pull request, so you see exactly what it did before anything is merged.
</Callout>

***

## Test Locally First [#test-locally-first]

Before deploying, verify your Dockerfile works:

```bash
# Build
docker build -t my-app .

# Run
docker run -p 3000:3000 my-app

# Test
curl http://localhost:3000
```

If it works locally, it'll work on Rock8Cloud.

***

## Monorepo Setup [#monorepo-setup]

If your Dockerfile is in a subdirectory, you have two options for build context:

### Option 1: Build from repository root (default) [#option-1-build-from-repository-root-default]

Your Dockerfile references paths from the repo root:

```dockerfile
# backend/Dockerfile
FROM node:20-alpine
WORKDIR /app

# Copy from repo root
COPY backend/package.json backend/package-lock.json ./
RUN npm install

COPY backend/ .
RUN npm run build

EXPOSE 3000
CMD ["node", "dist/index.js"]
```

### Option 2: Build from Dockerfile directory [#option-2-build-from-dockerfile-directory]

Enable &#x2A;*"Use Dockerfile directory as build context"** in service settings. Your Dockerfile uses relative paths:

```dockerfile
# backend/Dockerfile
FROM node:20-alpine
WORKDIR /app

# Copy from backend/ directory
COPY package.json package-lock.json ./
RUN npm install

COPY . .
RUN npm run build

EXPOSE 3000
CMD ["node", "dist/index.js"]
```

This option is useful when:

* Each service is self-contained in its folder
* You want faster builds (smaller context)
* Your Dockerfile already uses `COPY . .`

***

## Common Issues [#common-issues]

| Problem            | Solution                                                         |
| ------------------ | ---------------------------------------------------------------- |
| Build fails        | Run `docker build .` locally to see errors                       |
| App not accessible | Check your app binds to the correct port                         |
| Health check fails | Ensure port matches between Dockerfile and settings              |
| Missing files      | Check all `COPY` paths exist and aren't in `.dockerignore`       |
| Wrong files copied | Check build context setting matches your Dockerfile's COPY paths |

See [FAQ](/docs/faq) for more help.
