# Getting Started

This page starts node-image-server with Docker Compose and walks through the first upload and fetch.

## Prerequisites

| Item | Version |
|---|---|
| Docker and Docker Compose v2 | Recommended deployment |
| Node.js | 22 or higher (only for running on the host; the container uses `node:22-alpine`) |

## Start with Docker Compose

```bash
git clone https://github.com/pardnio/node-image-server.git
cd node-image-server
docker compose up -d
```

| Service | Image | Role |
|---|---|---|
| `nginx` | `nginx:stable-alpine` | Listens on `8080`, loads `config/nginx/nodejs.conf` |
| `nodejs` | `node:22-alpine` | Runs `npm install` on start, then loads `app.ts` with `npx pm2-runtime start app.json` |

## Run on the Host

```bash
cd node-image-server/app
npm install
mkdir -p storage/logs storage/image
npx pm2-runtime start app.json
```

Requests then reach Express directly (`http://localhost:8080`) without Nginx.

## First Upload

```bash
curl -fsS -X POST \
  -F "filepath=@./photo.jpg" \
  http://localhost:8080/upload/blog/2025 \
  || echo "upload failed"
```

A successful upload returns `201`:

```json
{
  "success": 1,
  "filename": "ERftP1gTS7WCTeJ8_1744080848530.jpg",
  "type": "image/jpeg",
  "size": 2501808,
  "src": "http://localhost:8080/c/img/blog/2025/ERftP1gTS7WCTeJ8_1744080848530.jpg"
}
```

## First Fetch

```bash
# Defaults: WebP, quality 75, long edge shrunk to 1024px when the short edge exceeds 1024px
curl -fsS -o photo.webp \
  http://localhost:8080/c/img/blog/2025/ERftP1gTS7WCTeJ8_1744080848530.jpg

# 800px-wide AVIF
curl -fsS -o w800.avif \
  "http://localhost:8080/c/img/blog/2025/ERftP1gTS7WCTeJ8_1744080848530.jpg?w=800&t=avif"
```

The first request converts the image with sharp and writes it to `storage/image/cache/`; later requests with the same parameters read the cache file.

## Next Steps

- Full parameter list: [Image Parameters](/api-reference-image)
- How caching is layered: [Caching Layers](/caching)
- Production settings: [Configuration](/configuration)
