惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Martin Fowler
Martin Fowler
Jina AI
Jina AI
J
Java Code Geeks
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
I
InfoQ
L
LangChain Blog
The Cloudflare Blog
IT之家
IT之家
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
B
Blog
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
Blog — PlanetScale
Blog — PlanetScale
罗磊的独立博客
云风的 BLOG
云风的 BLOG
Microsoft Azure Blog
Microsoft Azure Blog
Engineering at Meta
Engineering at Meta
F
Fortinet All Blogs
博客园 - 聂微东
美团技术团队
博客园_首页

Devoriales - DevOps and Python Tutorials

Python Multiprocessing vs Threading: Which One Actually Speeds Up CPU-Bound Work? Istio Traffic Mirroring: Correlating Shadow Requests Kubernetes 1.37: What Actually Landed Kimi K3 Open Weights: What Moonshot Actually Shipped Cloud & DevOps & AI Digest: The Week of Jun 28, 2026 Cloud & DevOps & AI Digest: The Week of Jun 20, 2026 Ansible for DevOps Engineers: Architecture, Core Concepts, and Hands-On Lab Login Must-Have Kubernetes CLI Tools Every Platform Engineer Should Know Login Login Login Why Your Best Engineers Are Quitting (And How to Stop It) Login ArgoCD Vulnerability: How the ServerSideDiff Feature Exposes Kubernetes Secrets Login How Kubernetes Controls What Your Containers Can Do Login Multi-AZ Is Not Disaster Recovery: What the AWS Bahrain Outage Finally Proved Trivy Supply Chain Attack: When Your Security Scanner Becomes the Threat Is Claude Opus 4.6 Fast Mode Really Worth 6× the Price? Login Unlocking Higher Pod Density in EKS with Prefix Delegation AWS Regional NAT Gateway: What It Is and Why You Should Care Kubernetes 1.35 Timbernetes Release AWS re:Invent 2025: The Future of Kubernetes on EKS Debate Series: How Do We Control Deployment Order in Kubernetes? Debate Series: Should We Eliminate Kubernetes Secrets Entirely? Kubernetes CRDs Explained: A Beginner-Friendly Guide to Extending the Kubernetes API Reduce Cloud Cross-Zone Data Transfer Costs with Kubernetes 1.33 trafficDistribution
Building Custom Bitnami Images: A Guide for Self-Hosted C...
Aleksandro Matejic · 2025-08-19 · via Devoriales - DevOps and Python Tutorials

bitnami images

The container ecosystem experienced a shift when Broadcom acquired VMware, subsequently implementing monetization strategies across the Bitnami portfolio. As detailed in my previous analysis of Broadcom's Bitnami monetization impact, these change altered how organizations access trusted container images.

Understanding the Technical Challenge

The monetization changes mean organizations previously pulling images like bitnami/redis or bitnami/postgresql without restrictions now face authentication requirements and usage limitations. While Bitnami offers commercial solutions for production environments, some teams need alternatives for development, testing, or learning purposes.

The solution involves:

  • Cloning Bitnami's open-source container definitions
  • Automating the build process with GitHub Actions
  • Storing images in a private container registry (AWS ECR)
  • Updating Helm charts to reference custom images

Important Disclaimers

This guide is for educational and development purposes. Building your own container images introduces complexity and responsibility that many organizations may not be prepared to handle. Consider these factors:

  • Bitnami's Official Stance: Bitnami explicitly does not recommend self-building their images for production environments
  • Support Limitations: Self-built images void any support agreements with Bitnami
  • Security Responsibility: You become responsible for timely security updates and vulnerability management
  • Maintenance Overhead: Managing a custom image pipeline requires dedicated resources and expertise

When This Approach Makes Sense:

  • Development and testing environments where cost control is priority
  • Organizations with mature DevOps teams capable of maintaining custom pipelines
  • Scenarios where you need custom modifications to base images
  • Learning environments for understanding container build processes

Recommended Alternatives:

  • Bitnami's commercial offerings for production workloads
  • Official upstream images where available
  • Other trusted community-maintained alternatives

This guide demonstrates the technical feasibility of building custom Bitnami images using GitHub Actions and AWS ECR, plus how to update your Helm charts to consume these self-hosted images. Use this knowledge responsibly and consider the trade-offs carefully.

Setting Up the Infrastructure

Repository Structure

Create a dedicated repository for your container images with this structure:

container-images/
├── containers/bitnami/          # Bitnami container definitions
│   ├── nginx/
│   ├── redis/
│   ├── postgresql/
│   └── ...
├── .github/workflows/           # GitHub Actions workflows
└── README.md

AWS ECR Registry Provisioning

Before building images, provision ECR repositories for each application you'll host:

# Create ECR repositories for common applications
aws ecr create-repository --repository-name acmeorg-bitnami-redis --region us-east-1
aws ecr create-repository --repository-name acmeorg-bitnami-nginx --region us-east-1
aws ecr create-repository --repository-name acmeorg-bitnami-postgresql --region us-east-1

For Infrastructure as Code approaches, use tools like Terraform or AWS CDK to manage these repositories.

Build Locally

This is straightforward. Just go inside the bitnami container folder and the tool you want to build image for. Assume we want to build an image for Redis. Enter the folder:

containers/bitnami/redis/8.2/debian-12

Now just run:

docker buildx build --platform linux/arm64 -t bitnami-redis . --load 

Because I’m building on Apple Silicon (ARM64), I use the --platform flag to avoid accidental mismatches. This guarantees the image is built for the correct architecture expected by my Kubernetes cluster.

Now you can test the REDIS:

docker run --rm bitnami-redis redis-server --version

Output:

redis 21:11:53.26 INFO  ==>

Redis server v=8.2.1 sha=00000000:1 malloc=jemalloc-5.3.0 bits=64 build=6242b285f6fb7236

Building the Automation Pipeline

GitHub Actions Workflow

Create a flexible workflow that handles multiple image types and versions. In the following example, I've written a workflow that is assuming a role in AWS. It pushes the images to the pre-created repositories in the previous step.

name: Build and Push Container Image to ECR

on:
  workflow_dispatch:
    inputs:
      image_type:
        description: 'Type of image to build'
        required: true
        type: choice
        options:
          - 'bitnami'
        default: 'bitnami'
      
      image_name:
        description: 'Image name (e.g., nginx, redis, postgresql)'
        required: true
        type: string
      
      image_version:
        description: 'Image version (e.g., 1.29, 8.2, latest)'
        required: true
        type: string
        default: 'latest'
      
      os_flavor:
        description: 'Operating system flavor'
        required: true
        type: choice
        options:
          - 'debian-12'
        default: 'debian-12'

      aws_region:
        description: 'AWS region'
        required: true
        type: string
        default: 'us-east-1'

env:
  AWS_REGION: ${{ inputs.aws_region }}
  ORG_PREFIX: "acmeorg"

permissions:
  id-token: write
  contents: read

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout repository
        uses: actions/checkout@v5
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          role-session-name: GitHubActions-ECR-Push
          aws-region: ${{ env.AWS_REGION }}
      
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2
      
      - name: Determine build context and Dockerfile path
        id: build-context
        run: |
          IMAGE_TYPE="${{ inputs.image_type }}"
          IMAGE_NAME="${{ inputs.image_name }}"
          IMAGE_VERSION="${{ inputs.image_version }}"
          OS_FLAVOR="${{ inputs.os_flavor }}"
          
          if [ "$IMAGE_TYPE" == "bitnami" ]; then
            BUILD_CONTEXT="containers/bitnami/${IMAGE_NAME}/${IMAGE_VERSION}/${OS_FLAVOR}"
            DOCKERFILE_PATH="${BUILD_CONTEXT}/Dockerfile"
            FULL_IMAGE_NAME="bitnami-${IMAGE_NAME}"
            ECR_REPOSITORY="${{ env.ORG_PREFIX }}-bitnami-${IMAGE_NAME}"
            ECR_REPOSITORY="${ECR_REPOSITORY,,}"
          elif [ "$IMAGE_TYPE" == "custom" ]; then
            BUILD_CONTEXT="containers/custom/${IMAGE_NAME}/${IMAGE_VERSION}/${OS_FLAVOR}"
            DOCKERFILE_PATH="${BUILD_CONTEXT}/Dockerfile"
            FULL_IMAGE_NAME="${IMAGE_NAME}"
            ECR_REPOSITORY="${{ env.ORG_PREFIX }}-custom-${IMAGE_NAME}"
            ECR_REPOSITORY="${ECR_REPOSITORY,,}"
          fi

          # Verify Dockerfile exists
          if [ ! -f "$DOCKERFILE_PATH" ]; then
            echo "Dockerfile not found at: $DOCKERFILE_PATH"
            echo "Available paths:"
            find . -name "Dockerfile" -path "./containers/${IMAGE_TYPE}/${IMAGE_NAME}/*" | head -10
            exit 1
          fi
          
          echo "build-context=$BUILD_CONTEXT" >> $GITHUB_OUTPUT
          echo "dockerfile-path=$DOCKERFILE_PATH" >> $GITHUB_OUTPUT
          echo "full-image-name=$FULL_IMAGE_NAME" >> $GITHUB_OUTPUT
          echo "ecr-repository=$ECR_REPOSITORY" >> $GITHUB_OUTPUT
      
      - name: Verify ECR repository exists
        run: |
          ECR_REPOSITORY="${{ steps.build-context.outputs.ecr-repository }}"
          
          if ! aws ecr describe-repositories --repository-names "$ECR_REPOSITORY" --region ${{ env.AWS_REGION }} >/dev/null 2>&1; then
            echo "ECR repository '$ECR_REPOSITORY' does not exist in region ${{ env.AWS_REGION }}"
            echo "Please create the repository first using AWS CLI or Console"
            exit 1
          else
            echo "ECR repository $ECR_REPOSITORY exists"
          fi
        
      - name: Generate image tags
        id: tags
        run: |
          ECR_REGISTRY="${{ steps.login-ecr.outputs.registry }}"
          ECR_REPOSITORY="${{ steps.build-context.outputs.ecr-repository }}"
          IMAGE_VERSION="${{ inputs.image_version }}"
          
          TIMESTAMP=$(date +%Y%m%d-%H%M%S)
          GIT_SHA=$(git rev-parse --short HEAD)
          
          # Generate tags
          TAGS="${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_VERSION}"
          TAGS="${TAGS},${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_VERSION}-${TIMESTAMP}"
          TAGS="${TAGS},${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_VERSION}-${GIT_SHA}"

          echo "tags=$TAGS" >> $GITHUB_OUTPUT
          echo "primary-tag=${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_VERSION}" >> $GITHUB_OUTPUT
          
      - name: Check if image exists
        run: |
          ECR_REGISTRY="${{ steps.login-ecr.outputs.registry }}"
          ECR_REPOSITORY="${{ steps.build-context.outputs.ecr-repository }}"
          IMAGE_VERSION="${{ inputs.image_version }}"

          if aws ecr describe-images --repository-name "$ECR_REPOSITORY" --image-ids imageTag="$IMAGE_VERSION" --region ${{ env.AWS_REGION }} >/dev/null 2>&1; then
            echo "Image $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_VERSION already exists. Skipping build."
            exit 0
          else
            echo "Image does not exist, proceeding with build."
          fi

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: ${{ steps.build-context.outputs.build-context }}
          file: ${{ steps.build-context.outputs.dockerfile-path }}
          push: true
          tags: ${{ steps.tags.outputs.tags }}
          platforms: linux/amd64
          cache-from: type=gha
          cache-to: type=gha,mode=max
          labels: |
            org.opencontainers.image.title=${{ steps.build-context.outputs.full-image-name }}
            org.opencontainers.image.version=${{ inputs.image_version }}
            org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
            org.opencontainers.image.revision=${{ github.sha }}
      
      - name: Output image details
        run: |
          echo "Successfully built and pushed image!"
          echo "Primary tag: ${{ steps.tags.outputs.primary-tag }}"
          echo "Pull command: docker pull ${{ steps.tags.outputs.primary-tag }}"

Key Workflow Features

The workflow supports both Bitnami and you could also add a custom image type, allowing you to extend beyond Bitnami's catalog as needed. Each build creates multiple tags including timestamped and Git SHA variants for precise version tracking.

It utilizes GitHub Actions cache to accelerate subsequent builds of the same image. I've also added a check for ECR repository existence and prevents duplicate builds of existing image versions.

You can extend this by implementing the Semantic Release and use tags instead. It's totally up to you.

Adding Bitnami Applications

Copying Container Definitions

To add a new application from Bitnami's catalog:

# Clone Bitnami's containers repository
git clone https://github.com/bitnami/containers.git bitnami-source
cd bitnami-source

# Copy specific application (e.g., Redis)
cp -r bitnami/redis ../containers/bitnami/

# Clean up
cd ..
rm -rf bitnami-source

Ensure the copied application follows Bitnami's standard structure:

containers/bitnami/redis/
├── 8.2/
│   └── debian-12/
│       ├── Dockerfile
│       ├── prebuildfs/
│       └── rootfs/
├── docker-compose.yml
└── README.md

Updating Helm Charts for Custom Images

Understanding Chart Dependencies

Most Bitnami Helm charts reference multiple container images. For Redis, the Chart.yaml typically includes:

annotations:
  images: |
    - name: kubectl
      image: bitnami/kubectl:1.33.3
    - name: redis
      image: bitnami/redis:8.2.0
    - name: redis-exporter
      image: bitnami/redis-exporter:1.74.0
    - name: redis-sentinel
      image: bitnami/redis-sentinel:8.0.3

Selective Image Replacement

You don't need to build every referenced image. Focus on the components you actually use in your deployment.

Values Configuration

Update your values.yaml to reference your custom registry:

# Primary Redis configuration
image:
  registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com
  repository: acmeorg-bitnami-redis
  tag: 8.2.0
  digest: ""

# Redis Sentinel (if enabled)
sentinel:
  enabled: false  # Disable if not needed
  # If enabled:
  # image:
  #   registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com
  #   repository: acmeorg-bitnami-redis-sentinel
  #   tag: 8.0.3

# Redis Exporter (if metrics enabled)
metrics:
  enabled: false  # Disable if not needed
  # If enabled:
  # image:
  #   registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com
  #   repository: acmeorg-bitnami-redis-exporter
  #   tag: 1.74.0

# kubectl image (used for init containers)
kubectl:
  image:
    registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com
    repository: acmeorg-bitnami-kubectl
    tag: 1.33.3

❗In the value file, you need to enable the allowInsecureImages: true

global:
  imageRegistry: ""
  ## E.g.
  ## imagePullSecrets:
  ##   - myRegistryKeySecretName
  ##
  imagePullSecrets: []
  defaultStorageClass: ""
  storageClass: ""
  ## Security parameters
  ##
  security:
    ## @param global.security.allowInsecureImages Allows skipping image verification
    allowInsecureImages: true <<<<< MAKE SURE YOU HAVE THIS

Deployment Example

Deploy Redis using your custom images:

# Add Bitnami Helm repository
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

# Deploy with custom values
helm install my-redis bitnami/redis \
  --values values.yaml \
  --namespace redis \
  --create-namespace

Advanced Configuration

Multi-Architecture Builds

For some environments you can set ARM64 (like AWS Graviton instances), just modify the workflow to build multi-platform images:

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    platforms: linux/amd64,linux/arm64
    # ... other configuration

Security Scanning

Integrate container scanning into your pipeline:

- name: Run Trivy vulnerability scanner
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ${{ steps.tags.outputs.primary-tag }}
    format: 'sarif'
    output: 'trivy-results.sarif'

- name: Upload Trivy scan results
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: 'trivy-results.sarif'

Automated Updates

Create scheduled workflows to check for new Bitnami releases:

name: Check for Updates

on:
  schedule:
    - cron: '0 6 * * 1'  # Weekly on Mondays

jobs:
  check-updates:
    runs-on: ubuntu-latest
    steps:
      - name: Check Bitnami repository for updates
        run: |
          # Script to compare your versions with upstream
          # Create issues or PRs for detected updates

Conclusion

Building your own Bitnami images is a technical exercise that requires careful consideration of the trade-offs involved. While this guide demonstrates the technical feasibility, remember that Bitnami does not recommend this approach for production environments.

Key Takeaways:

  • Educational Value: Understanding how to build container images strengthens your DevOps knowledge
  • Development Use Cases: This approach can be valuable for development and testing environments
  • Production Considerations: For production workloads, evaluate Bitnami's commercial offerings or other supported alternatives
  • Responsibility: Self-built images require ongoing maintenance, security updates, and vulnerability management

The GitHub Actions workflow presented here provides an idea for those who choose this path. Whether you use this for learning, development environments, or as part of a larger container strategy, approach it with full understanding of the responsibilities involved.

Organizations should carefully evaluate their specific needs, compliance requirements, and operational capabilities before implementing self-hosted container registries. For many use cases, Bitnami's commercial offerings or other officially supported alternatives is more appropriate.