Vex is a basic docker container image registry.
- Images, including multiplatform (list) manifests can be pushed to the authenticated, writable endpoint.
- All pushed data (repositories, images and blobs/layers) are public and can be pulled from the read-only endpoint.
- Serves on three HTTP(s) ports: 1. public read-only, for downloading images. 2. read-write, with authentication, for adding/removing images (manifests, tags, blobs/layers). 3. internal, for metrics.
- Authenticated users have full control over all repositories. Repositories are automatically created on first write operation on them (e.g. blob/layer upload).
- The public endpoint has a Web interface for browsing repositories, tags, manifests (images and multiplatform images).
- Data (images and their config/layer blobs) are kept consistent, and automatically removed when the last reference to them is removed. I.e. manifests will always have all their blobs available as well.
- Metadata is stored with a builtin transactional database, for fast and consistent data.
- Vex is a standalone static binary, easily reproducibly built, also when cross-compiled.
License: MIT
Create user to run as (optional) and run quickstart:
useradd -d /home/vex vex
mkdir /home/vex
cd /home/vex
# [...] download vex binary, see below.
# generate config files. optionally replace localhost with an internal
# host name, for self-signed tls certificate for pushing images.
./vex quickstart <username-for-pushing-images> localhost
The quickstart creates files and prints commands to start vex, optionally enable it as a service, and example commands to push and pull docker images.
You can easily (cross) compile if you have a recent Go toolchain installed (see "go version", it must be >= 1.19; otherwise, see https://go.dev/dl/ or https://go.dev/doc/manage-install and $HOME/go/bin):
GOBIN=$PWD CGO_ENABLED=0 go install github.com/mjl-/vex@latest
Or you can download a binary built with the latest Go toolchain from https://beta.gobuilds.org/github.com/mjl-/vex, and symlink or rename it to "vex".
Verify you have a working binary:
./vex version
- Repository names cannot currently contain a slash.
- Only application/vnd.docker.distribution.manifest.v2+json and application/vnd.docker.distribution.manifest.list.v2+json content-types are supported. The OCI copies are not currently recognized, i.e. application/vnd.oci.image.manifest.v1+json and application/vnd.oci.image.index.v1+json.
Data is stored sha256 content-addressed. A docker image consist of a JSON manifest (hashed to a digest) that references a JSON config blob (hashed to a blob digest) and layer blobs (also hashed to blob digests). A tag is a name for a manifest digest. Docker also has multiplatform ("list") manifests, which is a JSON document referencing multiple image manifests, for each supported os/architecture (platform). A tag can also point to a multiplatform/list manifest.
Uploading an image starts with uploading blobs, resulting in digests that the uploading tool verifies. Next the manifest is uploaded, also resulting in a digest. For multiplatform images, multiple manifests and their blobs are uploaded, and finally the multiplatform manifest itself, again resulting in a digest. Finally, a tag is created (or overwritten, e.g. "latest") pointing to the digest of the manifest.
Downloading an image typically starts with looking up a tag, resulting in a manifest digest. Then the manifest JSON is downloaded for that digest. And next the referenced blobs. The downloading tool will verify all digests. Only the initial tag is often not verified in practice, but it is if the pull address includes a digest, i.e. ending with "@sha256:...".
Blobs can be uploaded, and then never used in a manifest. This would result in storage waste. These layers can be cleaned up after a while.
We only allow objects to be removed when they are no longer referenced: a blob no longer referenced by an image manifest. An image manifest no longer referenced by a tag and multiplatform/list manifests. When the last reference to an object is removed, the object is automatically removed. So when an image manifest is removed, its blobs are automatically removed if no other image manifest references the image. And when a multiplatform/list manifest is removed, its now unreferenced image manifests (and their blobs) are automatically removed. I.e. we keep data consistent, and clean up automatically.
Vex was created after the "docker free teams sunset" announcement (which they sunrose again again shortly after).
Vex is more basic, simpler, smaller, and more limited in functionality than popular registry software. For example, the user permission/authorization model is very basic: any authenticated user has full control of the registry (convenient for small/medium-sized projects/organizations, internal registries and for testing/developing). Another example: popular registries typically depend on external components, e.g. PostgreSQL, redis, more... Vex is very self-contained: a statically compiled binary with no further dependencies. A final example: popular registries typically support pluggable or configurable storage backends (e.g. to AWS S3). Vex always stores files in the file system.
Popular registries are typically run using docker, and instructions assume that Vex doesn't assume docker and has instructions for running without docker. Useful if your users expect docker images but you haven't fully bought into the docker ecosystem.