<?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>DEV Community: Md. Abu Raihan Srabon</title>
    <description>The latest articles on DEV Community by Md. Abu Raihan Srabon (@msrabon).</description>
    <link>https://dev.to/msrabon</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%2F679577%2F24b53f93-15c5-4e33-85b3-4cf100964e5d.png</url>
      <title>DEV Community: Md. Abu Raihan Srabon</title>
      <link>https://dev.to/msrabon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msrabon"/>
    <language>en</language>
    <item>
      <title>Automating Docker Image Versioning, Build, Push, and Scanning Using GitHub Actions</title>
      <dc:creator>Md. Abu Raihan Srabon</dc:creator>
      <pubDate>Tue, 17 Dec 2024 15:47:28 +0000</pubDate>
      <link>https://dev.to/msrabon/automating-docker-image-versioning-build-push-and-scanning-using-github-actions-388n</link>
      <guid>https://dev.to/msrabon/automating-docker-image-versioning-build-push-and-scanning-using-github-actions-388n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In a previous blog post, &lt;a href="https://dev.to/msrabon/beginners-guide-build-push-and-deploy-docker-image-with-github-actions-aa7"&gt;Beginner’s Guide: Build, Push, and Deploy Docker Image with GitHub Actions&lt;/a&gt;, we explored how to set up a GitHub Actions workflow for building, pushing, and deploying Docker images. This guide takes it a step further by adding semantic versioning, cleaner build workflows, and vulnerability scanning to the CI/CD pipeline. By implementing these improvements, you can better automate Docker image lifecycle management with a robust and professional workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Update?
&lt;/h2&gt;

&lt;p&gt;The updated workflow introduces several notable enhancements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Semantic Versioning: Automatically bump Docker image versions based on commit messages.&lt;/li&gt;
&lt;li&gt;Improved Docker Build and Push: Cleaner setup with GitHub Container Registry (GHCR).&lt;/li&gt;
&lt;li&gt;Security Scanning: Use Trivy to scan Docker images for vulnerabilities before deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This workflow ensures version control, clean tagging, and improved security measures in an automated CI/CD pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete GitHub Actions Workflow
&lt;/h2&gt;

&lt;p&gt;Here is the updated GitHub Actions YAML workflow:&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%2Fq7jhba8v7gymi40ntbxg.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%2Fq7jhba8v7gymi40ntbxg.png" alt="Updated github actions workflow" width="800" height="1130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Improvements and Explanation
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Semantic Versioning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Managing Docker image versions can become tedious, especially in collaborative projects. Semantic versioning automates version bumps based on commit messages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default Behavior: Increments the patch version.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Custom Increments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add bump: major in a commit message to increment the major version.&lt;/li&gt;
&lt;li&gt;Add bump: minor in a commit message to increment the minor version.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Code Explanation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Determine Version Bump Type&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;determine-bump-type&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;echo "level=patch" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
    &lt;span class="s"&gt;if git log -1 --pretty=%B | grep -q 'bump: major'; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "level=major" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
    &lt;span class="s"&gt;elif git log -1 --pretty=%B | grep -q 'bump: minor'; then&lt;/span&gt;
      &lt;span class="s"&gt;echo "level=minor" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the script scans the latest commit message for keywords and determines the version bump level.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clean Docker Build and Push to GHCR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Docker image is built and pushed to GitHub Container Registry (GHCR), making it easier to manage images natively in GitHub.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Log in to the GHCR using GitHub credentials.&lt;/li&gt;
&lt;li&gt;Build and tag the image with the new version and latest tag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Push Docker Image&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v6&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./php-8.2&lt;/span&gt;
    &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./php-8.2/Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;ghcr.io/${{ github.repository }}:${{ needs.semver.outputs.new_version }}&lt;/span&gt;
      &lt;span class="s"&gt;ghcr.io/${{ github.repository }}:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Vulnerability Scanning with Trivy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Security is critical for containerized applications. Trivy scans the built Docker image for vulnerabilities before deployment. It exits with an error if vulnerabilities are found, ensuring only secure images are deployed.&lt;/p&gt;

&lt;p&gt;Code Explanation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Trivy Vulnerability Scan&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasecurity/trivy-action@0.28.0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;scan-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;image'&lt;/span&gt;
    &lt;span class="na"&gt;image-ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/${{ github.repository }}:${{ needs.semver.outputs.new_version }}&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;table'&lt;/span&gt;
    &lt;span class="na"&gt;exit-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt;
    &lt;span class="na"&gt;ignore-unfixed&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;vuln-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;os,library'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;scan-type: image&lt;/code&gt;: Scans the built image.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exit-code: 1&lt;/code&gt;: Fails the workflow if vulnerabilities are detected.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ignore-unfixed: true&lt;/code&gt;: Ignores vulnerabilities without known fixes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This enhanced GitHub Actions workflow adds automation, cleaner versioning, and security scanning to your Docker CI/CD pipeline. By leveraging &lt;strong&gt;semantic versioning&lt;/strong&gt;, Docker builds with &lt;strong&gt;GHCR&lt;/strong&gt;, and vulnerability scanning via &lt;strong&gt;Trivy&lt;/strong&gt;, you can ensure efficient, secure, and manageable image deployments.&lt;/p&gt;

&lt;p&gt;For a practical implementation, you can refer to the complete workflow in my &lt;a href="https://github.com/aburaihan-dev/docker-php-base-image" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're new to GitHub Actions or Docker automation, check out my earlier blog post for foundational concepts: &lt;a href="https://blog.lazycoder.ninja/beginners-guide-build-push-and-deploy-docker-image-with-github-actions" rel="noopener noreferrer"&gt;Beginner’s Guide: Build, Push, and Deploy Docker Image with GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy automating! &lt;/p&gt;

</description>
      <category>docker</category>
      <category>githubactions</category>
      <category>trivy</category>
      <category>git</category>
    </item>
    <item>
      <title>Beginner’s Guide: Build, Push, and Deploy Docker Image with GitHub Actions</title>
      <dc:creator>Md. Abu Raihan Srabon</dc:creator>
      <pubDate>Sun, 10 Nov 2024 14:04:25 +0000</pubDate>
      <link>https://dev.to/msrabon/beginners-guide-build-push-and-deploy-docker-image-with-github-actions-aa7</link>
      <guid>https://dev.to/msrabon/beginners-guide-build-push-and-deploy-docker-image-with-github-actions-aa7</guid>
      <description>&lt;p&gt;In this post, we’ll introduce GitHub Actions and explain how to use them for automating Docker image builds, pushing images to a self-hosted registry, and deploying them to a remote server. This guide is tailored for beginners who want to start simple and expand their knowledge over time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What’s GitHub Actions?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GitHub Actions is a powerful tool for automating software workflows directly within your GitHub repository. It allows you to build, test, and deploy your code directly from GitHub. You define your automation tasks as YAML files within your repository, and these tasks run on GitHub’s hosted servers (or self-hosted runners if you prefer).&lt;/p&gt;

&lt;p&gt;Why use GitHub Actions?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seamless integration with GitHub repositories.&lt;/li&gt;
&lt;li&gt;Customization: Create workflows tailored to your project needs.&lt;/li&gt;
&lt;li&gt;Ease of use: Simple YAML configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;What This Script Does&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The given GitHub Actions script automates the CI/CD pipeline for building, tagging, and pushing a Docker image to a self-hosted registry, then deploying it to a remote server. Let’s dive into the main sections of the script and understand how each part works.&lt;/p&gt;

&lt;p&gt;a. Checking Out the Code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Code&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step clones the repository into the GitHub Actions runner, enabling the workflow to access your project files.&lt;/p&gt;

&lt;p&gt;b. Setting Up Docker Buildx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker Buildx&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker Buildx allows the runner to build multi-platform images and use advanced build features.&lt;/p&gt;

&lt;p&gt;c. Configuring and Logging into the Docker Registry&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Add Registry to /etc/hosts&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;echo "${{ secrets.HOSTS_ENTRY }}" | sudo tee -a /etc/hosts&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure Docker for Insecure Registry&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;sudo mkdir -p /etc/docker&lt;/span&gt;
    &lt;span class="s"&gt;echo '{ "insecure-registries": ["https://harbor.example.com"] }' | sudo tee /etc/docker/daemon.json&lt;/span&gt;
    &lt;span class="s"&gt;sudo systemctl restart docker&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Log in to Docker Registry&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;harbor.example.com&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKER_USERNAME }}&lt;/span&gt;
    &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKER_PASSWORD }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These steps set up Docker on the runner to connect to the self-hosted Harbor registry. It configures Docker to treat the registry as an insecure source (use this cautiously) and logs in using provided credentials.&lt;/p&gt;

&lt;p&gt;d. Tagging with a Date-Time-Based Version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate Date-Time-Based Tag&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generate_tag&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;new_version=$(date -u +"v%Y.%m.%d.%H%M%S")&lt;/span&gt;
    &lt;span class="s"&gt;echo "Generated tag: $new_version"&lt;/span&gt;
    &lt;span class="s"&gt;echo "version=$new_version" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step creates a version tag based on the current UTC date and time, ensuring unique version identifiers for each image build.&lt;/p&gt;

&lt;p&gt;e. Building and Pushing the Docker Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Docker Image&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;PROJECT_NAME=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f2)&lt;/span&gt;
    &lt;span class="s"&gt;docker build -f .docker/Dockerfile \&lt;/span&gt;
      &lt;span class="s"&gt;-t harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:${{ env.version }} -t harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:latest .&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GITHUB_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.repository }}&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push Docker Image&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;PROJECT_NAME=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f2)&lt;/span&gt;
    &lt;span class="s"&gt;docker push harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:${{ env.version }}&lt;/span&gt;
    &lt;span class="s"&gt;docker push harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:latest&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GITHUB_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.repository }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This section builds the Docker image using the Dockerfile and tags it with both the generated version and latest. It then pushes the images to the Harbor registry.&lt;/p&gt;

&lt;p&gt;f. Deploying to a Remote Server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Remote Server&lt;/span&gt;
  &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success()&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;SSH_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_HOST }}&lt;/span&gt;
    &lt;span class="na"&gt;SSH_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_USERNAME }}&lt;/span&gt;
    &lt;span class="na"&gt;SSH_PRIVATE_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_PRIVATE_KEY }}&lt;/span&gt;
    &lt;span class="na"&gt;DEPLOY_COMMANDS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DEPLOY_COMMANDS }}&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;echo "${SSH_PRIVATE_KEY}" &amp;gt; /tmp/private_key&lt;/span&gt;
    &lt;span class="s"&gt;chmod 600 /tmp/private_key&lt;/span&gt;
    &lt;span class="s"&gt;ssh -o StrictHostKeyChecking=no -i /tmp/private_key ${SSH_USERNAME}@${SSH_HOST} "${DEPLOY_COMMANDS}"&lt;/span&gt;
  &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, this step connects to a remote server via SSH and runs the deployment commands specified in the GitHub secret &lt;code&gt;DEPLOY_COMMANDS&lt;/code&gt;. This helps automate the release process.&lt;/p&gt;

&lt;p&gt;Below is an image of the complete GitHub Actions script:&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%2Fxz6gg1a3ci4vob5h141u.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%2Fxz6gg1a3ci4vob5h141u.png" alt="Image description" width="800" height="1838"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What We Have Accomplished by Running This Script&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By running this GitHub Actions workflow, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated the process of checking out code and setting up Docker on a GitHub-hosted runner.&lt;/li&gt;
&lt;li&gt;Built a Docker image from the code and tagged it with both a version and latest.&lt;/li&gt;
&lt;li&gt;Pushed the Docker image to a self-hosted Harbor registry.&lt;/li&gt;
&lt;li&gt;Deployed the image to a remote server using secure SSH commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This streamlines the CI/CD process, making development and deployment faster and more reliable.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Link to GitHub Gist&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For an easy reference and to adapt this workflow to your needs, you can find the complete script here on &lt;a href="https://gist.github.com/abu-raihan-ddclbd/c9f68b562fa1b3b8e4c81d3234bb7d2a" rel="noopener noreferrer"&gt;GitHub Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feel free to use this template as a starting point for automating your Docker workflows and deployment pipelines. With GitHub Actions, you can achieve seamless automation with just a few configuration steps!&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>docker</category>
      <category>harbor</category>
      <category>ssh</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Setting Up Jenkins on Docker with Docker Agent-Based Builds</title>
      <dc:creator>Md. Abu Raihan Srabon</dc:creator>
      <pubDate>Mon, 15 Jan 2024 13:07:47 +0000</pubDate>
      <link>https://dev.to/msrabon/step-by-step-guide-to-setting-up-jenkins-on-docker-with-docker-agent-based-builds-43j5</link>
      <guid>https://dev.to/msrabon/step-by-step-guide-to-setting-up-jenkins-on-docker-with-docker-agent-based-builds-43j5</guid>
      <description>&lt;h2&gt;
  
  
  Part 1: Introduction to Docker and Jenkins, Setting Up Jenkins on Docker
&lt;/h2&gt;




&lt;h2&gt;
  
  
  Introduction to Docker and Jenkins
&lt;/h2&gt;

&lt;p&gt;Hello there! If you're stepping into the world of DevOps or are a Senior Software Engineer looking to dip your toes into automation, this section is a gentle introduction to two powerful tools: Docker and Jenkins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker - Simplifying Environments:&lt;/strong&gt; Docker is a tool that uses containerization to make it easier for you to develop, deploy, and run applications. Think of it as a virtual box where everything your application needs to run (code, runtime, system tools) is packaged together. This means no more 'it works on my machine' issues, as Docker ensures consistency across environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jenkins - Automating the Boring Stuff:&lt;/strong&gt; Jenkins is like a helpful robot for software teams. It automates parts of the software development process, particularly those repetitive tasks like building, testing, and deploying code. With Jenkins, you can focus more on writing great code and less on the process of getting that code into production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Are We Talking About Both?&lt;/strong&gt; Combining Docker and Jenkins can significantly streamline your development workflow. Docker provides a consistent environment for Jenkins to operate in, making your CI/CD pipelines more efficient and less prone to environment-related issues.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember, everyone starts somewhere, and questions are a sign of a great learner. Whether you're a beginner in DevOps or an experienced engineer new to automation, this guide aims to make your journey into Docker and Jenkins as smooth as possible. Let's get started and unlock the potential of these tools together!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Installing Docker and Jenkins
&lt;/h3&gt;

&lt;p&gt;In this section, we'll cover the basic steps for installing Docker and setting up Jenkins using a Dockerfile and docker-compose.yml. This setup ensures a smooth and consistent environment for your Jenkins instance.&lt;/p&gt;

&lt;p&gt;Installing Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Download Docker:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For Windows and Mac: Download Docker Desktop from the &lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;official Docker website&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For Linux: Follow the instructions specific to your Linux distribution on the &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker installation guide&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Install Docker:&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Follow the installation guide for your operating system on the Docker website. This typically involves running an installer or executing a few commands in the terminal.&lt;br&gt;
Verify Installation:&lt;/p&gt;

&lt;p&gt;Open a terminal or command prompt and run &lt;code&gt;docker --version&lt;/code&gt; to ensure Docker was installed successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# docker --version
Docker version 24.0.7, build afdd53b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up Jenkins in Docker:
&lt;/h3&gt;

&lt;p&gt;For Jenkins, we will use a custom Dockerfile and docker-compose.yml to create a Docker image with Jenkins installed. Here's a step-by-step guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepare the Dockerfile:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Jenkins JDK 17, JDK 11 is being deprecated
FROM jenkins/jenkins:latest-jdk17

USER root

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y lsb-release

RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
  https://download.docker.com/linux/debian/gpg

RUN echo "deb [arch=$(dpkg --print-architecture) \
  signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
  https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" &amp;gt; /etc/apt/sources.list.d/docker.list

RUN apt-get update &amp;amp;&amp;amp; apt-get install -y docker-ce-cli

RUN apt update &amp;amp;&amp;amp; apt install tzdata -y

ENV TZ="Asia/Dhaka"

USER jenkins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provided &lt;code&gt;Dockerfile&lt;/code&gt; sets up Jenkins with JDK 17 and installs Docker inside the Jenkins container. This setup allows Jenkins to run Docker commands, which is crucial for Docker Agent-based builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the Dockerfile:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The Dockerfile begins with the latest Jenkins image with JDK 17.&lt;/li&gt;
&lt;li&gt;It installs the necessary packages and Docker CLI inside the container.&lt;/li&gt;
&lt;li&gt;The timezone is set to 'Asia/Dhaka', which you can adjust as per your requirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setting Up docker-compose:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'
services:
  jenkins:
    build: 
      context: .
      dockerfile: .docker/Jenkins/Dockerfile
    image: jenkins-jdk-17
    container_name: jenkins-jdk-17
    privileged: true
    user: root
    restart: always
    ports:
      - 8080:8080
      - 50000:50000
    volumes:
      - jenkins_home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/usr/bin/docker

volumes:
  jenkins_home:
    name: jenkins_home

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The provided &lt;code&gt;docker-compose.yml&lt;/code&gt; file defines the Jenkins service, using the image built from our Dockerfile.&lt;/li&gt;
&lt;li&gt;It sets the container to run in privileged mode with root user, ensuring that Docker commands can be executed within Jenkins.&lt;/li&gt;
&lt;li&gt;Ports 8080 and 50000 are exposed for Jenkins web UI and agent connections.&lt;/li&gt;
&lt;li&gt;Volumes are used for persisting Jenkins data and for Docker socket binding, allowing Jenkins to control Docker on the host.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building and Running Jenkins Container:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the directory containing your Dockerfile and docker-compose.yml.&lt;/li&gt;
&lt;li&gt;Run docker-compose build to build your Jenkins image.&lt;/li&gt;
&lt;li&gt;Once the build is complete, run docker-compose up to start Jenkins.&lt;/li&gt;
&lt;li&gt;Jenkins should now be accessible at &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accessing Jenkins:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;On your browser, go to &lt;code&gt;http://localhost:8080&lt;/code&gt; to access the Jenkins web UI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/aL-ZI7YILBw"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the initial setup wizard to configure Jenkins. You will need the initial admin password, which can be found in the Jenkins console logs or inside your Jenkins container at /var/jenkins_home/secrets/initialAdminPassword.&lt;/li&gt;
&lt;/ul&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%2Folg1tnl4yw55zgxpjial.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%2Folg1tnl4yw55zgxpjial.png" alt="Image description" width="800" height="514"&gt;&lt;/a&gt; Pic: collect initial admin password from console.&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%2Fectxhf25qkb9wto3yydz.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%2Fectxhf25qkb9wto3yydz.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt; Pic: Jenkins UI for initial admin password&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%2F7tmltp0bn5xn8emahp01.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%2F7tmltp0bn5xn8emahp01.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt; Pic: Plugins Selection page (we will move forward with defaults).&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%2Fuzqjhngo1prpygs5jv2q.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%2Fuzqjhngo1prpygs5jv2q.png" alt="Image description" width="800" height="366"&gt;&lt;/a&gt; Pic: Default plugins are being installed.&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%2F5buj7u88a4dgx4qhgpu6.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%2F5buj7u88a4dgx4qhgpu6.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt; Pic: Setup Jenkins URL (This URL will be used to configure projects)&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%2F03jnu3x2iecpp40nptvh.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%2F03jnu3x2iecpp40nptvh.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt; Pic: admin user setup.&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%2F93k9wadjwpqu1imc4hfy.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%2F93k9wadjwpqu1imc4hfy.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt; Pic: Jenkins Home page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For a more detailed Docker installation guide, visit the &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To understand more about Jenkins and Docker, explore the &lt;a href="https://www.jenkins.io/doc/book/installing/docker/" rel="noopener noreferrer"&gt;official Jenkins documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitHub Repository:
&lt;/h3&gt;

&lt;p&gt;For the complete Dockerfile, docker-compose.yml, and additional configuration files, you can visit the GitHub repository: &lt;a href="https://github.com/aburaihan-dev/jenkins-in-docker" rel="noopener noreferrer"&gt;https://github.com/aburaihan-dev/jenkins-in-docker&lt;/a&gt;. This repository contains all the necessary files and instructions to get your Jenkins on Docker up and running.&lt;/p&gt;

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