# 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 ```bash # 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 ```bash 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) ```bash # 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 ```bash # 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 ``` ## Using Robot Accounts (Recommended for CI/CD) Robot accounts provide scoped credentials for automation. ### Create Robot Account 1. Go to your repository on Quay.io 2. Click **Settings** → **Robot 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 ```bash # Format: quay.io+username+robotname docker login quay.io Username: yourusername+sgo_builder Password: ``` ## 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`: ```yaml 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`: ```yaml 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 ```bash # 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 ```bash # 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 ### Recommended Tags ```bash # 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 ```bash 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 ```bash # 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 ```bash # 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`: ```yaml services: sgo: image: quay.io/yourusername/sgo:latest # rest of configuration... ``` Or pull specific version: ```yaml services: sgo: image: quay.io/yourusername/sgo:v1.0.0 # rest of configuration... ``` ## Troubleshooting ### Authentication Failed ```bash # 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 ```bash # Check Dockerfile syntax docker build --no-cache -t test . # View build logs docker build -t test . 2>&1 | tee build.log ``` ### Image Too Large ```bash # 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`: ```bash #!/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: ```bash chmod +x scripts/build-and-push.sh ``` Run it: ```bash ./scripts/build-and-push.sh ```