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.
-
Docker π³ basics.
-
Yaml π basics
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.
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
/src
index.html
index.css
/Dockerfile
/README.md
Let's take a look π at source files π
/src
- This folder contains source files π for our static site.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.README.md
- This is the file π you currently reading.
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
FROM nginx
- This line tells docker π³ to use Nginx π as the official image as a base image for our new image.ADD src/* /usr/share/nginx/html/
- This line copies files π ofsrc
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.EXPOSE 80
- This line tells docker π³ to open port 80 inside the docker π³ container so that we can communicate with the nginx π server inside.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.
- Open github repo and click on actions option.
- Search π for Simple workflow and select the most suitable from the option that appeared.
- Rename the file π with the name you want for your workflow.
-
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. Thison
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 theon:
section occurs.
-
Give a name to your workflow
name: Docker image CI
-
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" ]
-
-
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:
-
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 steprun:
- 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.
-
-
Add the following code π¨βπ» in the steps section
- uses: actions/checkout@v3 - name: Build the Docker image run: |
- notice
|
afterrun:
this allows us to write multiple commands π».
- notice
-
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.
-
-
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 π
-
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}}
-
-
-
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 imagedocker tag <image_name> ${{secrets.USERNAME}}/<image_name>
-
With our choosen name it will look π like something this
docker tag hackthenumber ${{secrets.USERNAME}}/hackthenumber
-
-
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"
-
Go to https://labs.play-with-docker.com and login π with dockerhub π³ credentials.
-
Click start and then Add New 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 exampledocker run -dp 8080:80 sandeepsource/hackthenumber
-
Click the port number
8080
on the right side of the open port button. If the button for port8080
not appeared then click theopen port
button and enter 8080 and click ok. -
Now if everything is gone well π you will able to see following output.