diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 9fdf340..86a8d7d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,11 +1,13 @@ { - "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18", + "image": "mcr.microsoft.com/devcontainers/javascript-node:4-24", "features": { "ghcr.io/devcontainers/features/git:1": {}, "ghcr.io/devcontainers/features/git-lfs:1": { "autoPull": "false" // do not automatically pull LFS files when creating the container }, - "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "moby": "false" // does not work with Debian Trixie based images + }, "ghcr.io/devcontainers-extra/features/pre-commit:2": { "version": "4.2.0" } diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..1718917 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,81 @@ +# S-CORE DevContainer Architecture + +This document explains how the S-CORE DevContainer is designed, built and what its requirements are. + +## Overview + +One has to take ones own medicin and for that reason the [S-CORE devcontainer](../src/) is developed using another [simpler devcontainer](../.devcontainer). + +``` + Host + │ + ▼ +┌───────────────────────────────────────────────────────────────────────┐ +│ Outer Dev Container (.devcontainer) │ +│ Base: devcontainers/javascript-node │ +│ Tools: devcontainer CLI, Docker CLI │ +│ │ +│ devcontainer build (scripts/build.sh) │ +│ │ │ +│ │ invokes docker build │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ Build S-CORE DevContainer (src/s-core-devcontainer) │ │ +│ │ - Dockerfile (Ubuntu base image) │ │ +│ │ - Pre-existing features (Git, LLVM/Clang, Rust, …) │ │ +│ │ - S-CORE local feature (available at /devcontainer/features/…) │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ run validation (scripts/test.sh) │ +│ │ │ +│ │ on success | +│ ▼ | +│ Publish image → ghcr.io/eclipse-score/devcontainer: | +└───────────────────────────────────────────────────────────────────────┘ +``` + +This [simpler devcontainer](../.devcontainer) must be able to run [the devcontainer command](https://github.com/devcontainers/cli), which is a nodejs application and Docker. +To achieve that, [javascript-node](https://github.com/devcontainers/images/tree/main/src/javascript-node) as base image and the [Docker-in-Docker](https://github.com/devcontainers/features/tree/main/src/docker-in-docker) feature were chosen. + +## The S-CORE DevContainer + +[DR-001-Infra: Integration Strategy for External Development Tools](https://github.com/eclipse-score/score/blob/main/docs/design_decisions/DR-001-infra.md) +and +[DR-003-Infra: Devcontainer Strategy for S-CORE](https://github.com/eclipse-score/score/blob/main/docs/design_decisions/DR-003-infra.md) +require that all tools / code inside the devcontainer are pinned and that it will be used by developers and CI. +Developers and CI should only need to download prebuild container images. +The container images should be able to build all of S-CORE without extra setup. +This requires that the needed tools are preinstalled, but not too much either to keep container image download times in check. + +To achieve this, a small base image [based on Ubuntu is chosen](https://github.com/docker-library/buildpack-deps/blob/master/ubuntu/noble/curl/Dockerfile). +To this image, the tools needed to build S-CORE and run its tests are added - either via pre-existing devcontainer features, or our own [S-CORE feature](../src/s-core-devcontainer/.devcontainer/s-core-local/). +The tools also need to support typical IDE features like enabling code completion. +All of these tools could have been added via a `Dockerfile` as well, but features are the mechanism to achieve composable devcontainer implementations and are preferred instead. + +The decision whether to use a pre-existing feature or to add a tool using the S-CORE feature is based on the tradeoff between build time and maintainability. +The chosen features are installed quickly, without us having to maintain them. +Other tools installed via the S-CORE feature either have no corresponding feature, or their feature took so much time to install, that it was quicker done using our own code (example: Python feature). + +### Proxy environments + +To support proxy environments, environment variables are set in the [`Dockerfile`](../src/s-core-devcontainer/.devcontainer/Dockerfile) and unset if empty to not interfere with non-proxy environments. + +## Tests + +After an image build, tests check that each tool expected to be in the image is installed with the specified version for [pre-existing features](../src/s-core-devcontainer/test-project/test.sh) and the [S-CORE feature](../src/s-core-devcontainer/.devcontainer/s-core-local/tests/test_default.sh). +This may seem overly complex at first, but prevents (1) accidentially wrong versions, (2) completely broken tools that cannot even execute. +Both cases can happen and have happened in the past already, e.g. due to unexpected interactions between devcontainer features. + +However it is not tested, if S-CORE can be build with that image. +The expectation is that **pinned-in-source-code** devcontainer versions are used by S-CORE repositories. +Updates of devcontainer versions thus are explicit pull-requests (which can be auto-generated via Dependabot or Renovate). +If such an image update fails to build/test/... a certain module, the version bump pull-request will fail in the CI and investigation can start. +Note that this **does not impact** the regular development of that module. + +## Why this setup + +This setup is predictable and fast because a pre-built image avoids per-repo Docker builds and ensures everyone shares the same toolchain. +It strengthens the supply chain by pinning versions and hashes, sourcing features from trusted catalogs, and gating publication via CI builds and tests. +Pre-built images have a higer availability than the set of all tools which are installed (one download from a location controlled by S-CORE vs. many downloads from "everywhere"). +Pre-built images can be easily archived anywhere, e.g. for reproducibility of builds in real production use-cases. +It also enforces a clear separation of concerns: general tooling is delivered through reusable features, S-CORE–specific logic lives in a dedicated feature, and image composition plus publishing are centralized. diff --git a/src/s-core-devcontainer/.devcontainer/Dockerfile b/src/s-core-devcontainer/.devcontainer/Dockerfile index 39be3b3..b838f86 100644 --- a/src/s-core-devcontainer/.devcontainer/Dockerfile +++ b/src/s-core-devcontainer/.devcontainer/Dockerfile @@ -1,6 +1,4 @@ -ARG VARIANT="noble" - -FROM buildpack-deps:${VARIANT:-noble}-curl +FROM buildpack-deps:noble-curl # Proxy arguments for build-time network access ARG HTTP_PROXY="" @@ -24,11 +22,4 @@ LABEL dev.containers.features="common" COPY unset-proxy.sh /etc/profile.d/unset-proxy.sh RUN chmod +x /etc/profile.d/unset-proxy.sh -ARG VARIANT -RUN if [ "$VARIANT" = "noble" ]; then \ - if id "ubuntu" &>/dev/null; then \ - echo "Deleting user 'ubuntu' for $VARIANT" && userdel -f -r ubuntu || echo "Failed to delete ubuntu user for $VARIANT"; \ - else \ - echo "User 'ubuntu' does not exist for $VARIANT"; \ - fi; \ - fi +RUN userdel -f -r ubuntu diff --git a/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh b/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh index 3e830c9..d1d17ca 100755 --- a/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh +++ b/src/s-core-devcontainer/.devcontainer/s-core-local/install.sh @@ -19,6 +19,10 @@ ARCHITECTURE=$(dpkg --print-architecture) apt-get update +# Unminimize the image to include standard packages like man pages +bash -c "yes || true" | unminimize +apt-get install -y man-db manpages manpages-dev manpages-posix manpages-posix-dev + # INSTALL CONTAINER BUILD DEPENDENCIES # Container build dependencies are not pinned, since they are removed anyway after container creation. apt-get install apt-transport-https -y