Skip to content

A bash-based orchestration framework for building, tagging, and deploying multi-platform Docker images.

License

Notifications You must be signed in to change notification settings

optimode/optibuild

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OptiBuild

A bash-based orchestration framework for building, tagging, and deploying multi-platform Docker images.

Philosophy

  • Simple is great
  • Configuration over convention - describe what to build, not how
  • Platform-explicit tagging - all image tags include platform suffix (-amd64, -arm64)
  • Private registry as source of truth - all operations happen there first
  • Clear separation of concerns - four distinct, independent phases

Features

  • Build multi-platform Docker images (amd64 + arm64)
  • Support for local and remote buildx builders
  • Automatic platform detection
  • Efficient tagging using crane (no data transfer)
  • Multiplatform manifest creation
  • Deploy to GitHub Container Registry and Docker Hub
  • Build caching via registry
  • Flexible phase execution (run all or specific phases)

Requirements

  • docker with buildx support
  • crane (for efficient image operations)
  • bash 4.0+

Install crane:

# macOS
brew install crane

# Linux
curl -sL "https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_$(uname -s)_$(uname -m).tar.gz" | tar -xz crane
sudo mv crane /usr/local/bin/

Quick Start

  1. Create a build.conf file in your project:
PROJECT_PATH="."
VERSION="1.0.5"
IMAGE_NAME="myproject"
REMOTE_BUILDER="amd64-builder"  # Optional: for cross-platform builds

TAGS=(
    "latest"
    "1.0"
)

BUILD_ARGS=(
    "PHP_VERSION=8.3"
)

GITHUB_ORG="optimode"
DOCKERHUB_ORG="optimode"
DEPLOY_TO_GITHUB=true
DEPLOY_TO_DOCKERHUB=true
  1. Run the build:
/path/to/optibuild all

Four Phases

1. BUILD

Builds Docker images for each platform with version tag.

Output (private registry):

registry.optimode.net/myproject:1.0.5-amd64
registry.optimode.net/myproject:1.0.5-arm64

Run separately:

optibuild build

2. TAG

Applies additional tags to already-built images (all platform-specific).

Output (private registry):

registry.optimode.net/myproject:latest-amd64
registry.optimode.net/myproject:latest-arm64
registry.optimode.net/myproject:1.0-amd64
registry.optimode.net/myproject:1.0-arm64

Run separately:

optibuild tag

3. MANIFEST

Creates multiplatform manifests (platform-agnostic tags).

Output (private registry):

registry.optimode.net/myproject:1.0.5  → points to -amd64 and -arm64
registry.optimode.net/myproject:latest → points to -amd64 and -arm64
registry.optimode.net/myproject:1.0    → points to -amd64 and -arm64

Run separately:

optibuild manifest

4. DEPLOY

Copies everything from private to public registries.

Output (public registries):

ghcr.io/optimode/myproject:1.0.5-amd64
ghcr.io/optimode/myproject:1.0.5-arm64
ghcr.io/optimode/myproject:1.0.5
ghcr.io/optimode/myproject:latest-amd64
ghcr.io/optimode/myproject:latest-arm64
ghcr.io/optimode/myproject:latest
... (all tags)

docker.io/optimode/myproject:* (same structure)

Run separately:

optibuild deploy

Configuration Reference

Required Fields

PROJECT_PATH="."              # Path to project directory (where Dockerfile is)
VERSION="1.0.5"               # Exact version to build
IMAGE_NAME="myproject"        # Image name (without registry)

Optional Fields

# Registry settings
PRIVATE_REGISTRY="registry.optimode.net"  # Default: registry.optimode.net

# Build settings
DOCKERFILE="Dockerfile"                    # Default: Dockerfile
BUILD_CONTEXT="."                          # Default: .

# Platform configuration
LOCAL_PLATFORM=""                          # Auto-detected if empty
REMOTE_PLATFORM=""                         # Auto-detected as opposite of local
REMOTE_BUILDER=""                          # Name of remote buildx builder (empty = local only)

# Tags (beyond the version itself)
TAGS=(
    "latest"
    "1.0"
    "1"
)

# Build arguments
BUILD_ARGS=(
    "PHP_VERSION=8.3"
    "COMPOSER_VERSION=2.7"
)

# Deploy targets
GITHUB_ORG="optimode"                      # For ghcr.io/optimode/...
DOCKERHUB_ORG="optimode"                   # For docker.io/optimode/...
DEPLOY_TO_GITHUB=true                      # Default: true
DEPLOY_TO_DOCKERHUB=true                   # Default: true

Usage Examples

Complete Pipeline

optibuild all

Build and Test Locally (skip deploy)

optibuild build tag manifest

Only Deploy (after manual verification)

optibuild deploy

Custom Configuration File

optibuild -c my-config.conf all

Verbose Output

optibuild --verbose build

Platform Detection

The framework automatically detects your local platform:

  • Mac M1/M2 (ARM64) → builds for linux/arm64 locally
  • Linux AMD64 → builds for linux/amd64 locally

If REMOTE_BUILDER is configured, it builds for the opposite platform using that builder.

Setting Up Remote Builder

For cross-platform builds, set up a remote buildx builder:

# On your remote AMD64 server
docker buildx create --name amd64-builder --driver docker-container

# From your local Mac
docker buildx create \
  --name amd64-builder \
  --driver docker-container \
  --platform linux/amd64 \
  ssh://user@remote-server

Then in your build.conf:

REMOTE_BUILDER="amd64-builder"

Authentication for Deployment

The framework supports automatic authentication to GitHub Container Registry and Docker Hub during deployment.

Token Priority Order

Tokens are searched in the following order:

  1. Environment variables
  2. Framework config file: ~/.optibuild/config
  3. Project build.conf file

GitHub Container Registry

Required variables (use any of these):

  • GITHUB_TOKEN - Personal Access Token with write:packages scope
  • GITHUB_CR_PAT - Container Registry Personal Access Token

Docker Hub

Required variables:

  • DOCKERHUB_TOKEN or DOCKERHUB_PASSWORD - Access token or password
  • DOCKERHUB_USERNAME (optional, defaults to DOCKERHUB_ORG)

Setup Methods

Option 1: Environment Variables (recommended for CI/CD)

export GITHUB_TOKEN="ghp_xxxxxxxxxxxxx"
export DOCKERHUB_TOKEN="dckr_pat_xxxxxxxxxxxxx"

optibuild deploy

Option 2: Framework Config File (recommended for local use)

Create ~/.optibuild/config:

# Copy the example file
mkdir -p ~/.optibuild
cp examples/framework-config-example ~/.optibuild/config

# Edit with your actual tokens
vim ~/.optibuild/config

# Make it readable only by you
chmod 600 ~/.optibuild/config

Example content:

# GitHub Container Registry
GITHUB_TOKEN="ghp_xxxxxxxxxxxxx"

# Docker Hub
DOCKERHUB_USERNAME="yourusername"
DOCKERHUB_TOKEN="dckr_pat_xxxxxxxxxxxxx"

Option 3: In build.conf (not recommended for security)

Add to your project's build.conf:

GITHUB_TOKEN="ghp_xxxxxxxxxxxxx"
DOCKERHUB_TOKEN="dckr_pat_xxxxxxxxxxxxx"

Warning: Don't commit tokens to git! Add build.conf to .gitignore if it contains secrets.

Creating Tokens

GitHub Personal Access Token:

  1. Go to https://github.com/settings/tokens
  2. Click "Generate new token (classic)"
  3. Select scopes: write:packages, read:packages, delete:packages
  4. Generate and copy the token

Docker Hub Access Token:

  1. Go to https://hub.docker.com/settings/security
  2. Click "New Access Token"
  3. Give it a description and select "Read, Write, Delete" permissions
  4. Generate and copy the token

Directory Structure

optibuild/
├── lib/
│   ├── common.sh        # Shared utilities, logging, error handling
│   ├── config.sh        # Configuration loading and validation
│   ├── build.sh         # Build phase functions
│   ├── tag.sh           # Tag phase functions
│   ├── manifest.sh      # Manifest creation functions
│   └── deploy.sh        # Deploy phase functions (with auto-authentication)
├── optibuild            # Main orchestrator script (executable)
├── README.md
├── .gitignore
└── examples/
    ├── framework-config-example    # Template for ~/.optibuild/config
    └── sample-project/
        ├── build.conf              # Project configuration with all options
        ├── Dockerfile              # Sample Dockerfile
        └── README.md               # Usage instructions

Troubleshooting

Error: "Base image not found"

Run phases in order:

optibuild build    # First build
optibuild tag      # Then tag
optibuild manifest # Then create manifests
optibuild deploy   # Finally deploy

Error: "Required command not found: crane"

Install crane (see Requirements section above).

Error: "docker buildx not found"

Install Docker Desktop or Docker CLI with buildx plugin.

Authentication Issues

The framework handles authentication automatically if tokens are configured (see "Authentication for Deployment" section).

Manual login (if needed):

# Private registry
docker login registry.optimode.net

# GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Docker Hub
echo $DOCKERHUB_TOKEN | docker login docker.io -u USERNAME --password-stdin

Common issues:

  • "GitHub token not found": Set GITHUB_TOKEN in environment, ~/.optibuild/config, or build.conf
  • "Docker Hub token not found": Set DOCKERHUB_TOKEN in environment, ~/.optibuild/config, or build.conf
  • "Failed to login": Check token validity and permissions
  • Already logged in: The framework automatically detects existing authentication

Remote Builder Issues

Test remote builder:

docker buildx ls
docker buildx inspect amd64-builder

Real-World Example

Building a Dovecot mail server image:

# build.conf
PROJECT_PATH="."
VERSION="2.4.0"
IMAGE_NAME="dovecot"
REMOTE_BUILDER="amd64-builder"

TAGS=(
    "latest"
    "2.4"
    "2"
)

BUILD_ARGS=(
    "DOVECOT_VERSION=2.4.0"
    "DEBIAN_VERSION=bookworm"
)

GITHUB_ORG="optimode"
DOCKERHUB_ORG="optimode"

Run:

optibuild all

Result:

  • Private registry has all platform-specific images and manifests
  • GitHub Container Registry has complete multiplatform image
  • Docker Hub has complete multiplatform image
  • Users can pull docker pull optimode/dovecot:latest on any platform

Error Handling

  • Fail fast: Any error in any phase stops the entire pipeline
  • No partial states: Either everything succeeds or nothing is deployed
  • Clear error messages: Always indicates what failed and why
  • Debugging: Use --verbose flag for detailed output

License

This is a simple bash framework and licensed under the MIT License - see the LICENSE file for details. Use it however you like.

Author

Optimode (Laszlo Malina) GitHub: @optimode

About

A bash-based orchestration framework for building, tagging, and deploying multi-platform Docker images.

Topics

Resources

License

Stars

Watchers

Forks

Languages