Ship software the way real teams ship it.
From the command line to a full CI/CD pipeline running containers in the cloud. No prior experience needed β we start at zero and build up to work you can put on a CV.
Read, do, complete, move on.
Open a lesson, read the notes, then mark it complete. Your progress is saved on this device.
Foundations: the toolkit every engineer shares
Before pipelines and clusters, you need the ground floor: the terminal, Git, and your first container. Everything later stands on this.
The developerβs terminal
FoundationsβΊWhat DevOps actually isβ
DevOps is not a tool and not a job title you buy with a certificate. It is a way of working where the people who write software and the people who run it stop throwing work over a wall and instead own it together, end to end.
The old way: developers wrote code, zipped it up, and handed it to an operations team who tried to make it run in production. When it broke at 2am, each side blamed the other. DevOps collapses that wall. The same team builds it, tests it automatically, ships it automatically, and watches it in production.
Three ideas carry the whole field:
- Automate everything that repeats β building, testing, deploying.
- Make small changes often β ten tiny safe releases beat one terrifying big one.
- Measure what happens β you cannot fix what you cannot see.
βΊLiving in the command line (Linux basics)β
Servers do not have a mouse. Almost every server on earth runs Linux, and you talk to it by typing. The terminal feels intimidating for a week, then becomes the fastest tool you own.
The commands you will use every single day:
pwdβ where am I? (print working directory)ls -laβ list everything here, including hidden filescd projectsβ move into a folder;cd ..goes back upcat file.txtβ print a file;less file.txtto scrollmkdir,cp,mv,rmβ make, copy, move, removegrep "error" app.logβ search inside files
failed in todayβs log and count them: grep failed app.log | wc -l. The | (pipe) feeds the output of one command into the next β this chaining is the heart of the Unix way.βΊFiles, permissions and packagesβ
Two things trip up every beginner on Linux: permissions and installing software.
Permissions
Every file has an owner and a set of permissions: read (r), write (w), execute (x). When a script "wonβt run", it usually just needs permission: chmod +x deploy.sh makes it executable. When you see Permission denied, you either need sudo (run as administrator) or you are touching a file you do not own.
Packages
You do not download installers on Linux β you use a package manager. On Ubuntu/Debian that is apt:
sudo apt updateβ refresh the cataloguesudo apt install gitβ install software
sudo apt update && sudo apt install -y git curl docker.io. The -y answers "yes" to prompts so it runs unattended.Version control with Git
Core skillβΊWhy Git, and the three-step rhythmβ
Git is the time machine for your code. It records every change so you can go back, see who changed what and when, and let many people work on the same project without overwriting each other.
Working without Git β final.js, final_v2.js, final_REAL_final.js β is a nightmare you will never go back to.
The daily rhythm is three steps:
git add .β stage your changes (choose what goes in)git commit -m "Add login form"β save a snapshot with a messagegit pushβ send it to the shared server (GitHub)
git init, then git add ., then git commit -m "First version". You now have a complete history you can return to forever.βΊBranches: working without fearβ
A branch is a parallel copy of your project where you can try something without touching the working version. This is what lets teams move fast without breaking things.
The pattern: main is always the stable, working code. To add a feature you branch off, do your work, then merge back when it is ready.
git checkout -b feature/paymentsβ create and switch to a new branch- work, add, commit as normal
git checkout mainthengit merge feature/paymentsβ bring it back in
main, fix the bug, ship it, then switch back and carry on. Nothing collided.βΊGitHub and pull requestsβ
GitHub is where your Git history lives online so a team can share it. It adds one hugely important idea on top of Git: the pull request (PR).
A pull request says: "here is my branch, please review it before it goes into main." A teammate reads the changes, comments, and approves. This review step is where quality and knowledge-sharing happen β and later, where automated tests run before anything merges.
feature/payments and open a PR titled "Add MTN MoMo checkout". A reviewer spots that you forgot to handle a failed payment, you fix it in the same branch, the PR updates automatically, they approve, you merge. The bug never reached a customer.Containers with Docker
Game-changerβΊWhat a container is (and why it changed everything)β
"It works on my machine" is the oldest excuse in software. Docker killed it.
A container packages your application with everything it needs β the code, the runtime, the libraries, the settings β into one sealed box that runs identically on your laptop, a colleagueβs laptop, and a server in a data centre.
People confuse containers with virtual machines. A VM carries a whole operating system (heavy, slow to start, gigabytes). A container shares the hostβs kernel and carries only your app (light, starts in a second, megabytes). You can run dozens of containers where you could run two or three VMs.
βΊImages, Dockerfile, build and runβ
Two words to keep straight: an image is the recipe (a saved blueprint); a container is a running instance of that image. You build an image once and run many containers from it.
You describe the image in a Dockerfile β a plain list of steps:
FROM node:20β start from an official Node.js imageCOPY . /appβ copy your code inRUN npm installβ install dependenciesCMD ["node","server.js"]β how to start it
docker build -t myapp . then docker run -p 3000:80 myapp. The -p 3000:80 maps your laptopβs port 3000 to the containerβs port 80 β now open the browser and your app is live.βΊDocker Compose: many services at onceβ
Real apps are not one container. A typical web app is a frontend, a backend API, and a database β three containers that must talk to each other. Starting and wiring them by hand is painful.
Docker Compose lets you describe the whole stack in one docker-compose.yml file and start it all with one command: docker compose up.
docker-compose.yml lists a web service, an api service, and a db service (PostgreSQL). One docker compose up starts all three, puts them on the same private network, and your API reaches the database just by the name db. A new teammate clones the repo and has the entire system running in 30 seconds.Your first deployment
Make it liveβΊWhat CI/CD meansβ
Two abbreviations you will hear constantly. CI (Continuous Integration): every time someone pushes code, it is automatically built and tested, so broken code is caught in minutes, not weeks. CD (Continuous Delivery/Deployment): once tests pass, the code is automatically shipped to a server.
Together they form a pipeline: push β build β test β deploy, with no human doing it by hand. Humans make mistakes when they deploy manually at midnight; a pipeline does the same safe steps every time.
βΊDeploying to a real serverβ
Let us get something on the internet. The simplest real deployment: a cheap Linux server (a VPS) running your container.
The steps, which you will later automate:
- Rent a VPS (DigitalOcean, Hetzner, Contabo β from a few dollars a month)
- Connect with
ssh user@your-server-ip - Install Docker, copy your image across,
docker runit - Point a domain name at the serverβs IP
docker run -d --restart unless-stopped -p 80:3000 myapp. The -d runs it in the background; --restart unless-stopped brings it back automatically if the server reboots.βΊEnvironments and secretsβ
Your app needs settings that differ between your laptop and production: database passwords, API keys, which URL to call. Two rules keep you safe.
Never hard-code secrets in your code. A password committed to Git is a password leaked forever β people scan GitHub for exactly this. Keep secrets in environment variables instead, loaded at runtime.
Keep environments separate. You want a development setup, maybe a staging copy for testing, and production for real users β each with its own config, so a test never touches real customer data.
docker run -e DB_PASSWORD="$DB_PASSWORD" myapp. The value comes from the serverβs environment, never from the code, so your Git history stays clean.Engineering: pipelines, clusters and infrastructure as code
Now we industrialise. You will automate the whole delivery flow, orchestrate containers at scale, define servers in code, and watch it all in production.
CI/CD pipelines with GitHub Actions
AutomationβΊYour first pipelineβ
GitHub Actions runs your pipeline for free, right where your code already lives. You describe it in a YAML file under .github/workflows/ and it triggers on events β most often "on every push".
A workflow is made of jobs, and each job is a list of steps. A step either runs a command or uses a pre-made action.
on: [push]jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm install && npm testβΊBuild, test, deploy stagesβ
A real pipeline has stages that run in order, and a later stage only runs if the earlier one passed. This is your safety net.
- Build β compile the code, build the Docker image
- Test β run automated tests; if any fail, stop here and alert
- Deploy β only reached on the
mainbranch, only if tests passed
You make jobs wait for each other with needs:, so deploy has needs: [build, test]. Broken code physically cannot reach production because the deploy step never runs.
βΊArtifacts, caching and secretsβ
Three things make pipelines fast and safe.
Caching: downloading dependencies on every run wastes minutes. Cache them so repeated runs are quick β a real cost saving on limited free minutes.
Artifacts: the output of a build (a compiled app, a built image) can be saved and passed to the next job instead of rebuilt.
Secrets: your deploy needs a server key or a registry password. Store these in GitHubβs encrypted Secrets, never in the YAML. Reference them as ${{ secrets.SSH_KEY }} β they are masked in logs so they never leak.
Orchestration with Kubernetes
ScaleβΊWhy orchestration existsβ
One container on one server is easy. But what happens when that server dies at 3am? Or when traffic triples during a campaign and one container cannot cope? Or when you need to update without downtime?
Kubernetes (K8s) is the system that manages containers across many servers for you. You tell it the desired state β "I want 3 copies of my app running at all times" β and it makes that true and keeps it true. A container crashes? It starts a new one. A server dies? It moves the work elsewhere. This is called self-healing.
βΊPods, deployments and servicesβ
Three core objects run almost everything in Kubernetes.
- A Pod is the smallest unit β usually one running container.
- A Deployment manages Pods: it keeps the number you asked for running and handles rolling updates.
- A Service gives your Pods a stable address, because individual Pods come and go. It also load-balances traffic across them.
replicas: 3. Kubernetes runs three Pods. You push a new version; Kubernetes replaces them one at a time (a rolling update) so your users never see downtime. Delete a Pod by hand and watch a replacement appear within seconds β that is the desired-state engine at work.βΊConfig, secrets and health checksβ
To run safely in production, Kubernetes needs to know three more things.
ConfigMaps hold non-secret settings (which API to call, feature flags). Secrets hold sensitive values (passwords, keys), kept separate from your images.
Health checks (probes) let Kubernetes know if a Pod is actually healthy. A liveness probe asks "are you alive?" β if not, restart it. A readiness probe asks "are you ready for traffic?" β if not, hold traffic back until it is. Without these, Kubernetes would send users to a Pod that is still starting up or silently frozen.
Infrastructure as Code with Terraform
RepeatableβΊWhy define infrastructure in codeβ
Clicking around a cloud console to create servers, networks and databases works once β and is a disaster to repeat, document or recover. Infrastructure as Code (IaC) means you write down your infrastructure as text files, version it in Git, and let a tool build it.
Terraform is the most popular IaC tool. You describe what you want (resources); Terraform figures out how to create, change or destroy them to match.
βΊProviders, resources and stateβ
Three concepts run Terraform.
- A provider is the plugin for a given platform (AWS, GCP, Azure, DigitalOcean).
- A resource is one thing you want to exist β a server, a database, a DNS record.
- The state file is Terraformβs memory of what it has already built, so it knows the difference between "create new" and "change existing".
resource "digitalocean_droplet" "web" { name = "web-1"; size = "s-1vcpu-1gb"; region = "fra1" }. Terraform reads this and creates exactly that server. Change size and re-apply, and it resizes the existing one β it does not make a second.βΊPlan, apply, and modulesβ
The Terraform workflow is deliberately safe.
terraform planβ shows you exactly what will change before anything happens. Always read this.terraform applyβ makes the changes.terraform destroyβ tears it all down cleanly (great for temporary test environments, and for not paying for idle servers).
Modules let you package a reusable piece of infrastructure (say, "a standard web server + firewall") and use it many times with different inputs β the same donβt-repeat-yourself principle as functions in code.
Monitoring and the capstone
See it allβΊMetrics, logs and the golden signalsβ
Once your app is live, you are flying blind unless you watch it. Two kinds of data matter: metrics (numbers over time β CPU, memory, request rate) and logs (the detailed text record of what happened).
Prometheus collects metrics; Grafana turns them into dashboards you can actually read. The four golden signals to watch on any service:
- Latency β how slow are responses?
- Traffic β how much demand?
- Errors β how many requests fail?
- Saturation β how full are your resources?
βΊAlerting without the noiseβ
A dashboard nobody looks at is useless at 3am. Alerting pushes a message (email, SMS, Slack) when something crosses a threshold β "errors above 5% for 5 minutes".
The art is to alert on symptoms users feel, not on every twitch. Alert on "the site is returning errors", not on "CPU hit 80% for 10 seconds". Too many false alarms and your team learns to ignore alerts β the most dangerous failure of all, called alert fatigue.
βΊCapstone: the full pipelineβ
Here is where everything connects. Your capstone project ties the whole course into one real system:
- Code lives in Git, reviewed through pull requests
- A GitHub Actions pipeline builds, tests and ships on every merge to
main - The app runs as a Docker container, orchestrated by Kubernetes
- The infrastructure is defined in Terraform
- Prometheus and Grafana watch it, with one real alert wired up
When you can point an employer at this β "I built this, here is the repo, here is the live dashboard" β you are no longer learning DevOps. You are doing it.
Eight labs that build one real pipeline
Reading is free and open. The labs are where it becomes real, so they live behind a free account, which keeps your progress and gives you a certificate.
Create a free Kaevor account to launch any lab and earn your certificate. One account, all your courses.
Create free accountLab 1 β Command the terminal
Navigate a Linux filesystem, chain commands with pipes, and write your first bash script.
Lab 2 β Your first repo and PR
Initialise a repo, branch, commit, push to GitHub and open a pull request.
Lab 3 β Dockerise an app
Write a Dockerfile, build an image, and run your app in a container.
Lab 4 β A Compose stack
Run a web app, API and database together with one docker-compose.yml.
Lab 5 β Build a pipeline
Write a GitHub Actions workflow that builds and tests on every push.
Lab 6 β Deploy to a server
Ship your container to a real VPS and point a domain at it.
Lab 7 β Terraform a server
Define a cloud server in code and bring it up with plan and apply.
Lab 8 β Watch it live
Stand up Prometheus and Grafana and build a dashboard with one real alert.
Two levels, one path
Beginner
Terminal, Git, Docker and your first live deployment. The toolkit every engineer shares.
Intermediate
CI/CD, Kubernetes, Terraform and monitoring β the full professional delivery pipeline.