Back

/ 3 min read

Devcontainer 📦

Introduction

Devcontainer is a feature in VS Code that allows you to develop in a containerized environment. But why would you want to develop in a containerized environment? Well, it ensures that everyone working on the project is using the same development environment. This means that you can say goodbye to the phrase “It works on my machine”.

Official documentation about devcontainer can be found here.

Prerequisites

Before we start, make sure you have the following installed:

Setting up a devcontainer

In order to set up a devcontainer, you need to create a .devcontainer folder in the root of your project. Inside this folder, create a devcontainer.json file. This file will contain the configuration for your devcontainer.

my-project/
.devcontainer/
devcontainer.json
dockerfile.devel

Here is an example of a devcontainer.json file:

.devcontainer/devcontainer.json
{
"name": "my-devcontainer",
"privileged": true,
"remoteUser": "didi",
"build": {
"dockerfile": "../dockerfile.devel",
"args": {
"USERNAME": "didi"
}
},
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.black-formatter",
"ms-python.isort",
"eamodio.gitlens",
"redhat.vscode-yaml",
"yzhang.markdown-all-in-one"
]
}
}
}

In this example, we are using a Dockerfile called dockerfile.devel to build our devcontainer. This Dockerfile will contain the necessary dependencies for our project. Here is an example of a dockerfile.devel file:

dockerfile.devel
FROM python:3.10-slim
ARG USERNAME=didi
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# create the user
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& apt-get update \
&& apt-get install -y sudo \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
# install dependencies
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update && apt-get install -y --no-install-recommends \
wget curl git \
&& rm -rf /var/lib/apt/lists/*
# set working directory
WORKDIR /workspace
# default user
USER $USERNAME
# entrypoint
CMD ["bash"]

The common mistake when setting up a devcontainer is files access permissions. Sometimes, the files created inside the devcontainer are owned by the root user (you can’t edit them outside the devcontainer). To avoid this, you can set the remoteUser property in the devcontainer.json file and create the user in the dockerfile.devel.

All set! Now you can open your project in VS Code and press CTRL + SHIFT + P and select Remote-Containers: Reopen in Container. This will build the devcontainer and open your project inside it.

Additional configurations

DooD

Docker-outside-of-Docker (DooD) is a technique that allows you to bind the host Docker socket a container (devcontainer). This feature allows you to manage host docker containers from within the devcontainer. To enable DooD, you need to add the following configuration to the devcontainer.json file:

{
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
},
}

This feature automatically installs the Docker engine inside the devcontainer and mounts the host Docker socket.

Bind existing ports

By default, the devcontainer does not expose any ports. If you want to bind existing ports (database, servies, etc.) from the host machine to the devcontainer, you can add the following configuration to the devcontainer.json file:

{
"appPort": [4900],
}

Bind localtime

By default, the devcontainer uses the UTC timezone. If you want to bind the localtime from the host machine to the devcontainer, you can add the following configuration to the devcontainer.json file:

{
"mounts": [
"source=/etc/localtime,target=/etc/localtime,type=bind,ro"
],
}

Conclusion

Devcontainer was a game-changer for me. It allowed me to develop in a consistent environment across different machines. I hope this article helps you set up a devcontainer for your project.