devcontainers / devcontainers/spec

Universal image build and reuse semantics

Open
#74 0 comments 4 reactions 0 assignees View on GitHub
proposal
Dominant language
No language data
Stars
5.7k
Forks
496
PR merge metrics
No merged PRs in 30d

Description

As dev container features (#61) are introduced into the spec and related CLI and tools/services, pre-building an image that includes features using a `devcontainer.json` file becomes critically important. However, `devcontainer.json`'s semantics currently support referencing an image or a Dockerfile/Docker Compose file. This means that you end up needing two `devcontainer.json` files to pre-build: one for the pre-build, and one for actual use with the `image` reference. While this works, ideally, we could have one file that can be used in either case. Even better, ideally this would work with any orchestrator.

To resolve this, I'd propose we decouple the idea of the `build` section from orchestration and enable referencing an image name to act as the primary label for a build. This label is then what is used by default when doing the build (unless a different label is passed into the dev container CLI via the `--image-name` argument). The image name can then be referenced either in the devcontainer.json file, or in a Docker Compose file.

This could be enabled through the introduction of an `imageNames` property into the `build` section of devcontainer.json. If specified, the logic would be to do the following:

1. First try to pull the image referenced in the `image` property - if this works, use it.
2. If this fails, build it using the contents of the `build` property features, and give it the names specified under imageNames. Then use the image.
3. If a **rebuild** is fired, then would ignore any centrally pushed images and then build as described in (2). An argument passed into the dev container CLI can also signal this should happen.

For Docker Compose or other orchestrators, the logic would be the same, but the image reference would just be in the orchestration format instead. Consider these examples...

Single container example:

```json
{
"image": "image-name-from-build",
"build": {
"imageNames": [ "image-name-from-build" ],
"dockerfile": "Dockerfile"
},
"features": {
"ghcr.com/devcontainers/features/docker-in-docker": {}
}
}
```

Docker Compose:

devcontainer.json
```json
{
"dockerComposeFile": "docker-compose.yaml",
"service": "foo",
"workspaceFolder": "/workspace",
"build": {
"imageNames": [ "image-name-from-build" ],
"dockerfile": "Dockerfile"
},
"features": {
"ghcr.com/devcontainers/features/docker-in-docker": {}
}
}
```
Related docker-compose.yaml:
```yaml
#...
services:
foo:
image: image-name-from-build
#...
```

For cases where a base image is all that is needed beyond features, we could also allow for an `baseImage` property in the build section. e.g.,

```json
{
"image": "image-name-from-build",
"build": {
"imageNames": [ "image-name-from-build" ],
"baseImage": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu"
},
"features": {
"ghcr.com/devcontainers/features/docker-in-docker": {}
}
}
```

This also allows for pre-builds as we consider long term support for supporting orchestrator formats in the dev container spec that do not inherently have a supported way to first do a build before spinning up a container.

Support for multi-container scenarios here can be handled in a similar way, though likely we want to at least introduce an array syntax to devcontainer.json to encapsulate multiple container image builds where appropriate as discussed in #10. For example:

```json
[
{
"dockerComposeFile": "docker-compose.yaml",
"service": "foo1",
"workspaceFolder": "/workspace/foo1",
"build": {
"imageNames": [ "image-name-from-build-1" ],
"dockerfile": "foo/Dockerfile"
},
"features": {
"ghcr.com/devcontainers/features/docker-in-docker": {}
}
},
{
"dockerComposeFile": "docker-compose.yaml",
"service": "foo2",
"workspaceFolder": "/workspace/foo2",
"build": {
"imageNames": [ "image-name-from-build-2" ],
"dockerfile": "foo2/Dockerfile"
},
"features": {
"ghcr.com/devcontainers/features/node": {}
}
}
]
```

//cc @craiglpeters @chrmarti given we've had discussions along these lines to date. FYI @bamurtaugh @jkeech @alexdima

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.