<?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: Arif Hossain</title>
    <description>The latest articles on Forem by Arif Hossain (@arif_hossain).</description>
    <link>https://forem.com/arif_hossain</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%2F2361050%2Ff778137a-b4fa-4705-882e-6612abd7b37c.jpg</url>
      <title>Forem: Arif Hossain</title>
      <link>https://forem.com/arif_hossain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arif_hossain"/>
    <language>en</language>
    <item>
      <title>Kubernetes-Nginx Ingress controller with Path based routing</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Tue, 10 Dec 2024 11:18:59 +0000</pubDate>
      <link>https://forem.com/arif_hossain/kubernetes-nginx-ingress-controller-with-path-based-routing-1l67</link>
      <guid>https://forem.com/arif_hossain/kubernetes-nginx-ingress-controller-with-path-based-routing-1l67</guid>
      <description>&lt;p&gt;Kubernetes Ingress Controller Setup Guide&lt;br&gt;
A comprehensive guide for setting up and configuring NGINX Ingress Controller in Kubernetes, supporting both domain-based and path-based routing configurations.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Project Structure&lt;br&gt;
.&lt;br&gt;
├── README.md&lt;br&gt;
├── ingress/&lt;br&gt;
│   └── controller/&lt;br&gt;
│       └── nginx/&lt;br&gt;
│           ├── manifests/&lt;br&gt;
│           │   └── nginx-ingress.1.5.1.yaml&lt;br&gt;
│           └── config/&lt;br&gt;
│               ├── domain-based-ingress.yaml&lt;br&gt;
│               └── path-based-ingress.yaml&lt;br&gt;
└── scripts/&lt;br&gt;
    └── install-helm.sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;br&gt;
Installing Helm&lt;br&gt;
Helm is required for managing the NGINX Ingress Controller installation. Follow these steps to install Helm:&lt;/p&gt;
&lt;h1&gt;
  
  
  Download Helm
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -o /tmp/helm.tar.gz -LO https://get.helm.sh/helm-v3.10.1-linux-amd64.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Extract the archive
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tar -C /tmp/ -zxvf /tmp/helm.tar.gz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Move helm binary to path
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv /tmp/linux-amd64/helm /usr/local/bin/helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Make it executable
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x /usr/local/bin/helm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Setting up Ingress Controller&lt;br&gt;
Add the NGINX Ingress repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm search repo ingress-nginx --versions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fe23r1c973qbnlra83qen.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%2Fe23r1c973qbnlra83qen.png" alt="Image description" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set Version Variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CHART_VERSION="4.4.0"
APP_VERSION="1.5.1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Version Selection Guide:&lt;/p&gt;

&lt;p&gt;The CHART_VERSION refers to the Helm chart version&lt;br&gt;
The APP_VERSION refers to the NGINX Ingress Controller version&lt;br&gt;
Always check the compatibility matrix&lt;br&gt;
For production environments, use stable versions&lt;br&gt;
Generate the Installation Manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create directory structure
`mkdir -p ./ingress-controller/nginx/manifests/`

# Generate manifest using helm template
`helm template ingress-nginx ingress-nginx \
--repo https://kubernetes.github.io/ingress-nginx \
--version ${CHART_VERSION} \
--namespace ingress-nginx \
&amp;gt; ./ingress-controller/nginx/manifests/nginx-ingress.${APP_VERSION}.yaml`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify Service Configuration:&lt;/p&gt;

&lt;p&gt;Open the generated manifest file&lt;br&gt;
Locate the Service configuration&lt;br&gt;
Change the service type to NodePort&lt;br&gt;
Configure ports:&lt;br&gt;
HTTP: 30080&lt;br&gt;
HTTPS: 30443&lt;br&gt;
Deploy the Controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create namespace
`kubectl create namespace ingress-nginx`

# Apply the configuration
`kubectl apply -f ./ingress-controller/nginx/manifests/nginx-ingress.${APP_VERSION}.ya`ml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4fgjf9y4vq81mlkiadk8.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%2F4fgjf9y4vq81mlkiadk8.png" alt="Image description" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configuration Guide&lt;br&gt;
Deploy an app&lt;br&gt;
deployment.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: blog-app
  labels:
    app: blog-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: blog-app
  template:
    metadata:
      labels:
        app: blog-app
    spec:
      containers:
      - name: blog-app
        image: &amp;lt;YOUR-DOCKER-HUB&amp;gt;/blog-app:1.7
        ports:
        - containerPort: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;service.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: blog-app-service
spec:
  selector:
    app: blog-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Path-based Routing&lt;br&gt;
For routing based on URL paths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: blog-service
spec:
  ingressClassName: nginx
  rules:
  - host: &amp;lt;YOUR-DOMAIN-NAME&amp;gt;
    http:
      paths:
      - path: /blog
        pathType: Prefix
        backend:
          service:
            name: blog-service
            port:
              number: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rewrite Rules&lt;br&gt;
For advanced path rewriting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: blog-service
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
  - host: &amp;lt;YOUR-DOMAIN-NAME&amp;gt;
    http:
      paths:
      - path: /path-a(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: blog-service
            port:
              number: 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Local Development&lt;br&gt;
For local development and testing:&lt;/p&gt;

&lt;p&gt;Port Forwarding Setup:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl port-forward -n ingress-nginx service/ingress-nginx-controller 8080:80&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For development and testing at poridhi lab, make sure you are using load balancer. Expose the ingress controller.&lt;/p&gt;

&lt;p&gt;Testing Configuration:&lt;/p&gt;

&lt;h1&gt;
  
  
  Test the endpoint-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;curl -H "Host: blog.&amp;lt;YOUR-DOMAIN-NAME&amp;gt;" http://localhost:8080/blog&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  For HTTPS-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;curl -k -H "Host: blog.&amp;lt;YOUR-DOMAIN-NAME&amp;gt;" https://localhost:8443/blog&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Troubleshooting&lt;br&gt;
Common issues and their solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Controller Pod Issues&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Check pod status-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl get pods -n ingress-nginx&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  View controller logs-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl logs -n ingress-nginx deploy/ingress-nginx-controller&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Describe pod for events-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl describe pod -n ingress-nginx &amp;lt;pod-name&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Routing Problems&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Verify ingress resource-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl describe ingress &amp;lt;ingress-name&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Check endpoints-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl get endpoints&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Validate service-
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;kubectl describe service &amp;lt;service-name&amp;gt;&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Common Error Solutions:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;404 Not Found:&lt;/strong&gt; &lt;br&gt;
Verify path configuration and service endpoint&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;503 Service Unavailable:&lt;/strong&gt; &lt;br&gt;
Check if backend service is running&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;502 Bad Gateway:&lt;/strong&gt; &lt;br&gt;
Validate service port configuration&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>nginx</category>
      <category>docker</category>
    </item>
    <item>
      <title>Self-Hosted GitHub Actions Runner in Kubernetes</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Mon, 11 Nov 2024 18:21:07 +0000</pubDate>
      <link>https://forem.com/arif_hossain/self-hosted-github-actions-runner-in-kubernetes-4l70</link>
      <guid>https://forem.com/arif_hossain/self-hosted-github-actions-runner-in-kubernetes-4l70</guid>
      <description>&lt;p&gt;Self Hosted Runner in K3s Cluster&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%2F7vp6287blbb5hefp6qe0.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%2F7vp6287blbb5hefp6qe0.png" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hands-on Guide: Self-Hosted GitHub Actions Runner in Kubernetes&lt;br&gt;
GitHub Actions is a powerful tool for automating software workflows, and it can be used to build, test, and deploy code right from GitHub. It provides a way to automate repetitive tasks and can be integrated with many popular tools and platforms.&lt;/p&gt;

&lt;p&gt;GitHub Actions can use two types of runners: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hosted and &lt;/li&gt;
&lt;li&gt;Self-hosted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Hosted runners&lt;/em&gt; are provided by GitHub and run on virtual machines in the cloud.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Self-hosted runners&lt;/em&gt; are machines that you set up and manage yourself. They run on your infrastructure, and you can customize them to meet your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
This guide provides step-by-step instructions for setting up a self-hosted GitHub Actions runner in Kubernetes using Docker-in-Docker (DinD). This setup allows you to run GitHub Actions workflows in your own infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;br&gt;
Before starting, ensure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A working Kubernetes cluster (k3s/kind/etc.)&lt;/li&gt;
&lt;li&gt;kubectl installed and configured&lt;/li&gt;
&lt;li&gt;Docker installed&lt;/li&gt;
&lt;li&gt;A GitHub account and repository&lt;/li&gt;
&lt;li&gt;A GitHub Personal Access Token (PAT)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Setting Up the Project Structure&lt;br&gt;
Create a new directory for the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir github-runner-k8s
cd github-runner-k8s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create necessary files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch Dockerfile entrypoint.sh kubernetes.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Creating the Dockerfile&lt;br&gt;
The Dockerfile creates a container image that serves as our GitHub Actions runner environment. It creates a reproducible environment for the runner and installs necessary tools (Docker CLI, jq, etc.). It forms the base container image for the runner pod in Kubernetes.&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%2Ftj0v04xry2sk3mdbgftz.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%2Ftj0v04xry2sk3mdbgftz.png" alt="Image description" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Create the &lt;em&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;/em&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM debian:bookworm-slim
ARG RUNNER_VERSION="2.302.1"
ENV GITHUB_PERSONAL_TOKEN ""
ENV GITHUB_OWNER ""
ENV GITHUB_REPOSITORY ""

# Install Docker
RUN apt-get update &amp;amp;&amp;amp; \
    apt-get install -y ca-certificates curl gnupg
RUN install -m 0755 -d /etc/apt/keyrings
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
RUN chmod a+r /etc/apt/keyrings/docker.gpg

# Add Docker repository
RUN echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release &amp;amp;&amp;amp; echo "$VERSION_CODENAME")" stable" | \
  tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
RUN apt-get update

# Install required packages
RUN apt-get install -y docker-ce-cli sudo jq

# Setup github user
RUN useradd -m github &amp;amp;&amp;amp; \
    usermod -aG sudo github &amp;amp;&amp;amp; \
    echo "%sudo ALL=(ALL) NOPASSWD:ALL" &amp;gt;&amp;gt; /etc/sudoers

# Create directories with correct permissions
RUN mkdir -p /actions-runner &amp;amp;&amp;amp; \
    chown -R github:github /actions-runner &amp;amp;&amp;amp; \
    mkdir -p /work &amp;amp;&amp;amp; \
    chown -R github:github /work

USER github
WORKDIR /actions-runner

# Download and install runner
RUN curl -Ls https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz -o actions-runner.tar.gz &amp;amp;&amp;amp; \
    tar xzf actions-runner.tar.gz &amp;amp;&amp;amp; \
    rm actions-runner.tar.gz &amp;amp;&amp;amp; \
    sudo ./bin/installdependencies.sh

COPY --chown=github:github entrypoint.sh /actions-runner/entrypoint.sh
RUN sudo chmod u+x /actions-runner/entrypoint.sh

ENTRYPOINT ["/actions-runner/entrypoint.sh"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Creating the Entrypoint Script&lt;br&gt;
The entrypoint script handles the runner's lifecycle - registration, execution, and cleanup. It automatically registers the runner with GitHub. It acts as the bridge between container and GitHub.&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%2F7nfmbr7ugis2b6zgyahy.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%2F7nfmbr7ugis2b6zgyahy.png" alt="Image description" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;entrypoint&lt;/p&gt;

&lt;p&gt;Create &lt;em&gt;&lt;strong&gt;entrypoint.sh&lt;/strong&gt;&lt;/em&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh
registration_url="https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPOSITORY}/actions/runners/registration-token"
echo "Requesting registration URL at '${registration_url}'"
payload=$(curl -sX POST -H "Authorization: token ${GITHUB_PERSONAL_TOKEN}" ${registration_url})
export RUNNER_TOKEN=$(echo $payload | jq .token --raw-output)

./config.sh \
    --name $(hostname) \
    --token ${RUNNER_TOKEN} \
    --labels my-runner \
    --url https://github.com/${GITHUB_OWNER}/${GITHUB_REPOSITORY} \
    --work "/work" \
    --unattended \
    --replace

remove() {
    ./config.sh remove --unattended --token "${RUNNER_TOKEN}"
}

trap 'remove; exit 130' INT
trap 'remove; exit 143' TERM

./run.sh "$*" &amp;amp;
wait $!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make the script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x entrypoint.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 4:&lt;/em&gt;&lt;/strong&gt; Creating the Kubernetes Deployment&lt;br&gt;
This step defines how the runner should be deployed and managed in Kubernetes.&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%2Fzjxs92vaxa7kj3ohe82r.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%2Fzjxs92vaxa7kj3ohe82r.png" alt="Image description" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;k8s-integration&lt;/p&gt;

&lt;p&gt;Create &lt;em&gt;&lt;strong&gt;kubernetes.yaml&lt;/strong&gt;&lt;/em&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: github-runner
  labels:
    app: github-runner
spec:
  replicas: 1
  selector:
    matchLabels:
      app: github-runner
  template:
    metadata:
      labels:
        app: github-runner
    spec:
      containers:
      - name: github-runner
        imagePullPolicy: Never
        image: github-runner:latest
        env:
        - name: GITHUB_OWNER
          valueFrom:
            secretKeyRef:
              name: github-secret
              key: GITHUB_OWNER
        - name: GITHUB_REPOSITORY
          valueFrom:
            secretKeyRef:
              name: github-secret
              key: GITHUB_REPOSITORY
        - name: GITHUB_PERSONAL_TOKEN
          valueFrom:
            secretKeyRef:
              name: github-secret
              key: GITHUB_PERSONAL_TOKEN
        - name: DOCKER_HOST
          value: tcp://localhost:2375
        volumeMounts:
        - name: data
          mountPath: /work/
      - name: dind
        image: docker:24.0.6-dind
        env:
        - name: DOCKER_TLS_CERTDIR
          value: ""
        resources:
          requests:
            cpu: 20m
            memory: 512Mi
        securityContext:
          privileged: true
        volumeMounts:
          - name: docker-graph-storage
            mountPath: /var/lib/docker
          - name: data
            mountPath: /work/
      volumes:
      - name: docker-graph-storage
        emptyDir: {}
      - name: data
        emptyDir: {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Building and Loading the Image&lt;br&gt;
Build the Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build . -t github-runner:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fe3500iazs1sij7gxk5wz.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%2Fe3500iazs1sij7gxk5wz.png" alt="Image description" width="775" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Load the image into your Kubernetes cluster:&lt;br&gt;
For k3s:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Save the image
docker save github-runner:latest -o github-runner.tar

# Import to k3s
sudo k3s ctr images import github-runner.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fkxo1nou3c3nz7wlwiq8l.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%2Fkxo1nou3c3nz7wlwiq8l.png" alt="Image description" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; Creating GitHub Token&lt;br&gt;
Go to &lt;em&gt;GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)&lt;/em&gt;&lt;br&gt;
Generate new token with following permissions:&lt;br&gt;
&lt;em&gt;repo (full control)&lt;br&gt;
workflow&lt;/em&gt;&lt;br&gt;
admin:org (if using organization repository)&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%2Fw8mdb9j2l6dzh6eu7flb.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%2Fw8mdb9j2l6dzh6eu7flb.png" alt="Image description" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; Creating Kubernetes Secrets&lt;br&gt;
Create namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace host-runner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F9a6ix3brg4gikodcsqj1.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%2F9a6ix3brg4gikodcsqj1.png" alt="Image description" width="735" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create secrets (replace placeholder values):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl -n host-runner create secret generic github-secret \
  --from-literal=GITHUB_OWNER=&amp;lt;your-github-username&amp;gt; \
  --from-literal=GITHUB_REPOSITORY=&amp;lt;your-repo-name&amp;gt; \
  --from-literal=GITHUB_PERSONAL_TOKEN=&amp;lt;your-github-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Frncgeta7sa77fly2sxjm.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%2Frncgeta7sa77fly2sxjm.png" alt="Image description" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8:&lt;/strong&gt; Deploying to Kubernetes&lt;br&gt;
Apply the Kubernetes deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl -n host-runner apply -f kubernetes.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check pod status
kubectl -n host-runner get pods

# Check runner logs
kubectl -n host-runner logs -f &amp;lt;pod-name&amp;gt; -c github-runner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 9:&lt;/strong&gt; Verifying the Setup&lt;br&gt;
Go to your GitHub repository&lt;br&gt;
Navigate to &lt;em&gt;Settings → Actions → Runners&lt;/em&gt;&lt;br&gt;
You should see your self-hosted runner listed and "Idle"&lt;br&gt;
Troubleshooting Guide&lt;br&gt;
Common Issues and Solutions&lt;br&gt;
&lt;strong&gt;&lt;code&gt;Image Pull Error&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check if image is properly loaded
sudo crictl images | grep github-runner

# If not visible, reload the image
sudo k3s ctr images import github-runner.tar
**Permission Issues**
# Check pod logs
kubectl -n host-runner logs -f &amp;lt;pod-name&amp;gt; -c github-runner

# Verify secrets
kubectl -n host-runner get secrets github-secret -o yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Runner Not Registering&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check if token is valid
kubectl -n host-runner logs &amp;lt;pod-name&amp;gt; -c github-runner | grep "Requesting registration URL"

# Verify network connectivity
kubectl -n host-runner exec &amp;lt;pod-name&amp;gt; -c github-runner -- curl -s https://api.github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cleanup Instructions&lt;/strong&gt;&lt;br&gt;
To remove the setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Delete the deployment
kubectl -n host-runner delete -f kubernetes.yaml

# Delete the secrets
kubectl -n host-runner delete secret github-secret

# Delete the namespace
kubectl delete namespace host-runner

# Remove local images
docker rmi github-runner:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing the Runner&lt;br&gt;
Create a simple workflow in your repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .github/workflows/test.yml
name: Test Self-Hosted Runner
on: [push]
jobs:
  test:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v2
      - name: Test Runner
        run: |
          echo "Hello from self-hosted runner!"
          docker --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push this file to your repository&lt;br&gt;
Check the Actions tab in your repository to see the workflow running&lt;br&gt;
Maintenance Tips&lt;br&gt;
Updating Runner Version:&lt;br&gt;
Update RUNNER_VERSION in Dockerfile&lt;/p&gt;

&lt;p&gt;Rebuild and redeploy&lt;br&gt;
Scaling Runners:&lt;br&gt;
Modify replicas in kubernetes.yaml&lt;br&gt;
Apply changes with kubectl&lt;/p&gt;

&lt;p&gt;Monitoring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Check runner status
kubectl -n host-runner get pods -w

# Check resource usage
kubectl -n host-runner top pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remember to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regularly update the runner version&lt;/li&gt;
&lt;li&gt;Monitor resource usage&lt;/li&gt;
&lt;li&gt;Rotate GitHub tokens periodically&lt;/li&gt;
&lt;li&gt;Keep Docker images updated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Benefits of using Self-Hosted Runner:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Improved Performance:&lt;/em&gt; By hosting your runners, you can ensure that the build and deployment processes are faster and more reliable, as you have complete control over the hardware and networking resources.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Increased Security:&lt;/em&gt; GitHub self-hosted runners can be configured to run on your own servers, which provides an extra layer of security compared to using shared runners. This helps to protect sensitive information and data in your workflows.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Customizable Environments:&lt;/em&gt; With self-hosted runners, you can create custom environments that match your exact needs, including specific software versions and configurations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cost-Effective:&lt;/em&gt; If you have a large number of workflows or use cases that require a lot of resources, self-hosted runners can be more cost-effective than using GitHub’s shared runners or cloud-based solutions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;High Availability:&lt;/em&gt; With self-hosted runners, you can set up Horizontal Runner Autoscaler, which provides redundancy and high availability for your workflows.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Greater Control:&lt;/em&gt; Self-hosted runners give you complete control over the resources and environment used for your workflows, which can help you optimize performance and ensure that your builds and deployments run smoothly.&lt;/p&gt;

&lt;p&gt;Overall, GitHub self-hosted runners offer greater flexibility, control, and customization options than using shared runners or cloud-based solutions. However, setting up and managing self-hosted runners requires additional effort and resources, so it’s essential to weigh the benefits against the costs and resources needed to maintain them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
In conclusion, the Actions Runner Controller with Self-Hosted Runner is a powerful tool that can help you improve your GitHub Actions workflows. It simplifies the management of runners by automating tasks such as the creation, scaling, and deletion of runners. It also provides an easy way to create and manage runners in a Kubernetes cluster. By using Actions Runner Controller with Self-Hosted Runner, you can take full advantage of the power of GitHub Actions while having full control over your infrastructure.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>kubernetes</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Actions Runner Controller (ARC) Setup Guide Using Kubernetes-cluster.</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 16:39:59 +0000</pubDate>
      <link>https://forem.com/arif_hossain/actions-runner-controller-arc-setup-guide-417k</link>
      <guid>https://forem.com/arif_hossain/actions-runner-controller-arc-setup-guide-417k</guid>
      <description>&lt;p&gt;Actions Runner Controller (ARC)&lt;br&gt;
This guide explains how to set up GitHub Actions Runner Controller (ARC) in a Kubernetes cluster.&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%2F2cqolz001befkr5xawlf.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%2F2cqolz001befkr5xawlf.png" alt="Image description" width="536" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster&lt;/li&gt;
&lt;li&gt;kubectl installed and configured&lt;/li&gt;
&lt;li&gt;GitHub Personal Access Token (PAT) with repo and workflow permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Installing Helm (if not installed)&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick Setup&lt;br&gt;
Install ARC Controller&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create namespace and install controller&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install arc \
  --namespace arc-systems \
  --create-namespace \
  oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller

# Verify installation
kubectl get pods -n arc-systems
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5h1uo34idevozi6qmhng.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%2F5h1uo34idevozi6qmhng.png" alt="Image description" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Create GitHub PAT&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Go to &lt;em&gt;&lt;strong&gt;GitHub → Settings → Developer Settings → Personal Access Tokens&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Create new token with repo and workflow permissions&lt;br&gt;
Save the token securely&lt;br&gt;
Install Runner Set&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Set your GitHub details
export GITHUB_CONFIG_URL="https://github.com/YOUR_USERNAME/YOUR_REPO"
export GITHUB_PAT="your_pat_here"

# Install runner set
helm install arc-runner-set \
    --namespace arc-runners \
    --create-namespace \
    --set githubConfigUrl="${GITHUB_CONFIG_URL}" \
    --set githubConfigSecret.github_token="${GITHUB_PAT}" \
    oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fsweslx6vv7w1ah50e009.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%2Fsweslx6vv7w1ah50e009.png" alt="Image description" width="800" height="375"&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%2Fnn3fxlrjd95lqhvesyu7.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%2Fnn3fxlrjd95lqhvesyu7.png" alt="Image description" width="800" height="361"&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%2Fromfvv7b3rcsuhf97925.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%2Fromfvv7b3rcsuhf97925.png" alt="Image description" width="800" height="304"&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%2Fmykr9lcqktevcr3ef1ui.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%2Fmykr9lcqktevcr3ef1ui.png" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;scale-set&lt;br&gt;
Using in GitHub Actions&lt;/p&gt;
&lt;h1&gt;
  
  
  In your workflow file (&lt;code&gt;.github/workflows/example.yml&lt;/code&gt;)
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: My Workflow
on: [push]
jobs:
  build:
    runs-on: arc-runner-set
    steps:
      - uses: actions/checkout@v2
      - run: echo "Hello from self-hosted runner!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Verification&lt;br&gt;
Check if everything is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n arc-systems
kubectl get pods -n arc-runners
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your runner should appear online in your GitHub repository under Settings → Actions → Runners.&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%2Fd7stgo2oznvq59guwfjg.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%2Fd7stgo2oznvq59guwfjg.png" alt="Image description" width="800" height="452"&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%2Fqip66skoocftyipl6utf.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%2Fqip66skoocftyipl6utf.png" alt="Image description" width="800" height="167"&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%2F915n3m2iwn3p8btd8h0d.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%2F915n3m2iwn3p8btd8h0d.png" alt="Image description" width="800" height="516"&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%2Fkz6bce4drsx20fd34uqe.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%2Fkz6bce4drsx20fd34uqe.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  In Another workflow file (&lt;code&gt;.github/workflows/example.yml&lt;/code&gt;)
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  # Build Job
  build:
    runs-on: arc-runner-set
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Build Application
        run: echo "Building application..."

  # Test Job
  test:
    runs-on: arc-runner-set
    needs: build
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Run Tests
        run: echo "Running tests..."

  # Lint Job
  lint:
    runs-on: arc-runner-set
    needs: build
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Lint Code
        run: echo "Linting code..."

  # Deploy Job
  deploy:
    runs-on: arc-runner-set
    needs: [build, test, lint]
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Deploy Application
        run: echo "Deploying application..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Possible outputs:&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%2F91y9optqxiv3h3elx885.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%2F91y9optqxiv3h3elx885.png" alt="Image description" width="800" height="381"&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%2Fgvcwqspdixdfgcwrqxqa.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%2Fgvcwqspdixdfgcwrqxqa.png" alt="Image description" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Troubleshooting&lt;br&gt;
If runners show as offline:&lt;/p&gt;

&lt;p&gt;Check runner pods: &lt;code&gt;kubectl get pods -n arc-runners&lt;/code&gt;&lt;br&gt;
View logs: &lt;code&gt;kubectl logs -n arc-runners &amp;lt;pod-name&amp;gt;&lt;/code&gt;&lt;br&gt;
Verify PAT permissions and expiration&lt;br&gt;
Ensure correct repository URL in configuration&lt;br&gt;
Check Namespace and Pod Status&lt;br&gt;
Ensure both namespaces, arc-systems and arc-runners, are created and pods are running without errors.&lt;br&gt;
Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n arc-systems
kubectl get pods -n arc-runners
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any pods are in a CrashLoopBackOff or Error state, inspect their logs for errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl logs &amp;lt;pod-name&amp;gt; -n arc-systems
kubectl logs &amp;lt;pod-name&amp;gt; -n arc-runners
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cleanup&lt;br&gt;
To remove ARC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm uninstall arc-runner-set -n arc-runners
helm uninstall arc -n arc-systems
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>docker</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Basic GitHub Actions Checkout</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 13:39:08 +0000</pubDate>
      <link>https://forem.com/arif_hossain/basic-github-actions-checkout-3588</link>
      <guid>https://forem.com/arif_hossain/basic-github-actions-checkout-3588</guid>
      <description>&lt;p&gt;Overview&lt;br&gt;
This hands-on lab introduces the fundamentals of GitHub Actions by implementing a basic workflow that demonstrates repository checkout and command execution. You'll learn how to create a workflow file, understand its structure, and execute various commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub account&lt;/li&gt;
&lt;li&gt;A GitHub repository where you have write access&lt;/li&gt;
&lt;li&gt;Basic understanding of YAML syntax&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of command line operations&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Learning Objectives&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
After completing this lab, you will be able to:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a basic GitHub Actions workflow file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understand workflow trigger conditions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute single and multi-line commands&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the checkout action&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View and interpret workflow results&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lab Structure&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your-repository/
├── .github/
│   └── workflows/
│       └── basic-checkout.yml
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Implementation Guide&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Step 1: Create Workflow Directory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p .github/workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create Workflow File&lt;br&gt;
Create .github/workflows/basic-checkout.yml with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Basic Checkout Lab

# Trigger on push to main branch
on:
  push:
    branches:
      - main

# Define jobs and their steps
jobs:
  basic-checkout:
    runs-on: ubuntu-latest
    steps:
      # Step 1: Checkout the repository
      - name: Checkout repository
        uses: actions/checkout@v4

      # Step 2: List repository contents
      - name: List files
        run: ls -la

      # Step 3: Display system information
      - name: Show system info
        run: |
          echo "Repository: $GITHUB_REPOSITORY"
          echo "Operating System: $(uname -a)"
          echo "Current Directory: $(pwd)"

      # Step 4: Check software versions
      - name: Check versions
        run: |
          echo "Node version: $(node --version)"
          echo "Python version: $(python --version)"
          echo "Git version: $(git --version)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Detailed Explanation&lt;/em&gt;&lt;br&gt;
Workflow Trigger&lt;br&gt;
on:&lt;br&gt;
  push:&lt;br&gt;
    branches:&lt;br&gt;
      - main&lt;br&gt;
This section configures the workflow to run whenever code is pushed to the main branch.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Job Configuration&lt;/em&gt;&lt;br&gt;
&lt;code&gt;jobs:&lt;br&gt;
  basic-checkout:&lt;br&gt;
    runs-on: ubuntu-latest&lt;/code&gt;&lt;br&gt;
Defines a single job named basic-checkout&lt;br&gt;
Specifies Ubuntu as the runner operating system&lt;br&gt;
&lt;em&gt;Steps Breakdown&lt;/em&gt;&lt;br&gt;
`Checkout Step&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name: Checkout repository
uses: actions/checkout@v4&lt;code&gt;
Uses the official checkout action
Clones your repository into the runner
Essential for accessing repository files
&lt;/code&gt;File Listing&lt;/li&gt;
&lt;li&gt;name: List files
run: ls -la&lt;code&gt;
Lists all files and directories
Includes hidden files
Shows file permissions and ownership
System Information
&lt;/code&gt;- name: Show system info
run: |
echo "Repository: $GITHUB_REPOSITORY"
echo "Operating System: $(uname -a)"
echo "Current Directory: $(pwd)"&lt;code&gt;
Uses multi-line commands
Demonstrates environment variable usage
Shows system details
&lt;/code&gt;Version Checks&lt;/li&gt;
&lt;li&gt;name: Check versions
run: |
echo "Node version: $(node --version)"
echo "Python version: $(python --version)"
echo "Git version: $(git --version)"`
Checks installed software versions
Uses command substitution
Demonstrates multi-line commands
Expected Outputs
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;File Listing Output
total 24
drwxr-xr-x 4 runner docker 4096 Feb 20 10:00 .
drwxr-xr-x 3 runner docker 4096 Feb 20 10:00 ..
drwxr-xr-x 8 runner docker 4096 Feb 20 10:00 .git
drwxr-xr-x 3 runner docker 4096 Feb 20 10:00 .github
-rw-r--r-- 1 runner docker  654 Feb 20 10:00 README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;System Information Output&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Repository: username/repository-name
Operating System: Linux runner-ubuntu-latest 5.15.0-1047-azure
Current Directory: /home/runner/work/repository-name/repository-name
Version Information Output
Node version: v20.11.0
Python version: Python 3.10.12
Git version: git version 2.42.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Practice Exercises&lt;br&gt;
Add New Commands Modify the workflow to include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current date and time&lt;/li&gt;
&lt;li&gt;Available disk space&lt;/li&gt;
&lt;li&gt;Memory usage
Custom Environment Variables Add environment variables:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;env:&lt;br&gt;
  CUSTOM_MESSAGE: "Hello from GitHub Actions!"&lt;/code&gt;&lt;br&gt;
Conditional Execution Add a conditional step:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;- name: Conditional step&lt;br&gt;
  if: github.event_name == 'push'&lt;br&gt;
  run: echo "This was triggered by a push event"&lt;/code&gt;&lt;br&gt;
Troubleshooting&lt;br&gt;
Common Issues and Solutions&lt;br&gt;
Workflow Not Triggering&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify branch name matches trigger condition&lt;/li&gt;
&lt;li&gt;Check workflow file syntax&lt;/li&gt;
&lt;li&gt;Ensure Actions are enabled in repository settings&lt;/li&gt;
&lt;li&gt;Checkout Action Fails&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Verify Git configuration
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git config --global --list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Check permissions
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ls -la .git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command Execution Errors&lt;/p&gt;

&lt;p&gt;Check command availability on runner&lt;br&gt;
Verify syntax for multi-line commands&lt;br&gt;
Ensure proper environment variable usage&lt;br&gt;
&lt;strong&gt;Debugging Tips&lt;/strong&gt;&lt;br&gt;
Enable debug logging by setting secret ACTIONS_RUNNER_DEBUG to true&lt;br&gt;
Check workflow run logs in GitHub Actions tab&lt;br&gt;
Use echo statements to debug variables&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Additional Resources&lt;/strong&gt;:
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;GitHub Actions Documentation&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Workflow Syntax Reference&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/actions/checkout" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Checkout Action Documentation&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.devzery.com/post/github-actions-complete-guide-to-actions-checkout" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;Guide to Actions Checkout&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Deploy The Multi-Container App</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 13:08:28 +0000</pubDate>
      <link>https://forem.com/arif_hossain/deploy-the-multi-container-app-56b</link>
      <guid>https://forem.com/arif_hossain/deploy-the-multi-container-app-56b</guid>
      <description>&lt;p&gt;&lt;em&gt;Deploy the multi-container application using Docker Compose&lt;/em&gt;&lt;br&gt;
In this session, we will learn how to define services, networks, and volumes in a Docker Compose file and verify the setup by running a simple application.&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%2F53guc8ujyrd2wcfbe7wc.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%2F53guc8ujyrd2wcfbe7wc.png" alt="Image description" width="758" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll need to set up the directory structure, create the necessary files (app.py, Dockerfile, compose.yaml), and then deploy and verify the application. &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%2Fhkm1ok07vvwv3bwptlzn.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%2Fhkm1ok07vvwv3bwptlzn.png" alt="Image description" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a step-by-step guide:&lt;/p&gt;

&lt;p&gt;Step 1: Set Up Directory Structure&lt;br&gt;
Create a directory for your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir multi-container
cd multi-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create &lt;strong&gt;app.py&lt;/strong&gt;&lt;br&gt;
Inside the multi-container directory, create a file named app.py:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
    count = redis.incr('hits')
    return f'Hello World! This page has been visited {count} times.\n'

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app.py script creates a simple web application using Flask. When accessed, it counts the number of visits to the root URL and displays a message with the visit count. This count is stored in a Redis database. The script runs a web server to serve the application on port 8080.&lt;/p&gt;

&lt;p&gt;Step 3: Create &lt;em&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Create a Dockerfile in the same directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use the official Python image from the Docker Hub
FROM python:3.9-alpine

# Set the working directory in the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install flask redis

# Make port 8080 available to the world outside this container
EXPOSE 8080

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Dockerfile builds a Docker image for the web-fe service in the Docker Compose setup. It uses the official Python 3.9 Alpine image, sets the working directory to /app, copies the current directory's contents into the container, installs Flask and Redis, exposes port 8080, and runs the Flask application (app.py) when the container starts. This setup ensures the web-fe service is ready to serve the application and interact with the Redis service defined in the compose.yaml file.&lt;/p&gt;

&lt;p&gt;Step 4: Create &lt;em&gt;&lt;strong&gt;compose.yaml&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Create a compose.yaml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'

services:
  web-fe:
    build: .
    command: python app.py
    ports:
      - target: 8080
        published: 5001
    networks:
      - counter-net
    volumes:
      - type: volume
        source: counter-vol
        target: /app

  redis:
    image: "redis:alpine"
    networks:
      - counter-net

networks:
  counter-net:

volumes:
  counter-vol:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F1fvb3kbz3yawj0n53ile.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%2F1fvb3kbz3yawj0n53ile.png" alt="Image description" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The compose.yaml file defines a multi-container application using Docker Compose. It consists of two services:&lt;/p&gt;

&lt;p&gt;web-fe:&lt;/p&gt;

&lt;p&gt;Builds an image using the current directory's Dockerfile.&lt;br&gt;
Runs a Python script (app.py) to serve a Flask application.&lt;br&gt;
Maps port 5001 on the host to port 8080 in the container.&lt;br&gt;
Connects to the counter-net network.&lt;br&gt;
Mounts a volume named counter-vol to the /app directory in the container.&lt;br&gt;
redis:&lt;/p&gt;

&lt;p&gt;Pulls the redis:alpine image from Docker Hub.&lt;br&gt;
Connects to the counter-net network.&lt;br&gt;
The counter-net network facilitates communication between the web-fe and redis services. Additionally, the counter-vol volume provides persistent storage for the web-fe service.&lt;/p&gt;

&lt;p&gt;It’s also worth knowing that Compose builds networks and volumes before deploying services. This makes sense, as networks and volumes are lower-level infrastructure objects that are consumed by services (containers).&lt;/p&gt;

&lt;p&gt;Step 5: Deploy the Application&lt;br&gt;
With all the files in place, you can now deploy the application using Docker Compose. Run the following command from the multi-container directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose -f compose.yaml up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fczbaqe7upspmce66lz4z.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%2Fczbaqe7upspmce66lz4z.png" alt="Image description" width="800" height="222"&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%2Fgb56vg1ozeaw9abdr0z3.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%2Fgb56vg1ozeaw9abdr0z3.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 6: Verify the Deployment&lt;br&gt;
Verify that the services are running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see two services: web-fe and redis.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2Fbnrtm0899egyxvqzdsti.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%2Fbnrtm0899egyxvqzdsti.png" alt="Image description" width="800" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the logs for any errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&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%2Fjyhqpbzowwnzqndzg6l6.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%2Fjyhqpbzowwnzqndzg6l6.png" alt="Image description" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl localhost:5001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the message indicating the number of visits to the page.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2F9obiw3wapcfae71oea7u.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%2F9obiw3wapcfae71oea7u.png" alt="Image description" width="716" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;List the processes running inside of each service (container):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose top
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fk8m1ckajhuy6n930n96g.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%2Fk8m1ckajhuy6n930n96g.png" alt="Image description" width="744" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following command to stop the app without deleting its resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fbanwlwpi5cn68sydvoqs.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%2Fbanwlwpi5cn68sydvoqs.png" alt="Image description" width="653" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the app in the stopped state, restart it with the docker compose restart command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F4tbxmydaa9ues26upil3.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%2F4tbxmydaa9ues26upil3.png" alt="Image description" width="651" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify the volume and network:&lt;br&gt;
List volumes to verify counter-vol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker volume ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fbpg66gqmjtejmslbq9ad.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%2Fbpg66gqmjtejmslbq9ad.png" alt="Image description" width="730" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;List networks to verify counter-net:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker network ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F3duly46orrpkjwfow501.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%2F3duly46orrpkjwfow501.png" alt="Image description" width="634" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cleanup&lt;br&gt;
When you're done testing, you can stop and remove the containers, networks, and volumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose down --volumes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjssm19k8xgb02nhdchid.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%2Fjssm19k8xgb02nhdchid.png" alt="Image description" width="766" height="171"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;###//Understand another Example//###
Let's investigate docker-compose.yml to understand.

version: '3.5'
services:
  api:
    build: .
    volumes:
      - "./app:/src/app"
    ports:
      - "1338:1338"
    depends_on:
      - db
      - cache
    networks:
        - test_nw
    environment:
      - DATABASE_HOST=mongodb://db:27017
      - REDIS_CACHE_HOST=redis://cache:6379
      - PORT=1338
  db:
    image: mongo:latest
    ports:
      - "27017:27017"
    networks:
        - test_nw
  cache:
    image: redis:latest
    ports:
      - "6379:6379"
    networks:
      - test_nw
networks:
  test_nw:
    driver: bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple docker-compse.yml example to deploy a Nodejs backend with MongoDb and Redis.&lt;/p&gt;

&lt;p&gt;The Commands&lt;br&gt;
Of course docker-compose has commands. Whaat! Okay I' will give you the most basic commands. I'm not super duper software engineer and I can live my life with these commands.&lt;br&gt;
&lt;code&gt;docker compose up&lt;/code&gt; is a command that will look for docker-compose.yml by default and will process the docker-compose.yml, create the environment and run the services.&lt;br&gt;
&lt;code&gt;-d&lt;/code&gt; means that terminal is yours, it runs the command detachable mode&lt;br&gt;
&lt;code&gt;-f&lt;/code&gt; #non-standard-compose.yml-name# means that you can pass a compose.yml file with different name. Usaually projects contains more than one docker-compose files. You can have compose file for production and development or you can seperate applications and tools in a different compose files.&lt;br&gt;
&lt;code&gt;docker compose down&lt;/code&gt; is a command that will look for running compose.yml file and shutdown containers then remove all of them including networks, volumes etc.&lt;br&gt;
&lt;code&gt;docker compose log&lt;/code&gt; is a command that will look for running compose.yml file and displays log which are generated by the containers.&lt;br&gt;
Top Level Definitions&lt;br&gt;
&lt;strong&gt;&lt;em&gt;version&lt;/em&gt; :&lt;/strong&gt; Defined by the Compose Specification for backward compatibility. It is only informative, and you'll receive a warning message that it is obsolete if used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;services :&lt;/em&gt;&lt;/strong&gt; A service is an abstract definition of a computing resource within an application which can be scaled or replaced independently from other components. These services run in their containers and can communicate with each other.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;network :&lt;/strong&gt;&lt;/em&gt; A layer that allows containers to communicate with each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;volume:&lt;/em&gt;&lt;/strong&gt; Volumes are persistent data stores implemented by the container engine. Compose offers a neutral way for services to mount volumes, and configuration parameters to allocate them to infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Definitions&lt;/strong&gt;&lt;br&gt;
build: Lets you define the Dockerfile path to build when the compose file is being processed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;volumes :&lt;/em&gt;&lt;/strong&gt; Lets you define service-level persisted volumes to mount local files and folders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;ports:&lt;/em&gt;&lt;/strong&gt; Lets you expose container ports. The left-hand of the definition is the localhost address and the right-hand will be the container port. It basically means binding port 1338 of the container to localhost:1338.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;depends_on :&lt;/em&gt;&lt;/strong&gt; option in Docker Compose is used to specify the dependencies between different services defined in your docker-compose.yml file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;networks:&lt;/em&gt;&lt;/strong&gt; option in Docker Compose is used to specify which network will be used by this container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;environment:&lt;/em&gt;&lt;/strong&gt; option in Docker Compose is used to specify environment variables which will be passed to container.&lt;/p&gt;

&lt;p&gt;This setup allows you to run and verify the multi-container Flask application using Docker Compose, with persistent storage and network configuration as described.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Introduction to Docker Compose</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 12:20:01 +0000</pubDate>
      <link>https://forem.com/arif_hossain/introduction-to-docker-compose-ddh</link>
      <guid>https://forem.com/arif_hossain/introduction-to-docker-compose-ddh</guid>
      <description>&lt;p&gt;Intro to Docker Compose&lt;br&gt;
In this session we will learn the basics of Docker Compose and how to manage multi-container applications easily.&lt;/p&gt;

&lt;p&gt;What are Multi-Container Applications?&lt;br&gt;
Modern cloud-native applications are often composed of multiple smaller services that work together to form a complete application.&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%2F40blaxrq5v54qb861f26.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%2F40blaxrq5v54qb861f26.png" alt="Image description" width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is known as the microservices pattern. These could include:&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%2F3tpx3eg6ty22m1f35zq6.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%2F3tpx3eg6ty22m1f35zq6.png" alt="Image description" width="643" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web front-end&lt;br&gt;
Database&lt;br&gt;
Authentication service&lt;br&gt;
and so on.&lt;/p&gt;

&lt;p&gt;Challenges with Microservices:&lt;br&gt;
Managing and deploying multiple microservices can be complex and cumbersome, requiring careful orchestration of each service.&lt;/p&gt;

&lt;p&gt;What is Docker Compose?&lt;br&gt;
Docker Compose is a tool that allows you to define and manage multi-container Docker applications. It uses a declarative configuration file, typically in YAML format, to specify the services, networks, and volumes required for the application.&lt;/p&gt;

&lt;p&gt;Benefits of Docker Compose:&lt;br&gt;
Simplifies the orchestration of multi-container applications.&lt;br&gt;
Allows for a single configuration file to define and manage all services.&lt;br&gt;
Integrates with version control systems for better management.&lt;br&gt;
Basic Docker Compose Commands&lt;br&gt;
Check Installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start an Application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stop an Application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;View Container Status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple Docker Compose Example&lt;br&gt;
Let's create a basic Docker Compose setup with a web server using nginx:alpine image and a redis service using redis:alpine image.&lt;/p&gt;

&lt;p&gt;Step 1: Create a Directory&lt;br&gt;
Create a directory for your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir myapp
cd myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create Docker Compose File&lt;br&gt;
Create a file named &lt;code&gt;docker-compose.yml&lt;/code&gt; and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
  redis:
    image: redis:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file defines two services: a web server (nginx) and a Redis server.&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%2Fgqvullstqerhkg5hvu1h.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%2Fgqvullstqerhkg5hvu1h.png" alt="Image description" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 3: Start the Application&lt;br&gt;
Run the following command to start the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see output indicating the services are starting.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2Fn6h78nzfs6hvn03ite30.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%2Fn6h78nzfs6hvn03ite30.png" alt="Image description" width="800" height="298"&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%2Fahxks5kwn7mpo64ezans.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%2Fahxks5kwn7mpo64ezans.png" alt="Image description" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 4: Verify the Setup&lt;br&gt;
Check localhost:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the default Nginx welcome page.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2Fea0qr3v7nkemvgff88iw.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%2Fea0qr3v7nkemvgff88iw.png" alt="Image description" width="800" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 5: View Status&lt;br&gt;
Check the status of the running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose ps
#or
docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&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%2Ftn0ndz7h8v8pkjkzr916.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%2Ftn0ndz7h8v8pkjkzr916.png" alt="Image description" width="800" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 6: Stop the Application&lt;br&gt;
Stop the services with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F78e0flcfcsmilke1xzaf.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%2F78e0flcfcsmilke1xzaf.png" alt="Image description" width="800" height="84"&gt;&lt;/a&gt;&lt;br&gt;
=====####====&lt;br&gt;
Let's discuss Another Example:&lt;br&gt;
Let's investigate &lt;code&gt;docker-compose.yml&lt;/code&gt; to understand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.5'
services:
  api:
    build: .
    volumes:
      - "./app:/src/app"
    ports:
      - "1338:1338"
    depends_on:
      - db
      - cache
    networks:
        - test_nw
    environment:
      - DATABASE_HOST=mongodb://db:27017
      - REDIS_CACHE_HOST=redis://cache:6379
      - PORT=1338
  db:
    image: mongo:latest
    ports:
      - "27017:27017"
    networks:
        - test_nw
  cache:
    image: redis:latest
    ports:
      - "6379:6379"
    networks:
      - test_nw
networks:
  test_nw:
    driver: bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simple &lt;strong&gt;docker-compse.yml&lt;/strong&gt; example to deploy a Nodejs backend with MongoDb and Redis.&lt;/p&gt;

&lt;p&gt;The Commands&lt;br&gt;
Of course docker-compose has commands. Whaat! Okay I' will give you the most basic commands. I'm not super duper software engineer and I can live my life with these commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a command that will look for docker-compose.yml by default and will process the docker-compose.yml, create the environment and run the services.&lt;br&gt;
&lt;code&gt;-d&lt;/code&gt; means that terminal is yours, it runs the command detachable mode&lt;br&gt;
&lt;code&gt;-f&lt;/code&gt; #non-standard-compose.yml-name# means that you can pass a compose.yml file with different name. Usually projects contains more than one docker-compose files. You can have compose file for production and development or you can seperate applications and tools in a different compose files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is a command that will look for running compose.yml file and shutdown containers then remove all of them including networks, volumes etc.&lt;br&gt;
docker compose log&lt;/p&gt;

&lt;p&gt;is a command that will look for running compose.yml file and displays log which are generated by the containers.&lt;br&gt;
&lt;strong&gt;Top Level Definitions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;version :&lt;br&gt;
Defined by the Compose Specification for backward compatibility. It is only informative, and you'll receive a warning message that it is obsolete if used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;services :&lt;br&gt;
A service is an abstract definition of a computing resource within an application which can be scaled or replaced independently from other components. These services run in their containers and can communicate with each other.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;network : &lt;br&gt;
A layer that allows containers to communicate with each other.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;volume:&lt;br&gt;
Volumes are persistent data stores implemented by the container engine. Compose offers a neutral way for services to mount volumes, and configuration parameters to allocate them to infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Service Definitions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;build:&lt;br&gt;
Lets you define the Dockerfile path to build when the compose file is being processed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;volumes :&lt;br&gt;
Lets you define service-level persisted volumes to mount local files and folders.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ports:&lt;br&gt;
Lets you expose container ports. The left-hand of the definition is the localhost address and the right-hand will be the container port. It basically means binding port 1338 of the container to localhost:1338.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;depends_on :&lt;br&gt;
option in Docker Compose is used to specify the dependencies between different services defined in your docker-compose.yml file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;networks:&lt;br&gt;
option in Docker Compose is used to specify which network will be used by this container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;environment:&lt;br&gt;
option in Docker Compose is used to specify environment variables which will be passed to container.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
You have learned the basics of Docker Compose, created a simple multi-container application, and practiced using basic commands. This knowledge will help you manage more complex applications in the future.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Multi-stage Builds with a Simple Node.js App</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 12:03:51 +0000</pubDate>
      <link>https://forem.com/arif_hossain/multi-stage-builds-with-a-simple-nodejs-app-cfp</link>
      <guid>https://forem.com/arif_hossain/multi-stage-builds-with-a-simple-nodejs-app-cfp</guid>
      <description>&lt;p&gt;Multi-stage Builds with a Simple Node.js App&lt;br&gt;
In the world of making programs run smoothly inside containers, we've found that using just one step to build them isn't always the best idea. When we stick to single steps, our containers can end up being really big and slow. But fear not! There's a better way: multi-stage builds. These help us make our containers smaller and faster without losing any important stuff.&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%2F3jcfdvywj08fdh03lghj.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%2F3jcfdvywj08fdh03lghj.png" alt="Image description" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today, we're going on an adventure to discover how multi-stage builds work. We'll break down the complicated bits into easy-to-understand pieces.&lt;/p&gt;

&lt;p&gt;Create a Simple Node.js App&lt;br&gt;
Create a directory for our project and navigate into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir node-app
cd node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a file named &lt;strong&gt;app.js&lt;/strong&gt; and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const http = require('http');

const server = http.createServer((req, res) =&amp;gt; {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello from Docker! Welcome to our application.\n');
});

const PORT = process.env.PORT || 3000;
server.listen(PORT, () =&amp;gt; {
  console.log(`Server running at http://localhost:${PORT}/`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple Node.js application creates an HTTP server that listens on port 3000 and responds with "Hello, world!" to all requests.&lt;/p&gt;

&lt;p&gt;Create a &lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
Next, let's create a Dockerfile to containerize our Node.js application using two-stage builds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stage 1: Build the Node.js application
FROM node:latest AS build

WORKDIR /app

COPY app.js .

# Stage 2: Create the production image
FROM node:slim

WORKDIR /app

COPY --from=build /app .

EXPOSE 3000

CMD ["node", "app.js"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stage 1 (build):&lt;br&gt;
Purpose: Build the Node.js application.&lt;br&gt;
Functionality:&lt;br&gt;
Uses node:latest image as the base, providing necessary build tools.&lt;br&gt;
Sets the working directory to /app where application code will be copied.&lt;br&gt;
Copies index.js into the image, preparing for application build.&lt;br&gt;
Stage 2:&lt;br&gt;
Purpose: Create the production image.&lt;br&gt;
Functionality:&lt;br&gt;
Uses node:slim image as the base, providing a minimal runtime environment.&lt;br&gt;
Sets the working directory to /app, ensuring consistency with the build stage.&lt;br&gt;
Copies the built application from the build stage into this stage, excluding unnecessary build tools.&lt;br&gt;
Exposes port 3000, allowing external communication with the application.&lt;br&gt;
Defines the command to run the application (node index.js), starting the HTTP server.&lt;br&gt;
Build and Run the Docker Image&lt;br&gt;
Now, let's build and run the Docker image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t node-app .
docker run -d -p 3000:3000 node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that the container is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will build the Docker image based on the Dockerfile and run a container based on that image. The application will be accessible at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Testing the App&lt;br&gt;
To test the app, we can use curl to send a request to the running container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should return:&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%2Ft607qkomqtphvb1991dy.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%2Ft607qkomqtphvb1991dy.png" alt="Image description" width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
In this guide, we've demonstrated how to use two-stage builds in Docker to containerize a simple Node.js application. Each stage has a specific purpose, allowing us to create smaller and more efficient Docker images by separating the build process into distinct steps.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>node</category>
    </item>
    <item>
      <title>Containerize a Single-Container App</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 07:53:23 +0000</pubDate>
      <link>https://forem.com/arif_hossain/containerize-a-single-container-app-43d4</link>
      <guid>https://forem.com/arif_hossain/containerize-a-single-container-app-43d4</guid>
      <description>&lt;p&gt;Containerize a Single-Container App&lt;br&gt;
In this guide, we will walk through the process of containerizing a simple Node.js application. Containerization involves packaging an application and all its dependencies, libraries, and configurations into a single package known as a container. This ensures the app runs consistently across different environments, whether it's your local machine, a server, or the cloud.&lt;/p&gt;

&lt;p&gt;Docker is the tool we'll use for containerization. It allows developers to automate the deployment of applications inside lightweight, portable containers. We’ll also explore how Docker layers work and their significance in the containerization process.&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%2Fdm2s4gkkqeu7otb8flyr.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%2Fdm2s4gkkqeu7otb8flyr.png" alt="Image description" width="735" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating the Application Code&lt;br&gt;
First, let's create a basic Node.js application. We will begin by creating a directory for the app and navigating into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir my-node-app
cd my-node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create a file named &lt;strong&gt;&lt;em&gt;app.js&lt;/em&gt;&lt;/strong&gt; with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app.js
const http = require('http');

const hostname = '0.0.0.0';
const port = 8080;

const server = http.createServer((req, res) =&amp;gt; {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello, World!\n');
});

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

&lt;/div&gt;



&lt;p&gt;This is a simple HTTP server that responds with "Hello, World!".&lt;/p&gt;

&lt;p&gt;Creating the &lt;em&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
A Dockerfile is a script that contains instructions for Docker to build your container image. Create a Dockerfile in the same directory with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use an official Node.js runtime as the base image
FROM node:14-alpine

# Set the working directory
WORKDIR /usr/src/app

# Copy the application code
COPY app.js .

# Install the necessary Node.js package
RUN npm install http@0.0.1-security

# Expose the port the app runs on
EXPOSE 8080

# Define the command to run the app
CMD ["node", "app.js"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FROM: Specifies the base image (Node.js with Alpine Linux, a lightweight version of Linux).&lt;br&gt;
WORKDIR: Sets the working directory inside the container.&lt;br&gt;
COPY: Copies app.js from the local machine to the container.&lt;br&gt;
RUN: Installs the necessary Node.js package.&lt;br&gt;
EXPOSE: Informs Docker the container listens on port 8080.&lt;br&gt;
CMD: Defines the command to run the app.&lt;br&gt;
Containerizing the App / Building the Image&lt;br&gt;
Now that the Dockerfile is ready, we can build the Docker image. In your terminal, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t my-node-app:1.0 .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells Docker to build an image named my-node-app with the version 1.0 using the current directory.&lt;/p&gt;

&lt;p&gt;To verify that the image was created, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ff3fkqwv9k90qspgs3619.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%2Ff3fkqwv9k90qspgs3619.png" alt="Image description" width="633" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will display a list of available images.&lt;/p&gt;

&lt;p&gt;Pushing the Image (Optional)&lt;br&gt;
If you'd like to share your image, you can push it to Docker Hub. Follow these steps:&lt;/p&gt;

&lt;p&gt;Log in to Docker Hub:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tag the image with your Docker ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag my-node-app:1.0 &amp;lt;docker-id&amp;gt;/my-node-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Push the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker push &amp;lt;docker-id&amp;gt;/my-node-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make the image available for others to pull and use.&lt;/p&gt;

&lt;p&gt;Running the App&lt;br&gt;
To run the containerized app, execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name my-node-app-container -p 80:8080 my-node-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-d: Runs the container in detached mode (in the background).&lt;br&gt;
--name: Assigns a name to the running container.&lt;br&gt;
-p 80:8080: Maps port 8080 inside the container to port 80 on your machine.&lt;br&gt;
Check that the container is running by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will list all active containers.&lt;/p&gt;

&lt;p&gt;Testing the App&lt;br&gt;
To test the app, you can use the curl command or open a browser and go to &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt;. Using curl, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fpczui7l38inxztxjpdwl.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%2Fpczui7l38inxztxjpdwl.png" alt="Image description" width="651" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Docker Layers and Efficiency&lt;br&gt;
Each instruction in the Dockerfile creates a layer. These layers are cached and reused during subsequent builds if the content doesn’t change, which improves build speed and reduces storage space. For example:&lt;/p&gt;

&lt;p&gt;FROM creates a base layer.&lt;br&gt;
COPY adds a new layer with the application files.&lt;br&gt;
RUN installs dependencies in a separate layer.&lt;br&gt;
You can inspect the layers of your image by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker history my-node-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjinjq47pd20tl6nk2shk.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%2Fjinjq47pd20tl6nk2shk.png" alt="Image description" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command displays each command from the Dockerfile and the corresponding layer it created.&lt;/p&gt;

&lt;p&gt;Optimizing Docker Images: Multi-Stage Builds&lt;br&gt;
To reduce image size, you can use multi-stage builds, especially for production environments. In multi-stage builds, unnecessary files (such as development dependencies) are not included in the final image.&lt;/p&gt;

&lt;p&gt;Here’s an example of a multi-stage Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stage 1: Build
FROM node:14-alpine AS builder
WORKDIR /usr/src/app
COPY app.js .
RUN npm install http@0.0.1-security

# Stage 2: Production
FROM node:14-alpine
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app .
EXPOSE 8080
CMD ["node", "app.js"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this setup, the first stage builds the app, and the second stage creates a minimal image without including the build tools, reducing the final image size.&lt;/p&gt;

&lt;p&gt;Container Management and Best Practices&lt;br&gt;
Restart Policies&lt;br&gt;
You can ensure that containers automatically restart if they crash or your system reboots. Add the --restart flag when running your container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker stop my-node-app-container
docker rm -f  my-node-app-container
docker build -t my-node-app:2.0 .
docker images

docker run -d --name my-node-app-container --restart always -p 80:8080 my-node-app:2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fxldxncaf7ltmy2r0hv7u.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%2Fxldxncaf7ltmy2r0hv7u.png" alt="Image description" width="800" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Environment Variables&lt;br&gt;
Environment variables allow you to pass dynamic configurations into your container at runtime. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -e NODE_ENV=production -p 80:8080 my-node-app:2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Official Base Images:&lt;br&gt;
Always start with trusted base images to reduce security risks.&lt;br&gt;
Scan for Vulnerabilities: Regularly scan your images for known vulnerabilities using tools like Trivy or Docker Scan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limit Privileges:&lt;br&gt;
Run containers with the least privileges needed by using Docker’s security options.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Containerizing applications with Docker ensures consistency, portability, and ease of deployment across various environments. By following best practices like using official base images, optimizing Docker layers, and employing security measures, you can create efficient and secure containerized applications.&lt;/p&gt;

&lt;p&gt;This guide provides a clear step-by-step process for containerizing a Node.js app while explaining Docker's functionality, Dockerfile instructions, and optimization strategies. Happy containerizing!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Exploring Docker Image Layers and Size Management</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 07:14:25 +0000</pubDate>
      <link>https://forem.com/arif_hossain/exploring-docker-image-layers-and-size-management-2jem</link>
      <guid>https://forem.com/arif_hossain/exploring-docker-image-layers-and-size-management-2jem</guid>
      <description>&lt;p&gt;Exploring Docker Image Layers and Size Management&lt;br&gt;
Docker images are built from layers, where each layer represents a set of filesystem changes. The size of an image on disk is the sum of the sizes of its component layers. Docker allows you to commit changes to a running container, creating new image layers.&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%2F9vf2ppr4y66z91o1cmxp.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%2F9vf2ppr4y66z91o1cmxp.png" alt="Image description" width="568" height="300"&gt;&lt;/a&gt;&lt;br&gt;
This lab will guide you through these concepts with hands-on practices, focusing on creating and modifying a Docker image with ubuntu as the base image. You will install and remove software within containers, observe the changes in image sizes, and understand the impact of Docker's Union File System (UFS) on image size.&lt;/p&gt;

&lt;p&gt;Task: Building and Modifying Docker Images&lt;br&gt;
Here, you will create a Docker image from the official Ubuntu image, install Git within a container, and commit the changes to create a new image. You will then modify this image by removing Git and observe how Docker manages image layers and size.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Pull the ubuntu image from Docker Hub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command fetches the latest ubuntu image from Docker Hub and stores it in your local Docker repository.&lt;/p&gt;

&lt;p&gt;Create a Container and Install Git:&lt;br&gt;
Create a container from the ubuntu image and install Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name ubuntu-git-container ubuntu sleep infinity
docker exec -it ubuntu-git-container apt-get update
docker exec -it ubuntu-git-container apt-get install -y git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands run a container named ubuntu-git-container from the ubuntu image and install Git inside the container. The sleep infinity command keeps the container running. The apt-get update and apt-get install -y git commands update the package list and install Git, respectively.&lt;/p&gt;

&lt;p&gt;Commit the Changes to Create a New Image:&lt;br&gt;
Commit the container to create a new image with Git installed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker commit ubuntu-git-container ubuntu-git:1.0
docker tag ubuntu-git:1.0 ubuntu-git:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands commit the current state of the ubuntu-git-container container to a new image named ubuntu-git with a tag 1.0, and then tag this image as latest.&lt;/p&gt;

&lt;p&gt;Check Image Sizes:&lt;br&gt;
Check the sizes of all the images created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&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%2Fsiuuwjkln90j9zhvr0cy.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%2Fsiuuwjkln90j9zhvr0cy.png" alt="Image description" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remove Git:&lt;br&gt;
Create a new container from the ubuntu-git image and remove Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name ubuntu-git-remove --entrypoint /bin/bash ubuntu-git:latest -c "apt-get remove -y git"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a container named ubuntu-git-remove from the ubuntu-git:latest image with an entrypoint set to /bin/bash, and removes Git from the container.&lt;/p&gt;

&lt;p&gt;Commit the Changes to Create a New Image with Git Removed:&lt;br&gt;
Commit the container to create a new image with Git removed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker commit ubuntu-git-remove ubuntu-git:2.0
docker tag ubuntu-git:2.0 ubuntu-git:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands commit the current state of the ubuntu-git-remove container to a new image named ubuntu-git:removed and reassign the latest tag to this new image.&lt;/p&gt;

&lt;p&gt;Check Image Sizes:&lt;br&gt;
Check the sizes of all the images created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&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%2Fjhrqpks8hx1poloix5cc.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%2Fjhrqpks8hx1poloix5cc.png" alt="Image description" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that even though you removed Git, the image actually same in size. Although you could examine the specific changes with docker diff, you should be quick to realize that the reason for the increase has to do with the union file system.&lt;/p&gt;

&lt;p&gt;Remember, UFS will mark a file as deleted by actually adding a file to the top layer. The original file and any copies that existed in other layers will still be present in the image. When a file is deleted, a delete record is written to the top layer, which overshadows any versions of that file on lower layers.&lt;/p&gt;

&lt;p&gt;It’s important to minimize image size for the sake of the people and systems that will be consuming your images. If you can avoid causing long download times and significant disk usage with smart image creation, then your consumers will benefit.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Modifying Docker Image Attributes</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 06:51:05 +0000</pubDate>
      <link>https://forem.com/arif_hossain/modifying-docker-image-attributes-346m</link>
      <guid>https://forem.com/arif_hossain/modifying-docker-image-attributes-346m</guid>
      <description>&lt;p&gt;Modifying Docker Image Attributes&lt;br&gt;
This lab aims to deepen your understanding of Docker image attributes and how they can be modified and inherited across different layers of an image.&lt;/p&gt;

&lt;p&gt;By the end of this exercise, you will be familiar with setting environment variables, working directories, exposed ports, volume definitions, container entrypoints, and commands.&lt;/p&gt;

&lt;p&gt;Description&lt;br&gt;
When you use docker container commit, you create a new layer for an image. This layer includes not only a snapshot of the filesystem but also metadata about the execution context. The following parameters, if set for a container, will be carried forward to the new image:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Working directory&lt;/li&gt;
&lt;li&gt;Exposed ports&lt;/li&gt;
&lt;li&gt;Volume definitions&lt;/li&gt;
&lt;li&gt;Container entrypoint&lt;/li&gt;
&lt;li&gt;Command and arguments
If these parameters are not explicitly set, they will be inherited from the original image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lab will provide you with hands-on experience in modifying these attributes and observing how they are inherited across image layers.&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%2Fjetytkq0pg56qntybtv2.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%2Fjetytkq0pg56qntybtv2.png" alt="Image description" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a Container with Environment Variables&lt;/p&gt;

&lt;p&gt;Run a Docker container from the busybox:latest image, setting two environment variables.&lt;br&gt;
Commit the running container to a new image.&lt;br&gt;
Modify the Entrypoint and Command&lt;/p&gt;

&lt;p&gt;Run a new container from the previously committed image, setting a new entrypoint and command.&lt;/p&gt;

&lt;p&gt;Commit this container to update the image.&lt;br&gt;
Verify Inheritance of Attributes&lt;/p&gt;

&lt;p&gt;Run a container from the final image without specifying any command or entrypoint to verify that the environment variables and the entrypoint/command are inherited correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution Steps&lt;/strong&gt;&lt;br&gt;
Create a Container with Environment Variables&lt;br&gt;
Run the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name container1 -e ENV_EXAMPLE1=value1 -e ENV_EXAMPLE2=value2 busybox:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new container named container1 from the busybox:latest image and sets two environment variables, ENV_EXAMPLE1 and ENV_EXAMPLE2.&lt;/p&gt;

&lt;p&gt;Commit the container to a new image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker commit container1 new-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command commits the container1 container to a new image named new-image.&lt;/p&gt;

&lt;p&gt;Varify the image creation using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run a new container with a specific entrypoint and command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name container2 --entrypoint "/bin/sh" new-image -c "echo \$ENV_EXAMPLE1 \$ENV_EXAMPLE2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a new container named container2 from the new-image image, setting the entrypoint to /bin/sh and the command to -c "echo \$ENV_EXAMPLE1 \$ENV_EXAMPLE2". This setup will print the values of the environment variables.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2Fitb6nqwfci0hj7x6fytv.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%2Fitb6nqwfci0hj7x6fytv.png" alt="Image description" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Commit this container to update the image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker commit container2 new-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will commit the container container2 to the new-image image, updating the image with the new entrypoint and command. The updated image will have the entrypoint and the command with it.&lt;/p&gt;

&lt;p&gt;Verify the new image's entrypoint and command settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker inspect --format '{{ .Config.Entrypoint }}' new-image
docker inspect --format '{{ .Config.Cmd }}' new-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&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%2F5y9vwfbasbojnscsphfr.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%2F5y9vwfbasbojnscsphfr.png" alt="Image description" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run a container from the final image to verify the inherited behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm new-image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a container from the final new-image image, verifying that the environment variables and the entrypoint/command are inherited correctly.&lt;/p&gt;

&lt;p&gt;Expected output:&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%2Fwvyoi9y3qqfol58ld72y.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%2Fwvyoi9y3qqfol58ld72y.png" alt="Image description" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By completing this lab, we hope, you have a practical understanding of how to modify and verify Docker image attributes, and how these changes are inherited across image layers.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Reviewing Filesystem Changes</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 06:40:46 +0000</pubDate>
      <link>https://forem.com/arif_hossain/reviewing-filesystem-changes-2339</link>
      <guid>https://forem.com/arif_hossain/reviewing-filesystem-changes-2339</guid>
      <description>&lt;p&gt;Reviewing filesystem changes&lt;br&gt;
In this lab, we will learn how to review filesystem changes made inside a Docker container. Docker provides a command to list all changes to the filesystem, including added, changed, or deleted files and directories.&lt;/p&gt;

&lt;p&gt;When you read a file from a union filesystem, that file will be read from the topmost layer where it exists. If a file was not created or changed on the top layer, the read will fall through the layers until it reaches a layer where that file does exist. Here is a simple example:&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%2Fb2791kuopggjnkwpuu1n.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%2Fb2791kuopggjnkwpuu1n.png" alt="Image description" width="530" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The layer functionality is hidden by the UFS. No special actions are required by the software running in a container to utilize these features. The UFS manages the complexity of handling files across multiple layers.&lt;/p&gt;

&lt;p&gt;Most union filesystems use something called copy-on-write, which is easier to under stand if you think of it as copy-on-change. When a file in a read-only layer (not the top layer) is modified, the whole file is first copied from the read-only layer into the writable layer before the change is made.&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%2Faqd07jgd1z5f6go39rlu.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%2Faqd07jgd1z5f6go39rlu.png" alt="Image description" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this illustration, files are added, changed, deleted, and added again over a range of three layers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Task&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Create a container and add a new file and review changes&lt;/li&gt;
&lt;li&gt;Create another container and delete an existing file and review changes&lt;/li&gt;
&lt;li&gt;Create yet another container and change an existing file and review changes&lt;/li&gt;
&lt;li&gt;Clean up our workspace
Steps
Follow these steps to complete the task:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a container and add a new file:&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%2F025ajcxxn0ct9skiv98w.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%2F025ajcxxn0ct9skiv98w.png" alt="Image description" width="433" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --name tweak-a busybox:latest touch /HelloWorld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a new container named tweak-a from the busybox:latest image and creates an empty file named /HelloWorld inside the container.&lt;/p&gt;

&lt;p&gt;Review the filesystem changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container diff tweak-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists all the changes made to the filesystem of the tweak-a container. You should see:&lt;/p&gt;

&lt;p&gt;Expected Output:&lt;/p&gt;

&lt;p&gt;A /HelloWorld&lt;br&gt;
This indicates that the file /HelloWorld was added.&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%2F4q4hc1q4cau1l69mqgw1.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%2F4q4hc1q4cau1l69mqgw1.png" alt="Image description" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create another container and delete an existing file:&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%2Fms3xrytsolmi4nl2lr8v.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%2Fms3xrytsolmi4nl2lr8v.png" alt="Image description" width="495" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --name tweak-d busybox:latest rm /bin/vi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a new container named tweak-d from the busybox:latest image and deletes the file /bin/vi.&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%2Fdmf80k5ogfjuq7zppgr7.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%2Fdmf80k5ogfjuq7zppgr7.png" alt="Image description" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Review the filesystem changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container diff tweak-d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command lists all the changes made to the filesystem of the tweak-d container. You should see:&lt;/p&gt;

&lt;p&gt;Expected Output:&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%2F9nvf6s1fcmwruz0reg4h.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%2F9nvf6s1fcmwruz0reg4h.png" alt="Image description" width="589" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This indicates that the directory /bin was changed and the file /bin/vi was deleted.&lt;/p&gt;

&lt;p&gt;Create yet another container and change an existing file:&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%2F67weezk7mksfze0xdecv.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%2F67weezk7mksfze0xdecv.png" alt="Image description" width="518" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --name tweak-c busybox:latest touch /bin/vi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a new container named tweak-c from the busybox:latest image and updates the modification time of the file /bin/vi.&lt;/p&gt;

&lt;p&gt;Review the filesystem changes:&lt;/p&gt;

&lt;p&gt;docker container diff tweak-c&lt;br&gt;
This command lists all the changes made to the filesystem of the tweak-c container. You should see:&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%2Fdtz8yga9vxsld5jjqa92.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%2Fdtz8yga9vxsld5jjqa92.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This indicates that the directories /bin and /bin/busybox were changed.&lt;/p&gt;

&lt;p&gt;Clean up our workspace by removing the containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container rm -vf tweak-a
docker container rm -vf tweak-d
docker container rm -vf tweak-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These commands forcefully remove the tweak-a, tweak-d, and tweak-c containers, cleaning up our workspace.&lt;/p&gt;

&lt;p&gt;Explanation of docker container diff Output&lt;br&gt;
Lines that start with an A indicate files that were added.&lt;br&gt;
Lines that start with a C indicate files that were changed.&lt;br&gt;
Lines that start with a D indicate files that were deleted.&lt;br&gt;
By following these steps, you'll be able to track and understand filesystem changes within Docker containers. This is particularly useful for debugging and for ensuring that your containerized applications behave as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#/Commands Summary
Create a container and add a new file:
docker container run --name tweak-a busybox:latest touch /HelloWorld

#Review the filesystem changes:
docker container diff tweak-a

#Create another container and delete an existing file:
docker container run --name tweak-d busybox:latest rm /bin/vi

#Review the filesystem changes:
docker container diff tweak-d

#Create yet another container and change an existing file:
docker container run --name tweak-c busybox:latest touch /bin/vi

#Review the filesystem changes:
docker container diff tweak-c

#Clean up your workspace:
docker container rm -vf tweak-a
docker container rm -vf tweak-d
docker container rm -vf tweak-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Create and Commit an Ubuntu Container with Git Installed</title>
      <dc:creator>Arif Hossain</dc:creator>
      <pubDate>Sat, 09 Nov 2024 06:20:44 +0000</pubDate>
      <link>https://forem.com/arif_hossain/create-and-commit-an-ubuntu-container-with-git-installed-5g83</link>
      <guid>https://forem.com/arif_hossain/create-and-commit-an-ubuntu-container-with-git-installed-5g83</guid>
      <description>&lt;p&gt;Create and Commit an Ubuntu Container with Git Installed&lt;br&gt;
This session will guide us through creating an Ubuntu container, installing Git, and committing the changes to a new image. Additionally, we'll learn how to set an entrypoint to make using the image more efficient.&lt;/p&gt;

&lt;p&gt;Task&lt;br&gt;
We will perform the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an ubuntu container and open a bash session.&lt;/li&gt;
&lt;li&gt;Install git inside the container and verify the git.&lt;/li&gt;
&lt;li&gt;Create new image by using commit.&lt;/li&gt;
&lt;li&gt;Set the entrypoint for the new image to make it easier to use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple Explanation of the Process&lt;br&gt;
In this lab, we will start by creating a container from the Ubuntu image and open a bash session within it. Inside this container, we will install git and verify that the installation was successful by checking the git version. After exiting the container, we will commit these changes to create a new Docker image that includes git. We will run a container from that image.&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%2Fqzlo1eyt7ex1h0dkoxe6.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%2Fqzlo1eyt7ex1h0dkoxe6.png" alt="Image description" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we will set an entrypoint for this new image to make it easier to use git directly without needing to specify the git command each time we start a container from this image.&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%2Fgpvgd4j11sk3zspdvp7m.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%2Fgpvgd4j11sk3zspdvp7m.png" alt="Image description" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Steps&lt;br&gt;
Create an Ubuntu container and open a bash session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -it --name image-dev ubuntu:latest /bin/bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new container named image-dev from the ubuntu:latest image and opens an interactive bash session.&lt;/p&gt;

&lt;p&gt;Install Git inside the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get update
apt-get install -y git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates the package list and installs Git in the container.&lt;/p&gt;

&lt;p&gt;Verify the Git installation by checking its version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git --version
Expected output:

root@d15b204bcec5:/# git --version
git version 2.43.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command confirms that Git was installed correctly.&lt;/p&gt;

&lt;p&gt;Exit the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command exits the interactive bash session and returns to the host terminal.&lt;/p&gt;

&lt;p&gt;Review the filesystem changes and commit these changes to create a new image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container commit -a "@arif" -m "Added git" image-dev ubuntu-git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command commits the changes made in the image-dev container to a new image named ubuntu-git with an author tag and a commit message.&lt;/p&gt;

&lt;p&gt;Remove the modified container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container rm -vf image-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command forcefully removes the image-dev container to clean up.&lt;/p&gt;

&lt;p&gt;Verify the new image by checking the Git version in a new container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --rm ubuntu-git git --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a temporary container from the ubuntu-git image to verify that Git is installed correctly.&lt;/p&gt;

&lt;p&gt;Setting the Entrypoint to Git&lt;br&gt;
Create a new container with the entrypoint set to Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --name cmd-git --entrypoint git ubuntu-git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a new container named cmd-git with the entrypoint set to git, showing the standard Git help and exiting.&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%2Fiukhck2uw09heoeho3do.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%2Fiukhck2uw09heoeho3do.png" alt="Image description" width="759" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Commit the new image with the entrypoint:&lt;/p&gt;

&lt;p&gt;docker container commit -m "Set CMD git" -a "@poridhi" cmd-git ubuntu-git&lt;br&gt;
This command commits the changes to the ubuntu-git image, setting the entrypoint to Git.&lt;/p&gt;

&lt;p&gt;Remove the modified container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container rm -vf cmd-git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command forcefully removes the cmd-git container to clean up.&lt;/p&gt;

&lt;p&gt;Test the new image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run --name cmd-git ubuntu-git version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command runs a new container from the ubuntu-git image, verifying that the entrypoint is set correctly and showing the Git version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git version 2.43.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fvql8wl3s8xvb9io4c846.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%2Fvql8wl3s8xvb9io4c846.png" alt="Image description" width="782" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup ensures that any container started from the ubuntu-git image will automatically use Git as the entrypoint, making it easier for users to work with Git directly.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
