The container images run the same server as the Windows app, configured entirely by environment variables. A container listens on the network by definition, so it needs two things before it serves: a paid licence key and at least one API key.
Images
| Image | Use |
|---|---|
softwaretailor/aiserver | A single server, or a worker behind a gateway. Linux x64. |
softwaretailor/aigateway | The AI Gateway: one endpoint in front of a pool of workers (Commercial). |
softwaretailor/aiserver-pro | Worker with Pro AI Engine A: Linux x64, NVIDIA driver r580 or later, CUDA 13. |
Tags are the release version (2.5.2) and latest. Pin the version in production. The images run as a non-root user (UID 1654) and keep all state in /data.
1. Issue an API key
The key is printed once; store it in your password manager. Only its hash is written to the volume.
The images include the aisuite-server-cli tool (from 2.5.2), so you can issue the key straight into the volume:
docker run --rm -v aisuite-data:/data --entrypoint aisuite-server-cli \
softwaretailor/aiserver:<version> keys add --label my-app
With 2.5.1 or earlier images, issue the key on the Windows app's API keys page (or with aisuite-server-cli keys add --label my-app --data ./seed where the CLI is installed) and copy the resulting credentials/server-keys.json into the volume:
docker run --rm -v aisuite-data:/data -v "$PWD/seed:/seed:ro" alpine \
sh -c 'mkdir -p /data/credentials && cp /seed/credentials/server-keys.json /data/credentials/ && chown -R 1654:1654 /data'
2. Start the server
Save the licence key in a file and mount it. Never pass it as an environment value: those show up in docker inspect and crash dumps.
docker run -d --name aiserver -p 8080:8080 \
-v aisuite-data:/data \
-v "$PWD/license.key:/run/secrets/aisuite-license:ro" \
-e AISUITE_LICENSE_KEY_FILE=/run/secrets/aisuite-license \
-e AISUITE_ENGINE=real \
-e AISUITE_NODE_NAME=ai-1 \
softwaretailor/aiserver:2.5.2
Note: Without AISUITE_ENGINE=real the image runs the stub engine, which answers with canned test replies and loads no models. It exists for checking a deployment; the log says STUB ENGINE when it is on.
At first start the node activates its licence over outbound HTTPS and caches a signed lease in /data. See licence activation for what is sent and how long a node keeps serving offline.
3. Check it
curl -fsS http://localhost:8080/readyz
curl -H "Authorization: Bearer <api-key>" http://localhost:8080/v1/models
docker logs aiserver 2>&1 | grep -i license
The log says whether the licence activated. Then download a model with POST /v1/models/pull (see models); a request for a model that is not installed answers 404 model_not_found.
Settings you will usually change
| Variable | Why |
|---|---|
AISUITE_ENGINE=real | Serve inference. |
AISUITE_LICENSE_KEY_FILE | Path of the mounted licence key file. |
AISUITE_NODE_NAME | Name shown for this node in the licence fleet view. |
AISUITE_TRUST_PROXY=1 and AISUITE_TRUSTED_PROXIES | Behind a reverse proxy or load balancer: trust its forwarded client address, and only from these addresses. |
AISUITE_PER_KEY_RPM, AISUITE_PER_IP_RPM | Requests per minute per key and per client IP (Commercial). |
AISUITE_LOG_LEVEL | Warning for quieter logs, Debug when troubleshooting. |
AISUITE_CACHE_ROOT | Put models on a separate, faster volume. |
The full list, with defaults and exit codes, is on the configuration reference.
Probes and shutdown
GET /livez— 200 while the process runs, even while draining. Use it to restart the container.GET /readyz— 503 once draining. Use it to route traffic.- On SIGTERM the server answers 503 on
/readyzforAISUITE_DRAIN_SECONDS(8 in the images), then finishes in-flight requests withinAISUITE_SHUTDOWN_SECONDS(30). Give Docker at least 40 seconds:stop_grace_period: 40s.
A gateway farm with Compose
A gateway in front of two workers gives you failover and zero-downtime upgrades on one host. Gateway mode needs AI Server Commercial; the gateway itself uses no licence seat, each worker uses one.
Each node needs its own API key store: the client key lives on the gateway, and each worker has the worker key that the gateway presents to it.
# Images after 2.5.2; with 2.5.2 use the copy step from section 1 for each volume.
for node in gateway worker-1 worker-2; do
docker run --rm -v "aisuite-farm_${node}-data:/data" --entrypoint aisuite-server-cli \
softwaretailor/aiserver:<version> keys add --label "$node"
done
gateway.json lists the workers and the key the gateway uses for each:
{
"enabled": true,
"routing_strategy": "least-connections",
"workers": [
{ "id": "worker-1", "base_url": "http://worker-1:8080", "bearer_token": "<key issued on worker-1>" },
{ "id": "worker-2", "base_url": "http://worker-2:8080", "bearer_token": "<key issued on worker-2>" }
]
}
services:
gateway:
image: softwaretailor/aigateway:2.5.2
ports: ["8080:8080"]
environment:
AISUITE_ENGINE: gateway
AISUITE_LICENSE_KEY_FILE: /run/secrets/aisuite-license
volumes:
- gateway-data:/data
- ./gateway.json:/data/gateway.json:ro
- ./license.key:/run/secrets/aisuite-license:ro
stop_grace_period: 40s
worker-1:
image: softwaretailor/aiserver:2.5.2
environment:
AISUITE_ENGINE: real
AISUITE_LICENSE_KEY_FILE: /run/secrets/aisuite-license
AISUITE_NODE_NAME: worker-1
AISUITE_TRUST_PROXY: "1"
volumes: [worker-1-data:/data, ./license.key:/run/secrets/aisuite-license:ro]
stop_grace_period: 40s
worker-2:
image: softwaretailor/aiserver:2.5.2
environment:
AISUITE_ENGINE: real
AISUITE_LICENSE_KEY_FILE: /run/secrets/aisuite-license
AISUITE_NODE_NAME: worker-2
AISUITE_TRUST_PROXY: "1"
volumes: [worker-2-data:/data, ./license.key:/run/secrets/aisuite-license:ro]
stop_grace_period: 40s
volumes: { gateway-data: {}, worker-1-data: {}, worker-2-data: {} }
Run it with the project name used for the volumes above: docker compose -p aisuite-farm up -d. Clients use the gateway's address and the gateway's client key. To check the pool, call GET /v1/gateway/workers with a key issued with --admin.
GPU workers need the NVIDIA Container Toolkit (--gpus all, or deploy.resources.reservations.devices in Compose).
Questions
Why does the container exit straight away? +
Exit code 2 means it refused to start: no API key in /data, no paid licence, or gateway mode without Commercial. Exit code 4 means the licence key was rejected. The reason is the last line of docker logs. All exit codes are in the configuration reference.
Can I run the container without a licence? +
Only bound to loopback inside the container (-e AISUITE_URLS=http://127.0.0.1:8080), which is useful for smoke tests and nothing else. Serving the network needs Personal or Commercial.
Where are models stored? +
Under /data (or AISUITE_CACHE_ROOT). Keep /data on a volume so a recreated container keeps its models, keys and licence lease.