Why You Should Code Inside Docker Containers and How (VS Code)

Nilabhra Roy Chowdhury
Varia Blog

--

Photo by Markus Spiske on Unsplash

If you are using Docker containers to ship your application, you have already had a fair taste of the ease of software engineering that containers bring. Not having to worry about your application behaving differently in production (or any other environment) is truly a major relief for developers. In this article, let me try to convince you to also Dockerize your development environment.

The main reasons which might compel you try out Dockerizing your dev environment are as follows:

  1. Once a development container has been set up, which usually comprises of installing tools, libraries and setting up a few environment variables in an existing Docker container, re-creating the same environment in the future becomes a 1-step process.
  2. It makes onboarding new contributors to the project a no-brainer since the only set-up needed on their side is the correct version of Docker Engine installed and running.
  3. If your Laptop/PC is running low on resources such Disk Space, Memory, Compute, etc. and/or it uses a CPU architecture that is not supported by the tools/libraries/services needed for your project(s) (In my case, I am using a MacBook with the first generation M1 chip which is yet to be supported by many popular softwares and libraries) but you have SSH access to a machine with the right resources running the Docker Engine (a post on this coming up soon).

If you have come this far and found one or more reasons mentioned above valid enough to develop inside a Docker container, let me show you how you may achieve this for an existing project by following a few simple steps.

Step 1: Install the Remote Containers plugin in VS Code

From the extensions tab in the side bar, search for “remote containers”, the first result should be the plugin you are looking for.

The remote containers plugin for VS Code

Install it and move on to the next step.

Step 2: Find or create a Docker container suitable for your project.

In order for you to develop inside a container, you will likely need and image that comes with a few more bells and whistles compared to the bare-bone images you might be using as the base to build the containers that run in testing and production. From here on, we will refer to the development containers as “Dev Containers”. To find an imagine that suits your needs, you have two options:

Option 1
Open the project you want to work on and then bring up the Command Palette and type>remote-containers . This should show a list of actions that can be taken using the Remote Containers plugin. Select the one that says Add development Configuration Files

You will be presented with 3 options, select the one that says From a predefined container configuration definition...

Once selected you would be presented with a list of popular configurations of Dev Containers in various programming languages. If you don’t see the one that is useful to you, you can search for it by selecting Show All Definitions and find the one that matches your needs.

(You can head over to https://hub.docker.com/_/microsoft-vscode-devcontainers to find a list of all available images)

Option 2

If you think the the base image that you use for the container in production is sufficient for development, you can either select From 'Dockerfile' or From 'docker-compose.yml' . When prompted, select the appropriate file to generate the configuration files. In most cases you will need to install some tools and libraries for formatting, linting, debugging, etc. You can set up the development to be different from the other environments by using Multi-Stage Builds.

Both the options mentioned above will result in the creation of a new directory called .devcontainerin the root directory of your project. You will find two files inside of .devcontainer if you went with option 1, one of them for sure will be a file called devcontainer.json and the other one would be a Dockerfile. If you chose option 2 and your project had a Dockerfile, then you will see only the JSON file inside .devcontainer and if you had a docker-compose.yml file, then you will see another docker-compose.yml file inside .devcontainer

(I lied at the beginning of this step when I said you have two options, you actually have third option where you create the .devcontainer directory and it’s contents manually)

Step 3: Configure the development container

VS Code Settings and Extensions
The devcontainer.json file inside .devcontainer has two properties that you must pay attention to, i.e.settings andextensions.

The settings property: This property contains a list of properties and values for VS Code settings that will be in effect inside the running container. You can disable or enable formatting, linting, change fonts, etc. You can add more properties as needed for development inside the container.

For example, if you want your code formatted automatically every time you save a file, you may set the editor.formatOnSave property to be true

"editor.formatOnSave": true

The extensions property: This property contains a list of VS Code extension IDs. These extensions will be installed inside the container once it is created. Be aware that there might be extensions that might not work in a particular container.

For example, if you want the GitLens plugin installed in the container (a very cool plugin to have in my opinion) you can add it to the extensions property like such

"extensions": [
"eamodio.gitlens"
]

You will also notice a property called remoteUser which is set to the default value vscode you can leave it as it is if you want to have super user access inside the container.

For a comprehensive list of properties and their functions you may refer to this page here: https://code.visualstudio.com/docs/remote/devcontainerjson-reference

Container configuration
If you decided to use a predefined Dev Container or if you generated the Dev Container settings from a docker-compose.yml you will find a Dockerfile or a docker-compose.yml file inside the .devcontainer directory.

For the Dockerfile you can go ahead and add the necessary build steps such as installing compilers, debugging tools, libraries, etc. These would be installed when the container is built and would be available to you once the container starts running.

For the docker-compose.yml file, you will probably won’t have to do much there. The installation of tools and libraries need to specified in the Dockerfile that lie at the root directory of your project. If you are using a multi-stage build, you can specify the build target in this YAML file to override the build targetdocker-compose.yml file in the root directory of your project. You will also see

command: /bin/sh -c "while sleep 1000; do :; done"

This ensures that once the container is built, the service that you will use for development doesn’t exit automatically. You should also notice the volume section of the service which specifies the mount point of your project directory. The volume will be cached by default which ensures that any file operation that you make on that volume will be reflected outside the container too.

Step 4: Building and running the Dev Container

The final step is to build and run the Dev Container. To do this, bring up the command palate in VS Code and select Remote-Containers: Rebuild and Reopen in Container

This will result in VS Code opening a new window and will take some time as the container will be build and the VS Code extensions will be installed inside the container. If you have multiple services in your docker-compose.yml, those services would also be built and run before you can start using the Dev Container. Once the build process is finished, you can finally start using VS Code as you would natively. You will notice that IntelliSense would be working and the extensions you wanted would be installed and active. In case an extension gets installed but fails to load, VS Code will prompt you to reload the window and it should work once you reload it.

If you started from a pre-defined container, this in when you clone your clone your repository using the terminal inside VS Code.

Once you are done developing inside the container, you can click on the button at the bottom left corner of the VS Code window and choose Close connection

My personal take

My work as an NLP Engineer at Varia requires me to switch between multiple projects all the time, sometimes within the same day. Each project is dependant on different environment variables that are needed to be set and multiple services such as databases and servers that are needed to be up and running during development, especially for debugging. VS Code paired with dev containers gives me the ability to set up the environment for any of the projects with just 2 clicks.

Conclusion

In this post I tried to convince you that developing inside Docker containers can be beneficial in certain conditions and I provided a very brief tutorial on how to do so using VS Code.

For a much more comprehensive guide to using VS Code for remote development, please refer to https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference

This is my first post ever, it would be nice if you could leave your feedback and opinions so that I may improve my writing skills

--

--

Nilabhra Roy Chowdhury
Varia Blog

NLP Engineer @ www.varia.media | Computer Engineer whose work is focused on Natural Language Processing