Table of Contents
- Motivation
- Anatomy of a dev environment
- A better way to do dotfiles - Dotbot
- Combining everything together
- Pick a host. GitHub Codespaces
- Example
- Summary
- Reference
Motivation
Crafting a perfect dev environment takes time and effort. It is a tedious process that you have to do every time you change a working environment. For example, you buy a new laptop, switch to another operating system, or switch to a new project that requires extra tools and configuration. The latter case is interesting to me because I like to try out new things. Varying from different tools, and frameworks to new programming languages.
There are lots of benefits to making a reproducible dev environment. For me the two main ones:
- You open a project and it just works. Image some open-source project that interests you but you donβt know how to even run it. With DEaaC the installation problems go away.
- You can share it with your peers. A codified developer setup is a form of knowledge that could be evaluated and evolved. It opens up tons of new opportunities.
Anatomy of a dev environment
Basically, you can divide aspects of a dev environment into next categories:
It might seem like a lot but luckily we have good tools to automate the scaffolding process. Namely dotfiles and devcontainers.
Dotfiles
Dotfiles are focused on personal configuration aspects and are usually maintained by a person. Dotfiles are tailored to make up a unique developer experience. Previously, I wrote about it here: Development environment based on Windows Terminal + WSL + ZSH + dotfiles
Usually, dotfiles are comprised of common configurations and utilities that could be used on various platforms and platform-specific configurations. For example, you use a specific package manager innate into the system to install dependencies.
Here is an example of how I do it: https://github.com/NikiforovAll/dotfiles. As you can see, there are three different setups for windows
, wsl
, and dev-containers
.
As result, we can create a dev environment of choice from a scratch. All you need to do is to run a one-liner:
bash -c "$(wget -qO - https://raw.github.com/nikiforovall/dotfiles/master/src/wsl/os/install.sh)"
An approach like this does work. But it is annoying and impractical. We can do better about it. I will show you in a moment.
DevContainers
From the official documentation:
The Visual Studio Code Remote - Containers extension lets you use a Docker container as a full-featured development environment. It allows you to open any folder or repository inside a container and take advantage of Visual Studio Codeβs full feature set. A devcontainer.json file in your project tells VS Code how to access (or create) a development container with a well-defined tool and runtime stack. This container can be used to run an application or to separate tools, libraries, or runtimes needed for working with a codebase.
A devcontainer.json file in your project tells Visual Studio Code (and other services and tools that support the format) how to access (or create) a development container with a well-defined tool and runtime stack. Itβs currently supported by the Remote - Containers extension and GitHub Codespaces.
DevContainers are meant to be reusable and extendable. From my experience, they have improved in this regard. Here is how you can add dependencies via .devconatiner.json
{
"name": "Azure Dev CLI",
"build": {
"dockerfile": "Dockerfile", // base docker image
"args": {
"VARIANT": "bullseye" // parametrization
}
},
"features": {
"github-cli": "2",
"azure-cli": "2.38",
"dotnet": "6.0",
"docker-from-docker": "20.10",
},
"extensions": [
"ms-azuretools.azure-dev",
"ms-azuretools.vscode-bicep",
"ms-azuretools.vscode-docker",
"ms-azuretools.vscode-azurefunctions",
"ms-dotnettools.csharp",
"ms-dotnettools.vscode-dotnet-runtime",
],
}
π‘DevContainers define project-specific configurations and dotfiles define user-specific configurations.
A better way to do dotfiles - Dotbot
π My initial version of dotfiles was intended for wsl & early devcontainers version. Since then, Iβve learned a couple of lessons. Mainly, it is a good idea to keep dotfiles simple and rely on essentials. You donβt need to bring tons of dependencies and convoluted configuration files. The simpler - the easier to maintain and synchronize.
So, Iβve created another dotfiles repo: https://github.com/NikiforovAll/dotbot. This one is based on https://github.com/anishathalye/dotbot. Dotbot is a tool that bootstraps your dotfiles. It is straightforward to use. I suggest you give it a try on your own.
As discussed, since I deliberately choose to not have heavy dependencies it takes a couple of seconds to install dotfiles. Exactly as I want it to be. My general suggestion is to move the heavy lifting of dependencies installation to DevContainers.
One-liner: cd ~ && git clone https://github.com/NikiforovAll/dotbot && cd ./dotbot && cd ./install
Here is what the project structure looks like:
# oleksii_nikiforov in ~/dotbot
> tree -L 2
.
βββ bash
β βββ plugins.bash
β βββ prompt.bash
βββ bash_profile
βββ bashrc
βββ gitconfig
βββ gitignore_global
βββ install
βββ install.conf.yaml
βββ pre-install.sh
βββ shell
β βββ aliases.sh
β βββ bootstrap.sh
β βββ dircolors.extra
β βββ external.sh
β βββ functions.sh
β βββ plugins
βββ zsh
β βββ plugins
β βββ plugins_after.zsh
β βββ plugins_before.zsh
β βββ prompt.zsh
β βββ settings.zsh
βββ zshrc
Combining everything together
The resulting dev environment is combined from diverse sources. Roughly speaking a host (developer machine/codespace) is composed of the next pieces:
Pick a host. GitHub Codespaces
The suggested approach abstracts away the host. It doesnβt necessarily have to be your machine. This is what βGitHub Codespacesβ product is about.
A codespace is a development environment thatβs hosted in the cloud. You can customize your project for GitHub Codespaces by committing configuration files to your repository (often known as Configuration-as-Code), which creates a repeatable codespace configuration for all users of your project.
GitHub Codespaces run on a variety of VM-based compute options hosted by GitHub.com, which you can configure from 2 core machines up to 32 core machines. You can connect to your codespaces from the browser or locally using Visual Studio Code.
Example
We will examine Azure Developer CLI (azd
) template - todo-csharp-cosmos-sql. Here is a repo that will be used as an example: https://github.com/NikiforovAll/todo-csharp-cosmos-sql.
The end goal is to set up a full-featured dev environment and measure how much time it takes.
This application utilizes the following Azure resources:
- Azure App Services to host the Web frontend and API backend
- Azure Cosmos DB SQL API for storage
- Azure Monitor for monitoring and logging
- Azure Key Vault for securing secrets
The demo combines techniques from both Infrastructure as a Code (IaaC) and Dev Environment as a Code (DEaaC). It takes only 15 staggering minutes from zero to deployed azure resources on the first launch.
1οΈβ£ Configure dotfiles in βSettings>Codespacesβ:
2οΈβ£ Go to repository and launch a codespace:
3οΈβ£ Open the codespace in the browser or locally (I will go with browser option for the demo)
4οΈβ£ Login to Azure via CLI or VSCode extension:
az login --use-device-code
5οΈβ£ Run azd up
6οΈβ£ Setup the breakpoint
7οΈβ£ Inspect forwarded ports. Note, codespaces allocates some random URL
8οΈβ£ Generate load
9οΈβ£ Inspect logs by running azd monitor --logs
π Tear down the dev environment in Azure azd down
As result we have:
- Deployed whole developer setup in 15 minutes
- Terminal/Shell is configured
- Git is configured
- All project tooling and dependencies are installed:
dotnet
,az
, etc. - VSCode contains user extensions as well as suggested by devcontainer
- One happy developer π
Summary
DEaaS has lots of advantages. Most of the time it just works. But it definitely required investing some time to learn about the moving parts to know how to maintain and troubleshoot the setup. I have not shown you the dark side of using DevContainers but I can assure you that it could be hard to understand when something goes wrong. Despite all challenges, it opens new horizons and it is a future of large-scale and open-source development.
Reference
- https://dotfiles.github.io
- https://nikiforovall.github.io/productivity/2019/11/30/nikiforovall-setup.html
- https://code.visualstudio.com/docs/remote/create-dev-container
- https://docs.github.com/en/codespaces/overview
- https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/introduction-to-dev-containers
- https://docs.github.com/en/codespaces/customizing-your-codespace/personalizing-github-codespaces-for-your-account