When I started getting deeper into DevOps, I kept coming across the same tools again and again: Git, Docker, Terraform, Azure CLI, GitHub CLI, and others.
Knowing their names was one thing. Understanding why I needed each one and how they fit into an actual DevOps workflow was different.
Recently, I decided to properly set up the toolchain I will be using for my DevOps work on Windows. I expected it to be mostly downloading applications and checking their versions.
It wasn't quite that simple.
Along the way, I ran into issues with Docker not connecting to its engine, Terraform not being recognized outside its folder, Azure CLI not appearing in an already-open terminal, and GitHub CLI working in PowerShell but not immediately inside VS Code.
Working through those problems actually helped me understand the tools better than simply installing them without any issues.
In this article, I'll walk through the DevOps toolchain I set up, what each tool does, how I verified that everything was working, and some of the problems I encountered along the way.
One thing I should make clear from the beginning: there isn't one universal DevOps toolchain that every engineer uses.
Different teams use different cloud providers, CI/CD platforms, container tools, and infrastructure technologies.
For the Azure-focused environment I'm currently working with, these are the tools I started with:
- Git
- Azure CLI
- Docker
- Terraform
- Visual Studio Code
- GitHub CLI
By the end of the setup, I wanted more than six installed applications. I wanted a workstation where I could actually use all of them from the terminal and start connecting them together in real DevOps workflows.
What exactly is a DevOps toolchain?
DevOps is not one application.
It is a workflow made up of different tools that handle different parts of building, testing, deploying, and managing software.
The easiest way I found to understand the tools was to stop looking at them individually and think about how they connect.
For the toolchain I set up, the flow looks roughly like this:
VS Code
↓
Git
↓
GitHub
↓
Docker
↓
Terraform
↓
Azure
VS Code gives me the environment where I work.
Git tracks the changes I make.
GitHub gives me somewhere to store and share those changes remotely.
Docker packages applications into containers.
Terraform lets me describe infrastructure using code.
Azure CLI lets me interact with Azure directly from the terminal.
GitHub CLI also gives me another way to work with GitHub without constantly going back to the browser.
Each tool solves a different problem, but together they form the beginning of a practical DevOps environment.
Git: tracking changes from the beginning
Git was already installed on my system, so the first thing I needed to do was verify it.
git --version
My system returned:
git version 2.56.0.windows.1
Git is a version-control system.
Its job is to track changes made to files over time.
That becomes important very quickly in DevOps because almost everything eventually becomes a file that needs to be tracked: application code, Dockerfiles, Terraform configuration, CI/CD pipelines, documentation, and more.
If something changes, Git gives me a way to know what changed, when it changed, and which version I am currently working with.
This is also why Git usually sits near the beginning of a DevOps workflow.
Before automating or deploying something, it makes sense to first have proper control over the files being changed.
Azure CLI: working with Azure from the terminal
The next tool was Azure CLI.
Azure has a graphical web portal where resources can be created and managed, but DevOps workflows should not depend entirely on manually clicking through a dashboard.
Azure CLI gives me a way to interact with Azure directly from the terminal.
On Windows, I installed it using WinGet:
winget install --exact --id Microsoft.AzureCLI
The installation completed successfully.
Then I ran:
az version
and got this:
az : The term 'az' is not recognized as the name of a cmdlet,
function, script file, or operable program.
At first, I thought something had gone wrong with the installation.
But Azure CLI had actually installed correctly.
The problem was that I was still using a PowerShell session that had already been open before the installation.
I closed PowerShell, opened a fresh session, and tried again:
az version
This time it worked and returned the installed Azure CLI version.
That taught me something useful very early in the setup:
Installing a command-line tool does not always mean an already-open terminal will immediately know where to find it.
Sometimes the terminal simply needs to be restarted so it can pick up the updated environment.
Docker: having the CLI is not enough
Docker was one of the most interesting parts of the setup.
Docker is used to package applications into containers so that they can run more consistently across different environments.
I installed Docker Desktop and checked whether the CLI was available:
docker --version
The command worked:
Docker version 29.8.2
At that point, I assumed Docker was ready.
Then I ran:
docker run hello-world
and got an error:
failed to connect to the docker API at
npipe:////./pipe/dockerDesktopLinuxEngine
The system cannot find the file specified.
This was where I learned the difference between having the Docker command installed and having the Docker engine running.
The Docker CLI was available, but Docker Desktop had not fully started the engine the CLI needed to communicate with.
After starting Docker Desktop properly, I ran:
docker info
This time I could see both client and server information.
Then I tried again:
docker run hello-world
Docker pulled the image and successfully created the container.
Hello from Docker!
This message shows that your installation appears to be working correctly.
That test was more meaningful than simply checking the version.
docker --version proved that the command existed.
docker run hello-world proved that Docker could actually contact the daemon, pull an image, create a container, and run it.
Terraform: when the application works but Windows cannot find it
Terraform gave me a completely different problem.
Terraform is an Infrastructure as Code tool.
Instead of manually creating every infrastructure resource through a cloud dashboard, Terraform allows infrastructure to be defined in configuration files.
For Windows, I downloaded the Terraform ZIP file and extracted the application into a folder.
Then I tried:
terraform -version
PowerShell returned:
terraform : The term 'terraform' is not recognized as the name
of a cmdlet, function, script file, or operable program.
At this point, I needed to know whether Terraform itself was broken or whether Windows simply did not know where the application was located.
I changed into the folder where I had placed Terraform:
cd C:\Users\<USER>\Documents\Terraform
Then I ran:
.\terraform.exe -version
This worked:
Terraform v1.16.5
on windows_amd64
That told me immediately that Terraform itself was fine.
The problem was PATH.
Windows uses the PATH environment variable to know which directories it should search when I enter commands such as:
git
docker
terraform
az
I added the Terraform folder to my user PATH.
After closing PowerShell and opening a new session, I ran:
terraform -version
again.
This time it worked from anywhere.
That was probably the clearest lesson I got from the entire setup about how command-line tools actually become available system-wide.
VS Code: where everything starts coming together
VS Code was already my main development environment, so there wasn't much installation work to do here.
I verified that its CLI command was working with:
code --version
The useful part for me was seeing how all the other tools could come together inside the VS Code integrated terminal.
Instead of constantly switching between different applications, I could use Git, Azure CLI, Docker, Terraform, and GitHub CLI from the same workspace where I was editing my files.
That made the setup start feeling less like a collection of individual programs and more like an actual working environment.
GitHub CLI: GitHub from the terminal
The last major tool I added was GitHub CLI.
Git and GitHub are related, but they solve different problems.
Git handles version control locally.
GitHub hosts repositories remotely and provides tools for collaboration.
GitHub CLI allows many GitHub operations to happen directly from the terminal.
After installing it, I verified the command:
gh --version
Then I authenticated using:
gh auth login
I selected:
GitHub.com
HTTPS
Login with a web browser
The CLI generated a temporary device code and completed the authentication through my browser.
But I ran into one more environment problem.
gh worked correctly inside normal PowerShell, but when I tried:
gh --version
inside VS Code, the terminal still returned:
gh : The term 'gh' is not recognized...
Closing and reopening the terminal did not solve it.
What eventually worked was closing VS Code completely, opening PowerShell where gh was already recognized, changing into my project directory, and launching VS Code from there:
code .
Once VS Code opened from that fresh PowerShell environment, its integrated terminal could also recognize GitHub CLI.
That was another reminder that applications can inherit environment information when they start.
If that environment changes while an application is already running, opening another terminal inside the same application may not always be enough.
Verifying the full toolchain
After fixing everything, I verified the complete setup from my terminal:
git --version
az version
docker --version
terraform -version
code --version
gh --version
At this stage, all six tools were available and working.
The versions themselves are not the important part because they will change as new releases come out.
What matters is that each command successfully returns a result before I depend on that tool later in a DevOps workflow.
Turning the setup into a real Git project
I didn't want to finish the exercise with nothing except installed applications.
I wanted the work documented and stored on GitHub.
I created a project directory:
mkdir devops-workstation
cd devops-workstation
Then initialized Git:
git init
I created a README.md documenting the tools, their versions, the commands I used to verify them, and what I learned during the setup.
After that, I staged the file:
git add README.md
and committed it:
git commit -m "docs: add workstation setup verification"
Publishing the project to GitHub
With the local repository ready, I created a public GitHub repository directly from the terminal:
gh repo create devops-workstation --public
Then I connected the local repository to GitHub:
git remote add origin https://github.com/<YOUR_USERNAME>/devops-workstation.git
I renamed the branch to main:
git branch -M main
and pushed the project:
git push -u origin main
After the push, I checked the repository status:
git status
and got:
On branch main
Your branch is up to date with 'origin/main'.
nothing to commit, working tree clean
At that point, the setup was no longer something that existed only on my laptop.
It had become a small documented project that I could keep on GitHub and build on later.
Check out the repository
You can find the completed DevOps workstation setup and README on GitHub:
View the devops-workstation repository on GitHub
The problems that taught me the most
Looking back, the most useful parts of this setup were actually the moments when something didn't work.
I ran into four main problems.
Docker was installed but the engine wasn't running
The Docker CLI worked, but containers couldn't run until Docker Desktop had properly started the engine.
Azure CLI installed successfully but PowerShell couldn't see it
A new PowerShell session was needed before the az command became available.
Terraform only worked inside its own folder
The application itself was fine. The missing step was adding its directory to PATH.
GitHub CLI worked in PowerShell but not immediately in VS Code
VS Code was still running with an older environment, so I had to launch a fresh instance after the new CLI was available.
None of these were huge errors.
But fixing them forced me to understand what was actually happening underneath the commands instead of just copying installation instructions until something worked.
What I took away from the setup
Before doing this, I mostly thought about installing developer tools like this:
Download → Install → Done
Now I think about it more like this:
Install
↓
Make the command available
↓
Verify it
↓
Test the actual functionality
↓
Document the setup
That distinction matters.
Docker being installed is not the same as Docker being able to run containers.
Terraform existing somewhere on my laptop is not the same as being able to call terraform from my terminal.
Azure CLI being installed is not useful if my working environment cannot find az.
And a local Git repository becomes much more useful once it is documented and pushed somewhere I can actually share it.
This setup gave me a much clearer picture of how the different tools in a DevOps toolchain begin to connect.
What's next?
The next step is to start using these tools together for more practical work: containerizing applications, managing infrastructure through code, deploying resources to Azure, and eventually working with CI/CD pipelines.
Setting up the toolchain may not be the most exciting part of DevOps.
But before building anything serious, it helps to know that the tools underneath your workflow actually work.




Top comments (2)
Well-written🫡; welldone!
Glad you enjoyed it 😁 More to come 🚀