
Introduction: The Mission of Modern CI/CD#
Today we’re leaving office chat about coffee and plants to focus on something more practical and, yes, more sexy: how to take your local code to a Container Registry in the cloud in minutes, with tests, scanning and zero human intervention. Sounds ambitious, but it’s totally possible. Ready? Take a deep breath and let’s go.
If your pipeline requires human intervention, it’s not CI/CD: it’s «C and D-why-don’t-you-automate?». The goal is clear: transform code into a deployable artifact without anyone touching more keys than the commit. Here we’ll combine Quarkus, Docker (multi-stage), GitHub Actions and Azure Container Registry (ACR) to achieve an automatic, secure and fast flow — from your dev container to ACR in minutes.
Promise: every image that reaches the registry will have passed tests and scanning. If something fails, the pipeline stops. Period. Are you with me?

Key Technologies#
- Quarkus (Java optimized for the cloud)
- Docker with multi-stage builds and clean Dockerfile
- GitHub Actions as CI/CD orchestrator
- Azure Container Registry (ACR) as private, scalable destination
- Trivy for security scanning
- Dev Containers for reproducible environments
Why Quarkus? Build-time and Performance#
Remember when starting a Java app meant «grab a coffee»? Quarkus changed that. It pushes work to build-time so runtime is lightweight and super fast. With GraalVM or optimized builds you get ultra-fast startup and lower memory consumption — ideal for microservices and serverless environments.
Benefits that make me smile:
- Ultra-fast startup (goodbye cold-starts)
- Smaller images with native builds or reduced runtime
- Live coding: see changes instantly
- Less latency, fewer resources and less drama in production

CI/CD Pipeline Architecture, Containers and Timeline#
Pipeline Architecture#
Picture this: local code → commit → GitHub → pipeline → image in ACR. Within the pipeline you separate jobs for speed and control:
- Local development in Dev Container
- Commit and push to GitHub
- GitHub Actions triggers jobs: build + tests (Maven), Docker image build (multi-stage), scanning with Trivy
- Push to ACR
- Optional: webhook to AKS or Container Apps for automatic deployment
Target Timeline: ~13 minutes#
- 3 min: build + tests (cached Maven)
- 5 min: Docker image build (cached layers)
- 2 min: scanning with Trivy
- 3 min: push and overhead
Golden rule: if one step fails, the image doesn’t get published.
Standardized Local Development: Dev Containers#
The classic «it works on my machine» kills projects. Use Dev Containers in VS Code for an identical environment between devs and CI. Benefits:
- Java 21, Quarkus extensions and Maven preconfigured
- Faster onboarding and less «works on my machine»
- Tip: in
application.propertiesusequarkus.http.host=0.0.0.0to expose the service from the container
Container Strategy: Docker Multi-stage#
Multi-stage builds is pure practicality: you compile in one stage and copy only essentials to a minimal final image. Result: smaller size and smaller attack surface.
Best practices:
- Optimize Dockerfile to separate build and runtime
- Use distroless or Alpine images for runtime
- Run as non-root user (
USER 1000) - Reasonable goal: reduce images from ~900MB to 400MB or less
Automation with GitHub Actions#
GitHub Actions orchestrates everything: separates jobs, caches Maven and Docker layers, and passes artifacts between jobs when needed. Store credentials in GitHub Secrets or use Azure managed identities.
Pipeline tips:
- Cache Maven (
~/.m2/repository) to speed up builds - Use
docker/build-push-actionto leverage layer caching - Configure Trivy to fail the pipeline if HIGH or CRITICAL vulnerabilities appear

Automated Security, ACR Destination and Impact#
Automated Security: Trivy#
Before publishing, Trivy analyzes the image layer by layer. Integrate scanning into the pipeline and define clear policies. Quick local commands to test:
trivy image --severity HIGH,CRITICAL myregistry.azurecr.io/myapp:latest
Recommendations: adjust severity based on risk, schedule periodic rescans and update base images. Complement with SCA and license scanning.
Destination: Azure Container Registry (ACR)#
ACR is a private registry, integrated with AKS and Container Apps. It supports webhooks, replication and policies that help keep deployments auditable.
Push best practices:
- Automate from the pipeline
- Use managed identities or service principals in Secrets
- Avoid plain text credentials
Real Impact: Metrics and Benefits#
Beyond technical enthusiasm, what matters:
- Lighter images (~50% less with multi-stage)
- Drastically faster startup with Quarkus
- Fewer human errors thanks to automated pipeline
- Infrastructure savings: smaller instances and faster startup reduce costs
Quick Playbook: From Code to ACR in Minutes#
- Create Quarkus project:
mvn io.quarkus:quarkus-maven-plugin:create - Develop in Dev Container and configure
quarkus.http.host=0.0.0.0 - Commit & push to GitHub
- Workflow: build/test (Maven) → Docker build (multi-stage) → trivy scan → push to ACR
- Validate in ACR and configure webhook to AKS/Container Apps
Final Tips and Next Steps#
You’ve achieved a reproducible pipeline that transforms local code into a secure and optimized image in Azure Container Registry, all in minutes with zero manual intervention. Points to follow:
- Add integration tests and contract testing
- Integrate SCA and license scanning
- Implement image signing and blocking policies if scanning fails
- Automate environment promotions (staging → prod) with gates and approvals
Useful Resources#
As part of this presentation, the complete workshop (code, workflow, Dockerfile, and devcontainer setup) is shared in this repository:
