As more folks are working with VS Code while developing on Swift packages, it seems we could use a general devContainer template as a common baseline for Swift packages. To accommodate this, I've got a draft up in Swift's repo-templates repository to provide a baseline.
Two repositories in swiftlang already have devContainers in their repos - sourcekit-lsp and swift-package-manager, and both of those started with a baseline of swift-nightly images. I wasn't entirely sure if that's what we'd want as a default, so I started off with the latest swift release image (swift:6.2) instead for this draft.
There seems to be two paths for providing devContainers, and I'm not entirely sure which would be more useful as a default:
leverage the pre-built Swift image, and extend capabilities of the image using the devContainer features
provide a Dockerfile that's built, and including all features within the Dockerfile setup, eschewing the "features" capability.
The existing devContainers used in Swift lean into this second path.
Please take this PR as a straw-man proposal, as I'm not deeply wed to any specific pattern here, and am looking for feedback from the broader Swift community as to what would make the most sense for our needs.
@adam-fowler had setup a devcontainer for the SSWG so may have some thoughts
The vscode-swift extension made a change literally just this week to install swiftly into our devcontainer to make it easier to swap between toolchain versions without having to modify the base image vscode-swift/.devcontainer/Dockerfile at main ¡ swiftlang/vscode-swift ¡ GitHub . If we did something like that here, maybe then the postCreateCommand would check for a .swift-version file in the workspace and if so run swiftly install --use (not sure thatâs the right command) so that for any given package project they have the right toolchain version. Just a thought.
If the container used Swiftly to install a toolchain then the base image should probably be whatever swiftâs images are based on, instead of a swift:x.y image to avoid paying the cost of downloading two toolchains (one in the image, then one with swiftly).
Yes thanks @plemarquand I forgot to make that point, because in addition to that swiftlang publishes base images for more distros than just Jammy. Bookworm is the first one coming to mind which I know there are users of the VSCode extension who are using it.
I definitely kept a close eye on @adam-fowler examples - in the valkey-swift repository, he included the jemalloc feature to enable the benchmarked, which I adopted over into this draft.
If anyone has the "dev equivalent" image that uses Swiftly from the get-go, please let me know. That sounds like it'd be a really nice "dev" image variant that's perfect for this use case. (failing an existing example, I'll see what I can cobble up)
UPDATE: I've updated the image so that it'll build and install using swiftly from the get-go. Since the default swift:6.2 docker image builds on Ubuntu 24.04, I did the same - so the packages and such are all tuned for Ubuntu.
I setup the devcontainer template as part of my work on the VSCode extension. I was hoping as I let go of maintenance for the extension someone might also take on the devcontainer so it is great that someone is looking into this. For instance there is a PR up for including Swift 6.2 At this point in time the publish process for the template is a manual process and Iâm away so cannot do this. It can be automated but not relying on one individual ie me, to publish would be good.
Using swiftly to install Swift does have its issues. The double install where we install a Swift image and then install Swift using swiftly has already been pointed out by @plemarquand . But if we use a base image like Ubuntu or Bookworm and use swiftly to install Swift we have the issue where rebuilding a devcontainer involves downloading a whole Swift install.
Outside of this, there is an issue with the current template where there is a clash between the vscode user and the ubuntu user setup inside the swift docker image for 6.1 and 6.2. There was a PR posted to resolve this but it never got merged as I wasnât confident it was the best solution. Someone who had better knowledge of container building might be better placed.
Finally if the template is to move to the swiftlang org we need to update VSCode to find it there. This involves updating a config file in a repo I canât remember offhand.
Following up on this - the PR I have up is just the devContainer image declaration, but I did manage to wrangle the ubuntu vs. vscode user setup in the container build, and the PR up today has the equivalent of the swift:latest docker base image, but uses Swiftly to have that installed, so it should work quite smoothly with the VS Code for Swift extension in changing toolchains (it has in my test/experiments using the setup).
The downside of this setup is that the first time you use this devContainer, VS Code will need to wrangle building it - which can take a bit (~3-5 min in my laptop experiments), but afterwards is seamless and happy.
If anyone (not just Adam) can help illuminate these details - I'd really appreciate it.
I switched the PR from a draft to up for review - would be lovely to have other folks take a look and try it out, see what they think if you're interested.
I would much prefer we donât use swiftly to install swift on devcontainer creation, or at least we donât use if we arenât creating prebuilt images. Using swiftly means every time we use a new devcontainer we have to download over 1GB of data, instead of downloading a swift docker container once.
An alternative is to create a devcontainer feature that uses swiftly to install swift. Then create prebuilt images that include this feature. The devcontainer template that references the prebuilt images. This is how Microsoft has set it up to work for other languages. There are three repositories in the devcontainers ¡ GitHub organisation features, images and templates that include each stage of this.
(Thank you for the reminder links of the upstream devContainer registry pieces. Its been a moment since I made those features, and completely lost track of where that was)
I can definitely see your point about not wanting to take the hit to build the whole darn image each time - both in terms of delay and in downloading data that it requires.
An accommodation for this might be to provide a pre-made container that creates an installation using Swiftly with the default, latest Swift version available by default. From the PR side of this, it would potentially be easy to reference a docker image that the Swift CI systems already create - and it would be pretty direct to make a developer-focused image that starts with Swiftly installed and potentially offer it.
@mishal_shah is that something we might consider? It adds an additional variation into the collection already in GitHub - swiftlang/swift-docker: Docker Official Image packaging for Swift, but I'd be happy to assemble a PR to create a container that's using Swiftly, sort of explicitly to support the .devContainer (or any other container-based development) workflow.
I see value in having a devContainer image that includes Swiftly, to work with the features in the VS Code Swift extension that can leverage that tooling to make it easy to switch toolchains.