DEV Community

Theodor Heiselberg
Theodor Heiselberg

Posted on • Edited on

Run Elm and lunarvim in a devcontainer

Let's use docker-compose

As your project grows you'll need eg. sql, nginx etc.
This setup will prepare your project for this.
Image description

This dev-environment is using elm-watch.

.devcontainer/d-c-lunarvim.yml

name: d-c-lunarvim-x

services:
  lvim:
    build:
      context: .
      dockerfile: Dockerfile.lunarvim
    networks:
      - internal  # Ensure DevContainer connects to the same network
    volumes:
      - lvim-cs-dependency-cache:/home/lunaruser/.elm
      - ..:/workspace
    command: ["sleep", "infinity"]

volumes:
  lvim-cs-dependency-cache:

networks:
  internal:
    driver: bridge
Enter fullscreen mode Exit fullscreen mode

.devcontainer/devcontainer.json

{
    "name": "lunarvim-devcontainer",
    "service": "lvim",
    "dockerComposeFile": "d-c-lunarvim.yml",
    "mounts": [
        "source=${localEnv:HOME}/.bashrc,target=/home/lunaruser/.bashrc,type=bind",
        "source=lvim-cs-dependency-cache,target=/home/lunaruser/.elm,type=volume"

      ],
    "workspaceFolder": "/workspace",
    // In order to make elm-watch pick up changes
    "containerEnv": {
        "CHOKIDAR_USEPOLLING": "true"
    },
    // Configure tool-specific properties.
    "customizations": {
        // Configure properties specific to VS Code.
        "vscode": {
            // Add the IDs of extensions you want installed when the container is created.
            "extensions": [
                "Elmtooling.elm-ls-vscode",
                "ritwickdey.LiveServer",
                "streetsidesoftware.code-spell-checker",
                "GitHub.copilot-chat",
                "GitHub.copilot",
                "eamodio.gitlens",
                "elmTooling.elm-ls-vscode",
                "kisstkondoros.vscode-gutter-preview",
                "mongodb.mongodb-vscode"
            ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

.devcontainer/Dockerfile.lunarvim

# Use a stable version of Alpine as the base image
FROM alpine:3.20.3

# Set up the working directory
WORKDIR /tmp

# Set environment variables
ENV HOME_DIR="/home/lunaruser"
ENV LV_BRANCH="release-1.4/neovim-0.9"
ENV PATH="$PATH:$HOME_DIR/.local/bin"

# Install dependencies
RUN apk update && \
    apk add --no-cache \
        yarn \
        git \
        python3 \
        cargo \
        neovim \
        xclip \
        ripgrep \
        alpine-sdk \
        bash \
        curl \
        nodejs \
        npm \
        sudo \
        libc6-compat  # Install if needed for compatibility with Elm binaries

# Configuring Elm version
ARG ELM_VERSION=latest-0.19.1
ARG ELM_TEST_VERSION=latest-0.19.1
ARG ELM_FORMAT_VERSION=latest-0.19.1

# This Dockerfile adds a non-root user with sudo access.
ARG USERNAME=lunaruser
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Add a non-root user and group
RUN addgroup -S $USERNAME && \
    adduser -S $USERNAME -G $USERNAME --shell /bin/sh

# Install Elm using the provided method, elm-test and elm-format via npm
RUN export DEBIAN_FRONTEND=noninteractive && \
    # Install Elm binary
    curl -L -o elm.gz https://github.com/elm/compiler/releases/download/0.19.1/binary-for-linux-64-bit.gz && \
    gunzip elm.gz && \
    chmod +x elm && \
    mv elm /usr/local/bin/elm && \
    # Install elm-test and elm-format via npm
    npm install --global \
        elm-test@${ELM_TEST_VERSION} \
        elm-format@${ELM_FORMAT_VERSION} \
        elm-watch@beta && \
    # [Optional] Update UID/GID if needed
    if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \
        groupmod --gid $USER_GID $USERNAME && \
        usermod --uid $USER_UID --gid $USER_GID $USERNAME && \
        chown -R $USER_UID:$USER_GID /home/$USERNAME; \
    fi && \
    # Create the elm cache directory where we can mount a volume
    mkdir /home/$USERNAME/.elm && \
    chown $USERNAME:$USERNAME /home/$USERNAME/.elm

# Switch to the non-root user
USER $USERNAME

# Run LunarVim installation as the non-root user
RUN curl -s https://raw.githubusercontent.com/lunarvim/lunarvim/$LV_BRANCH/utils/installer/install.sh | \
    bash -s -- --no-install-dependencies

# Define the volume for the .bashrc file
VOLUME /home/lunaruser/

# Set default command to open LunarVim - when running directly in a docker container
# CMD ["/home/lunaruser/.local/bin/lvim"]
Enter fullscreen mode Exit fullscreen mode

Personal preferences:
.vscode/settings.json

{
    "liveServer.settings.root": "/wwwroot",
    "editor.formatOnSave": true,
    "files.autoSave": "onFocusChange",
    "editor.defaultFormatter": "elmTooling.elm-ls-vscode"
}
Enter fullscreen mode Exit fullscreen mode

Run elm-format on save

Open the config.

Image description

~/.config/lvim/config.lua

lvim.format_on_save.enabled = true
lvim.format_on_save.allow_filetypes = { "elm" }

local formatters = require ("lvim.lsp.null-ls.formatters")
formatters.setup({
    {
        exe = "elm-format",
        filetypes = { "elm" },
    }
})
Enter fullscreen mode Exit fullscreen mode

I'm stil to find out how to load your own personal configurations (*.lua files)

Top comments (3)

Collapse
 
sukkergris profile image
Info Comment hidden by post author - thread only accessible via permalink
Theodor Heiselberg

Hi great question ☺️
The answer is tooling. Every project I work on also involves databases and various other services. Using vs code and devcontainers with all the necessary extensions ties my entire dev environment together with my ide of choice. One ide to rule the entire project 👍
(Hence the usage of docker compose)
Personally I’m not that mush a cli expert to be using the cli exclusively.
What’s your opinion?

Collapse
 
daniel_hamngren_9ca73b73b profile image
Daniel Hamngren

Intesting post! But I don’t really understand how you use your devcontainer. Are you using both lunarvim and vs code in your devcontainer? How do you interact with lunarvim when you have your devcontainer running on e.g. codespaces?

What do you see is the best thing with the setup in your post?

Collapse
 
sukkergris profile image
Theodor Heiselberg • Edited

question ☺️
The answer is tooling. Every project I work on also involves databases and various other services. Using vs code and devcontainers with all the necessary extensions ties my entire dev environment together with my ide of choice. One ide to rule the entire project 👍
(Hence the usage of docker compose)
Personally I’m not that mush a cli expert to be using the cli exclusively.
What’s your opinion?

Some comments have been hidden by the post's author - find out more