The buildah command is a powerful tool for building Open Container Initiative (OCI) compliant container images in Linux environments. Unlike Docker, buildah provides a more granular approach to image construction, allowing developers to build containers without requiring a daemon process.
What is buildah?
Buildah is a command-line tool designed specifically for building container images. It creates OCI-compliant images that can run on any container runtime, including Docker, Podman, and Kubernetes. The tool focuses solely on image building, making it lightweight and efficient for CI/CD pipelines.
Key Features of buildah
- Daemonless operation – no background service required
- OCI-compliant image creation
- Dockerfile compatibility
- Rootless container building support
- Fine-grained control over image layers
- Integration with Podman and other container tools
Installing buildah
Before using buildah commands, ensure it’s installed on your Linux system:
Ubuntu/Debian Installation
sudo apt update
sudo apt install buildah
CentOS/RHEL/Fedora Installation
# For CentOS/RHEL
sudo yum install buildah
# For Fedora
sudo dnf install buildah
Basic buildah Command Syntax
The general syntax for buildah commands follows this pattern:
buildah [global-options] command [command-options] [arguments]
Common Global Options
| Option | Description |
|---|---|
--help |
Display help information |
--version |
Show buildah version |
--storage-driver |
Specify storage driver |
--root |
Set storage root directory |
Essential buildah Commands
1. Building Images from Dockerfile
The most common use case is building images from a Dockerfile:
buildah build -t myapp:latest .
Example Output:
STEP 1/4: FROM ubuntu:20.04
Getting image source signatures
Copying blob 7c3b88808835 done
Copying config 1318b700e4 done
Writing manifest to image destination
Storing signatures
STEP 2/4: RUN apt-get update && apt-get install -y nginx
--> Running in a1b2c3d4e5f6
Reading package lists...
Building dependency tree...
STEP 3/4: COPY index.html /var/www/html/
--> a7b8c9d0e1f2
STEP 4/4: EXPOSE 80
COMMIT myapp:latest
--> b2c3d4e5f6a7
Successfully tagged localhost/myapp:latest
b2c3d4e5f6a7c8d9e0f1a2b3c4d5e6f7g8h9i0j1
2. Creating a Working Container
Start with a base image and create a working container:
buildah from ubuntu:20.04
Output:
ubuntu-working-container
3. Running Commands in Container
Execute commands inside the working container:
buildah run ubuntu-working-container -- apt-get update
buildah run ubuntu-working-container -- apt-get install -y python3
4. Copying Files to Container
Add files from your host system to the container:
buildah copy ubuntu-working-container app.py /usr/local/bin/
5. Configuring Container Settings
Set various container configurations:
# Set working directory
buildah config --workingdir /app ubuntu-working-container
# Set environment variables
buildah config --env PATH=/usr/local/bin:$PATH ubuntu-working-container
# Set entry point
buildah config --entrypoint '["python3", "/usr/local/bin/app.py"]' ubuntu-working-container
# Expose ports
buildah config --port 8080 ubuntu-working-container
6. Committing Changes to Image
Save your container as a new image:
buildah commit ubuntu-working-container myapp:v1.0
Output:
Getting image source signatures
Copying blob 1234567890ab done
Copying config abcdef123456 done
Writing manifest to image destination
Storing signatures
abcdef123456789012345678901234567890abcdef123456789012345678901234
Advanced buildah Usage
Multi-stage Builds
Create efficient images using multi-stage builds:
# Create build stage
buildah from --name builder golang:1.19-alpine
buildah copy builder . /src
buildah config --workingdir /src builder
buildah run builder -- go build -o app .
# Create runtime stage
buildah from --name runtime alpine:latest
buildah copy --from builder /src/app /usr/local/bin/
buildah config --entrypoint '["./usr/local/bin/app"]' runtime
buildah commit runtime myapp:optimized
Buildah with Custom Storage
Specify custom storage locations:
buildah --root /custom/storage --runroot /custom/run build -t myapp .
Building Images Without Dockerfile
Create images programmatically without a Dockerfile:
#!/bin/bash
# Create a working container
container=$(buildah from alpine:latest)
# Install packages
buildah run $container -- apk add --no-cache nodejs npm
# Copy application files
buildah copy $container package.json /app/
buildah copy $container server.js /app/
# Set working directory and install dependencies
buildah config --workingdir /app $container
buildah run $container -- npm install
# Configure the container
buildah config --port 3000 $container
buildah config --cmd '["node", "server.js"]' $container
# Commit the image
buildah commit $container nodejs-app:latest
# Clean up
buildah rm $container
Managing Container Images
Listing Images
buildah images
Sample Output:
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/myapp latest b2c3d4e5f6a7 2 hours ago 245 MB
localhost/nodejs-app latest a1b2c3d4e5f6 1 hour ago 156 MB
docker.io/library/alpine latest c1d2e3f4g5h6 3 days ago 5.61 MB
Removing Images
# Remove specific image
buildah rmi myapp:latest
# Remove all unused images
buildah rmi --prune
Inspecting Images
buildah inspect myapp:latest
Working with Containers
Listing Working Containers
buildah containers
Output:
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
a1b2c3d4e5f6 * 1234567890ab docker.io/library/ubuntu ubuntu-working-container
Mounting Container Filesystem
Access container filesystem directly:
# Mount container filesystem
mountpoint=$(buildah mount ubuntu-working-container)
echo $mountpoint
# Make changes directly
echo "Hello World" > $mountpoint/tmp/greeting.txt
# Unmount when done
buildah umount ubuntu-working-container
Removing Working Containers
# Remove specific container
buildah rm ubuntu-working-container
# Remove all containers
buildah rm --all
buildah vs Docker Comparison
| Feature | buildah | Docker |
|---|---|---|
| Daemon Required | No | Yes |
| Root Access | Optional (rootless) | Required by default |
| Focus | Building only | Full container lifecycle |
| OCI Compliance | Native | Supported |
Best Practices
1. Use Multi-stage Builds
Minimize final image size by separating build and runtime environments:
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
2. Optimize Layer Caching
Order Dockerfile instructions to maximize cache efficiency:
# Good - dependencies change less frequently
COPY package.json ./
RUN npm install
COPY . .
# Bad - invalidates cache on every code change
COPY . .
RUN npm install
3. Use .dockerignore
Exclude unnecessary files to reduce build context:
# .dockerignore
node_modules
.git
*.log
.DS_Store
README.md
Troubleshooting Common Issues
Permission Denied Errors
If you encounter permission issues, try running in rootless mode:
buildah --storage-driver vfs build -t myapp .
Storage Space Issues
Clean up unused resources regularly:
# Remove unused images
buildah rmi --prune
# Remove all stopped containers
buildah rm --all
# Check storage usage
buildah info
Network Issues During Build
Configure network settings if needed:
buildah build --network host -t myapp .
Integration with CI/CD
Buildah works excellently in CI/CD pipelines due to its daemonless architecture:
#!/bin/bash
# CI/CD build script
set -e
# Build the image
buildah build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
# Tag as latest if on main branch
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
buildah tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
fi
# Push to registry
buildah push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
buildah push $CI_REGISTRY_IMAGE:latest
fi
Conclusion
The buildah command provides a powerful, flexible approach to building container images in Linux environments. Its daemonless architecture, OCI compliance, and fine-grained control make it an excellent choice for both development and production scenarios. Whether you’re building simple applications or complex multi-stage images, buildah offers the tools needed for efficient container image creation.
By mastering buildah’s commands and best practices, you can create optimized, secure container images that integrate seamlessly with modern container orchestration platforms and CI/CD pipelines.








