SGO/wiki/Building-and-Publishing.md
Eduardo Figueroa a6b2cea31f
Some checks failed
CI / syntax-check (push) Has been cancelled
CI / security-scan (push) Has been cancelled
CI / container-lint (push) Has been cancelled
CI / container-build (push) Has been cancelled
Publish / publish (push) Has been cancelled
Migrate to Podman, Forgejo Actions; clean up cruft
Container:
- Dockerfile → Containerfile; drop gosu, entrypoint, PUID/PGID user-switching
- HOME=/config so Path.home()/.aws resolves to runtime-mounted credentials
- docker-compose.yml → compose.yml with userns_mode: keep-id for Podman rootless
- .dockerignore → .containerignore
- boto3 unpinned from 1.34.0 to >=1.34.0

CI:
- Remove Woodpecker (.woodpecker.yml, .woodpecker/)
- Add Forgejo Actions (.forgejo/workflows/ci.yml, publish.yml)
- CI: syntax check, security scan, container lint (hadolint), build test
- Publish: build and push to Quay.io on main push and version tags

Cleanup:
- Remove entrypoint.sh (no longer needed)
- Remove scripts/build-and-push.sh and PUBLISHING.md (superseded by CI)
- All docker → podman command references updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:41:08 -07:00

8.5 KiB

Building and Publishing to Quay.io

This guide covers how to build and publish SGO container images to Quay.io.

Prerequisites

  1. Quay.io account: Create account at https://quay.io
  2. Repository created: Create a repository (e.g., yourusername/sgo)
  3. Docker or Podman installed: For building and pushing images

Manual Build and Push

Step 1: Login to Quay.io

# Using Docker
docker login quay.io

# Using Podman
podman login quay.io

# You'll be prompted for:
# Username: your_quay_username
# Password: your_quay_password (or robot account token)

Step 2: Build the Image

cd /home/eduardo_figueroa/Dev/sgo

# Build with Docker
docker build -t quay.io/yourusername/sgo:latest .

# Build with Podman
podman build -t quay.io/yourusername/sgo:latest .

Step 3: Tag for Version (Optional)

# Tag with version number
docker tag quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:v1.0.0

# Tag with git commit
docker tag quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:$(git rev-parse --short HEAD)

Step 4: Push to Quay.io

# Push latest tag
docker push quay.io/yourusername/sgo:latest

# Push version tag
docker push quay.io/yourusername/sgo:v1.0.0

# Push all tags
docker push quay.io/yourusername/sgo --all-tags

Robot accounts provide scoped credentials for automation.

Create Robot Account

  1. Go to your repository on Quay.io
  2. Click SettingsRobot Accounts
  3. Click Create Robot Account
  4. Name it (e.g., sgo_builder)
  5. Grant Write permissions
  6. Save the credentials (username and token)

Login with Robot Account

# Format: quay.io+username+robotname
docker login quay.io
Username: yourusername+sgo_builder
Password: <robot-token>

Automated Build with Woodpecker CI

Step 1: Add Secrets to Woodpecker

Add these secrets to your Woodpecker CI configuration:

  • QUAY_USERNAME - Your quay.io username or robot account
  • QUAY_PASSWORD - Your quay.io password or robot token

Step 2: Create Woodpecker Pipeline

Create .woodpecker/docker-publish.yml:

pipeline:
  docker-build-and-push:
    image: docker:dind
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - QUAY_USERNAME
      - QUAY_PASSWORD
    commands:
      # Login to Quay.io
      - echo "$QUAY_PASSWORD" | docker login quay.io -u "$QUAY_USERNAME" --password-stdin

      # Build image
      - docker build -t quay.io/yourusername/sgo:latest .
      - docker tag quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:${CI_COMMIT_SHA}

      # Push images
      - docker push quay.io/yourusername/sgo:latest
      - docker push quay.io/yourusername/sgo:${CI_COMMIT_SHA}

when:
  branch:
    - main
  event:
    - push
    - tag

Step 3: Update Main Woodpecker Config

Add to .woodpecker.yml:

when:
  event: [push, pull_request, tag]

pipeline:
  dependencies:
    image: python:3.11-slim
    commands:
      - pip install -r requirements.txt

  syntax-check:
    image: python:3.11-slim
    commands:
      - python -m py_compile app.py
      - python -m py_compile import_from_aws.py
      - python -m py_compile import_data.py

  docker-build:
    image: docker:dind
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    commands:
      - docker build -t sgo:${CI_COMMIT_SHA} .

  security-scan:
    image: python:3.11-slim
    commands:
      - pip install bandit safety
      - bandit -r . -ll || true
      - safety check --file requirements.txt || true

  # Only push on main branch
  publish-to-quay:
    image: docker:dind
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    secrets: [quay_username, quay_password]
    commands:
      - echo "$QUAY_PASSWORD" | docker login quay.io -u "$QUAY_USERNAME" --password-stdin
      - docker build -t quay.io/yourusername/sgo:latest .
      - docker tag quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:${CI_COMMIT_SHA}
      - docker push quay.io/yourusername/sgo:latest
      - docker push quay.io/yourusername/sgo:${CI_COMMIT_SHA}
    when:
      branch: main
      event: push

Multi-Architecture Builds

Build for multiple architectures (amd64, arm64):

Using Docker Buildx

# Create builder
docker buildx create --name multiarch --use

# Build and push multi-arch image
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t quay.io/yourusername/sgo:latest \
  --push \
  .

Using Podman

# Build for amd64
podman build --platform linux/amd64 -t quay.io/yourusername/sgo:latest-amd64 .

# Build for arm64
podman build --platform linux/arm64 -t quay.io/yourusername/sgo:latest-arm64 .

# Create and push manifest
podman manifest create quay.io/yourusername/sgo:latest
podman manifest add quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:latest-amd64
podman manifest add quay.io/yourusername/sgo:latest quay.io/yourusername/sgo:latest-arm64
podman manifest push quay.io/yourusername/sgo:latest

Tagging Strategy

# Latest - always points to newest build
quay.io/yourusername/sgo:latest

# Version tags - for releases
quay.io/yourusername/sgo:v1.0.0
quay.io/yourusername/sgo:v1.0
quay.io/yourusername/sgo:v1

# Git commit SHA - for specific commits
quay.io/yourusername/sgo:abc1234

# Branch name - for development branches
quay.io/yourusername/sgo:dev
quay.io/yourusername/sgo:feature-xyz

Applying Multiple Tags

IMAGE_NAME="quay.io/yourusername/sgo"
VERSION="v1.0.0"
COMMIT=$(git rev-parse --short HEAD)

# Build once
docker build -t ${IMAGE_NAME}:${VERSION} .

# Apply multiple tags
docker tag ${IMAGE_NAME}:${VERSION} ${IMAGE_NAME}:latest
docker tag ${IMAGE_NAME}:${VERSION} ${IMAGE_NAME}:${COMMIT}

# Push all tags
docker push ${IMAGE_NAME}:${VERSION}
docker push ${IMAGE_NAME}:latest
docker push ${IMAGE_NAME}:${COMMIT}

Verifying the Published Image

Pull and Test

# Pull the image
docker pull quay.io/yourusername/sgo:latest

# Test it works
docker run --rm \
  -e AWS_CONFIG_PATH=/tmp/aws-host \
  -e PUID=1000 \
  -e PGID=1000 \
  -v $HOME/.aws:/tmp/aws-host:ro \
  -v sgo-data:/app/data \
  -p 5000:5000 \
  quay.io/yourusername/sgo:latest

Check Image Details

# Inspect image
docker inspect quay.io/yourusername/sgo:latest

# Check image size
docker images quay.io/yourusername/sgo

# View image history
docker history quay.io/yourusername/sgo:latest

Making Repository Public

By default, Quay.io repositories are private.

To make public:

  1. Go to repository on Quay.io
  2. Click Settings
  3. Change Repository Visibility to Public
  4. Click Save

Updating docker-compose.yml for Quay.io

Users can pull from Quay.io by updating their docker-compose.yml:

services:
  sgo:
    image: quay.io/yourusername/sgo:latest
    # rest of configuration...

Or pull specific version:

services:
  sgo:
    image: quay.io/yourusername/sgo:v1.0.0
    # rest of configuration...

Troubleshooting

Authentication Failed

# Clear old credentials
rm ~/.docker/config.json

# Login again
docker login quay.io

Push Denied

  • Verify repository exists on Quay.io
  • Check robot account has Write permissions
  • Ensure you're logged in to correct account

Build Fails

# Check Dockerfile syntax
docker build --no-cache -t test .

# View build logs
docker build -t test . 2>&1 | tee build.log

Image Too Large

# Check image size
docker images quay.io/yourusername/sgo

# Use .dockerignore to exclude files
# Already configured in project

# Use multi-stage builds (if applicable)
# Current Dockerfile is already optimized

Complete Build Script

Create scripts/build-and-push.sh:

#!/bin/bash
set -e

# Configuration
REGISTRY="quay.io"
USERNAME="yourusername"
REPO="sgo"
IMAGE="${REGISTRY}/${USERNAME}/${REPO}"

# Get version from git tag or use dev
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "dev")
COMMIT=$(git rev-parse --short HEAD)

echo "Building ${IMAGE}:${VERSION}"

# Build image
docker build -t ${IMAGE}:${VERSION} .

# Tag with multiple tags
docker tag ${IMAGE}:${VERSION} ${IMAGE}:latest
docker tag ${IMAGE}:${VERSION} ${IMAGE}:${COMMIT}

echo "Pushing to ${REGISTRY}"

# Push all tags
docker push ${IMAGE}:${VERSION}
docker push ${IMAGE}:latest
docker push ${IMAGE}:${COMMIT}

echo "Successfully pushed:"
echo "  - ${IMAGE}:${VERSION}"
echo "  - ${IMAGE}:latest"
echo "  - ${IMAGE}:${COMMIT}"

Make it executable:

chmod +x scripts/build-and-push.sh

Run it:

./scripts/build-and-push.sh