<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Adekunle Osatuyi</title>
    <description>The latest articles on Forem by Adekunle Osatuyi (@shakol).</description>
    <link>https://forem.com/shakol</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3637952%2F73809083-9ded-4ed9-b83b-420b60eaaca3.png</url>
      <title>Forem: Adekunle Osatuyi</title>
      <link>https://forem.com/shakol</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shakol"/>
    <language>en</language>
    <item>
      <title>STEP 3: SETTING UP AKS STEP-BY-STEP</title>
      <dc:creator>Adekunle Osatuyi</dc:creator>
      <pubDate>Sat, 27 Dec 2025 00:01:01 +0000</pubDate>
      <link>https://forem.com/shakol/step-3-setting-up-aks-step-by-step-pk1</link>
      <guid>https://forem.com/shakol/step-3-setting-up-aks-step-by-step-pk1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
i.   Azure CLI installed: &lt;em&gt;az version&lt;/em&gt; &lt;br&gt;
ii.  Login Azure: &lt;em&gt;az login&lt;/em&gt; &lt;br&gt;
iii. Login to ACR: _az acr login --name &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 1:&lt;/strong&gt; Create AKS Cluster&lt;br&gt;
The command below will create a 2-node cluster (you can adjust as needed):&lt;br&gt;
&lt;em&gt;az aks create --resource-group devops-rg --name myAKSCluster --node-count 2 --enable-addons monitoring --generate-ssh-keys&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx1u1rggko6vjjwcji65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzx1u1rggko6vjjwcji65.png" alt=" " width="715" height="1018"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 2:&lt;/strong&gt; Connecting AKS to ACR&lt;br&gt;
This lets your cluster pull container images securely.&lt;br&gt;
&lt;em&gt;az aks update --resource-group devops-rg --name myAKSCluster --attach-acr &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxumts88tk8j8kwmdxu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzxumts88tk8j8kwmdxu9.png" alt=" " width="767" height="1017"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 3:&lt;/strong&gt; Get AKS Credentials for kubectl&lt;br&gt;
This will download the kubeconfig locally.&lt;br&gt;
&lt;em&gt;az aks get-credentials --resource-group devops-rg --name myAKSCluster&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 4:&lt;/strong&gt; Verify Connection&lt;br&gt;
Check if kubectl can see your nodes:&lt;br&gt;
&lt;em&gt;kubectl get nodes&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitfqpbxo4brdtr5h74yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitfqpbxo4brdtr5h74yb.png" alt=" " width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 6:&lt;/strong&gt; Verify Namespaces&lt;br&gt;
It shows a default system namespaces:&lt;br&gt;
&lt;em&gt;kubectl get namespaces&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femag3488sn391l64yulw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femag3488sn391l64yulw.png" alt=" " width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 7 (Optional):&lt;/strong&gt; Enable Autoscaling&lt;br&gt;
This enables automatic node scaling:&lt;br&gt;
&lt;em&gt;az aks update --resource-group devops-rg --name myAKSCluster --enable-cluster-autoscaler --min-count 1 --max-count 5&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr599s0jc7sq7camc3pw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxr599s0jc7sq7camc3pw.png" alt=" " width="800" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 8:&lt;/strong&gt; Create Deployment&lt;br&gt;
&lt;em&gt;kubectl create deployment myapp --image=myapp&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 9:&lt;/strong&gt; Update &amp;amp;Restart the Deployment image&lt;br&gt;
&lt;em&gt;kubectl edit deployment myapp&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N:B: Edit image:&lt;/strong&gt; myapp with your ACR LOGIN SERVER i.e image: image: .azurecr.io/myapp:latest&lt;/p&gt;

&lt;p&gt;&lt;em&gt;kubectl rollout restart deployment myapp&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check pods&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;kubectl get pods&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcizgn9u554t3kyeh9lq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzcizgn9u554t3kyeh9lq.png" alt=" " width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 10:&lt;/strong&gt; Expose deployment&lt;br&gt;
&lt;em&gt;kubectl expose deployment myapp --port=80 --target-port=3000 --type=LoadBalancer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;STEP 11:&lt;/em&gt;* Get services&lt;br&gt;
&lt;em&gt;kubectl get service myapp&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuc1q0vh7radk7gf597k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuc1q0vh7radk7gf597k.png" alt=" " width="800" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 12:&lt;/strong&gt; Test in browser&lt;br&gt;
http:// &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt4scimixtsh285shaf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt4scimixtsh285shaf6.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>STEP 2: Automating Docker Build &amp; Push with GitHub Actions</title>
      <dc:creator>Adekunle Osatuyi</dc:creator>
      <pubDate>Fri, 26 Dec 2025 22:29:50 +0000</pubDate>
      <link>https://forem.com/shakol/step-2-automating-docker-build-push-with-github-actions-4gba</link>
      <guid>https://forem.com/shakol/step-2-automating-docker-build-push-with-github-actions-4gba</guid>
      <description>&lt;p&gt;&lt;strong&gt;STEP 1:&lt;/strong&gt; Prepare Your GitHub Repo&lt;br&gt;
On GitHub → create a new repo_ &lt;br&gt;
Clone it to the local system&lt;br&gt;
&lt;em&gt;git clone &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;https://github.com/&lt;/a&gt;/docker-automation-demo.git&lt;/em&gt;&lt;br&gt;
cd docker-automation-demo&lt;br&gt;
Add your app files and a Dockerfile to local directory&lt;br&gt;
&lt;strong&gt;i. Dockerfile:&lt;/strong&gt;&lt;br&gt;
     FROM node:18-alpine&lt;br&gt;
     WORKDIR /app&lt;br&gt;
     COPY package*.json ./&lt;br&gt;
     RUN npm install&lt;br&gt;
     COPY . .&lt;br&gt;
     EXPOSE 3000&lt;br&gt;
     CMD ["npm", "start"]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ii. app.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;const http = require('http');&lt;br&gt;
const port = 3000;&lt;/p&gt;

&lt;p&gt;const server = http.createServer((req, res) =&amp;gt; {&lt;br&gt;
  res.statusCode = 200;&lt;br&gt;
  res.end('Hello, LUbemart is done with Docker!\n');&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;server.listen(port, "0.0.0.0", () =&amp;gt; {&lt;br&gt;
  console.log(&lt;code&gt;Server running on port ${port}&lt;/code&gt;);&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iii. package.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "name": "docker-lab",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "main": "app.js",&lt;br&gt;
  "scripts": {&lt;br&gt;
    "start": "node app.js"&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iv. Commit files:&lt;/strong&gt;&lt;br&gt;
      git add .&lt;br&gt;
      git commit -m "New Dockerfile for automation"&lt;br&gt;
      git push origin main&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Add GitHub Secrets for ACR&lt;br&gt;
From the GitHub repo: &lt;br&gt;
Go to Settings → Secrets and variables → Actions → New repository secret&lt;br&gt;
Add these secrets:&lt;br&gt;
Secret Name          Description&lt;br&gt;&lt;br&gt;
AZURE_CONTAINER_REGISTRY     ACR name&lt;br&gt;&lt;br&gt;
ACR_LOGIN_SERVER         ACR login server&lt;br&gt;&lt;br&gt;
ACR_USERNAME             ACR admin username (copy from credentials)&lt;br&gt;&lt;br&gt;
ACR_PASSWORD             ACR admin password (copy from credentials) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB:Fetch credentials with:&lt;/strong&gt;&lt;br&gt;
az acr credential show --name &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Create a GitHub Actions Workflow&lt;br&gt;
  In your repo, create a new file:&lt;br&gt;
  &lt;em&gt;.github/workflows/docker-build.yml&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PASTE-INSIDE-FILE&lt;/strong&gt;&lt;br&gt;
on:&lt;br&gt;
  push:&lt;br&gt;
    branches:&lt;br&gt;
      - main&lt;/p&gt;

&lt;p&gt;env:&lt;br&gt;
  IMAGE_NAME: myapp&lt;/p&gt;

&lt;p&gt;jobs:&lt;br&gt;
  build-and-push:&lt;br&gt;
    runs-on: ubuntu-latest&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;steps:
  - name: Checkout source code
    uses: actions/checkout@v4

  - name: Login to Azure Container Registry
    run: |
      echo "${{ secrets.ACR_PASSWORD }}" | \
      docker login ${{ secrets.ACR_LOGIN_SERVER }} \
      -u ${{ secrets.ACR_USERNAME }} \
      --password-stdin

  - name: Build Docker image
    run: |
      docker build \
        -t ${{ secrets.ACR_LOGIN_SERVER }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
        -t ${{ secrets.ACR_LOGIN_SERVER }}/${{ env.IMAGE_NAME }}:latest \
        .

  - name: Push Docker image
    run: |
      docker push ${{ secrets.ACR_LOGIN_SERVER }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
      docker push ${{ secrets.ACR_LOGIN_SERVER }}/${{ env.IMAGE_NAME }}:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Commit and Push Workflow&lt;br&gt;
         git add .github/workflows/docker-build.yml&lt;br&gt;
         git commit -m "Add GitHub Actions workflow for ACR push"&lt;br&gt;
         git push origin main&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbbzsdzzpwef7h983oiy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbbzsdzzpwef7h983oiy.png" alt=" " width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Go to your GitHub repo → Actions tab&lt;br&gt;
Check for a new workflow triggered on your latest commit.&lt;br&gt;
&lt;em&gt;Inside — you have the following steps:&lt;/em&gt;&lt;br&gt;
Checkout code &lt;br&gt;
Login to ACR &lt;br&gt;
Build Docker image &lt;br&gt;
Push to ACR&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabvo7d4g84adr5mwmw9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabvo7d4g84adr5mwmw9l.png" alt=" " width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; Verify in ACR&lt;br&gt;
az acr repository list --name  --output table&lt;br&gt;
&lt;em&gt;You’ll now see:&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;myapp&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo9gh9vnrxjr94ad4ky0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo9gh9vnrxjr94ad4ky0.png" alt=" " width="800" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note--&amp;gt; At this level, every code pushed to main triggers an image build + push to Azure Container Registry.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>cicd</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>STEP 1: Setting up Azure CLI and ACR</title>
      <dc:creator>Adekunle Osatuyi</dc:creator>
      <pubDate>Fri, 26 Dec 2025 21:49:49 +0000</pubDate>
      <link>https://forem.com/shakol/step-1-setting-up-azure-cli-and-acr-12b0</link>
      <guid>https://forem.com/shakol/step-1-setting-up-azure-cli-and-acr-12b0</guid>
      <description>&lt;p&gt;&lt;strong&gt;STEP 1:&lt;/strong&gt; Login &amp;amp; Create a Resource Group&lt;br&gt;
&lt;em&gt;az login&lt;/em&gt;&lt;br&gt;
&lt;em&gt;az group create --name devops-rg --location canadacentral&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Register the Container Registry provider (Optional)&lt;br&gt;
&lt;em&gt;az provider register --namespace Microsoft.ContainerRegistry&lt;/em&gt;&lt;br&gt;
&lt;em&gt;az provider register --namespace Microsoft.Insights&lt;/em&gt;&lt;br&gt;
Check registration status&lt;br&gt;
&lt;em&gt;az provider show --namespace Microsoft.ContainerRegistry --query "registrationState"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 2:&lt;/strong&gt; Create Azure Container Registry (ACR names must be globally unique)&lt;br&gt;
&lt;em&gt;az acr create --resource group devops-rg --name osatuyiacr001 --sku Basic --admin-enabled true&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Login to ACR&lt;br&gt;
&lt;em&gt;az acr login --name osatuyiacr001&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ajlpaj2wmioqc7v5dw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ajlpaj2wmioqc7v5dw7.png" alt=" " width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 3:&lt;/strong&gt; Tag a Local Image for ACR&lt;br&gt;
&lt;em&gt;docker pull Shakol090/docker-lab:2.0&lt;/em&gt;&lt;br&gt;
&lt;em&gt;docker tag shakol090/docker-lab:1.0 osatuyiacr001.azurecr.io/docker-lab:v2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STEP 4:&lt;/strong&gt; Push the Image to ACR&lt;br&gt;
&lt;em&gt;docker push osatuyiacr001.azurecr.io/docker-lab:v2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Verify the Image Exists (Optional)&lt;br&gt;
&lt;em&gt;az acr repository list --name osatuyiacr001 --output table&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected output:&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;docker-lab&lt;/p&gt;

</description>
      <category>azure</category>
      <category>container</category>
      <category>cli</category>
      <category>docker</category>
    </item>
    <item>
      <title>Building a Multi-Container App using Docker</title>
      <dc:creator>Adekunle Osatuyi</dc:creator>
      <pubDate>Wed, 17 Dec 2025 19:10:26 +0000</pubDate>
      <link>https://forem.com/shakol/building-a-multi-container-app-using-docker-25o3</link>
      <guid>https://forem.com/shakol/building-a-multi-container-app-using-docker-25o3</guid>
      <description>&lt;h2&gt;
  
  
  Aim of this project is to containerize a Node.js and MySQL stack using Docker Compose.
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Project Structure&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
node-mysql-compose/&lt;br&gt;
├── app/&lt;br&gt;
│   ├── Dockerfile&lt;br&gt;
│   ├── server.js&lt;br&gt;
│   └── package.json&lt;br&gt;
├── docker-compose.yml&lt;br&gt;
└── .env&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 1: Make a Directory&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;code&gt;mkdir node-mysql-compose&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 2: Create app/ inside node-mysql-compose and cd into the app/ then  create the files inside the app/&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;FROM node:18&lt;br&gt;
WORKDIR /app&lt;br&gt;
COPY package*.json ./&lt;br&gt;
RUN npm install&lt;br&gt;
COPY . .&lt;br&gt;
EXPOSE 3000&lt;br&gt;
CMD ["node", "server.js"]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;server.js&lt;/strong&gt;&lt;br&gt;
`const express = require('express');&lt;br&gt;
const mysql = require('mysql2');&lt;br&gt;
const app = express();&lt;br&gt;
const port = 3000;&lt;/p&gt;

&lt;p&gt;const dbConfig = {&lt;br&gt;
  host: 'db',&lt;br&gt;
  user: 'root',&lt;br&gt;
  password: process.env.MYSQL_ROOT_PASSWORD,&lt;br&gt;
  database: process.env.MYSQL_DATABASE&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;function connectWithRetry() {&lt;br&gt;
  const db = mysql.createConnection(dbConfig);&lt;/p&gt;

&lt;p&gt;db.connect(err =&amp;gt; {&lt;br&gt;
    if (err) {&lt;br&gt;
      console.log('❌ MySQL not ready, retrying in 5 seconds...');&lt;br&gt;
      setTimeout(connectWithRetry, 5000);&lt;br&gt;
    } else {&lt;br&gt;
      console.log('✅ Connected to MySQL!');&lt;br&gt;
    }&lt;br&gt;
  });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;connectWithRetry();&lt;/p&gt;

&lt;p&gt;app.get('/', (req, res) =&amp;gt; {&lt;br&gt;
  res.send('Hello Guest, Welcome to Lubemart Multi-Container App using Node.js and MySQL!');&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;app.listen(port, '0.0.0.0', () =&amp;gt; {&lt;br&gt;
  console.log(&lt;code&gt;App running on port ${port}&lt;/code&gt;);&lt;br&gt;
});`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;package.json&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;{&lt;br&gt;
  "name": "node-mysql-app",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "main": "server.js",&lt;br&gt;
  "dependencies": {&lt;br&gt;
    "express": "^4.18.2",&lt;br&gt;
    "mysql2": "^3.2.0"&lt;br&gt;
  }&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3a: (Create File)&lt;/strong&gt; &lt;em&gt;docker-compose.yml&lt;/em&gt;&lt;br&gt;
 services:&lt;br&gt;
  db:&lt;br&gt;
    image: mysql:5.7&lt;br&gt;
    restart: always&lt;br&gt;
    environment:&lt;br&gt;
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}&lt;br&gt;
      MYSQL_DATABASE: ${MYSQL_DATABASE}&lt;br&gt;
    volumes:&lt;br&gt;
      - db_data:/var/lib/mysql&lt;br&gt;
    networks:&lt;br&gt;
      - mynetwork2&lt;/p&gt;

&lt;p&gt;app:&lt;br&gt;
    build: ./app&lt;br&gt;
    ports:&lt;br&gt;
      - "3000:3000"&lt;br&gt;
    environment:&lt;br&gt;
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}&lt;br&gt;
      MYSQL_DATABASE: ${MYSQL_DATABASE}&lt;br&gt;
    depends_on:&lt;br&gt;
      - db&lt;br&gt;
    networks:&lt;br&gt;
      - mynetwork2&lt;/p&gt;

&lt;p&gt;volumes:&lt;br&gt;
  db_data:&lt;/p&gt;

&lt;p&gt;networks:&lt;br&gt;
  mynetwork2:&lt;br&gt;
    driver: bridge&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3b: (Create File)&lt;/strong&gt; &lt;em&gt;.env&lt;/em&gt;&lt;br&gt;
&lt;code&gt;MYSQL_ROOT_PASSWORD=example&lt;br&gt;
MYSQL_DATABASE=testdb&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbet5tolnfntzlfvtr313.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbet5tolnfntzlfvtr313.png" alt=" " width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9gdwrelp2vi7qcyjp6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9gdwrelp2vi7qcyjp6r.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>containers</category>
      <category>devops</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Building and Pushing a Custom Docker Image to Docker Hub</title>
      <dc:creator>Adekunle Osatuyi</dc:creator>
      <pubDate>Sat, 13 Dec 2025 16:16:19 +0000</pubDate>
      <link>https://forem.com/shakol/hands-on-lab-1-building-custom-docker-image-with-dockerfile-4nbi</link>
      <guid>https://forem.com/shakol/hands-on-lab-1-building-custom-docker-image-with-dockerfile-4nbi</guid>
      <description>&lt;p&gt;Tools: Docker Desktop, VScode&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am creating a simple Node.js web app and containerize it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; – Create a Project Directory**&lt;br&gt;
mkdir docker-lab&lt;br&gt;
cd docker-lab&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; – Create app.js**&lt;br&gt;
&lt;em&gt;nano app.js code:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;const http = require('http');&lt;br&gt;
const port = 3000;&lt;/p&gt;

&lt;p&gt;const server = http.createServer((req, res) =&amp;gt; {&lt;br&gt;
  res.statusCode = 200;&lt;br&gt;
  res.end('Hello, Docker World. Welcome to Lubemart Docker-Space!\n');&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;server.listen(port, () =&amp;gt; {&lt;br&gt;
  console.log(&lt;code&gt;Server running at http://localhost:${port}/&lt;/code&gt;);&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;Save (Ctrl + S).&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; – Create package.json**&lt;br&gt;
&lt;em&gt;nano package.json code:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
  "name": "docker-lab",&lt;br&gt;
  "version": "1.0.0",&lt;br&gt;
  "main": "app.js",&lt;br&gt;
  "scripts": {&lt;br&gt;
    "start": "node app.js"&lt;br&gt;
  }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;Save (Ctrl + S).&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt; – Create the Dockerfile**&lt;br&gt;
&lt;em&gt;nano Dockerfile code:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;FROM node:18-alpine&lt;br&gt;
WORKDIR /app&lt;br&gt;
COPY package*.json ./&lt;br&gt;
RUN npm install&lt;br&gt;
COPY . &lt;br&gt;
EXPOSE 3000&lt;br&gt;
CMD ["npm", "start"]&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;Save (Ctrl + S).&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fporg0v9iw77co31zigou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fporg0v9iw77co31zigou.png" alt=" " width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt; – Build the Image (Using Terminal Console)**&lt;br&gt;
docker build -t docker-lab:2.0 .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This command does the following;&lt;br&gt;
Reads the Dockerfile.&lt;br&gt;
Downloads Node.js base image.&lt;br&gt;
Installs dependencies.&lt;br&gt;
Creates an image named docker-lab with version 2.0&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt; – Run the Container**&lt;br&gt;
docker run -d -p 3000:3000 --name lubemart-app docker-lab:2.0&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5iw6opruy7sciuwssuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5iw6opruy7sciuwssuw.png" alt=" " width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt; - Result**&lt;br&gt;
&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Hello, Docker World. Welcome to Lubemart Docker-Space!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjoh6as2xr7a0cca3rba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjoh6as2xr7a0cca3rba.png" alt=" " width="800" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Output&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsynwv6h498mlaa3l3kil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsynwv6h498mlaa3l3kil.png" alt=" " width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8&lt;/strong&gt; -Tagging Image and Pushing to Docker Hub**&lt;br&gt;
docker tag docker-lab:2.0 shakol090/docker-lab:2.0&lt;br&gt;
docker images&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x7sazf3tqcpe9vkngw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2x7sazf3tqcpe9vkngw2.png" alt=" " width="800" height="254"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;docker push shakol090/docker-lab:2.0&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr95ckxtf4hdhznsmpj7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr95ckxtf4hdhznsmpj7k.png" alt=" " width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9yo5965x5aerrqox31p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn9yo5965x5aerrqox31p.png" alt=" " width="800" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>documentation</category>
      <category>nginx</category>
      <category>node</category>
    </item>
  </channel>
</rss>
