Skip to content

Demo repo to demonstrate building a docker image from github repository with github actions

License

Notifications You must be signed in to change notification settings

Sandeep-source/Docker-Image-with-GitHub-Actions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

36 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Docker-Image-with-GitHub-Actions

This repo provides a guide πŸ“— to creating a simple pipeline to build βš™ and upload docker 🐳 image artifacts to the docker hub 🐳 repo with the help of GitHub actions as changes take place in GitHub main branch.

Prerequisites

  1. Docker 🐳 basics.

  2. Yaml πŸ“„ basics

Note

If you are viewing this page from GitHub pages then some code for GitHub secrets will not be shown, you will only see a $ sign. Check out GitHub repo from πŸ‘‰Here for the correct code.

Scanario

For this demo, the application is to be dockerized 🐳 in a static site. It is a simple game of guessing πŸ€” numbers between 0 0️⃣ to 9 9️⃣. You access this page Here

Screenshot

Repository structure

/src
  index.html
  index.css
/Dockerfile
/README.md

Let's take a look πŸ‘€ at source files πŸ—ƒ

  1. /src - This folder contains source files πŸ“ for our static site.
  2. Dockerfile - This is a basic Dockerfile 🐳 which specifies how the image should be built from the source. We will take a look πŸ‘€ at this in a moment.
  3. README.md - This is the file πŸ“„ you currently reading.

Dockerfile

Dockerfile 🐳 provides a set of instuctions to build βš™ the image. For this repo it looks πŸ‘€ like the following.

 FROM nginx
 ADD src/* /usr/share/nginx/html/
 EXPOSE 80
 CMD ["nginx","-g","daemon off;"]

Let's take a look πŸ‘€ at each instruction to understand what these instructions mean

  1. FROM nginx - This line tells docker 🐳 to use Nginx πŸ†– as the official image as a base image for our new image.
  2. ADD src/* /usr/share/nginx/html/ - This line copies files πŸ—ƒ of src folder inside the /usr/share/nginx/html/ folder of image. /usr/share/nginx/html/ folder is used by the nginx πŸ†– server as entry point of website.
  3. EXPOSE 80 - This line tells docker 🐳 to open port 80 inside the docker 🐳 container so that we can communicate with the nginx πŸ†– server inside.
  4. CMD ["nginx","-g","daemon off;"] - This last cline starts Nginx πŸ†– server and runs β–Ά every time the docker 🐳 container start.

It's all about what we need to get started. Let's take a look πŸ‘€ how to setup GitHub actions to create a pipeline.

Steps to create πŸ›  a pipeline

Create github workflow

  1. Open github repo and click on actions option.
  2. Search πŸ” for Simple workflow and select the most suitable from the option that appeared.
  3. Rename the file πŸ“„ with the name you want for your workflow.

Writing Code πŸ‘¨β€πŸ’» for workflow

  1. Replace πŸ” the code πŸ‘©β€πŸ’» of workflow with the following.

    name:
    on:
    jobs:
    

    Let's understand πŸ€” what this code πŸ‘©β€πŸ’» means

    • The lines starting with # represents comments in YAML.
    • name: - Defines the name for your workflow.
    • on: - When we create a GitHub action, we want the action to run β–Ά on certain events i.e push to a branch. This on parameter describes the events in which the action is going to run β–Ά.
    • jobs: - jobs work section is the place where we define what going to happen when events specified in the on: section occurs.
  2. Give a name to your workflow

    name: Docker image CI
  3. Specify the event of our interest in this case push event

    • Add event

      name: Docker image CI
      on:
        push:
    • Add branches for which we going to perform some action

      name: Docker image CI
      on:
        push:
          branches: [ "main" ]
  4. Now the remaining part of the workflow is jobs section. Jobs define the set of actions (Tasks) to be performed. These action can run β–Ά sequentially or in parallel. for this demo we are just going to create one job named docker-build.

    name: Docker image CI
    on:
       push:
         branches: [ "main" ]
    jobs:
       docker-build:
  5. Each job section has following things

    • runs-on: - Tells πŸ“’ the platform on which this job(Task) is going to run β–Ά on. For this demo, we are taking 'ubuntu-latest'.

    • steps: - This defines a set of steps to be performed to get the job done.

    • Now our code πŸ‘©β€πŸ’» will look πŸ‘€ like this.

       name: Docker image CI
       on:
          push:
            branches: [ "main" ]
       jobs:
          docker-build:
               runs-on: ubuntu-latest
               steps: 

    Each step in steps walk section has the following parts

    • name: - name of the step
    • run: - set of command πŸ’» to run β–Ά
    • uses: - rerefence of any other action which is used by the current steps. The referenced action will run β–Ά first.optional
    • Apart from these, there are many other optional parts.
  6. Add the following code πŸ‘¨β€πŸ’» in the steps section

    - uses: actions/checkout@v3
    - name: Build the Docker image
      run: |
    • notice | after run: this allows us to write multiple commands πŸ’».
  7. To build βš™ image add the following command πŸ’» to the Build the Docker image step and replace <image_name> With the name of your choice.

     docker build . --file Dockerfile --tag <image_name>
    • Now our file πŸ“„ look πŸ‘€ something like this

      name: Docker image CI
      on:
        push:
          branches: [ "main" ]
      jobs:
          docker-build:
             runs-on: ubuntu-latest
               steps:
                 - uses: actions/checkout@v3
                 - name: Build the Docker image
                   run: |
                      docker build . --file Dockerfile --tag hackthenumber
    • Notice πŸ“ the uses part specifies actions/checkout@v3. This action checks if our repository is present and if we have access to it.

    • Command πŸ’» docker build . --file Dockerfile --tag hackthenumber builds βš™ an image named hackthenumber it is currently stored at the local system at which the job is running.

  8. Login πŸ” to dockerhub 🐳

    To make push the image to the docker hub 🐳 we need to login to the docker hub 🐳. Docker recommends creating access tokens for logins πŸ” instead of using password πŸ”‘.

    • Creating dockerhub 🐳 Access token πŸ—

      • To create an access token login πŸ” to docker hub 🐳. Goto access Account Setting > Security > New Access token.

        acc

        security

      • Enter description for the token and click generate βš™.

      • Select Copy and Close.

    • Adding passwords πŸ”‘ directly to workflow files πŸ“„ can be a potential threat. To make this secure GitHub provides secrets to store passwords πŸ”‘ etc. To add the secrets to GitHub repo do the following.

      • Goto your repo.
      • Open Settings πŸ”§.
      • Select Secret > Actions > New Repository Secret
      • Add DOCKERHUB as name and your docker hub username as secret.
      • Add another secret for TOKEN as the name and paste the access token you generated βš™ in the previous step.
    • Login πŸ” to Dockerhub 🐳

      • Add the following lines to run part to login πŸ”

        docker login -u ${{secrets.USERNAME}} -p ${{secrets.TOKEN}}
  9. Tag image to refer to Dockerhub 🐳 repo

    • To tag image add the following command πŸ’» by replacing <image_name> with the image name you have choosen for your image

      docker tag <image_name> ${{secrets.USERNAME}}/<image_name> 
    • With our choosen name it will look πŸ‘€ like something this

      docker tag hackthenumber ${{secrets.USERNAME}}/hackthenumber
  10. Add the following line to push image to dockerhub 🐳

    docker push ${{secrets.USERNAME}}/hackthenumber

Now our file πŸ“„ will look πŸ‘€ like something this

name: Docker image CI
on:
  push:
    branches: [ "main" ]
jobs:
    docker-build:
        runs-on: ubuntu-latest
           steps:
              - uses: actions/checkout@v3
              - name: Build the Docker image
                run: |
                   docker build . --file Dockerfile --tag hackthenumber
                   docker login -u ${{secrets.USERNAME}} -p ${{secrets.TOKEN}}
                   docker tag hackthenumber ${{secrets.USERNAME}}/hackthenumber
                   docker push ${{secrets.USERNAME}}/hackthenumber

Similarly, you can add code to test if everything is working fine in the same script. After adding the testing code, our final code will look like this.

name: Docker image CI
on:
  push:
    branches: [ "main" ]
jobs:
  docker-build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: Build the Docker image
            run: |
                  docker build . --file Dockerfile --tag hackthenumber
                  docker login -u ${{secrets.USERNAME}} -p ${{secrets.TOKEN}}
                  docker tag hackthenumber ${{secrets.USERNAME}}/hackthenumber
                  
  docker-test:
        runs-on: ubuntu-latest
        needs: docker-build
        steps:
          - uses: actions/checkout@v3
          - name: Test image presence
            run: |
              docker image inspect ${{secrets.USERNAME}}/hackthenumber
              if [[ $? -eq 1 ]]; then
                  echo "❌ Image not found!"
                  exit 1  # This will cause the job to fail
              else
                  echo "βœ… Image Build Successfully!"
              fi
          - name: Test image response
            run: |
                  docker run -itdp 8000:80 --rm ${{secrets.USERNAME}}/hackthenumber
                  response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8000)
                  if [[ $response -ne 200 ]]; then
                    echo "❌ Image response is not 200!"
                    exit 1
                  else
                    echo "βœ… Image response is 200!"
                  fi
  docker-deploy:
        runs-on: ubuntu-latest
        needs: docker-test
        steps:
            - uses: actions/checkout@v3
            - name: Deploy to docker hub
              run: |
                docker push ${{secrets.USERNAME}}/hackthenumber && echo "βœ… Deployed to Docker Hub" || echo "❌ Deployment to Docker Hub failed"

Quick Test deployed image

  • Go to https://labs.play-with-docker.com and login πŸ” with dockerhub 🐳 credentials.

  • Click start and then Add New Instance.

    image

    Add instance

  • Run βš™ the command πŸ’» docker run -dp 8080:80 <username>/<image_name> by replacing <username> with the dockerhub username and <image_name> with the image name used in the GitHub action. For example

    docker run -dp 8080:80 sandeepsource/hackthenumber
  • Click the port number 8080 on the right side of the open port button. If the button for port 8080 not appeared then click the open port button and enter 8080 and click ok.

    open port

  • Now if everything is gone well πŸ™Œ you will able to see following output.

    output