DEV Community

Cover image for Beginner’s Guide: Build, Push, and Deploy Docker Image with GitHub Actions
Md. Abu Raihan Srabon
Md. Abu Raihan Srabon

Posted on • Edited on

2

Beginner’s Guide: Build, Push, and Deploy Docker Image with GitHub Actions

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.

  1. What’s GitHub Actions?

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).

Why use GitHub Actions?

  • Seamless integration with GitHub repositories.
  • Customization: Create workflows tailored to your project needs.
  • Ease of use: Simple YAML configuration.
  1. What This Script Does

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.

a. Checking Out the Code

- name: Checkout Code
  uses: actions/checkout@v3
Enter fullscreen mode Exit fullscreen mode

This step clones the repository into the GitHub Actions runner, enabling the workflow to access your project files.

b. Setting Up Docker Buildx

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v2
Enter fullscreen mode Exit fullscreen mode

Docker Buildx allows the runner to build multi-platform images and use advanced build features.

c. Configuring and Logging into the Docker Registry

- name: Add Registry to /etc/hosts
  run: |
    echo "${{ secrets.HOSTS_ENTRY }}" | sudo tee -a /etc/hosts

- name: Configure Docker for Insecure Registry
  run: |
    sudo mkdir -p /etc/docker
    echo '{ "insecure-registries": ["https://harbor.example.com"] }' | sudo tee /etc/docker/daemon.json
    sudo systemctl restart docker

- name: Log in to Docker Registry
  uses: docker/login-action@v2
  with:
    registry: harbor.example.com
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}
Enter fullscreen mode Exit fullscreen mode

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.

d. Tagging with a Date-Time-Based Version

- name: Generate Date-Time-Based Tag
  id: generate_tag
  run: |
    new_version=$(date -u +"v%Y.%m.%d.%H%M%S")
    echo "Generated tag: $new_version"
    echo "version=$new_version" >> $GITHUB_ENV
Enter fullscreen mode Exit fullscreen mode

This step creates a version tag based on the current UTC date and time, ensuring unique version identifiers for each image build.

e. Building and Pushing the Docker Image

- name: Build Docker Image
  run: |
    PROJECT_NAME=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f2)
    docker build -f .docker/Dockerfile \
      -t harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:${{ env.version }} -t harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:latest .
  env:
    GITHUB_REPOSITORY: ${{ github.repository }}

- name: Push Docker Image
  run: |
    PROJECT_NAME=$(echo "${GITHUB_REPOSITORY}" | cut -d'/' -f2)
    docker push harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:${{ env.version }}
    docker push harbor.example.com/${{ vars.PROJECT_NAME }}/$PROJECT_NAME:latest
  env:
    GITHUB_REPOSITORY: ${{ github.repository }}
Enter fullscreen mode Exit fullscreen mode

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.

f. Deploying to a Remote Server

- name: Deploy to Remote Server
  if: success()
  env:
    SSH_HOST: ${{ secrets.SSH_HOST }}
    SSH_USERNAME: ${{ secrets.SSH_USERNAME }}
    SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
    DEPLOY_COMMANDS: ${{ secrets.DEPLOY_COMMANDS }}
  run: |
    echo "${SSH_PRIVATE_KEY}" > /tmp/private_key
    chmod 600 /tmp/private_key
    ssh -o StrictHostKeyChecking=no -i /tmp/private_key ${SSH_USERNAME}@${SSH_HOST} "${DEPLOY_COMMANDS}"
  shell: bash
Enter fullscreen mode Exit fullscreen mode

Finally, this step connects to a remote server via SSH and runs the deployment commands specified in the GitHub secret DEPLOY_COMMANDS. This helps automate the release process.

Below is an image of the complete GitHub Actions script:

Image description

  1. What We Have Accomplished by Running This Script

By running this GitHub Actions workflow, we have:

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

This streamlines the CI/CD process, making development and deployment faster and more reliable.

  1. Link to GitHub Gist

For an easy reference and to adapt this workflow to your needs, you can find the complete script here on GitHub Gist.

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!

Image of AssemblyAI

Automatic Speech Recognition with AssemblyAI

Experience near-human accuracy, low-latency performance, and advanced Speech AI capabilities with AssemblyAI's Speech-to-Text API. Sign up today and get $50 in API credit. No credit card required.

Try the API

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay