This guide walks you through:
- Creating an AKS cluster
- Building and pushing a secure Docker image to Azure Container Registry (ACR)
- Deploying the application to AKS with non-root security best practices
- Fixing container registry permission issues
- Connecting to the Kubernetes Dashboard
- Accessing the shell of a running pod
Before starting, ensure you have:
- Azure CLI installed → Install Guide
- kubectl installed → Install Guide
- Docker installed → Install Guide
- An Azure subscription → Sign Up
az login
If you have multiple subscriptions, set the correct one:
az account set --subscription "<your-subscription-id>"
az group create --name aks-resource-group --location eastus
az aks create --resource-group aks-resource-group \
--name myAKSCluster \
--node-count 2 \
--enable-managed-identity \
--generate-ssh-keys
✅ Creates an AKS cluster with 2 nodes and managed identity.
az aks get-credentials --resource-group aks-resource-group --name myAKSCluster
✅ Downloads credentials and sets up kubectl
access.
kubectl get nodes
✅ Should display two worker nodes.
mkdir hello-world-aks && cd hello-world-aks
nano server.js
Paste:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World from AKS!\n');
});
server.listen(3000, () => {
console.log('Server running on port 3000');
});
nano Dockerfile
Paste:
FROM node:18-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY server.js .
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
✅ Security Best Practices Applied: Non-root user, proper permissions.
az acr create --resource-group aks-resource-group \
--name myacrregistry168168 --sku Basic
az acr login --name myacrregistry168168
docker build -t myacrregistry168168.azurecr.io/hello-world:latest .
docker push myacrregistry168168.azurecr.io/hello-world:latest
If you get 401 Unauthorized while pulling images, run:
az aks update --resource-group aks-resource-group --name myAKSCluster --attach-acr myacrregistry168168
✅ Grants AKS permission to pull images from ACR.
Restart the deployment:
kubectl rollout restart deployment hello-world
nano deployment.yaml
Paste:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 2
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
containers:
- name: hello-world
image: myacrregistry168168.azurecr.io/hello-world:latest
ports:
- containerPort: 3000
kubectl apply -f deployment.yaml
nano service.yaml
Paste:
apiVersion: v1
kind: Service
metadata:
name: hello-world-service
spec:
selector:
app: hello-world
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer
Deploy the service:
kubectl apply -f service.yaml
Get the external IP:
kubectl get service hello-world-service
✅ Open the EXTERNAL-IP in a browser.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
kubectl create serviceaccount dashboard-admin -n kubernetes-dashboard
kubectl create clusterrolebinding dashboard-admin-binding --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:dashboard-admin
kubectl proxy
Open:
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
kubectl get pods
kubectl exec -it <pod-name> -- /bin/sh
For a multi-container pod:
kubectl exec -it <pod-name> -c <container-name> -- /bin/sh
kubectl delete -f deployment.yaml
kubectl delete -f service.yaml
az aks delete --resource-group aks-resource-group --name myAKSCluster --yes --no-wait
az acr delete --resource-group aks-resource-group --name myacrregistry168168 --yes
✅ AKS cluster and resources removed successfully! 🚀