From 8114008bd5d6c892ea1508b307f72c04383f30e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20S=C3=B6derberg?= Date: Wed, 26 Mar 2025 00:09:14 +0100 Subject: [PATCH] Added Terraform file and updated Dockerfile with python-pip --- README.md | 25 +++++ Dockerfile => build/Dockerfile | 28 ++--- main.tf | 190 +++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+), 12 deletions(-) create mode 100644 README.md rename Dockerfile => build/Dockerfile (82%) create mode 100644 main.tf diff --git a/README.md b/README.md new file mode 100644 index 0000000..271f7c5 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# LTH Docker + +Create a workspace by pressing the button below! + +[![Open in Coder](https://coder.soderberg.tech/open-in-coder.svg)](https://coder.soderberg.tech/templates/LTH/workspace) + +## Configure X11 capabilities + +1. Install a X Server on your device, [X410](https://x410.dev/) is recommended. + +3. Open VS Code and add two entries to the ***coder.sshConfig*** setting (restart VS Code afterwards): + - `ForwardX11 yes` + - `ForwardX11Trusted yes` + +> You might need to input the following into a terminal on Windows: `setx DISPLAY "127.0.0.1:0.0"` if the X11 display can't be found. + + +## Architecture + +This template provisions the following resources: + +- Docker image (built by Docker socket and kept locally) +- Docker volume (persistent on `/home/{User}`) + +This means, when the workspace restarts, any tools or files outside of the home directory are not persisted. To pre-bake tools into the workspace (e.g. `python3`), modify the container image. diff --git a/Dockerfile b/build/Dockerfile similarity index 82% rename from Dockerfile rename to build/Dockerfile index d79606d..6606bfe 100644 --- a/Dockerfile +++ b/build/Dockerfile @@ -10,14 +10,25 @@ RUN apt-get update \ wget \ locales +# Sets local +RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 +ENV LANG=en_US.utf8 + # Install Python RUN apt-get install -y \ python3 \ - python3-venv \ - python3-pip \ + python3-pip \ + python3-venv \ python3-tk \ python-is-python3 +# Install Python Packages +RUN pip install \ + requests \ + rich \ + ipykernel \ + --break-system-packages + # Install JAVA RUN apt-get install -y \ default-jdk \ @@ -40,19 +51,12 @@ RUN apt-get install -y \ libcurl4-openssl-dev \ libssl-dev \ libxml2-dev \ - libfontconfig1-dev - # && Rscript -e 'install.packages(c("languageserver", "ggplot2", "reshape2", "httpgd"))' - -# Install TeX-live -# RUN apt-get install -y texlive-full + libfontconfig1-dev \ + && Rscript -e 'install.packages(c("languageserver", "ggplot2", "reshape2", "httpgd"))' # Clears apt lists RUN rm -rf /var/lib/apt/lists/* -# Sets local -RUN localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 -ENV LANG=en_US.utf8 - # Adds the default User ARG USER=lth-student RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \ @@ -61,4 +65,4 @@ RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \ # Sets user and work directory USER ${USER} -WORKDIR /home/${USER} +WORKDIR /home/${USER} \ No newline at end of file diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..a22e373 --- /dev/null +++ b/main.tf @@ -0,0 +1,190 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +locals { + username = data.coder_workspace_owner.me.name +} + +data "coder_provisioner" "me" { +} + +provider "docker" { +} + +data "coder_workspace" "me" { +} +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <<-EOT + set -e + + # Prepare user home with default files on first start. + if [ ! -f ~/.init_done ]; then + cp -rT /etc/skel ~ + touch ~/.init_done + fi + + EOT + + # These environment variables allow you to make Git commits right away after creating a + # workspace. Note that they take precedence over configuration defined in ~/.gitconfig! + # You can remove this block if you'd prefer to configure Git manually or using + # dotfiles. (see docs/dotfiles.md) + env = { + GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" + GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" + } + + # The following metadata blocks are optional. They are used to display + # information about your workspace in the dashboard. You can remove them + # if you don't want to display any information. + # For basic resources, you can use the `coder stat` command. + # If you need more control, you can write your own script. + metadata { + display_name = "CPU Usage" + key = "0_cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM Usage" + key = "1_ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Home Disk" + key = "3_home_disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } + +} + +module "code-server" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/modules/code-server/coder" + version = "1.0.29" + display_name = "VS Code WEB" + agent_id = coder_agent.main.id + install_prefix = "/home/${local.username}/.vscode-web" + folder = "/home/${local.username}" + use_cached_extensions = true + extensions = [ + "scalameta.metals", + "James-Yu.latex-workshop", + "scala-lang.scala", + "ms-python.python", + "formulahendry.code-runner", + "ritwickdey.LiveServer", + "ms-python.isort", + "njpwerner.autodocstring", + "ms-vscode.hexeditor" + ] + settings = { + "workbench.startupEditor": "none", + "workbench.colorTheme": "Default Dark Modern", + "window.menuBarVisibility": "classic", + "files.exclude": { + ".*/": true + } + } +} + + +resource "docker_volume" "home_volume" { + name = "coder-${data.coder_workspace.me.id}-home" + # Protect the volume from being deleted due to changes in attributes. + lifecycle { + ignore_changes = all + } + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace_owner.me.name + } + labels { + label = "coder.owner_id" + value = data.coder_workspace_owner.me.id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + # This field becomes outdated if the workspace is renamed but can + # be useful for debugging or cleaning out dangling volumes. + labels { + label = "coder.workspace_name_at_creation" + value = data.coder_workspace.me.name + } +} + +resource "docker_image" "main" { + name = "coder-${data.coder_workspace.me.id}" + build { + context = "./build" + build_args = { + USER = local.username + } + } + triggers = { + dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)])) + } +} + +resource "docker_container" "workspace" { + count = data.coder_workspace.me.start_count + image = docker_image.main.name + # Uses lower() to avoid Docker restriction on container names. + name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" + # Hostname makes the shell more user friendly: coder@my-workspace:~$ + hostname = data.coder_workspace.me.name + # Use the docker gateway if the access URL is 127.0.0.1 + entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")] + env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] + host { + host = "host.docker.internal" + ip = "host-gateway" + } + volumes { + container_path = "/home/${local.username}" + volume_name = docker_volume.home_volume.name + read_only = false + } + + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace_owner.me.name + } + labels { + label = "coder.owner_id" + value = data.coder_workspace_owner.me.id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + labels { + label = "coder.workspace_name" + value = data.coder_workspace.me.name + } +}