Images
Comprehensive guide to Podman image management including building, pulling, pushing, and registry operations.
Image Basics
Listing Images
# List all images
podman images
podman images -a # Include intermediate images
podman images --format table # Formatted table output
podman images --format json # JSON output
# Filter images
podman images alpine # Images matching 'alpine'
podman images --filter dangling=true # Dangling images
podman images --filter before=nginx # Images created before nginx
podman images --filter since=alpine # Images created after alpine
# Sort images
podman images --sort created # Sort by creation time
podman images --sort size # Sort by size
Pulling Images
# Pull from default registry (docker.io)
podman pull alpine
podman pull alpine:3.18
podman pull alpine:latest
# Pull from specific registry
podman pull quay.io/podman/hello
podman pull registry.redhat.io/rhel8/httpd-24
podman pull gcr.io/google-containers/pause
# Pull all tags
podman pull --all-tags alpine
# Pull with specific platform
podman pull --platform linux/amd64 alpine
podman pull --platform linux/arm64 nginx
# Pull quietly
podman pull -q nginx
Image Information
# Inspect image
podman inspect alpine
podman inspect alpine:3.18
# Image history (layers)
podman history alpine
podman history --human alpine # Human readable sizes
podman history --no-trunc alpine # Full layer IDs
# Image size and details
podman images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.Created}}"
Building Images
Building from Dockerfile
# Basic build
podman build -t myapp .
podman build -t myapp:v1.0 .
podman build -t registry.example.com/myapp:latest .
# Build with specific Dockerfile
podman build -f Dockerfile.prod -t myapp:prod .
podman build -f containers/Dockerfile -t myapp .
# Build with build args
podman build --build-arg VERSION=1.0 -t myapp .
podman build --build-arg USER_ID=$(id -u) -t myapp .
# Build with specific platform
podman build --platform linux/amd64 -t myapp .
podman build --platform linux/arm64 -t myapp-arm .
# Multi-platform build
podman build --platform linux/amd64,linux/arm64 -t myapp .
Advanced Build Options
# Build without cache
podman build --no-cache -t myapp .
# Build with custom context
podman build -t myapp /path/to/context
# Build from Git repository
podman build -t myapp https://github.com/user/repo.git
podman build -t myapp https://github.com/user/repo.git#branch
# Build from stdin
echo -e 'FROM alpine\nRUN echo "hello"' | podman build -t myapp -
# Build with labels
podman build --label version=1.0 --label maintainer=user@example.com -t myapp .
# Build with resource limits
podman build --memory=1g --cpus=2 -t myapp .
Dockerfile Examples
Multi-stage Build
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# Runtime stage
FROM node:18-alpine AS runtime
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Minimal Security-focused Build
FROM alpine:3.18 AS base
RUN apk update && apk upgrade && \
apk add --no-cache ca-certificates && \
addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
FROM base AS runtime
COPY app /app/
USER appuser
WORKDIR /app
CMD ["./app"]
Registry Operations
Pushing Images
# Login to registry
podman login docker.io
podman login -u username registry.example.com
podman login --password-stdin registry.example.com
# Push to registry
podman push myapp:latest
podman push registry.example.com/myapp:v1.0
# Push to specific registry
podman tag myapp:latest registry.example.com/myapp:latest
podman push registry.example.com/myapp:latest
# Push all tags
podman push --all-tags myapp
Registry Configuration
# Configure registries
sudo tee /etc/containers/registries.conf <<EOF
[registries.search]
registries = ['docker.io', 'quay.io', 'registry.redhat.io']
[registries.insecure]
registries = ['registry.local:5000']
[registries.block]
registries = ['untrusted-registry.com']
[[registry]]
location = "internal-registry.company.com"
insecure = false
blocked = false
mirror = [
{ location = "mirror1.company.com" },
{ location = "mirror2.company.com" }
]
EOF
Private Registry Setup
# Run local registry
podman run -d \
--name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry:2
# Use local registry
podman build -t localhost:5000/myapp .
podman push localhost:5000/myapp
podman pull localhost:5000/myapp
Image Management
Tagging Images
# Tag image
podman tag alpine myapp:base
podman tag myapp:latest myapp:v1.0
podman tag myapp:latest registry.example.com/myapp:latest
# Multiple tags
podman tag myapp:latest myapp:stable myapp:production
Removing Images
# Remove specific image
podman rmi alpine
podman rmi alpine:3.18
podman rmi myapp:v1.0
# Force remove (even if containers exist)
podman rmi -f myapp
# Remove multiple images
podman rmi alpine nginx ubuntu
# Remove all images
podman rmi $(podman images -q)
# Remove dangling images
podman image prune
# Remove all unused images
podman image prune -a
# Remove images with filter
podman image prune --filter "until=24h"
Image Import/Export
# Save image to tar file
podman save alpine > alpine.tar
podman save -o alpine.tar alpine
podman save myapp:latest | gzip > myapp.tar.gz
# Load image from tar file
podman load < alpine.tar
podman load -i alpine.tar
# Save multiple images
podman save -o images.tar alpine nginx ubuntu
# Export container as tar
podman export container_name > container.tar
# Import tar as image
podman import container.tar new_image:latest
podman import - new_image:latest < container.tar
Image Optimization
Reducing Image Size
# Use minimal base images
FROM alpine:3.18 # ~5MB
FROM debian:bullseye-slim # ~80MB
FROM scratch # 0MB (static binaries)
# Multi-stage builds
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
FROM alpine:3.18
RUN apk add --no-cache ca-certificates
COPY /app/app /app
CMD ["/app"]
# Combine RUN commands
RUN apk update && \
apk add --no-cache curl && \
apk del .build-deps && \
rm -rf /var/cache/apk/*
# Use .dockerignore
# .dockerignore
.git
*.md
node_modules
tests/
Layer Optimization
# Analyze image layers
podman history myapp
podman history --no-trunc myapp
# Use dive to analyze layers (external tool)
dive myapp:latest
# Optimize layer caching
# Order Dockerfile instructions from least to most likely to change
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./ # Copy package files first
RUN npm ci # Install dependencies
COPY . . # Copy source code last
RUN npm run build
Image Security
Vulnerability Scanning
# Scan with Trivy
podman run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image myapp:latest
# Scan specific severity
podman run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image --severity HIGH,CRITICAL myapp:latest
# Generate report
podman run --rm -v /var/run/docker.sock:/var/run/docker.sock \
-v $(pwd):/output \
aquasec/trivy image --format json --output /output/report.json myapp:latest
Secure Image Practices
# Use specific versions
FROM node:18.17.0-alpine3.18 # ✓ Specific version
FROM node:18-alpine # ✓ Acceptable
FROM node:latest # ✗ Unpredictable
# Run as non-root user
FROM alpine:3.18
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
USER appuser
# Update packages
RUN apk update && apk upgrade
# Remove unnecessary packages
RUN apk add --no-cache --virtual .build-deps \
build-base && \
# build commands here
apk del .build-deps
Image Formats and Standards
OCI Compliance
# Build OCI-compliant image
podman build --format oci -t myapp .
# Build Docker format
podman build --format docker -t myapp .
# Check image format
podman inspect myapp | grep -i format
Manifest Operations
# Create manifest list
podman manifest create myapp:latest
# Add images to manifest
podman manifest add myapp:latest myapp:amd64
podman manifest add myapp:latest myapp:arm64
# Push manifest
podman manifest push myapp:latest registry.example.com/myapp:latest
# Inspect manifest
podman manifest inspect myapp:latest
Automation and CI/CD
Build Scripts
#!/bin/bash
# build.sh
set -e
IMAGE_NAME="myapp"
VERSION=${1:-latest}
REGISTRY="registry.example.com"
echo "Building $IMAGE_NAME:$VERSION"
podman build -t $IMAGE_NAME:$VERSION .
echo "Tagging for registry"
podman tag $IMAGE_NAME:$VERSION $REGISTRY/$IMAGE_NAME:$VERSION
echo "Pushing to registry"
podman push $REGISTRY/$IMAGE_NAME:$VERSION
echo "Cleaning up"
podman image prune -f
GitHub Actions Example
name: Build and Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Podman
run: |
sudo apt update
sudo apt install -y podman
- name: Build image
run: podman build -t myapp:${{ github.sha }} .
- name: Push image
run: |
echo ${{ secrets.REGISTRY_PASSWORD }} | \
podman login -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin registry.example.com
podman push myapp:${{ github.sha }}
Quick Reference
Essential Image Commands
# Building
podman build -t myapp .
podman build --no-cache -t myapp .
# Managing
podman images
podman rmi myapp
podman image prune
# Registry
podman pull alpine
podman push myapp
podman login registry.example.com
# Import/Export
podman save myapp > myapp.tar
podman load < myapp.tar
Common Patterns
# Build and tag for multiple environments
podman build -t myapp:dev .
podman tag myapp:dev myapp:staging
podman tag myapp:dev registry.com/myapp:prod
# Clean development images
podman image prune --filter "label=stage=development"
# Update base image
podman pull alpine:latest
podman build --pull -t myapp .