Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -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"
}
Expand Down
74 changes: 74 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# S-CORE DevContainer Architecture

This document explains how the S-CORE DevContainer is designed, build and what its requirements are.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This document explains how the S-CORE DevContainer is designed, build and what its requirements are.
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 (mounted at /devcontainer/features/…) │ │
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
│ │ - S-CORE local feature (mounted at /devcontainer/features/…) │ │
│ │ - S-CORE local feature (available at /devcontainer/features/…) │ │

Just a proposal - but "mounted" somehow implies actual "file system mounting", which is not the case and may confuse readers?

│ └─────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ run validation (scripts/test.sh) │
│ │ │
│ │ on success |
│ ▼ |
│ Publish image → ghcr.io/eclipse-score/devcontainer:<tag> |
└───────────────────────────────────────────────────────────────────────┘
```

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) were chosen.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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) were chosen.
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 to keep download times in check.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This requires that the needed tools are preinstalled, but not too much to keep download times in check.
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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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 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 via either pre-existing devcontainer or our own S-CORE feature the tools needed to build S-CORE and run its tests are added.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To this image via either pre-existing devcontainer or our own S-CORE feature the tools needed to build S-CORE and run its tests are added.
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 IDEs like enabling code completion.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The tools also need to support IDEs like enabling code completion.
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
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 pre-existing feature or to add a tool using the S-CORE feature is based on the tradeoff between build time and maintainability.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The decision whether to use pre-existing feature or to add a tool using the S-CORE feature is based on the tradeoff between build time and maintainability.
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 either have no corresponding feature, or their feature took so much time to install, that it was quicker done using our own code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Other tools installed via the S-CORE either have no corresponding feature, or their feature took so much time to install, that it was quicker done using our own code.
Other tools installed via the S-CORE 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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.
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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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).
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 devcontainer versions are used by S-CORE repos and when an image update fails to build a certain module its version bump pull request will fail CI.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The expectation is that pinned devcontainer versions are used by S-CORE repos and when an image update fails to build a certain module its version bump pull request will fail CI.
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It strengthens the supply chain by pinning versions and hashes, sourcing features from trusted catalogs, and gating publication via CI builds and tests.
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.
13 changes: 2 additions & 11 deletions src/s-core-devcontainer/.devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
ARG VARIANT="noble"

FROM buildpack-deps:${VARIANT:-noble}-curl
FROM buildpack-deps:noble-curl
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that makes sense.


# Proxy arguments for build-time network access
ARG HTTP_PROXY=""
Expand All @@ -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
Comment on lines -27 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

4 changes: 4 additions & 0 deletions src/s-core-devcontainer/.devcontainer/s-core-local/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down