Create a Devcontainer (VSCode)
Tags: docker, node, vscode, tutorial
Published: 2022-11-02 07:00:00

- [❓ What's a devcontainer](#whats-a-devcontainer)
- [🏗 Create your own devcontainer](#create-your-own-devcontainer)
- [🔗 Devcontainer with docker-compose](#devcontainer-with-docker-compose)

## ❓ What's a devcontainer
A devcontainer is a feature of **Visual Studio Code** that let your run _docker containers_ locally for development. This brings a lot of **advantages**!
I listed a few here:
- Useful for bigger groups
- Doesn't matter what operating system, version or compatability your local device has. (It's built for that purpose!)
- Fast and secure

## 🏗 Create your own devcontainer
_**FYI:** For this part some docker knowledge is required and is not getting teached._

Now in this example let's create a simple and small **NodeJS devcontainer**

We start with creating a `.devcontainer` folder in the root directory of our project.

![Devcontainer folder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tnlju3sozed9d15yfuf.png)

All we need more for our devcontainer are two more files. The `devcontainer.json` for configs and a default `Dockerfile`.
**devcontainer.json**
```json
{
    "name": "YourProjectName",
    "build": {
        "dockerfile": "Dockerfile"
    },
    "settings": {
        "terminal.integrated.profiles.linux": {
            "zsh": {
                "path": "/bin/zsh"
            }
        },
        "terminal.integrated.defaultProfile.linux": "zsh",
        "editor.formatOnSave": true
    },
    "extensions": ["esbenp.prettier-vscode"]
}
```
**`name`** - The name of your devcontainer and most likely the same as your application.

**`build`** - In this example we defined where the Dockerfile is but ther are many more options for the build process.

**`settings`** - Have explicit settings like the shell in this example is set to zsh (Need to be installed in Dockerfile) and _autoformat_ on save is set to _true_.

**`extensions`** - An array of vscode extensions that are automatically getting installed on startup and used. (Locally installed extensions not available anymore)

_For even more settings see in the docs: https://containers.dev/implementors/json_reference/_

**Dockerfile**
```docker
FROM node:18


RUN apt-get update
# Install dependencies
RUN apt-get install -y wget zsh git \
# Install oh-my-zsh
RUN wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh \
  && cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
```

Now if you reload your window or restart it completely you should see a popup on the right bottom corner saying "Reopen in Container". Click in it and your container is starting up. 

![Reopen in container window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1edjg0tnori53wuutcd0.png)

**Congratulations!**
You just created your very own node devcontainer.
This is possible in every language and with many more settings and stuff. I just briefly teached you the very basics.

## 🔗 Devcontainer with docker-compose
You are not limited to only one container, you can even use docker-compose and build your complete development environment with e.g. database or two different servers.

Let's make some changes to our **devcontainer.json**:
```json
{
    "name": "YourProjectName",
    # Changes 👇
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspace",
    "settings": {
        "terminal.integrated.profiles.linux": {
            "zsh": {
                "path": "/bin/zsh"
            }
        },
        "terminal.integrated.defaultProfile.linux": "zsh",
        "editor.formatOnSave": true
    },
    "extensions": ["esbenp.prettier-vscode"]
}
```

**`dockerComposeFile`** - The location of your docker-compose.yml file.

**`service`** - Define which service you are going to work in.

**`workspaceFolder`** - The folder where you are going to work in.

Now let's create our _docker-compose.yml_ file.
**docker-compose.yml**
```docker
version: "3"

services:
  app:
    container_name: projectname_app
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
    volumes:
      - ..:/workspace:cached
    depends_on: [database]
    command: sleep infinity

  database:
    container_name: projectname_db
    image: mariadb:10.9
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD='yes'
      - MYSQL_ROOT_HOST=%
      - MYSQL_DATABASE=development
      - MYSQL_USER=root
    ports: ["3373:3306"]
    volumes:
      - ./data/db:/var/lib/mysql

volumes:
  vendor: null
```

We now created our docker-compose file to start not only our application but a **MariaDB** database at the same time.

If you now reload your project again and startup your containers. You will see that your project started up but at the same time you have a database running ready to use in your project. How cool is that!

**Thanks for reading!**
<a href="https://www.buymeacoffee.com/jannisdev" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-blue.png" alt="Support me" height="20" width="80"></a>