Skip to content

virt.podman #

Podman Module

A clean, consolidated module for working with Podman containers and Buildah builders.

Overview

This module provides two complementary APIs for Podman functionality:

  1. Simple API: Direct functions for quick operations (podman.run_container(), podman.list_containers())
  2. Factory API: Advanced factory pattern for complex workflows and state management

Key Features

  • Container Management: Create, run, stop, and manage containers
  • Image Management: List, inspect, and manage container images
  • Builder Integration: Seamless Buildah integration for image building
  • Unified Error Handling: Consistent error types across all operations
  • Cross-Platform: Works on Linux and macOS

Platform Support

  • Linux: Full support
  • macOS: Full support (requires podman installation)
  • Windows: Not supported

Module Structure

  • factory.v - Main entry point with both simple API and factory pattern
  • container.v - All container types and management functions
  • image.v - All image types and management functions
  • builder.v - Buildah integration for image building
  • errors.v - Unified error handling system

API Approaches

1. Simple API (Quick Operations)

For simple container operations, use the direct functions:

import incubaid.herolib.virt.podman

// List containers and images
containers := podman.list_containers(true)!  // true = include stopped
images := podman.list_images()!

// Run a container
options := podman.RunOptions{
    name: 'my-app'
    detach: true
    ports: ['8080:80']
    volumes: ['/data:/app/data']
    env: {'ENV': 'production'}
}
container_id := podman.run_container('nginx:latest', options)!

// Manage containers
podman.stop_container(container_id)!
podman.remove_container(container_id, force: true)!
podman.remove_image('nginx:latest', force: false)!

2. Factory API (Advanced Workflows)

For complex operations and state management, use the factory pattern:

import incubaid.herolib.virt.podman

// Create factory (with auto-install)
mut factory := podman.new(install: true, herocompile: false)!

// Create containers with advanced options
container := factory.container_create(
    name: 'web-server'
    image_repo: 'nginx'
    image_tag: 'alpine'
    forwarded_ports: ['80:8080']
    memory: '512m'
    cpus: 1.0
)!

// Build images with Buildah
mut builder := factory.builder_new(
    name: 'my-app'
    from: 'ubuntu:latest'
)!
builder.run('apt-get update && apt-get install -y nodejs')!
builder.copy('./app', '/usr/src/app')!
builder.set_entrypoint('node /usr/src/app/server.js')!
builder.commit('my-app:latest')!

// Seamless integration: build with buildah, run with podman
app_container_id := factory.create_from_buildah_image('my-app:latest', config)!

Container Operations

Simple Container Management

// List containers
all_containers := podman.list_containers(true)!  // Include stopped
running_containers := podman.list_containers(false)!  // Only running

// Inspect container details
container_info := podman.inspect_container('container_id')!
println('Container status: ${container_info.status}')

// Container lifecycle
podman.stop_container('container_id')!
podman.remove_container('container_id', force: true)!

Advanced Container Creation

// Factory approach with full configuration
mut factory := podman.new()!

container := factory.container_create(
    name: 'web-app'
    image_repo: 'nginx'
    image_tag: 'alpine'

    // Resource limits
    memory: '1g'
    cpus: 2.0

    // Networking
    forwarded_ports: ['80:8080', '443:8443']
    network: 'bridge'

    // Storage
    mounted_volumes: ['/data:/app/data:ro', '/logs:/var/log']

    // Environment
    env: {'NODE_ENV': 'production', 'PORT': '8080'}

    // Runtime options
    detach: true
    remove_when_done: false
)!

Image Operations

Simple Image Management

// List all images
images := podman.list_images()!
for image in images {
    println('${image.repository}:${image.tag} - ${image.size}')
}

// Remove images
podman.remove_image('nginx:latest', force: false)!
podman.remove_image('old-image:v1.0', force: true)!  // Force removal

Factory Image Management

mut factory := podman.new()!

// Load and inspect images
factory.images_load()!  // Refresh image cache
images := factory.images_get()!

// Find specific images
image := factory.image_get(repo: 'nginx', tag: 'latest')!
println('Image ID: ${image.id}')

// Check if image exists
if factory.image_exists(repo: 'my-app', tag: 'v1.0')! {
    println('Image exists')
}

Builder Integration (Buildah)

Creating and Using Builders

mut factory := podman.new()!

// Create a builder
mut builder := factory.builder_new(
    name: 'my-app-builder'
    from: 'ubuntu:22.04'
    delete: true  // Remove existing builder with same name
)!

// Build operations
builder.run('apt-get update && apt-get install -y nodejs npm')!
builder.copy('./package.json', '/app/')!
builder.run('cd /app && npm install')!
builder.copy('./src', '/app/src')!

// Configure the image
builder.set_workingdir('/app')!
builder.set_entrypoint('node src/server.js')!

// Commit to image (automatically available in podman)
builder.commit('my-app:latest')!

// Use the built image immediately with podman
container_id := factory.create_from_buildah_image('my-app:latest', config)!

Build-to-Run Workflow

// Complete workflow: build with buildah, run with podman
container_id := factory.build_and_run_workflow(
    build_config: build_config,
    run_config: run_config,
    image_name: 'my-app'
)!

Error Handling

The module provides comprehensive error handling with specific error types:

// Simple API error handling
containers := podman.list_containers(true) or {
    match err {
        podman.ContainerError {
            println('Container operation failed: ${err.msg()}')
        }
        podman.ImageError {
            println('Image operation failed: ${err.msg()}')
        }
        else {
            println('Unexpected error: ${err.msg()}')
        }
    }
    []podman.PodmanContainer{}
}

// Factory API error handling
mut factory := podman.new() or {
    println('Failed to create factory: ${err}')
    exit(1)
}

container := factory.container_create(args) or {
    if err is podman.ContainerError {
        println('Container creation failed: ${err.msg()}')
    } else if err is podman.ImageError {
        println('Image error: ${err.msg()}')
    } else {
        println('Creation failed: ${err.msg()}')
    }
    return
}

// Builder error handling
mut builder := factory.builder_new(name: 'test', from: 'nonexistent:latest') or {
    println('Builder creation failed: ${err.msg()}')
    return
}

builder.run('invalid_command') or {
    println('Command execution failed: ${err.msg()}')
    // Continue with fallback or cleanup
}

Installation and Setup

import incubaid.herolib.virt.podman

// Automatic installation
mut factory := podman.new(install: true)!  // Will install podman if needed

// Manual installation check
mut factory := podman.new(install: false) or {
    println('Podman not found. Please install podman first.')
    exit(1)
}

Complete Example

See examples/virt/podman/podman.vsh for a comprehensive example that demonstrates:

  • Automatic podman installation
  • Simple API usage (run_container, list_containers, etc.)
  • Factory API usage (advanced container creation, builder workflows)
  • Error handling patterns
  • Integration between buildah and podman
  • Cleanup and uninstallation

API Reference

Simple API Functions

  • run_container(image, options) - Run a container with simple options
  • list_containers(all) - List containers (all=true includes stopped)
  • list_images() - List all available images
  • inspect_container(id) - Get detailed container information
  • stop_container(id) - Stop a running container
  • remove_container(id, force) - Remove a container
  • remove_image(id, force) - Remove an image

Factory API Methods

  • new(install, herocompile) - Create a new PodmanFactory
  • container_create(args) - Create container with advanced options
  • create_from_buildah_image(image, config) - Run container from buildah image
  • build_and_run_workflow(build_config, run_config, image_name) - Complete workflow
  • builder_new(name, from) - Create a new buildah builder
  • load() - Refresh factory state (containers, images, builders)
  • reset_all() - Remove all containers, images, and builders (CAREFUL!)

Future Enhancements

  • nerdctl compatibility: Make module compatible with nerdctl
  • Docker compatibility: Add Docker runtime support
  • Kubernetes integration: Support for pod and deployment management
  • Registry operations: Enhanced image push/pull capabilities

fn new_container_error #

fn new_container_error(operation string, container string, exit_code int, message string, stderr string) ContainerError

new_container_error creates a new container error

fn new_image_error #

fn new_image_error(operation string, image string, exit_code int, message string, stderr string) ImageError

new_image_error creates a new image error

fn new_podman_error #

fn new_podman_error(operation string, resource string, exit_code int, message string) PodmanError

new_podman_error creates a new podman error

fn (PodmanFactory) builder_base #

fn (mut e PodmanFactory) builder_base(args GetArgs) !Builder

builder machine based on arch and install vlang

fn (PodmanFactory) builder_delete #

fn (mut e PodmanFactory) builder_delete(name string) !

fn (PodmanFactory) builder_exists #

fn (mut e PodmanFactory) builder_exists(name string) !bool

fn (PodmanFactory) builder_get #

fn (mut e PodmanFactory) builder_get(name string) !Builder

fn (PodmanFactory) builder_hero #

fn (mut e PodmanFactory) builder_hero(args GetArgs) !Builder

builder with hero tools

fn (PodmanFactory) builder_new #

fn (mut e PodmanFactory) builder_new(args_ BuilderNewArgs) !Builder

fn (PodmanFactory) builders_delete_all #

fn (mut self PodmanFactory) builders_delete_all() !

delete all buildah containers/builders

fn (PodmanFactory) builders_get #

fn (mut e PodmanFactory) builders_get() ![]Builder

get buildah containers

fn (PodmanFactory) builders_load #

fn (mut self PodmanFactory) builders_load() !

load all buildah containers/builders

fn (PodmanFactory) container_create #

fn (mut e PodmanFactory) container_create(args_ ContainerCreateArgs) !&Container

create a new container from an image

fn (PodmanFactory) container_delete #

fn (mut self PodmanFactory) container_delete(args ContainerGetArgs) !

fn (PodmanFactory) container_exists #

fn (mut self PodmanFactory) container_exists(args ContainerGetArgs) !bool

fn (PodmanFactory) container_get #

fn (mut self PodmanFactory) container_get(args_ ContainerGetArgs) !&Container

get container from memory

fn (PodmanFactory) containers_delete #

fn (mut self PodmanFactory) containers_delete(args ContainerGetArgs) !

remove one or more container

fn (PodmanFactory) containers_get #

fn (mut self PodmanFactory) containers_get(args_ ContainerGetArgs) ![]&Container

get containers from memory

fn (PodmanFactory) containers_load #

fn (mut self PodmanFactory) containers_load() !

load all containers, they can be consulted in self.containers see obj: Container as result in self.containers

fn (PodmanFactory) image_exists #

fn (mut self PodmanFactory) image_exists(args ImageGetArgs) !bool

fn (PodmanFactory) image_get #

fn (mut self PodmanFactory) image_get(args ImageGetArgs) !Image

find image based on repo and optional tag

fn (PodmanFactory) image_load #

fn (mut engine PodmanFactory) image_load(path string) !

import image back into the local env

fn (PodmanFactory) images_get #

fn (mut self PodmanFactory) images_get() ![]Image

get images

fn (PodmanFactory) images_load #

fn (mut self PodmanFactory) images_load() !

Image management functions

enum ContainerStatus #

enum ContainerStatus {
	unknown
	created
	up
	down
	exited
	paused
	restarting
}

ContainerStatus represents the status of a container

struct BuildError #

struct BuildError {
	Error
pub:
	operation string
	container string
	exit_code int
	message   string
	stderr    string
}

BuildError represents errors that occur during build operations

fn (BuildError) msg #

fn (err BuildError) msg() string

fn (BuildError) code #

fn (err BuildError) code() int

struct Builder #

@[heap]
struct Builder {
pub mut:
	id            string
	containername string
	imageid       string
	imagename     string
	created       time.Time
	engine        &PodmanFactory @[skip; str: skip]
}

fn (Builder) delete #

fn (mut self Builder) delete() !

Builder methods

fn (Builder) run #

fn (mut self Builder) run(cmd string) !

fn (Builder) copy #

fn (mut self Builder) copy(src string, dest string) !

fn (Builder) shell #

fn (mut self Builder) shell() !

fn (Builder) commit #

fn (mut self Builder) commit(image_name string) !

fn (Builder) set_entrypoint #

fn (self Builder) set_entrypoint(entrypoint string) !

fn (Builder) set_workingdir #

fn (self Builder) set_workingdir(workdir string) !

fn (Builder) set_cmd #

fn (self Builder) set_cmd(command string) !

fn (Builder) mount_to_path #

fn (mut self Builder) mount_to_path() !string

mount the build container to a path and return the path where its mounted

struct BuilderInfo #

struct BuilderInfo {
pub:
	id            string
	containername string
	imageid       string
	imagename     string
	created       string
}

struct BuilderNewArgs #

@[params]
struct BuilderNewArgs {
pub mut:
	name   string = 'default'
	from   string = 'docker.io/ubuntu:latest'
	delete bool   = true
}

struct Container #

@[heap]
struct Container {
pub mut:
	id              string
	name            string
	created         time.Time
	ssh_enabled     bool // if yes make sure ssh is enabled to the container
	ipaddr          IPAddress
	forwarded_ports []string
	mounts          []ContainerVolume
	ssh_port        int // ssh port on node that is used to get ssh
	ports           []string
	networks        []string
	labels          map[string]string @[str: skip]
	image           &Image            @[str: skip]
	engine          &PodmanFactory    @[skip; str: skip]
	status          ContainerStatus
	memsize         int // in MB
	command         string
}

fn (Container) start #

fn (mut container Container) start() !

create/start container (first need to get a herocontainerscontainer before we can start)

fn (Container) halt #

fn (mut container Container) halt() !

delete container

fn (Container) delete #

fn (mut container Container) delete() !

delete container

fn (Container) restart #

fn (mut container Container) restart() !

restart container

fn (Container) logs #

fn (mut container Container) logs() !string

get logs from container

fn (Container) shell #

fn (mut container Container) shell() !

open shell to the container

fn (Container) execute #

fn (mut container Container) execute(cmd_ string, silent bool) !

struct ContainerCreateArgs #

@[params]
struct ContainerCreateArgs {
pub mut:
	name             string
	hostname         string
	forwarded_ports  []string          // ["80:9000/tcp", "1000, 10000/udp"]
	mounted_volumes  []string          // ["/root:/root", ]
	env              map[string]string // map of environment variables that will be passed to the container
	privileged       bool
	remove_when_done bool = true // remove the container when it shuts down
	// Resource limits
	memory             string // Memory limit (e.g. "100m", "2g")
	memory_reservation string // Memory soft limit
	memory_swap        string // Memory + swap limit
	cpus               f64    // Number of CPUs (e.g. 1.5)
	cpu_shares         int    // CPU shares (relative weight)
	cpu_period         int    // CPU CFS period in microseconds (default: 100000)
	cpu_quota          int    // CPU CFS quota in microseconds (e.g. 50000 for 0.5 CPU)
	cpuset_cpus        string // CPUs in which to allow execution (e.g. "0-3", "1,3")
	// Network configuration
	network         string   // Network mode (bridge, host, none, container:id)
	network_aliases []string // Add network-scoped aliases
	exposed_ports   []string // Ports to expose without publishing (e.g. "80/tcp", "53/udp")
	// DNS configuration
	dns_servers []string // Set custom DNS servers
	dns_options []string // Set custom DNS options
	dns_search  []string // Set custom DNS search domains
	// Device configuration
	devices             []string // Host devices to add (e.g. "/dev/sdc:/dev/xvdc:rwm")
	device_cgroup_rules []string // Add rules to cgroup allowed devices list
	// Runtime configuration
	detach      bool = true // Run container in background
	attach      []string // Attach to STDIN, STDOUT, and/or STDERR
	interactive bool     // Keep STDIN open even if not attached (-i)
	// Storage configuration
	rootfs          string   // Use directory as container's root filesystem
	mounts          []string // Mount filesystem (type=bind,src=,dst=,etc)
	volumes         []string // Bind mount a volume (alternative to mounted_volumes)
	published_ports []string // Publish container ports to host (alternative to forwarded_ports)
	image_repo      string
	image_tag       string
	command         string = '/bin/bash'
}

Container creation arguments

struct ContainerError #

struct ContainerError {
	Error
pub:
	operation string
	container string
	exit_code int
	message   string
	stderr    string
}

ContainerError represents container-specific errors

fn (ContainerError) msg #

fn (err ContainerError) msg() string

fn (ContainerError) code #

fn (err ContainerError) code() int

struct ContainerGetArgs #

@[params]
struct ContainerGetArgs {
pub mut:
	name     string
	id       string
	image_id string
}

struct ContainerGetError #

struct ContainerGetError {
	Error
pub:
	args     ContainerGetArgs
	notfound bool
	toomany  bool
}

fn (ContainerGetError) msg #

fn (err ContainerGetError) msg() string

fn (ContainerGetError) code #

fn (err ContainerGetError) code() int

struct ContainerVolume #

struct ContainerVolume {
pub:
	source      string
	destination string
	mode        string
}

ContainerVolume represents a container volume mount

struct GetArgs #

@[params]
struct GetArgs {
pub mut:
	reset bool
}

Builder solution methods for common setups

struct Image #

@[heap]
struct Image {
pub mut:
	repo    string
	id      string
	id_full string
	tag     string
	digest  string
	size    int // size in MB
	created time.Time
	engine  &PodmanFactory @[skip; str: skip]
}

fn (Image) delete #

fn (mut image Image) delete(force bool) !

delete podman image

fn (Image) export #

fn (mut image Image) export(path string) !string

export podman image to tar.gz

struct ImageError #

struct ImageError {
	Error
pub:
	operation string
	image     string
	exit_code int
	message   string
	stderr    string
}

ImageError represents image-specific errors

fn (ImageError) msg #

fn (err ImageError) msg() string

fn (ImageError) code #

fn (err ImageError) code() int

struct ImageGetArgs #

@[params]
struct ImageGetArgs {
pub:
	repo    string
	tag     string
	digest  string
	id      string
	id_full string
}

struct ImageGetError #

struct ImageGetError {
	Error
pub:
	args     ImageGetArgs
	notfound bool
	toomany  bool
}

fn (ImageGetError) msg #

fn (err ImageGetError) msg() string

fn (ImageGetError) code #

fn (err ImageGetError) code() int

struct PodmanContainer #

struct PodmanContainer {
pub:
	id      string            @[json: 'Id']      // Container ID
	image   string            @[json: 'Image']   // Image name
	command string            @[json: 'Command'] // Command being run
	status  string            @[json: 'Status']  // Container status (running, exited, etc.)
	names   []string          @[json: 'Names']   // Container names
	ports   []string          @[json: 'Ports']   // Port mappings
	created string            @[json: 'Created'] // Creation timestamp
	state   string            @[json: 'State']   // Container state
	labels  map[string]string @[json: 'Labels']  // Container labels
}

PodmanContainer represents a podman container with structured data from CLI JSON output

struct PodmanError #

struct PodmanError {
	Error
pub:
	code    int    // Error code from podman command
	message string // Error message
}

PodmanError represents errors that occur during podman operations

fn (PodmanError) msg #

fn (err PodmanError) msg() string

msg returns the error message

fn (PodmanError) code #

fn (err PodmanError) code() int

code returns the error code

struct PodmanImage #

struct PodmanImage {
pub:
	id         string @[json: 'Id']         // Image ID
	repository string @[json: 'Repository'] // Repository name
	tag        string @[json: 'Tag']        // Image tag
	size       string @[json: 'Size']       // Image size
	digest     string @[json: 'Digest']     // Image digest
	created    string @[json: 'Created']    // Creation timestamp
}

PodmanImage represents a podman image with structured data from CLI JSON output

struct RunOptions #

struct RunOptions {
pub:
	name        string // Container name
	detach      bool = true // Run in background
	interactive bool              // Keep STDIN open
	tty         bool              // Allocate a pseudo-TTY
	remove      bool              // Remove container when it exits
	env         map[string]string // Environment variables
	ports       []string          // Port mappings (e.g., "8080:80")
	volumes     []string          // Volume mounts (e.g., "/host:/container")
	working_dir string            // Working directory
	entrypoint  string            // Override entrypoint
	command     []string          // Command to run
}

RunOptions contains options for running a container