DEV Community

Theodor Heiselberg
Theodor Heiselberg

Posted on

Run devcontainers as a non-root user

Even when just developing locally I never work directly from the root user.
The reason is that I don't want by accident to create new files with root privileges which then can't run in a cluster since the containers typically don't have root privileges.

In this blog we will se how we can create an dev environment able to:

  • Run containers without root privileges (non-root user)
  • Install dotnet sdk
  • Add dotnet tools
  • Run additional servers

And while we are at it - let's use our own drive name instead of the default "workspace" folder created when running the devcontainer.

Image description

Documentation you should differently read in order to understand the selected configurations in the following files:
Decontainers: add-nonroot-user
Unserstanding the docker user instruction
Change the default mount

.devcontainer/devcontainer.json

{
    "name": "alpine-nvim-dev-environment",
    "service": "dev-machine",
    "dockerComposeFile": "nvim-d-c.yml",
    "workspaceFolder": "/home/container-user/project",
    "remoteUser": "container-user",
    "mounts": [
        "source=${localWorkspaceFolder}/.devcontainer/nvim,target=/home/container-user/.config/nvim,type=bind",
        "source=${localWorkspaceFolder}/.devcontainer/.alpine/.bashrc,target=/home/container-user/.bashrc,type=bind",
        "source=${localWorkspaceFolder}/.devcontainer/.alpine/test.txt,target=/home/container-user/test.txt,type=bind"
    ],
    "customizations": {
        "vscode": {
            "extensions": [
                "jebbs.plantuml",
                "ms-dotnettools.dotnet-interactive-vscode",
                "ms-dotnettools.csdevkit",
                "EditorConfig.EditorConfig",
                "ms-vscode.test-adapter-converter",
                "Continue.continue"
                ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

.devcontainer/Dockerfile.dev-image

FROM alpine:3.20.3

ENV USER_ID=1000
ENV GROUP_ID=1000
ENV USER_NAME=container-user
ENV GROUP_NAME=container-user

RUN addgroup -g $GROUP_ID $GROUP_NAME && \
    adduser --shell /bin/bash --disabled-password \
    --uid $USER_ID --ingroup $GROUP_NAME $USER_NAME 

# Ensure /home/container-user is owned by container-user
RUN mkdir -p /home/container-user/.vscode-server && \
    chown -R $USER_NAME:$GROUP_NAME /home/container-user

RUN mkdir -p /home/container-user/project && \
    chown -R $USER_NAME:$GROUP_NAME /home/container-user

RUN apk update && \
    apk add --no-cache \
        yarn \
        git \
        neovim \
        neovim-doc \
        ripgrep \
        bash \
        curl \
        nodejs \
        npm \
        sudo \
        grep \
        dotnet8-sdk

ENV ENV=/$USER_NAME/.profile

USER $USER_NAME

ENV PATH="$PATH:/home/container-user/.dotnet/tools"
RUN dotnet tool install --global dotnet-format
RUN dotnet tool install --global Nuke.GlobalTool
Enter fullscreen mode Exit fullscreen mode

.devcontainer/nvim-d-c.yml

name: nvim-d-c-x

services:
  dev-machine:
    build:
      context: .
      dockerfile: Dockerfile.dev-image
    volumes:
      - ..:/home/container-user/project
    networks:
      - internal
    command: ["sleep", "infinity"] 
  plantuml:
    image: plantuml/plantuml-server:jetty
    networks:
     - internal
    ports:
      - "8080:8080"
networks:

  internal:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

Top comments (0)