The Ops Community ⚙️

Cover image for A Simple Idea To Learn CI For Beginner
Nurul Ramadhona
Nurul Ramadhona

Posted on • Updated on

A Simple Idea To Learn CI For Beginner

Are you currently learning about DevOps? So you must have heard about CI/CD right? But are you the one of those who are confused about it? Then, you are not alone :)

Last time, I've published Getting Started With Jenkins series. Today I come back with an idea to learn about basic CI for beginner (like me) and I'll give you an example of simple task that we can do to get started. Maybe it's a common use case but I saw many people make it harder by combining it with Go, Node.js and many more. So here I just make it to be easier to understand. Before that, let me show you what Continuous Integration is!

CI is a practice where we commit code changes into a repository or project (can be in GitHub or GitLab for example), then it will trigger an automated sequence to build and test of each change.

Now, let's make it to be simple! Here's the scenario:

  1. Upload Dockerfile to the repository
  2. Create the workflows to build a Docker image and post it to Docker Hub or Registry
  3. Run the workflows

We also need GitHub/GitLab account and Docker Hub account.
(Click the link to sign up if you don't have yet)

I'll do the same task above with GitHub Actions and GitLab CI/CD. We'll see the differences as well. So, let's get started!


GitHub Actions

GitHub Actions

1. Prepare the files

  • Dockerfile
FROM nurulramadhona/httpd:v1
COPY index.html /usr/local/apache2/htdocs
EXPOSE 80
Enter fullscreen mode Exit fullscreen mode
  • index.html
<html><body><h1>LEARNING GITHUB ACTIONS</h1></body></html>
Enter fullscreen mode Exit fullscreen mode
  • docker-test

As an additional task, I've created a bash script named docker-test to create a docker container from the built docker image and get the output.

#!/bin/bash
docker container create --name web-server -p 8080:80 httpd:github
docker container start web-server
curl http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

2. Create a new repository and push the files to your repository
(You can create via web browser if you haven't installed gh CLI)

$ gh repo create learn-ci --public --clone
✓ Created repository nurulramadhona/learn-ci on GitHub
Initialized empty Git repository in /media/nurulramadhona/ops/repo/learn-ci/.git/
$ cd learn-ci/
$ gh repo list --visibility=public | grep learn-ci
nurulramadhona/learn-ci     public  2022-07-15T11:18:54Z
$ cd learn-ci/
/learn-ci$ vim index.html
/learn-ci$ vim Dockerfile
/learn-ci$ vim ./docker-test
/learn-ci$ git add .
/learn-ci$ git commit -m "upload docker files"
[master (root-commit) 5ec7453] upload docker files
 3 files changed, 8 insertions(+)
 create mode 100644 Dockerfile
 create mode 100644 docker-test
 create mode 100644 index.html
/learn-ci$ git branch -M main
/learn-ci$ git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 542 bytes | 135.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To github.com:nurulramadhona/learn-ci.git
 * [new branch]      main -> main
Enter fullscreen mode Exit fullscreen mode

3. Create Workflows
Go to the GitHub page via web browser and switch to the Actions menu. There you'll see a list of provided workflows templates. Here I'll use the one to build and push Docker image but I'll add some additional tasks like below:

  • docker-image.yml
name: Docker Image CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Build the Docker image
      run: docker build . --file Dockerfile --tag httpd:github
    - name: Bash script permission
      run: chmod +x ./docker-test
    - name: Run bash script
      run: ./docker-test
    - name: Login to DockerHub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}
    - name: Build and push
      uses: docker/build-push-action@v3
      with:
        push: true
        tags: nurulramadhona/httpd:github
Enter fullscreen mode Exit fullscreen mode

on to define an event, every single thing that happened in/out of the repository.
jobs to define the sequence of tasks, what have to do.
runs-on to define the runner environment.

4. Set the value for each variable
As you can see, there are two variables and we need to define them. Switch to Settings menu, then find Secrets under Security. Enter the values for your Docker Hub username and password.
GitHub Actions Secrets
Now, we're ready to commit and run the workflows!
Actions 1
See the workflows! Red means fail and green means success.
Actions 2
That's the example of failed workflows when I made a typo and turned into green when I fixed it.
Actions 3
Here's the sample output of what the GitHub Actions has done.
Actions 4

5. Check the image on Docker Hub
Actions 5
The image is pushed and already exist on my registry. Let's see if it'll work on our localhost!

/learn-ci$ docker container create --name web-github -p 8081:80 nurulramadhona/httpd:github
Unable to find image 'nurulramadhona/httpd:github' locally
github: Pulling from nurulramadhona/httpd
a330b6cecb98: Already exists 
14e3dd65f04d: Already exists 
fe59ad2e7efe: Already exists 
68eb42ff9345: Already exists 
9d5052bb82be: Already exists 
2197b58d1db7: Already exists 
a1a818bde354: Pull complete 
Digest: sha256:09860b29e1644d4ecbc8ce61364c40dda0e9e16e0c1ad1eb77ab8b80b453b165
Status: Downloaded newer image for nurulramadhona/httpd:github
e3f99f246acbe720456cfb237ed21b585cc5714f83f2d5db3f62adb029da45b7
/learn-ci$ docker container start web-github
web-github
/learn-ci$ curl localhost:8081
<html><body><h1>LEARNING GITHUB ACTIONS</h1></body></html>
Enter fullscreen mode Exit fullscreen mode

Web 8081


GitLab CI/CD

GitLab CICD

1. Prepare the files
You can download here.

  • Dockerfile
FROM nurulramadhona/httpd:v1
COPY index.html /usr/local/apache2/htdocs
EXPOSE 80
Enter fullscreen mode Exit fullscreen mode
  • index.html
<html><body><h1>LEARNING GITLAB CI</h1></body></html>
Enter fullscreen mode Exit fullscreen mode

2. Create a new project and push the file to your project
(Please create the project via web browser and clone it)

/gitlab$ git clone git@gitlab.com:nurulramadhona/learn-ci.git
Cloning into 'learn-ci'...
warning: You appear to have cloned an empty repository.
/gitlab$ cd learn-ci/
/gitlab/learn-ci$ git switch -c main
Switched to a new branch 'main'
/gitlab/learn-ci$ vim Dockerfile
/gitlab/learn-ci$ vim index.html
/gitlab/learn-ci$ git add .
/gitlab/learn-ci$ git commit -m "upload docker files"
[master (root-commit) 311f555] upload docker files
 2 files changed, 4 insertions(+)
 create mode 100644 Dockerfile
 create mode 100644 index.html
/gitlab/learn-ci$ git push origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 394 bytes | 131.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To gitlab.com:nurulramadhona/learn-ci.git
 * [new branch]      main -> main
Enter fullscreen mode Exit fullscreen mode

3. Create Pipelines
Create a new file named .gitlab-ci.yml or go to Editor menu under CICD, then put the code below.
GitLab CICD Pipeline

stages:
    - build

build-job:
    stage: build
    image: docker:latest
    services:
        - name: docker:dind
    script:
        - docker build . --file Dockerfile --tag httpd:gitlab
    before_script:
        - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    script:
        - docker build --pull -t "$CI_REGISTRY_IMAGE" .
        - docker push "$CI_REGISTRY_IMAGE"
Enter fullscreen mode Exit fullscreen mode

stages to define how many stage will be used.
image to define the image will be used to run the scripts.
script to define the commands in every job/stage.
before script to define the commands to be executed before script.

4. Set the value for each variable
As you can see, there are four variables and we need to define them. Switch to Settings => CI/CD, then expand Variables. Enter the values for your Docker Hub username and password.
GitLab CICD Variables
The additional things to add compared to GitHub Actions:
CI_REGISTRY = docker.io
CI_REGISTRY_IMAGE = index.docker.io/username/image:tag
By default, the variable goes to GitLab Registry. So, we need to change them to go to our Docker Registry.
Note*: Don't forget to add tag if you don't want to make it as latest version!

Now, we're ready to commit and run the job! Failed means fail and passed means success.
GitLab CICD Pipeline
That's the example of failed jobs when I used wrong image tag by using / instead of :. Then, it turned into passed again when I fixed it.

5. Check the image on Docker Hub
Docker Hub GitLab
The image is pushed and already exist on my registry. Let's see if it'll work on our localhost!

/learn-ci$ docker container create --name web-gitlab-2 -p 8083:80 nurulramadhona/httpd:gitlab
Unable to find image 'nurulramadhona/httpd:gitlab' locally
gitlab: Pulling from nurulramadhona/httpd
a330b6cecb98: Already exists 
14e3dd65f04d: Already exists 
fe59ad2e7efe: Already exists 
68eb42ff9345: Already exists 
9d5052bb82be: Already exists 
2197b58d1db7: Already exists 
5b35b4b65a23: Pull complete 
Digest: sha256:a0fde1e9823cb0ab6f604e59c4947cb5ed1035f1fecc921561cfcd4723cfdd6b
Status: Downloaded newer image for nurulramadhona/httpd:gitlab
dcc9222dcff7f2a0ef1a6e4170e6a82a75fdbce8ac44588f52d2c40fc530b2ae
/learn-ci$ docker container start web-gitlab-2
web-gitlab-2
/learn-ci$ curl localhost:8083
<html><body><h1>LEARNING GITLAB CI</h1></body></html>
Enter fullscreen mode Exit fullscreen mode

Web 8083


Alright, that's it for now! Any feedback are very welcome and thank you for coming. Follow me to get notified when new post is published by me! Thank you.

References:

Top comments (2)

Collapse
 
jatin profile image
Jatin Mehrotra

That's a great article to understand CI concepts.

Collapse
 
nurulramadhona profile image
Nurul Ramadhona

Thank you @jatin