Container Images
Section titled “Container Images”Every container starts from an image: the operating system, pre-installed software, and default configuration it boots with. The platform carries one base image, Debian 13 (debian/13). The marketplace lists images, both free community images and paid images that arrive pre-configured.
This page covers how to pick an image, how to import or purchase one, and how to use it when you create a container.
Available base image
Section titled “Available base image”| OS | Version | Image Name | Size |
|---|---|---|---|
| Debian | 13 (Trixie) | debian/13 | ~500 MB |
A create accepts only the base images enabled for its realm, which is debian/13. Naming any other image returns 400, and the error lists the accepted names. If you omit container_image, debian/13 is used.
API endpoints summary
Section titled “API endpoints summary”This page explains image concepts and selection. The endpoint reference carries the full request and response schemas.
Public marketplace:
- GET /api/v1/images/public - Browse available images
- GET /api/v1/images/public/{id} - Get image details
- GET /api/v1/images/{id}/icon - Download image icon
Your images:
- GET /api/v1/images/user - List imported/purchased images
- POST /api/v1/images/import/{id} - Import free image
- POST /api/v1/images/purchase/{id} - Purchase paid image
- POST /api/v1/images/rate/{id} - Rate image (0-5 stars)
What an image provides
Section titled “What an image provides”Creating a container instantiates an image:
Container Image (Debian 13) ↓Container Creation ↓Running Container (Debian 13 + your work)The image provides:
- Base operating system (Linux distribution)
- System libraries and tools
- Default package manager (apt)
- Initial filesystem structure
- Sometimes: Pre-installed software (databases, web servers, dev tools)
Your work builds on top: install applications, configure services, add data, and change the environment.
The image marketplace
Section titled “The image marketplace”Browse images
Section titled “Browse images” Filter with query parameters:
os- Filter by operating system (debian)architecture- Filter by CPU architecture (amd64, arm64, armhf)min_price/max_price- Filter by price rangemin_rating- Filter by minimum ratingsearch- Search by keywordsort_by/sort_order- Sort results
Image properties
Section titled “Image properties”Each image has:
| Property | Description | Example Values |
|---|---|---|
| OS | Operating system | debian |
| Release | Version/release | 13 |
| Architecture | CPU architecture | amd64, arm64, armhf |
| Size | Disk space required | 500 MB - 5 GB |
| Price | Cost in USD | 0 (free), 5, 10, 25 |
| Rating | Community rating | 0.0 - 5.0 stars |
| Variant | Special configuration | default, null |
Debian 13
Section titled “Debian 13”debian/13 (Trixie) is the base image for every workload: development, production services, databases, and Docker or Kubernetes hosts.
Characteristics:
- glibc and the apt package manager, with Debian’s full package repository
- Stable, slow-moving releases with security updates
- Minimal but complete environment (~500 MB)
CPU architecture
Section titled “CPU architecture”Match the image’s architecture to the server it will run on.
amd64 (x86-64)
Section titled “amd64 (x86-64)”The most common choice: standard Intel and AMD processors. Nearly all deployments use amd64 unless you specifically have ARM servers.
arm64 (ARM 64-bit)
Section titled “arm64 (ARM 64-bit)”ARM processors, such as Apple Silicon, AWS Graviton, and Raspberry Pi 4 and later. Used for ARM-based servers and cost-optimized cloud instances.
armhf (ARM hard float)
Section titled “armhf (ARM hard float)”Older ARM devices, Raspberry Pi 3 and earlier. Rarely needed in modern deployments.
Docker and Kubernetes inside containers
Section titled “Docker and Kubernetes inside containers”Hoody containers support Docker, Kubernetes, and other container orchestration platforms.
Docker inside containers
Section titled “Docker inside containers”A container created with hoody_kit: true gets the dev kit by default, and the dev kit already includes Docker Engine, Docker Compose, and Docker Buildx. Nothing to install and nothing to start: the Docker daemon starts on the first docker command, and the default user can run docker without sudo.
# In a container created with hoody_kit (dev kit on by default)docker run hello-worlddocker compose up -ddocker build -t myapp .In a container without the dev kit, install Docker Engine from Docker’s own Debian repository by following Docker’s installation guide for Debian, then use it the same way.
What works:
- Docker daemon runs inside the container
- Docker Compose and Docker Buildx
- Building and running Docker images
- Docker networking and volumes
- Resource limits such as
--memoryand--cpus, and--privilegedcontainers - Multi-container applications via Docker Compose
Kubernetes inside containers
Section titled “Kubernetes inside containers”Kind, Minikube and K3s each run a full Kubernetes cluster inside a Hoody container. Each one needs a short setup, shown below. Start from a container created with hoody_kit: true so Docker is already there for Kind and Minikube.
Kind runs each Kubernetes node as a Docker container, so it uses the Docker that the dev kit installs. It needs no extra settings.
- Install the
kindrelease binary from Kind’s Quick Start, andkubectlfrom the Kubernetes install guide. - Create the cluster and check it:
kind create clusterkubectl get nodesThe node reports Ready after about 20 seconds. kind delete cluster removes it.
K3s needs one kubelet setting before you install it. Without it, the K3s service restarts in a loop and the log shows open /dev/kmsg: no such file or directory.
sudo mkdir -p /etc/rancher/k3ssudo tee /etc/rancher/k3s/config.yaml >/dev/null <<'EOF'kubelet-arg: - "feature-gates=KubeletInUserNamespace=true"EOFcurl -sfL https://get.k3s.io | sudo sh -sudo k3s kubectl get nodesThe node reports Ready after about 10 seconds. A K3s server uses about 600 MB of memory, so give the container enough for it plus your workloads. To remove K3s, run /usr/local/bin/k3s-uninstall.sh.
Minikube
Section titled “Minikube”Minikube runs its node as a Docker container, like Kind. Install minikube from Minikube’s Get Started page and kubectl as for Kind, then start it with the Docker driver and the Docker container runtime:
minikube start --driver=docker --container-runtime=dockerkubectl get nodesPass --container-runtime=docker every time: with Minikube’s default runtime, containerd, no control-plane pod starts. Right after minikube start, give the cluster a few seconds before your first kubectl run: until the default service account exists, it fails with serviceaccount "default" not found.
Podman inside containers
Section titled “Podman inside containers”Install Podman from Debian:
sudo apt-get install -y podman slirp4netnsAs root, Podman works as installed. To run Podman as the default user (rootless), use the slirp4netns network, because the default rootless network does not start in a Hoody container. Make it the default once:
mkdir -p ~/.config/containerscat > ~/.config/containers/containers.conf <<'EOF'[network]default_rootless_network_cmd = "slirp4netns"EOFpodman run --rm docker.io/library/alpine wget -qO- https://example.comOr pass --network=slirp4netns on each podman run.
Recommended base image for Docker
Section titled “Recommended base image for Docker”Use debian/13 as the base image when running Docker:
POST /api/v1/projects/{id}/containers{ "name": "docker-host", "server_id": "{server_id}", "container_image": "debian/13", "hoody_kit": true}Why Debian:
- Stable enough for long-running Docker daemons
- Docker packages are well supported
- Minimal conflicts with container runtimes
- Well-tested in production environments
With hoody_kit: true, Docker is ready as soon as the container is: use it for single containers, Docker Compose stacks, or a full orchestration platform.
Import and purchase images
Section titled “Import and purchase images”Import free images
Section titled “Import free images”Most OS images are free.
First, find images in the marketplace:
Then import to your library:
Response:
{ "statusCode": 200, "message": "Free image imported successfully", "data": {}}The image is now in your library (GET /api/v1/images/user). A create still names its base image in the {os}/{release} format, debian/13.
Purchase premium images
Section titled “Purchase premium images”Some images include pre-installed commercial software.
First, check image details (including price):
Then purchase the image:
Response:
{ "statusCode": 200, "message": "Image purchased successfully", "data": { "price_paid": 15, "remaining_balance": 485 }}The price is deducted from your wallet balance. It is a one-time payment, and access is permanent.
Imported and purchased images
Section titled “Imported and purchased images” The response lists the images you have imported or purchased. A create still accepts only the base images enabled for its realm (debian/13), whatever your library holds.
Image ratings
Section titled “Image ratings”Rate images to help other people choose:
Rating scale (0-5):
- 5 stars: Excellent (works perfectly, well-configured)
- 4 stars: Good (minor issues or missing documentation)
- 3 stars: Average (works but needs tweaking)
- 2 stars: Poor (significant issues)
- 1 star: Broken (doesn’t work as advertised)
- 0 stars: Lowest possible rating (also accepted by the API)
Use an image at creation
Section titled “Use an image at creation”Specify the image
Section titled “Specify the image” The container_image parameter:
- Format:
{os}/{release}, which isdebian/13 - Must match a base image enabled for the realm; anything else returns
400with the accepted names in the message - If omitted or null:
debian/13
Image selection examples
Section titled “Image selection examples”Web application stack
Section titled “Web application stack”A Node.js application: create the container with debian/13, then install Node.js over the terminal URL or SSH.
Database container
Section titled “Database container”PostgreSQL on debian/13. Install PostgreSQL with apt.
Multi-architecture support
Section titled “Multi-architecture support”The same application on both AMD64 servers (Intel and AMD) and ARM64 servers (Graviton, Apple Silicon). Use debian/13 on both; the architecture follows the target server automatically.
Image variants
Section titled “Image variants”Some images come in specialized variants:
| Variant | Description | When to Use |
|---|---|---|
| default | Default full-featured | General use |
| minimal | Stripped-down version | Size-constrained scenarios |
| cloud | Optimized for cloud deployment | Production servers |
| desktop | Includes GUI components | When using displays |
Format: Specify the image by its alias (debian/13). The variant is exposed as a separate variant field in each image’s marketplace metadata; it is not selected by appending a suffix to the alias.
Check the marketplace for the variants available.
Build templates from images
Section titled “Build templates from images”Images and snapshots together give you reusable environment templates:
The template workflow
Section titled “The template workflow”Start with a clean container from the debian/13 image, with Hoody Kit enabled.
Install Node.js, tools, and dependencies over the terminal URL. Add global npm packages (TypeScript, pnpm, yarn), configure Git, and prepare the development environment.
Capture that state as a snapshot with a readable alias, “nodejs-dev-template-2025”. Set expiry to null to keep it permanently.
Copy from the template snapshot into new projects. The tools are already installed, so there is no setup step. One template serves any number of containers.
Discover and search images
Section titled “Discover and search images”Search by keyword
Section titled “Search by keyword”# Find Docker-related imageshoody images list --search docker
# Find database imageshoody images list --search database
# Find Node.js imageshoody images list --search nodejs// Find Docker-related imagesconst dockerImages = await client.api.images.listPublic({ search: 'docker' });
// Find database imagesconst dbImages = await client.api.images.listPublic({ search: 'database' });# Find Docker-related imagescurl "https://api.hoody.com/api/v1/images/public?search=docker" \ -H "Authorization: Bearer $HOODY_TOKEN"
# Find database imagescurl "https://api.hoody.com/api/v1/images/public?search=database" \ -H "Authorization: Bearer $HOODY_TOKEN"
# Find Node.js imagescurl "https://api.hoody.com/api/v1/images/public?search=nodejs" \ -H "Authorization: Bearer $HOODY_TOKEN"One request, one link
cURL runs inside your container and can wrap any HTTP request into a single GET URL. The call stops being something you need a client for and becomes something you can paste into a browser, send in a chat, bookmark, schedule with cron, or drop into a no-code tool.
Nothing is installed on the machine that opens it. The link does carry whatever credentials the call needs, so treat it as you would treat those credentials.
Slashes, colons and braces pass through as they are. The one character you must
encode is an & inside a value, which happens when the wrapped URL
carries its own query string. Left raw it ends the value early, and the rest is
read as cURL's own parameters, so you get a 200 on a request you did
not make.
How the wrapping works Chaining calls into one link Turning a link into a shortcut
Each link searches the public marketplace for a different keyword.
# Docker images
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?search=docker&method=GET&bearer_token=TOKEN&response=transparent
# Database images
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?search=database&method=GET&bearer_token=TOKEN&response=transparent
# Node.js images
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?search=nodejs&method=GET&bearer_token=TOKEN&response=transparent The link carries a credential and executes with it, so it is as sensitive as the credential itself — and it passes through the cURL service's request log on the way, not just the target's. Share it only where you would share the secret, and prefer a delegated token with minimal permissions and an expiry: see API tokens.
Searches: image name, description, and tags.
Sort by rating
Section titled “Sort by rating”# Highest rated imageshoody images list --sort-by rating --sort-order desc --limit 10// Highest rated imagesconst topImages = await client.api.images.listPublic({ page: 1, limit: 10, sort_by: 'rating', sort_order: 'desc',});# Highest rated imagescurl "https://api.hoody.com/api/v1/images/public?sort_by=rating&sort_order=desc&limit=10" \ -H "Authorization: Bearer $HOODY_TOKEN"One request, one link
cURL runs inside your container and can wrap any HTTP request into a single GET URL. The call stops being something you need a client for and becomes something you can paste into a browser, send in a chat, bookmark, schedule with cron, or drop into a no-code tool.
Nothing is installed on the machine that opens it. The link does carry whatever credentials the call needs, so treat it as you would treat those credentials.
Slashes, colons and braces pass through as they are. The one character you must
encode is an & inside a value, which happens when the wrapped URL
carries its own query string. Left raw it ends the value early, and the rest is
read as cURL's own parameters, so you get a 200 on a request you did
not make.
How the wrapping works Chaining calls into one link Turning a link into a shortcut
Lists the ten highest-rated public images.
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?sort_by=rating%26sort_order=desc%26limit=10&method=GET&bearer_token=TOKEN&response=transparent The link carries a credential and executes with it, so it is as sensitive as the credential itself — and it passes through the cURL service's request log on the way, not just the target's. Share it only where you would share the secret, and prefer a delegated token with minimal permissions and an expiry: see API tokens.
Filter by price range
Section titled “Filter by price range”# Free images onlyhoody images list --min-price 0 --max-price 0
# Budget images ($0-$10)hoody images list --min-price 0 --max-price 10
# Premium images ($25+)hoody images list --min-price 25// Free images onlyconst freeImages = await client.api.images.listPublic({ min_price: 0, max_price: 0 });
// Budget images ($0-$10)const budgetImages = await client.api.images.listPublic({ min_price: 0, max_price: 10 });
// Premium images ($25+)const premiumImages = await client.api.images.listPublic({ min_price: 25 });# Free images onlycurl "https://api.hoody.com/api/v1/images/public?min_price=0&max_price=0" \ -H "Authorization: Bearer $HOODY_TOKEN"
# Budget images ($0-$10)curl "https://api.hoody.com/api/v1/images/public?min_price=0&max_price=10" \ -H "Authorization: Bearer $HOODY_TOKEN"
# Premium images ($25+)curl "https://api.hoody.com/api/v1/images/public?min_price=25" \ -H "Authorization: Bearer $HOODY_TOKEN"One request, one link
cURL runs inside your container and can wrap any HTTP request into a single GET URL. The call stops being something you need a client for and becomes something you can paste into a browser, send in a chat, bookmark, schedule with cron, or drop into a no-code tool.
Nothing is installed on the machine that opens it. The link does carry whatever credentials the call needs, so treat it as you would treat those credentials.
Slashes, colons and braces pass through as they are. The one character you must
encode is an & inside a value, which happens when the wrapped URL
carries its own query string. Left raw it ends the value early, and the rest is
read as cURL's own parameters, so you get a 200 on a request you did
not make.
How the wrapping works Chaining calls into one link Turning a link into a shortcut
Each link filters the public marketplace to a different price range.
# Free images only
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?min_price=0%26max_price=0&method=GET&bearer_token=TOKEN&response=transparent
# Budget images ($0-$10)
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?min_price=0%26max_price=10&method=GET&bearer_token=TOKEN&response=transparent
# Premium images ($25+)
https://PROJECT_ID-CONTAINER_ID-curl-1.SERVER.containers.hoody.com/api/v1/curl/request?url=https://api.hoody.com/api/v1/images/public?min_price=25&method=GET&bearer_token=TOKEN&response=transparent The link carries a credential and executes with it, so it is as sensitive as the credential itself — and it passes through the cURL service's request log on the way, not just the target's. Share it only where you would share the secret, and prefer a delegated token with minimal permissions and an expiry: see API tokens.
Image metadata
Section titled “Image metadata”Get detailed information about a single image:
Response:
{ "statusCode": 200, "message": "Public image details retrieved successfully", "data": { "id": "63a3e4b5c6d7e8f9a0b1c2d3", "alias": "debian/13", "description": "Debian 13 (Trixie)", "image_name": "debian-13-amd64", "architecture": "amd64", "os": "debian", "release": "13", "serial": "20250809", "variant": "default", "size": 524288000, "price": 0, "added_date": "2023-11-09T00:00:00.000Z", "average_rating": 4.8, "rating_count": 1247, "icon_url": "/api/v1/images/63a3e4b5c6d7e8f9a0b1c2d3/icon" }}Use to:
- Verify architecture matches server
- Check size for storage planning
- Read description for pre-installed software
- See community ratings for quality
Best practices
Section titled “Best practices”Match architecture to the server
Section titled “Match architecture to the server”Verify the server’s architecture before selecting an image. Query GET /api/v1/servers/{id} and filter images by that architecture. A mismatch means the container will not start.
Import before bulk creation
Section titled “Import before bulk creation”If you are creating many containers from the same image, import it once first. Later creations then skip the import wait.
Name the exact image
Section titled “Name the exact image”Name the exact image, debian/13, rather than a bare debian, so a script keeps working if the default changes.
Use debian/13 for Docker hosts
Section titled “Use debian/13 for Docker hosts”When running Docker or Kubernetes inside a container, start with debian/13. Its Docker packages are well supported and it conflicts less with container runtimes.
Rate images after use
Section titled “Rate images after use”After using an image, rate it honestly on the 0 to 5 scale. Ratings are what the next person sees when picking an image.
Useful questions
Section titled “Useful questions”Can I change a container’s image after creation?
Section titled “Can I change a container’s image after creation?”No. The image is fixed once the container exists. To start again from a clean base:
- Snapshot your data
- Create a new container from
debian/13 - Transfer data manually or via storage shares
- Delete old container
What happens if I import an image I already have?
Section titled “What happens if I import an image I already have?”The API returns 400 Bad Request with the message Image is not free or already imported. Re-importing is not idempotent. You do not need to re-import anyway: images already in your library are immediately available, so skip the import step entirely for an image you own.
Do purchased images work on all my servers?
Section titled “Do purchased images work on all my servers?”A purchase is tied to your account, not to one server, so it stays in your library on all of them. Container creation still accepts only debian/13.
Can I create my own custom images?
Section titled “Can I create my own custom images?”Not directly through the API. The template workflow gets close: start from a base image, configure it, snapshot it, then copy from that snapshot. The snapshot becomes your reusable template.
What’s the difference between image variants?
Section titled “What’s the difference between image variants?”Variants are different configurations of the same OS version. “minimal” has fewer pre-installed packages (smaller size), “cloud” is optimized for cloud deployment, “desktop” includes GUI components for display service.
Do images include the Hoody Kit?
Section titled “Do images include the Hoody Kit?”No. Images are base operating systems only. The Hoody Kit (19 HTTP services) is installed when you create the container if you set hoody_kit: true in the creation request.
Can I roll back to a previous image version?
Section titled “Can I roll back to a previous image version?”No. The platform carries one release, debian/13. To return to a known state, snapshot a working container and copy from that snapshot.
How do I know which image to use for my application?
Section titled “How do I know which image to use for my application?”Use debian/13. Check that the packages your application needs are in Debian’s repository, and that the image’s architecture matches your server.
Do images affect container pricing?
Section titled “Do images affect container pricing?”Indirectly. Larger images need more storage, which costs more, and premium images carry a purchase price. Image choice does not affect compute pricing: CPU and RAM are charged on allocation, not on the OS.
Troubleshooting
Section titled “Troubleshooting”Image not found at creation
Section titled “Image not found at creation”Problem: Container creation fails with “image not found”
Solutions:
-
Import the image first:
Terminal window # Find image in marketplaceGET /api/v1/images/public?search=debian# Import itPOST /api/v1/images/import/{image_id} -
Check image name format:
Terminal window # Canonical: "debian/13"# Also accepted: "debian:13", "debian-13", "debian 13", and "debian" (resolved to debian/13) -
Verify image in your library:
Terminal window GET /api/v1/images/user# Ensure image appears in list -
Check the base-image allowlist. A create that returns
400 Invalid base imageis not a lookup failure: the name is not enabled for the realm. The error lists what is:debian/13.
Architecture mismatch
Section titled “Architecture mismatch”Problem: Container creation fails or crashes immediately
Cause: Image architecture doesn’t match server
Solution:
-
Check your server details:
Terminal window GET /api/v1/servers/{id}# Review the server's CPU to know which architecture to target -
Filter images by architecture:
Terminal window GET /api/v1/images/public?architecture=amd64# Or: ?architecture=arm64 -
Import matching image:
Terminal window POST /api/v1/images/import/{correct_architecture_image_id}
Insufficient balance for purchase
Section titled “Insufficient balance for purchase”Problem: Image purchase fails with insufficient funds
Solution:
# Check wallet balanceGET /api/v1/wallet/balances
# Add funds if needed# (via platform billing system)
# Then purchasePOST /api/v1/images/purchase/{image_id}Container creation is slow
Section titled “Container creation is slow”Problem: Container takes longer than expected to create
Cause: the first creation on a server pulls the image to it. Later containers from the same image on that server are faster. This is normal.
What’s next
Section titled “What’s next”Next pages:
- Create, Edit, Delete → - Use images in container creation
- Managing → - Operate containers regardless of image
- Snapshots → - Snapshot configured containers as templates
- Copy & Sync → - Duplicate configured environments
The Hoody Kit:
- The Hoody Kit → - 19 HTTP services, on any image
- API Reference → - Complete endpoint documentation
What this page covered:
- Images are OS templates for containers
debian/13is the base image the platform carries- Import free images or purchase premium ones
- Images are immutable and cannot change after creation
- Architecture must match the server
- Rating an image helps the next person choose