diff --git a/k8s/base-image/Makefile b/k8s/base-image/Makefile index 07e538b7..053fbb90 100644 --- a/k8s/base-image/Makefile +++ b/k8s/base-image/Makefile @@ -1,6 +1,10 @@ .PHONY: build push test update clean help +# Detect container engine (podman or docker) +CONTAINER_CMD := $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null) + REGISTRY ?= registry.gitlab.com/towerops/towerops +DOCKERHUB_REGISTRY ?= docker.io/gmcintire IMAGE_NAME ?= elixir-runtime ERLANG_VERSION ?= 28.3 ELIXIR_VERSION ?= 1.19.5 @@ -18,34 +22,46 @@ update: build ## Alias for build (rebuilds with latest packages) test: ## Test the built image @echo "Testing Erlang..." - @docker run --rm $(REGISTRY)/$(IMAGE_NAME):latest erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell + @$(CONTAINER_CMD) run --rm $(REGISTRY)/$(IMAGE_NAME):latest erl -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell @echo "Testing Elixir..." - @docker run --rm $(REGISTRY)/$(IMAGE_NAME):latest elixir --version + @$(CONTAINER_CMD) run --rm $(REGISTRY)/$(IMAGE_NAME):latest elixir --version @echo "Testing locale..." - @docker run --rm $(REGISTRY)/$(IMAGE_NAME):latest locale + @$(CONTAINER_CMD) run --rm $(REGISTRY)/$(IMAGE_NAME):latest locale @echo "✅ All tests passed!" -push: ## Push image to registry - @docker push $(REGISTRY)/$(IMAGE_NAME):$(TAG) - @docker push $(REGISTRY)/$(IMAGE_NAME):latest +push: ## Push image to GitLab and Docker Hub + @echo "Pushing to GitLab registry..." + @$(CONTAINER_CMD) push $(REGISTRY)/$(IMAGE_NAME):$(TAG) + @$(CONTAINER_CMD) push $(REGISTRY)/$(IMAGE_NAME):latest + @echo "Tagging for Docker Hub..." + @$(CONTAINER_CMD) tag $(REGISTRY)/$(IMAGE_NAME):$(TAG) $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):$(TAG) + @$(CONTAINER_CMD) tag $(REGISTRY)/$(IMAGE_NAME):latest $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):latest + @echo "Pushing to Docker Hub..." + @$(CONTAINER_CMD) push $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):$(TAG) + @$(CONTAINER_CMD) push $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):latest pull: ## Pull latest image from registry - @docker pull $(REGISTRY)/$(IMAGE_NAME):latest + @$(CONTAINER_CMD) pull $(REGISTRY)/$(IMAGE_NAME):latest inspect: ## Show image details (size, layers, labels) @echo "Image size:" - @docker images $(REGISTRY)/$(IMAGE_NAME):latest --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" + @$(CONTAINER_CMD) images $(REGISTRY)/$(IMAGE_NAME):latest --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}" @echo "" @echo "Image labels:" - @docker inspect $(REGISTRY)/$(IMAGE_NAME):latest --format '{{range $$k, $$v := .Config.Labels}}{{$$k}}={{$$v}}{{println}}{{end}}' + @$(CONTAINER_CMD) inspect $(REGISTRY)/$(IMAGE_NAME):latest --format '{{range $$k, $$v := .Config.Labels}}{{$$k}}={{$$v}}{{println}}{{end}}' clean: ## Remove local images - @docker rmi $(REGISTRY)/$(IMAGE_NAME):$(TAG) || true - @docker rmi $(REGISTRY)/$(IMAGE_NAME):latest || true + @$(CONTAINER_CMD) rmi $(REGISTRY)/$(IMAGE_NAME):$(TAG) || true + @$(CONTAINER_CMD) rmi $(REGISTRY)/$(IMAGE_NAME):latest || true + @$(CONTAINER_CMD) rmi $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):$(TAG) || true + @$(CONTAINER_CMD) rmi $(DOCKERHUB_REGISTRY)/$(IMAGE_NAME):latest || true @echo "✅ Cleaned local images" login: ## Login to GitLab container registry - @docker login registry.gitlab.com + @$(CONTAINER_CMD) login registry.gitlab.com + +login-dockerhub: ## Login to Docker Hub + @$(CONTAINER_CMD) login docker.io # Quick commands b: build ## Shortcut for build diff --git a/k8s/base-image/QUICKSTART.md b/k8s/base-image/QUICKSTART.md index eefd9ce5..a7bb5080 100644 --- a/k8s/base-image/QUICKSTART.md +++ b/k8s/base-image/QUICKSTART.md @@ -2,11 +2,14 @@ ## One-Time Setup +Works with both **Podman** and **Docker** - the scripts auto-detect which one you have installed. + ```bash cd k8s/base-image -# Login to GitLab registry -docker login registry.gitlab.com +# Login to registries +make login # GitLab registry +make login-dockerhub # Docker Hub # Build the base image make build @@ -14,7 +17,7 @@ make build # Test it works make test -# Push to registry +# Push to both registries make push ``` @@ -81,14 +84,17 @@ make clean # Remove local images **Build fails:** ```bash -# Try with verbose output +# Try with verbose output (use podman or docker) +podman build --progress=plain --no-cache -f Dockerfile . +# or docker build --progress=plain --no-cache -f Dockerfile . ``` **Can't push to registry:** ```bash # Re-login -docker login registry.gitlab.com +make login +make login-dockerhub ``` **Application crashes with missing library:** diff --git a/k8s/base-image/README.md b/k8s/base-image/README.md index 01e651cd..dce6eaf5 100644 --- a/k8s/base-image/README.md +++ b/k8s/base-image/README.md @@ -2,6 +2,10 @@ This directory contains scripts to build a minimal Debian 13 (Trixie) base image with Erlang/OTP and Elixir runtime pre-installed. +## Container Engine Support + +The build scripts automatically detect and use either **Podman** or **Docker**, preferring Podman if both are installed. No configuration needed - just install your preferred container engine and the scripts will use it. + ## Why a Custom Base Image? Building a custom base image provides several benefits: @@ -66,13 +70,22 @@ Verifies: - Elixir is installed and working - Locale is configured correctly -### Pushing to Registry +### Pushing to Registries ```bash +# Login to registries (one-time setup) +make login # GitLab Container Registry +make login-dockerhub # Docker Hub + +# Push to both GitLab and Docker Hub make push ``` -Pushes both versioned and `:latest` tags to GitLab Container Registry. +Automatically pushes to both: +- **GitLab Container Registry**: `registry.gitlab.com/towerops/towerops/elixir-runtime` +- **Docker Hub**: `docker.io/gmcintire/elixir-runtime` + +Both versioned and `:latest` tags are pushed to each registry. ## Image Tags diff --git a/k8s/base-image/build.sh b/k8s/base-image/build.sh index 825e7b8a..bdf7a581 100755 --- a/k8s/base-image/build.sh +++ b/k8s/base-image/build.sh @@ -4,6 +4,16 @@ set -euo pipefail # Build script for minimal Debian base image with Erlang/OTP and Elixir # This script can be re-run to rebuild with latest packages +# Detect container engine (podman or docker) +if command -v podman &> /dev/null; then + CONTAINER_CMD="podman" +elif command -v docker &> /dev/null; then + CONTAINER_CMD="docker" +else + echo "Error: Neither podman nor docker found. Please install one of them." + exit 1 +fi + # Configuration REGISTRY="${REGISTRY:-registry.gitlab.com/towerops/towerops}" IMAGE_NAME="${IMAGE_NAME:-elixir-runtime}" @@ -23,6 +33,7 @@ TAG_DATED="${TAG_FULL}-${BUILD_DATE//[:-]*/}" # YYYY-MM-DD format echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "Building Minimal Debian Base Image" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "Container: ${CONTAINER_CMD}" echo "Registry: ${REGISTRY}" echo "Image: ${IMAGE_NAME}" echo "Erlang: ${ERLANG_VERSION}" @@ -35,7 +46,7 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━ # Build the image with no cache to ensure latest packages echo "" echo "🔨 Building image (no cache, pulling latest packages)..." -docker build \ +$CONTAINER_CMD build \ --no-cache \ --pull \ --build-arg DEBIAN_VERSION="${DEBIAN_VERSION}" \ @@ -62,33 +73,50 @@ echo "" # Show image size echo "📦 Image size:" -docker images "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}" +$CONTAINER_CMD images "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}" echo "" # Verify image works echo "🔍 Verifying image..." -docker run --rm "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" erl -eval 'io:format("Erlang/OTP: ~s~n", [erlang:system_info(otp_release)]), halt().' -noshell -docker run --rm "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" elixir --version +$CONTAINER_CMD run --rm "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" erl -eval 'io:format("Erlang/OTP: ~s~n", [erlang:system_info(otp_release)]), halt().' -noshell +$CONTAINER_CMD run --rm "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" elixir --version echo "" # Ask if user wants to push -read -p "Push to registry? (y/N) " -n 1 -r +read -p "Push to registries? (y/N) " -n 1 -r echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then - echo "🚀 Pushing to registry..." - docker push "${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" - docker push "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" - docker push "${REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" + echo "🚀 Pushing to GitLab registry..." + $CONTAINER_CMD push "${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" + $CONTAINER_CMD push "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" + $CONTAINER_CMD push "${REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" echo "" - echo "✅ Pushed successfully!" + + echo "🚀 Tagging for Docker Hub..." + DOCKERHUB_REGISTRY="docker.io/gmcintire" + $CONTAINER_CMD tag "${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" + $CONTAINER_CMD tag "${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" + $CONTAINER_CMD tag "${REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" + + echo "🚀 Pushing to Docker Hub..." + $CONTAINER_CMD push "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" + $CONTAINER_CMD push "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" + $CONTAINER_CMD push "${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" + echo "" + + echo "✅ Pushed successfully to both registries!" echo "" echo "Update your main Dockerfile to use:" - echo " ARG RUNNER_IMAGE=\"${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}\"" + echo " GitLab: ARG RUNNER_IMAGE=\"${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}\"" + echo " Docker Hub: ARG RUNNER_IMAGE=\"${DOCKERHUB_REGISTRY}/${IMAGE_NAME}:${TAG_FULL}\"" else echo "⏭️ Skipping push. To push later, run:" - echo " docker push ${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" - echo " docker push ${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" - echo " docker push ${REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" + echo " $CONTAINER_CMD push ${REGISTRY}/${IMAGE_NAME}:${TAG_FULL}" + echo " $CONTAINER_CMD push ${REGISTRY}/${IMAGE_NAME}:${TAG_LATEST}" + echo " $CONTAINER_CMD push ${REGISTRY}/${IMAGE_NAME}:${TAG_DATED}" + echo " $CONTAINER_CMD push docker.io/gmcintire/${IMAGE_NAME}:${TAG_FULL}" + echo " $CONTAINER_CMD push docker.io/gmcintire/${IMAGE_NAME}:${TAG_LATEST}" + echo " $CONTAINER_CMD push docker.io/gmcintire/${IMAGE_NAME}:${TAG_DATED}" fi echo ""