Developing in a docker container
Tags: docker, netcore, productivity
Published: 2020-06-16 20:36:42

---
title: Developing in a docker container
published: true
date: 2020-06-13 13:26:56 UTC
tags: Docker,NETCore,Productivity
canonical_url: https://SimonReynolds.ie/developing-in-a-docker-container/
---

Ah, a new open source project that looks interesting. Let's pull it down from GitHub, open it up in the IDE of our choice and.... Oh... It turns out the build scripts assume you have some build tool already installed or, even worse, a specific version of it.

This is a great example of where the [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) extension pack for [Visual Studio Code](https://code.visualstudio.com) comes in. Grab it and you can do all your development in a docker container for your projects!

Naturally, you'll need to have Docker installed, either [Docker Desktop](https://www.docker.com/products/docker-desktop) for Windows or MacOS, or [Docker CE/EE](https://docs.docker.com/install/#supported-platforms) for the Linux distribution of your choosing.

And in even better news, with the release of WSL 2, Docker now uses it instead of Hyper-V as the backend, so you can run Docker on Windows 10 Home Edition too! Read more about it [here](https://www.docker.com/blog/docker-hearts-wsl-2/).

Once that's installed all you need to add is a `.devcontainer` folder in the root of your project and throw in a `devcontainer.json` file. You can use it to either specify a prebuilt `image` or specify a `DOCKERFILE` that you can use to build a custom development environment.

You can use this for any project in any language, I'm going to detail how I use it for a .NET Core project built in F# but the same ideas can be applied to any project.

You can base your Dockerfile on any image, [PHP](https://hub.docker.com/_/php/), [NodeJS](https://hub.docker.com/_/node/), the [.NET Core SDK](https://hub.docker.com/_/microsoft-dotnet-core-sdk/), whatever tech stack you're building with.  Then build on it, add in whatever extra tools you need, maybe you want to add `git`?

A prebuilt environment containing everything you need, with exactly the versions you want. What more could you need?

![Developing in a docker container](https://simonreynolds.ie/content/images/2019/08/ButWaitTheresMore.png)<figcaption>But wait...there's more!</figcaption>

Why stop at specifying just your build environment? How about what VS Code settings or extensions are needed?

Let's extend the `devcontainer.json` with some extra instructions. We can say we want some extensions installed by default. If you use VS Code for F# then you probably already have the amazing [Ionide](https://ionide.io/) plugin installed.

But you want your project to be easy for newcomers to get up and running. Telling them to go install 5 different extensions just get started isn't the best way to start off a relationship with a potential new user or contributor.

Let's just list the extensions we need instead...

<!--kg-card-begin: markdown-->
```json
{
    "name": "MyAwesomeApp",
    "dockerFile": "Dockerfile",
    "appPort": [8080],
    "extensions": [
        "ionide.ionide-fsharp",
        "ms-vscode.csharp",
        "editorconfig.editorconfig",        
        "ionide.ionide-paket",
        "ionide.ionide-fake"
    ]
} 
```
<!--kg-card-end: markdown-->

What about VS Code settings? All settings in VS Code are specified in json files, so we just add one to the `.devcontainer` folder and reference it in the Dockerfile.

<!--kg-card-begin: markdown-->
```json
{
    "FSharp.fsacRuntime":"netcore"
}
```
<!--kg-card-end: markdown-->

This example is named `settings.vscode.json` so we add it to our Dockerfile

<!--kg-card-begin: markdown-->
```docker
FROM fsharp:netcore

# Copy endpoint specific user settings into container to specify
# .NET Core should be used as the runtime.
COPY settings.vscode.json /root/.vscode-remote/data/Machine/settings.json

# Install git, process tools
RUN apt-get update && apt-get -y install git procps
```
<!--kg-card-end: markdown-->

So now when we open the project in VS Code we get a prompt to reopen it in a container. It will create a Docker container based on the supplied `DOCKERFILE`, automatically open and forward port 8080 from the container to the host and install all the extensions listed. Now we can happily write our build script that assumes the presence of a build tool and make sure that making changes to it is a smoother experience because VS Code will even have the right extensions for it!

The full reference for what `devcontainer.json` can do is [here](https://code.visualstudio.com/docs/remote/containers#_devcontainerjson-reference), and it can do a lot!