DEV Community 👩‍💻👨‍💻

Cover image for Why are people developing inside containers?
Rizèl Scarlett for GitHub

Posted on • Updated on

Why are people developing inside containers?

Nine years ago, in March 2013, Solomon Hykes and his cofounders revolutionized how we do software development with an open source platform called Docker. Although the creators of Docker didn't invent containers, they popularized them. Thanks to Docker, engineers can create tools, like GitHub Codespaces, that enable us to code in a development container hosted in the cloud.

I’ll admit that when I first heard about development containers, I had two questions:

  • Why are people developing inside containers?
  • What are containers?

If you have similar questions, this post is for you.

In this blog post, I'll explain what containers are, how they benefit engineers, and how to setup devcontainers in GitHub Codespaces.

What does it mean to develop inside a container?

Raise your hand if you’ve ever uttered the words, "It works on my machine." (Don’t worry; you're not alone)!

If you're not familiar with this phrase, it's a meme, but it's also a real phrase developers find themselves saying if they work in a codebase where the environments vary. Although working in varying environments is not ideal, it does happen. From my experience, situations like this occur when my local environment, my coworkers' local environments, staging, and production all have slight differences. Because the environments had slightly different configurations, bugs existed in one environment but didn’t exist in the other environment. It can feel so embarrassing and frustrating to build a feature or fix a bug that works locally but doesn't work in production or staging.

However, containers solve the issue of inconsistent developer environments. Containers enable software engineers to program in a consistent environment. Now, your coding environment can mirror production by using the same operating system, configurations, and dependencies. This ensures bugs and features behave the same across all environments relieving developers from the embarrassment of saying, "It works on my machine."

Now that we understand the purpose of containers, let’s explore how Codespaces leverages containers.

GitHub Codespaces takes software and cloud development to the next level

GitHub Codespaces allows you to code in a container hosted in the cloud. In this context, the cloud is an environment that doesn't reside on your computer but rather on the internet.

Faster onboarding

Typically, software engineers are responsible for setting up their local environment when they join a team. Local environment setup includes installing the required dependencies, linters, environment variables, and more. Developers may spend up to a week configuring their environment, depending on the quality of the documentation. When I was purely a software engineer, it took me about 2 days to set up my environment, and the experience was painful because I wanted to start coding immediately. Instead, I had to seed my database and edit my .zshrc file.

Fortunately, organizations can automate the onboarding process using GitHub Codespaces to configure a custom environment. When a new engineer joins the team, they can open a codespace and skip the local environment setup because the required extensions, dependencies, and environment variables exist within the codespace.

Code from anywhere

With Codespaces, I can code anywhere that I have internet access. If I switch devices or forget my laptop at home, I can easily resume my work on an iPad while I’m on the plane without cloning a repository, downloading my preferred IDE, and setting up a local environment. This is possible because Codespaces opens a Visual Studio Code-like editor inside the browser. The best part is Codespaces can autosave my code even if I forget to push my changes to my repository.

Consistent environments

As mentioned in the paragraphs above, containers allow you to work in a mirrored production environment. Because GitHub Codespaces uses containers, you can get the same results and developer experience in your local environment as you would in your production environment.

Additionally, sometimes when changes happen to the codebase, such as infrastructure enhancements, local environments can break. When local environments break, it’s up to the developer to restore their developer environment. However, GitHub Codespaces use of containers brings uniformity to developer environments and reduces the chances of working in a broken environment.

Three files you may need to configure a Codespace

You can leverage three files to make the Codespaces experience works for you and your teammates: the devcontainer.json file, the Dockerfile, and the docker-compose.yml file. Each of these files lives in the .devcontainer directory at the root of your repository.

The devcontainer.json file

The devcontainer.json file is a configuration file that tells GitHub Codespaces how to configure a codespace. Inside a devcontainer file, you can configure the following:

  • Extensions
  • Environment variables
  • Dockerfile
  • Port forwarding
  • Post-creation commands
  • And more

This means that whenever you or someone opens a codepspace, the extensions, environment variables, and other configurations you specify in the devcontainer.json file will automatically install when they open a codespace in the specified repository. For example, if I wanted folks to have the same linter and extensions as me, I could add the following to my devcontainer.json file:
devcontainer.json

 {
    "name": "Node.js",
    "build": {
        "dockerfile": "Dockerfile",
        // Update 'VARIANT' to pick a Node version: 18, 16, 14.
        // Append -bullseye or -buster to pin to an OS version.
        // Use -bullseye variants on local arm64/Apple Silicon.
        "args": { "VARIANT": "16-bullseye" }
    },

    // Configure tool-specific properties.
    "customizations": {
        // Configure properties specific to VS Code.
        "vscode": {
            // Add the IDs of extensions you want installed when the container is created.
            "extensions": [
                "dbaeumer.vscode-eslint", // this is the exentension id for eslint
                "esbenp.prettier-vscode", // this is the extension id for prettier
                "ms-vsliveshare.vsliveshare", // this is the extension id for live share
            ]
        }
    },

    // Use 'forwardPorts' to make a list of ports inside the container available locally.
    // "forwardPorts": [],

    // Use 'postCreateCommand' to run commands after the container is created.
    // "postCreateCommand": "yarn install",

    // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
    "remoteUser": "node"
}
Enter fullscreen mode Exit fullscreen mode

You can learn more about the devcontainer.json file here.

The Dockerfile

The Dockerfile is a configuration file that tells GitHub Codespaces how to build a container. It contains a list of commands that the Docker client calls while creating an image. Dockerfiles are used to automate the installation and configuration of a container. For example, if I wanted to install Node.js in a container, I could add the following to my Dockerfile:
Dockerfile

FROM node:16-bullseye
Enter fullscreen mode Exit fullscreen mode

You can learn more about Dockerfiles here, and you can learn more about setting up a node.js in Codespaces here.

The docker-compose.yml file

You don't need a docker-compose.yml file in a Codespace, but it's useful if you want to run multiple containers. For example, if you want to run a database and a web server in a Codespace, you can use the docker-compose.yml file to run both containers. You can learn more about docker-compose.yml files here. Here's an example of what a docker-compose.yml file that's connecting to a database might look like:
docker-compose.yml

version: '3.8'

services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
      args:
        VARIANT: "3"
        NODE_VERSION: "none"

    volumes:
      - ..:/workspace:cached

    command: sleep infinity

    network_mode: service:db

  db:
    image: postgres:latest
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    hostname: postgres
    environment:
      POSTGRES_DB: my_media
      POSTGRES_USER: example
      POSTGRES_PASSWORD: pass
      POSTGRES_HOST_AUTH_METHOD: trust
    ports:
      - 5432:5432

volumes:
  postgres-data: null
Enter fullscreen mode Exit fullscreen mode

Codespaces is not the same as GitHub’s web editor

GitHub Codespaces is not the same as GitHub’s web editor. The web editor is the editor that appears when you press "." in a repository. It is a lightweight editor that allows you to edit files in your repository. The web editor is great for making minor changes to a file, but it’s not ideal for writing and running full stack web applications. This is because the GitHub web editor does not have a terminal. However, Codespaces allows you to run a full-fledged IDE in the browser equipped with a terminal and more.

See the below image to understand the differences between GitHub's web editor and GitHub Codespaces. This image is from the GitHub official documentation. You can read more details here.

Both the web-based editor and GitHub Codespaces allow you to edit your code straight from your repository. However, both have slightly different benefits, depending on your use case

P.S. I wrote this blog post with GitHub Copilot. 😉 (These are all my own words, thoughts, and frustrations, but Copilot helped unblock me when I couldn’t find the right phrases or motivation.)

There's so much to learn about GitHub Codespaces. Comment below if you have any topics regarding GitHub Codespaces you'd like me to cover in future posts. Follow me and GitHub on DEV if you want to see more content like this. Thanks for reading! 🙏🏿

Top comments (14)

Collapse
 
sadeedpv profile image
Sadeedpv • Edited on

I was struggling with the whole containerization concept and this article really helped me 🔥

Collapse
 
blackgirlbytes profile image
Rizèl Scarlett Author

I’m glad it helped. This comment made my day!

Collapse
 
lockykeaney profile image
Locky Keaney

I've recently been using Docker for developing my API in a little project because mongodb doesn't work on M1 yet.

And from that necessary use case I am now hooked on them. Not having my machine bogged down with different versions of things and programs is great. And a single command from a single terminal to get my BE going means I'm more likely to jump in a tinker around when I've got nothing to do.

I have been interested in codespaces since I saw the reveal video, but I only have experience with GitPod which was super handy.

Collapse
 
okbrown profile image
Orlando Brown • Edited on

And what successful alternatives are they that do the same thing but do not have a vendor lock-in to Github?

Collapse
 
blackgirlbytes profile image
Rizèl Scarlett Author • Edited on

Hmm, maybe GitPod, CodeSandbox, and Repl.it. Transparently, I work at GitHub, and I'm most familiar with using GitHub Codespaces..so I don't know what the set up looks like for these tools or if you can pre-install things like extensions in those IDEs. I think you can with GitPod..that may be the closest alternative.

Any reason why you're looking for something outside of GitHub?

Collapse
 
igoro00 profile image
Igor Ordecha • Edited on

Because it's vendor lock in. GitHub's pricing may be competitive now but how can I know it will still be few years from now? In the worst case scenario I can't selfhost codespaces.
GitPod on the other hand can be selfhosted and you're not vendor locked-in to GitHub with your repo(GitHub is currently the best Git service but who knows if that's gonna be the case in the future)

The same with databases. You shouldn't use Firestore(or Firebase as a whole) for that reason. You should use something standard (SQL) so when your provider of choice goes under, you dump everything, create a DB with another provider or you selfhost one, restore the dump on the new database, change environment variables and you're good to go.

Thread Thread
 
blackgirlbytes profile image
Rizèl Scarlett Author

Fair points!!

Collapse
 
devangtomar profile image
Devang Tomar

Thanks for sharing this. I like the way it starts from very scratch. 🙌🎈

Collapse
 
blackgirlbytes profile image
Rizèl Scarlett Author

Thank you! I wrote it in the way that I learn best. Appreciate your comment.

Collapse
 
netch80 profile image
Valentin Nechayev

The caption is misleading and a bit clickbait. Let's avoid this.

GitHub is a specific environment not suitable to all development.

Containers on their own can't help facing tons of other issues, as e.g. different runtime placement and timeouts in interaction to a public service. Well, they definitely have huge advantage of exact stable environment, but it is not absolute.

Collapse
 
blackgirlbytes profile image
Rizèl Scarlett Author • Edited on

Hi Valentin,
The blog banner I used says "Why are people developing in containers: GitHub Codespaces." I work at GitHub, so my goal is to continue informing people about Codespaces as an option for development. I also thought it would be cool to give beginners more context about containers. I was able to accomplish my goal of introducing people to both GitHub Codespaces and containers. People have messaged me that this post clarified a bit for them. I am also in the process of learning, so I'm sharing as I learn.

If you have more to share about containers, I encourage you to write about it and share it. Thank you!

Collapse
 
incrementis profile image
Akin C.

Hello Rizèl Scarlett,

thank you for your article.
Now I understand Docker a bit better.
I love the structure in your article and it was easy to read.
I am also glad of the links your article provides because I think it adds more credibility.

As the next article, I would very much like to know in detail how Copilot helped you to write this article.

Collapse
 
dels07 profile image
Deli Soetiawan

Is it possible to use 2 repo for 1 project?

My company use 1 repo for development container and other for actual code

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more

🌚 Life is too short to browse without dark mode