Getting started with the server

Copy Markdown View Source

In this guide we'll run image_pipe_server in Docker, point it at a folder of photos on your machine, and open resized, cropped, and converted copies of a photo in the browser.

You need Docker, port 8080 free, and a JPEG photo.

Getting the server image

docker pull ghcr.io/hlindset/image_pipe_server:0.1

Adding a folder of images

The server reads originals from a folder and makes processed copies of them on request. Let's create a working directory with an images folder:

mkdir -p image-server/images
cd image-server

Copy any JPEG photo into images as photo.jpg:

cp /path/to/your/photo.jpg images/photo.jpg

The examples below use a 4000×2667 photo. With your photo, the widths match and the heights follow its proportions.

Writing the configuration

Next, we tell the server where the originals are. Create config.toml in the image-server directory:

# config.toml
[sources.photos]
adapter = "file"
match = "path"
root = "/data/images"
root_id = "photos"

This defines one source named photos. A source is a place the server reads originals from:

  • adapter = "file" reads files from a directory.
  • match = "path" sends every image path in a URL to this source.
  • root is that directory, as the server sees it inside the container. We mount our images folder there in the next step.
  • root_id is a stable name for this directory.

Starting the server

Let's start the server in the background, with our configuration file and our images folder mounted at the paths in config.toml:

docker run -d --name image-server -p 8080:8080 \
  -v "$PWD/config.toml:/etc/image_pipe/config.toml:ro" \
  -v "$PWD/images:/data/images:ro" \
  ghcr.io/hlindset/image_pipe_server:0.1

The server reads /etc/image_pipe/config.toml at startup. Open http://localhost:8080/health/ready in your browser. Within a second or two it shows:

ok

If the page doesn't load, the server didn't start. A mistake in config.toml stops it. Check its log:

docker logs image-server

The log ends with a line that names the setting. Leaving out match, for example, ends the log with:

invalid configuration: sources.photos.match: required

Fix config.toml, remove the stopped container with docker rm image-server, and run the docker run command again.

Resizing an image

An image URL lists processing options, then src/, then the image's path in the source. Let's ask for photo.jpg at 400 pixels wide. Open this URL:

http://localhost:8080/w=400/src/photo.jpg

GET /w=400/src/photo.jpg (in Chrome)
200 OK, content-type: image/avif, 400×267

The browser's tab title shows the size, 400×267. Notice that:

  • src/photo.jpg is /data/images/photo.jpg in the photos source, which is images/photo.jpg on your machine. A photo in a subfolder, images/trips/beach.jpg, is src/trips/beach.jpg.
  • w=400 sets only the width. The height follows the photo's proportions.
  • The original is a JPEG, but Chrome got AVIF, as its developer tools show. Without a format option, the server picks AVIF or WebP when the browser asks for one of them. A client that asks for neither, such as curl, gets a JPEG.

Now change w=400 to w=800:

http://localhost:8080/w=800/src/photo.jpg

GET /w=800/src/photo.jpg
200 OK, content-type: image/avif, 800×533

Files you add to images can be requested right away, without restarting the server.

If a request fails, the status and body say why:

  • 404 with source not found: the file name is mistyped.
  • 400 with invalid transformation options: the URL leaves out src/, as in /w=400/photo.jpg. The body ends with missing src/, src64/, or enc/ before the image path.
  • 500 with source unavailable: the server can't read the file, for example because only your user can read it. Make it readable with chmod a+r images/photo.jpg.

Fitting an image in a box

With both a width and a height, the server fits the photo inside that box:

http://localhost:8080/w=300/h=300/src/photo.jpg

GET /w=300/h=300/src/photo.jpg
200 OK, content-type: image/avif, 300×200

Notice that the result is 300×200, not 300×300. By default the whole photo stays visible, so the wide photo fills the box's width and leaves its height short. Add fit=cover to fill the box instead:

http://localhost:8080/w=300/h=300/fit=cover/src/photo.jpg

GET /w=300/h=300/fit=cover/src/photo.jpg
200 OK, content-type: image/avif, 300×300

The photo now covers the whole 300×300 square, and the parts that don't fit are cropped off both sides, keeping the center.

The order of options doesn't matter: fit=cover/h=300/w=300 gives the same image. An unknown value gets a 400, and the body points at the problem. With fit=fill:

invalid transformation options

/w=300/h=300/fit=fill/src/photo.jpg
                 ^^^^
                 |
                 invalid value: expected contain, cover, stretch, or auto

Choosing the output format

To get the same format whatever the browser accepts, add format:

http://localhost:8080/w=300/h=300/fit=cover/format=png/src/photo.jpg

GET /w=300/h=300/fit=cover/format=png/src/photo.jpg
200 OK, content-type: image/png, 300×300

format also takes webp, avif, and jpeg.

When you're done, stop and remove the container:

docker rm -f image-server

Next steps

We ran the server against a folder of originals and requested resized, cropped, and converted copies by URL. From here:

Before exposing the server, set up URL signing with the [url] keys setting. Building URLs for the server shows the application side, which signs the URLs.