appwrite/docker-ollama: Baking AI Models Into Docker Layers

How Appwrite uses a build-time Ollama server, multi-arch Docker tricks, and pre-pulled weights to make local inference start instantly.

6 to 8 min read View on GitHub More from appwrite

A Docker container is shown as a workshop split open to reveal stacked model layers inside. A tiny temporary server runs during the build phase while heavy weight blocks are pulled into place, and a second path shows the runtime container starting with those blocks already embedded. The image explains how model downloads become part of the image rather than a startup task.
Appwrite turns model acquisition into a build artifact, so runtime startup has less work to do.
Key Takeaways

The interesting thing here is not that Appwrite ships an Ollama image. It is that the repo moves model fetching into docker build, which changes the economics of startup. The container does the slow work once, then starts like a normal service later.

The trick: model pulls happen before the container ever runs

The Dockerfile starts a temporary ollama serve process inside a build step, waits until the API wakes up, and then pulls the target model. That means the model files land in image layers, not in a frantic first-boot download.

A temporary server exists only to make the final image self-sufficient.

RUN ollama serve & \
    until ollama list >/dev/null 2>&1; do sleep 1; done \
 && ollama pull ${MODELS}

That is the core move. A model pull is usually a startup tax. Here it becomes a build-time cost that Docker can cache, reproduce, and distribute.

Why Appwrite cares about instant AI startup

The default model choice points to the real use case. The repo ships with embeddinggemma, which says this is not primarily about chat toys. It is about embeddings, retrieval, and backend features that need local inference to feel native.

We are working on ollama integration right now :D

Eldad Fux, Founder & CEO of Appwrite · Appwrite GitHub Discussions
GoalTypical Ollama setupappwrite/docker-ollama
Primary focusRun models locallyPackage local inference for Appwrite
Model acquisitionPull after startupPull during image build
Startup behaviorWait for downloads if neededStart with weights already present
Operational feelGeneral-purpose runnerBackend plumbing for a platform
Best fitExploration and manual useRepeatable Appwrite deployments

That makes the project feel less like a wrapper and more like infrastructure. Appwrite is trying to make local inference behave like any other backend dependency: declared once, present when needed, invisible when it works.

How the image build works without collapsing

The build-time daemon pattern is clever, but it also needs guardrails. The repo uses architecture-aware logic, readiness polling, and strict shell settings so the optimization does not turn into a fragile shell trick.

A close-up scene shows three terminal windows stacked inside a larger machine. One terminal launches ollama serve in the background, another repeatedly checks readiness, and a third pulls a model once the server responds. The image explains the hidden build-time daemon pattern and the sequence that makes it work.
The build step behaves like a ghost server that exists only long enough to cache the model.
#!/usr/bin/env bash
set -euo pipefail

if [[ -n "${MODELS:-}" ]] && ! model_exists "${MODELS}"; then
  echo "Model not found locally"
fi

exec ollama serve

The runtime script is simple on purpose. It checks for the model, then hands control to ollama serve. That keeps the build-time shortcut from becoming a hidden assumption at runtime.

This is a platform strategy, not a standalone tool

The repo reads like plumbing for Appwrite’s broader AI story. If you are building with Appwrite, the value is not a new model runner. The value is that local inference can slot into the platform the same way storage or auth does.

ProjectPrimary goalWhat it optimizes for
appwrite/docker-ollamaBaked-in local inferencePlatform integration and instant startup
Official Ollama DockerGeneral local model runnerFlexibility and simplicity
Docker Model RunnerOCI-native model distributionDocker Desktop integration
LocalAIBroad OpenAI-style backendFeature breadth and backend variety

That positioning matters. Appwrite is not trying to win the entire model-serving market. It is making sure its own developers can treat AI like a first-class backend capability.

What it beats, and what it gives up

Compared with the official Ollama image, Appwrite’s version is less generic but more opinionated. Compared with Docker Model Runner, it is less about OCI-native model distribution and more about practical bundling. Compared with LocalAI, it is narrower but simpler to operate.

The trade-off is obvious: bigger images, slower registry pushes, and less flexibility at build time. The payoff is equally obvious: predictable deployments, offline readiness, and no first-run model download.

Why the repo feels unusually mature for plumbing

The polish shows up in the details. Multi-arch builds, smoke tests that hit /api/embed, named volumes for persistence, and strict shell mode all point to a repo that is meant to be depended on, not admired from a distance.

That is the real signal. This is not a hack that happened to work once. It is a repeatable way to ship model weights the same way teams already ship containers.