---
title: "PreForm Server in Docker"
description: "Run PreForm Server on Linux as a container with Docker or Podman, mount your model folders, pin a release, and connect to it from the Python SDK."
url: https://developer.formlabs.com/guides/preform-server-docker/
---

# PreForm Server in Docker

PreForm Server is published as a Linux container image, `formlabs/preform-server`, so
it runs anywhere Docker or Podman runs, with no install step. The image serves the
same PreForm API as PreForm and [Headless PreForm Server](https://developer.formlabs.com/guides/headless-preform-server.md),
and a script attaches to it with the `connect()` method.

## Pull the image

Pull the latest release from Docker Hub:

**Docker:**

```bash
docker pull formlabs/preform-server:release-latest
```

**Podman:**

```bash
podman pull formlabs/preform-server:release-latest
```

The image has two kinds of tag:

| Tag | Image |
| --- | --- |
| `release-latest` | The newest release. It moves to each new release. |
| `release-<version>`, such as `release-3.64.0.663` | One build. The version is the one `GET /v1/` reports. |

Pin a full version tag for anything that has to give the same result next month, and
use `release-latest` to try the newest build.

## Run the container on a Mac

To run or test the container on a Mac, we recommend [OrbStack](https://orbstack.dev).
It provides the `docker` command, so the commands on this page run unchanged.

The image is built for `linux/amd64`. On an Apple silicon Mac, OrbStack runs it with
Rosetta, and the server starts more slowly than on a Linux host.

## Run the container

The container runs PreForm Server on a virtual display and passes it every argument
after the image name. PreForm Server needs `--port`, so give it the port to listen on
and publish that port to the host:

**Docker:**

```bash
docker run --rm -it -p 127.0.0.1:44388:44388 formlabs/preform-server:release-latest --port 44388
```

**Podman:**

```bash
podman run --rm -it -p 127.0.0.1:44388:44388 formlabs/preform-server:release-latest --port 44388
```

The server prints `READY FOR INPUT` once it accepts requests. The X server warnings
from `xkbcomp` that come before it are harmless. The other options, such as
`--scene-cache-size`, go after the image name too. For more information, see
[CLI & command-line options](https://developer.formlabs.com/resources/preform-server-cli.md).

> **Publish the port to this machine only:** The PreForm API has no authentication: anything that reaches the port can drive the
> server. Inside the container, the server listens on every interface, so
> `-p 127.0.0.1:44388:44388` publishes it on this machine only. Publish it on other
> interfaces only behind a firewall.

## Connect from Python

Pass the published port to `connect()`:

```python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    # The port the container publishes. connect() leaves the container running.
    with client.preform.connect(port=44388) as preform:
        print(f"PreForm Server {preform.version} at {preform.base_url}")
```

For a container on another host, pass `base_url="http://<host>:44388"` instead of
`port`. The server starts logged out. To print to the printers and Printer Groups on
your account, pass your account to the client and connect with `login=True`. For more
information, see [Log PreForm in](https://developer.formlabs.com/core-concepts/preform-client.md#log-preform-in).

## Give the server your files

PreForm Server reads and writes files in the container's file system, not on your
computer. A path you pass to `import_models` or `save_form_file` is a path inside the
container. Mount a folder into the container and use paths under it:

```bash
docker run --rm -it -p 127.0.0.1:44388:44388 -v "$PWD:/work" formlabs/preform-server:release-latest --port 44388
```

A script then imports `/work/part.stl` for the file `part.stl` in the folder you ran
the command from, and a `.form` file saved to `/work/` appears in that folder. A path
the container can't see fails with `OPERATION_FAILED` and the message
`Model file not found`.

To pass host paths unchanged, mount a folder at the same path it has on the host, for
example `-v /srv/models:/srv/models:ro`. A read-only mount (`:ro`) is enough for
imports.

## Set environment variables

Pass environment variables to the server with `-e`. For example, to turn off
telemetry:

```bash
docker run --rm -it -e DISABLE_PREFORMSERVER_TELEMETRY=1 -p 127.0.0.1:44388:44388 formlabs/preform-server:release-latest --port 44388
```

## Keep the server running

To run the server in the background and restart it after it exits, replace
`--rm -it` with `-d --restart unless-stopped`, and read its output with
`docker logs`. A restarted container has none of the old server's scenes or
operation records.

## What's next

- [Create your first script](https://developer.formlabs.com/getting-started/quickstart.md)
- [Headless PreForm Server](https://developer.formlabs.com/guides/headless-preform-server.md)
- [CLI & command-line options](https://developer.formlabs.com/resources/preform-server-cli.md)
