The Missing SENG Course – Docker, Git, and Bash

Table of Contents

Docker

Docker Tutorial

  1. Open up a console and see what commands are available for docker
    docker --help
  2. Download an Ubuntu image – https://hub.docker.com/
    docker pull ubuntu:22.04
  3. See what images you current have on your computer
    docker images
  4. Run a container using the Ubuntu image
    docker run --interactive --tty --name my_container ubuntu:22.04
  5. See what docker containers are currently running.
    docker ps -a
  6. Add another terminal to the same docker container
    docker exec -it my_container /bin/bash
  7. Delete a container
    docker rm my_container
  8. Delete an image.
    docker rmi ubuntu:22.04
  9. Bind a volume.
    docker run -it --rm --name my_container -v $(pwd):/usr/src/project -w /usr/src/project ubuntu:22.04

    Note for Windows users: Replace $(pwd) with %cd% or ${PWD} for command prompt or powershell, respectively. Windows also forces all mounts to be on the C drive.

  10. Copy a file from a docker container to local host
    docker cp my_container:/usr/src/project/file .
  11. Copy a file from to docker container from local host
    docker cp file my_container:/usr/src/project

Dockerfile Tutorial

See the following example Dockerfile – https://gitlab.eng.tru.ca/-/snippets/5

# syntax=docker/dockerfile:1
FROM ubuntu:22.04

LABEL org.opencontainers.image.title="My First Docker Container"
LABEL org.opencontainers.image.authors="gefink@tru.ca"
LABEL org.opencontainers.image.description="An example Dockerfile to learn how to write Dockerfiles."

ARG DEBIAN_FRONTEND=noninteractive
ARG SRC_DIR=/usr/src/
ENV MY_NAME="Geoff"

RUN sed 's@archive.ubuntu.com@mirror.it.ubc.ca/ubuntu@' -i /etc/apt/sources.list
RUN apt-get update
RUN apt-get install -y vim-tiny
RUN apt-get install -y git
RUN apt-get install -y openssh-client
RUN apt-get install -y build-essential gcc g++ make autoconf autopoint pkg-config bison wget gperf gettext texinfo

RUN git clone git://git.sv.gnu.org/coreutils /usr/src/coreutils
WORKDIR $SRC_DIR/coreutils
RUN git submodule update --init --recursive
RUN ./bootstrap
RUN FORCE_UNSAFE_CONFIGURE=1 ./configure
RUN make -j8
RUN make install

ENTRYPOINT echo Hello $MY_NAME, you are logged in as $(whoami) && bash
  1. Build the Dockerfile
    docker build --no-cache . --tag my_first_image:latest --tag my_first_image:1.0.0
  2. Inspect the image
    docker inspect my_first_image:latest

Git

  • What is Git? – https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F

    So, what is Git in a nutshell? This is an important section to absorb, because if you understand what Git is and the fundamentals of how it works, then using Git effectively will probably be much easier for you. As you learn Git, try to clear your mind of the things you may know about other VCSs, such as CVS, Subversion or Perforce — doing so will help you avoid subtle confusion when using the tool. Even though Git’s user interface is fairly similar to these other VCSs, Git stores and thinks about information in a very different way, and understanding these differences will help you avoid becoming confused while using it.

  • Do I have to use Git?
    No, but you SHOULD ALWAYS use version control! Vast majority of programmers use Git.
  • Git Branching Syle? Very Important!
  • Git Commit Style? Very important!
    Do no write "update", "update", "update" … as the information adds no context or meaning. Lots of good information out there. For example read: https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/

Git Tutorial

  1. Start a new git repository
    git init --initial-branch=main
  2. Write a "Hello World" program.
    #include <iostream>
    int main() {
    std::cout << "Hello World!" << std::endl;
    return 0;
    }
  3. Compile the program
    g++ hello.cpp
  4. Run the program
    ./a.out
  5. See what has changed in git. This is the go to command!
    git status
  6. Stage the source code
    git add hello.cpp
  7. Commit the change
    git commit -m "Initial commit"
  8. Make a git ignore file
    echo "a.out" > .gitignore
  9. See the history
    git log
  10. Push repo to remote repository
    git remote set-url origin URL && git push
  11. Get latest updates from remote repository, but do not modify head
    git fetch 
  12. Git latest updates from remote repository, and fast-forward or merge (depending on settings)
    git pull
  13. Get a new repository from a remote server
    git clone URL

Gitlab

  • Both GitLab (https://about.gitlab.com/) and GitHub (https://github.com/) are quite similiar. It doesn’t really matter which you learn.
  • I have a GitLab server hosted at TRU – https://gitlab.eng.tru.ca/
    • You can sign up for a new account here – https://gitlab.eng.tru.ca/users/sign_up
    • Your user name must be the first letter of your first name and then your last name; all lowercase. For example my name "Geoff Fink" become "gfink".
    • Your email must be your TRU email.
    • After signing up you must add an ssh key here – https://gitlab.eng.tru.ca/-/profile/keys
      ssh-keygen -t ed25519 -C "your_email@mytru.ca"

      Put you public key into the website. Do not lose your private key.

    • When cloning be sure use the "Clone with SSH" URL not the HTTPS URL.

      Gitlab CI/CD Tutorial

  • Unfortunately, this is too much material for one day! But start reading here: https://docs.gitlab.com/ee/ci/
  • Then you can start trying it out for the homework.
variables:
  BUILD_DOCKER_IMAGE: "false"

image: $CI_REGISTRY/$CI_PROJECT_PATH/my_first_container

stages:
  - docker
  - build
  - test
  - deploy

before_script:
  - echo "Before Script"

build-job:
  stage: build
  script:
    - g++ hello.cpp
  artifacts:
    expire_in: 10 mins
    paths:
      - a.out

test-job1:
  stage: test
  dependencies:
    - build-job
  script:
    - ./a.out

test-job-2:
  stage: test
  dependencies:
    - build-job  
  script:
    - ./a.out abc

deploy-job:
  stage: deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - echo "Deploy code to public server"

build-docker-image:
  stage: docker
  image: docker:stable
  rules:
    - if: $BUILD_DOCKER_IMAGE == "true"
  script:
    - docker build -f docker/Dockerfile --network=host --no-cache -t $CI_REGISTRY/$CI_PROJECT_PATH/my_first_container .
    - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
    - docker push $CI_REGISTRY/$CI_PROJECT_PATH/my_first_container

Bash

  • What is Bash? – https://www.gnu.org/software/bash/manual/html_node/What-is-Bash_003f.html

    Bash is the shell, or command language interpreter, for the GNU operating system. The name is an acronym for the ‘Bourne-Again SHell’, a pun on Stephen Bourne, the author of the direct ancestor of the current Unix shell sh, which appeared in the Seventh Edition Bell Labs Research version of Unix.

    Bash is largely compatible with sh and incorporates useful features from the Korn shell ksh and the C shell csh. It is intended to be a conformant implementation of the IEEE POSIX Shell and Tools portion of the IEEE POSIX specification (IEEE Standard 1003.1). It offers functional improvements over sh for both interactive and programming use.

    While the GNU operating system provides other shells, including a version of csh, Bash is the default shell. Like other GNU software, Bash is quite portable. It currently runs on nearly every version of Unix and a few other operating systems – independently-supported ports exist for MS-DOS, OS/2, and Windows platforms.

  • Why do I want to use it? Because it is a very powerful tool. Like all tools/programming languages, it is important to know when to use and when not to use it.

  • It seems too complicated? Don’t worry. You’ve already got a head start, you’ve been using it all along! In the Linux tutorial, docker tutorial, gitlab tutorial. Its everywhere!


Bash Script Tutorial

  1. Make a new file: script.bash
    touch script.bash
  2. Make sure it is executable
    chmod +x script.bash
  3. Add a shebang
    #!/bin/bash
  4. Add some generic code
    echo "Start of Scipt"
    echo "End of Script"
  5. Run your script
    ./script.bash
  6. Variables
    STR="Hello World!"
    echo $STR
  7. While loops
    counter=1
    while [ $counter -le 10 ]; do
    echo $counter
    ((counter++))
    done
  8. Until Loops
    counter=1
    until [ $counter -gt 10 ]; do
    echo $counter
    ((counter++))
    done
  9. For Loops
    names='Luke Ben Leia'
    for name in $names; do
    echo $name
    done
    for value in {1..10..2}; do
    echo $value
    done
    for ((num=1;num<=5;num++)); do
    echo $num
    done
  10. Convert all jpg files to png files
    for file in *.jpg; do
    convert $file $(basename -s .jpg $file).png
    done
  11. Input
    read -p 'Username: ' username
    read -sp 'Password: ' password
    echo
    echo "Hi $username, you're password is $password"
  12. STDIN – read from pipe. There are also STDOUT and STDERR
    cat /dev/stdin
  13. Math
    let x=5+4
    echo x=$x
    let "y = x   *   2"
    echo y=$y
    expr 5 + 4
    z=$(expr 5 + 4)
    echo z=$z
    a=$((5+4))
    echo a=$a
    b=$((a++))
    echo a=$a b=$b
    ((b++))
    echo $b
  14. Length of a Variable
    str="Hello World"
    echo ${#str}
    num=4593
    echo ${#num}
  15. If Statement
    if [ 5 -gt 10 ]; then
    echo "Huh?"
    elif [ 10 -lt 5 ]; then
    echo "Huh?"
    else
    echo "Good"
    fi
  16. Test the square brackets [ ] are running the command test. It has many operators including: ! (not), -n (length of string), -z (length of string is zero), = (strings are equal), != (strings are not equal), -eq (numbers are equal), -gt (greather than), -lt (less than), -d (file exists).
  17. Boolean operators: and (&&), or (||)
    if [  $USER == "BOB" ] || [ $USER == "ALICE" ]; then
    echo "OK"
    else
    echo "NOT OK"
    fi
  18. Special Variables in bash
    echo $0 # Script Name
    echo $# # Number of arguments
    echo $* # Entire command string
    echo $@ # List of every argument
    echo $1 #The first argument
    echo $2 # The second argument
    echo $! # Process ID of last background command
    echo $$ # Process ID of current shell
    echo $- # Current shell options
  19. Functions
    say_hello() {
    echo "Hello $1"
    return 2
    }
    say_hello
    say_hello class
    say_hello world
    echo The previous function has a return value of $?

Problems

  1. Write a bash script that:
    • Find all of the text files in a folder and subfolder that contain the the word "VIRUS".
    • Display the file names, and the total number of files
    • Display the file size and the total size of all the files
    • Replace the word "VIRUS" with the word "CURE"
  2. Create a new Dockerfile that:
    • Installs a c++ compiler
    • Compiles your c++ program
    • Runs the program when starting the container
  3. Try the following in git:
    • Create a repository
    • Make a c++ program that contains atleast 20 lines of code and 3 different functions.
    • Stage and commit the script to the main branch.
    • Make two new branch from this commit A and B.
    • In branch A modify what each of the functions does. And then stage/commit the code to branch A.
    • In branch B modify the order of the 3 functions. And then stage/commit the code to branch B.
    • Now merge all of the branches back into main.
  4. Now combine everything we learnt together:
    • Write a Hello World program in c++
    • Make a docker image to compile the code in
    • Write a bash script that will run your docker build command
    • Make a git repository for your code.
    • Upload everything to GitLab and have GitLab CI/CD build your dockerfile, compile, and run your code.

Leave a comment

Your email address will not be published. Required fields are marked *