Introduction
In the world of DevOps, the ability to package applications into containers and manage them with version control is a fundamental skill. This guide walks you through creating a minimal Node.js app, containerizing it with Docker, and pushing it to GitHub for collaboration and backup.
By following these steps, you’ll not only learn how to build and run containers but also understand how version control ties into modern cloud workflows. This exercise emphasizes operational excellence, reliability, and performance efficiency — three pillars of cloud-native engineering.
Create Folder
Implementation Guide 1
Create Folder
Instruction Summary
Creates a dedicated working directory for the lab and moves your shell into it.
Why It's Needed
Keeps the app and Dockerfile isolated from other files on the machine so the build context stays clean.
Pillar Connection
Operational Excellence — Setting up a clean workspace before you start.
- To create a folder named "Container-Lab", run this command "mkdir -p ~\container-lab && cd ~\container-lab"
Create app.js
Implementation Guide 1
Create app.js: Create app.js using touch and write the Node.js console log statement
Instruction Summary
Creates the Node.js source file that the container will run.
Why It's Needed
This is the application code your Dockerfile will package into the image.
Pillar Connection
Performance Efficiency — Shipping the smallest possible app for the container.
- To create app.js, run this command "touch app.js && echo 'console.log("Hello, DevOps!");' > app.js"
Note: The first part of the command, "touch app.js" means to create an app known as app.js
While the second part of the command, echo 'console.log("Hello, DevOps!");' > app.js
Implementation Guide 1
Create Dockerfile
Instruction Summary
Writes the build recipe Docker uses to package your app: base image, files to copy in, and the startup command.
Why It's Needed
Without a Dockerfile, Docker has no instructions for turning your source code into a runnable image.
Pillar Connection
Operational Excellence — Reproducible builds defined as code.
- The two commands are in existence. The first command is to create a Dockerfile which "touch Dockerfile "
while the second command prints into the dockerfile created "echo -e 'FROM node:18-alpine\nCOPY app.js .\nCMD ["node","app.js"]' > Dockerfile"

Implementation Guide
- Build Image
Instruction Summary
Reads the Dockerfile and builds a portable, versioned image containing your app and its runtime.
Why It's Needed
The image is the artifact that actually gets shipped and run anywhere Docker is installed.
Pillar Connection
Reliability — A versioned image guarantees the same app runs identically everywhere.
- In other to Build a Docker image from the Dockerfile in the current directory, run this Command "docker build -t simple-container-lab:1.0 ."
# Note: Ensure you run your docker engine before running this docker image buiding command "docker build -t simple-container-lab:1.0 ." to avoide error notification on your IDE
Implementation Guide
- Run Container
Instruction Summary
Starts a container from the image you just built and removes it automatically when it exits.
Why It's Needed
Confirms the image actually runs your app correctly before you ship it anywhere.
Pillar Connection
Operational Excellence — Verify before you trust a build.
- To create and start a new container from the specified image, "docker run --rm simple-container-lab:1.0"
Implementation Guide
1 Initialize Git
Instruction Summary
Creates a local .git directory so version control can start tracking your project.
Why It's Needed
Without a repository, Git has nothing to track changes against.
Pillar Connection
Operational Excellence — Version control is the foundation of every DevOps workflow.
-To nitialize a new Git repository in the current directory, run this command "git init"

Implementation Guide
1 Stage Files
Instruction Summary
Marks the project files as ready to be included in the next commit.
Why It's Needed
Git only commits what has been staged — this moves files from the working directory into the staging area.
Pillar Connection
Operational Excellence — Deliberate, reviewable changesets.
- To know the files that are not staged, run this command "git status"
-To stage all changed files for the next commit, run this command "git add ."
**
**Note: In other to view Staged file, re run this command "git status"
Implementation Guide
- Commit Files
Instruction Summary
Saves the staged files as a permanent, named snapshot in your repository's history.
Why It's Needed
Commits are the checkpoints you can always return to, diff against, or roll back.
Pillar Connection
Reliability — A clear history makes recovery and audits possible.
- Run *git commit -m 'feat: first container'
* to create a new commit with all staged changes and the message after -m.
Implementation Guide
- Set GitHub Username
Instruction Summary
Stores your GitHub username in a shell variable.
Why It's Needed
Lets the next command build the correct remote URL without you retyping your username.
Pillar Connection
Operational Excellence — Reusable, less error-prone commands.
-To Set the shell variable GITHUB_USERNAME so later commands can reference it with $GITHUB_USERNAME. Run this command "GITHUB_USERNAME="BAOKONCEPTS"

Implementation Guide
- Add Remote
Instruction Summary
Links your local repository to a repository on GitHub named "origin".
Why It's Needed
Without a remote, there is nowhere for your local commits to be pushed to.
Pillar Connection
Operational Excellence — Connecting local work to a shared, backed-up remote.
- tO Stage the specified file(s) for the next commit, "git remote add origin https://github.com/${GITHUB_USERNAME}/simple-container-lab.git"
Implementation Guide
- Rename Branch
Instruction Summary
Renames the current branch to "main".
Why It's Needed
Matches the default branch name GitHub expects for new repositories, avoiding a push error.
Pillar Connection
Operational Excellence — Consistent naming conventions across your team.
- To rename the default branch to main, run this command "git branch -M main"
Implementation Guide
1 Push to GitHub
Instruction Summary
Uploads your commits to the "origin" remote and sets "main" to track it.
Why It's Needed
This is what actually gets your work onto GitHub and sets up future pushes/pulls to sync automatically.
Pillar Connection
Reliability — Your work is now backed up and shareable outside your local machine.
- To Upload your local commits to the remote repository, run this command "git push -u origin main"
Summary
This hands-on lab covered the following stages;
Creating a clean project folder.
Writing a minimal Node.js app (app.js).
Defining a Dockerfile for reproducible builds.
Building and running a Docker image.
Initializing Git and staging files.
Linking to GitHub, renaming the branch, and pushing code.
Together, these steps demonstrate the end-to-end DevOps lifecycle starting from writing code to shipping it in a container and backing it up in a shared repository.
Conclusion
By completing this workflow, you’ve learned how to;
Create and run a Node.js app inside a Docker container.
Use Dockerfiles to define reproducible builds.
Apply Git version control to track and manage changes.
Push your project to GitHub for collaboration and reliability.
This exercise demonstrates the core practices of DevOps: automation, reproducibility, and collaboration.
Key takeaways from this hands-on lab;
Containers make applications portable and consistent across environments.
-Dockerfiles are the blueprint for reproducible builds.
Git ensures deliberate, reviewable changes and collaboration.
GitHub integration connects local work to a shared, backed-up remote.
Practicing all steps as detailed in this article, builds confidence in cloud-native workflows and prepares you for real-world DevOps tasks.


Top comments (0)