microsoft/vscode-remote-release

Allow additional build flags when building a container

marchingphoenix opened this issue ยท 51 comments

When building a devcontainer from dockerfile it will be useful to expose out additional docker build args that can be used when the container is created.
This can be done either by direct linking of these commands to the build property in the .devcontainer.json or via a catch-all array like build.command_flags: ["--network=host", "--compress"] etc

Example, a dockerfile is installing packages from an internal repository but your machine is on a vpn. Would need to pass --network=host to the build command to ensure that traversal happens correctly on Linux hosts.

Any word on when this might get added? We work in Amazon Workspaces Linux instances and in order to build/run Docker images/containers you need to pass --network host to allow the running container to access the network. There is already a runArgs that allows passing Docker run options there also needs to be a buildOpts to allow passing docker build options

I can work around this by building the container outside vscode and then open my devcontainer project in vscode. I then use the "runArgs": ["--network=host"]. This is less than optimal.

We are trying to make this a standard for projects we support but without this it is difficult.

In my case I would like to use --cache-from repo/devcontainer:cache as my devcontainer takes around 30 minutes to build, so I can prebuild it in CI and let the VSCode leverage the build cache.

For some cases (such as mine), the following workaround can be useful:

// pre build image to leverage --cache-from
"initializeCommand": [
  "docker",
  "build",
  "--target=devcontainer",
  "--cache-from=armdocker.rnd.ericsson.se/proj-river/cicd-devcontainer",
  "."
],

This will build the image the way I want, and later when VS Code tries to build it, it will be already cached and will be almost instantaneous.

Hello,
any update on this ticket ? we really need this feature to be able to use --network=host.

Regards

Another very important use-case I don't see mentioned above is that this feature is needed in order to use docker "build --ssh=default".

This is used to allow the host ssh-agent to sign for build commands (such as pulling from a private github repository using ssh).

And since I have the docker buildx plugin I cannot run it since I have to pass --load argument for the image to be loaded into docker locally.

--load is implicit, unless you are not using the native/default builder.

docker buildx use default

--load is implicit, unless you are not using the native/default builder.

docker buildx use default

I am using this emulator (https://github.com/tonistiigi/binfmt), does that makes --load not implicit?

does that makes --load not implicit?

Yes

0Grit commented

Another very important use-case I don't see mentioned above is that this feature is needed in order to use docker "build --ssh=default".

This is used to allow the host ssh-agent to sign for build commands (such as pulling from a private github repository using ssh).

Yes, this has been blocking me for years.

I am in Japan and the apt command for Ubuntu Docker images is very slow.
This is due to the distance from Japan to archive.ubuntu.com, which is greatly improved by using a mirror server in Japan (jp.archive.ubuntu.com) with option --add-host=archive.ubuntu.com:160.26.2.187 set.

When building from Remote-Containers, this technique cannot be used and builds take a long time...

I'm not sure if this was said here or not, but Remote Containers supports docker-compose. It means you can leverage whatever docker-compose let you do in the build. Even if it's for a single container.

Was curious if theres been any progress on this? I'm basically unable to use the built-in .devcontainer system due to not being able to pass the --ssh default flag on build. Something like a

"buildOptions": ["--ssh default"]

would be incredibly helpful.

For some cases (such as mine), the following workaround can be useful

Thanks!

	"initializeCommand": [
		"docker", "build", "--network=host", ".devcontainer"
	],

worked for me.

Wondering if @Chuxel, @bamurtaugh or if @chrmarti would have an update on this? The feature is quite useful indeed. Anyone building images that require cloning from private repositories would be really well served with this option.

Also, does someone has a working workaround to use ssh agent based authentication when building a container image based on devcontainer.json ? I don't immediately understand what @Trass3r is doing.

As of today, using the pre-release version of the plugin (don't know if available on the release version),
there is a new build attribute in devontainer.json with new sub-attributes like args, cacheFrom and target:

"build": {
	"args": {
		"BUILD_ARG1": "value1",
		"BUILD_ARG2": "value2"
	}
},

@LudovicTOURMAN I've just retested using Remote - Containers v0.241.1 Pre-Release version.

My devcontainer.json looks like:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.234.0/containers/docker-existing-dockerfile
{
	"name": "Quark Dev Environment",
    [...]
	"build": {
		"args": { "--ssh": "default" }
    }
}

The container creation fails, see log below:

[556 ms] Setting up container for folder or workspace: /root/quark
[559 ms] Start: Check Docker is running
[...]
[1472 ms] Start: Run: docker ps -q -a --filter label=devcontainer.local_folder=\\wsl$\Ubuntu-vscode-quark\root\quark
[1573 ms] Start: Run: docker buildx build --load --build-arg BUILDKIT_INLINE_CACHE=1 -f /root/quark/Dockerfile -t vsc-quark-91dd4a23334f30b21c17b16e0490c8cf --build-arg --ssh=default /root/quark
[6309 ms] Error: Command failed: docker buildx build --load --build-arg BUILDKIT_INLINE_CACHE=1 -f /root/quark/Dockerfile -t vsc-quark-91dd4a23334f30b21c17b16e0490c8cf --build-arg --ssh=default /root/quark

The offending part is --build-arg --ssh=default

I was expecting something on the lines of:
docker build --ssh default .

Which actually works fine for me when the container creation is launched directly from the WSLs command line. Any hints ?

It looks amazing that 53 upvotes of this issue in 2 years changed nothing. Even when there is a myriad of problems that it could potentially solve ๐Ÿ˜”. It looks there was a time when this feature worked.

๐Ÿ‘‰ Any update on this?

For the people who used initializeCommand as a workaround. It seems like SSH_AUTH_SOCK is not set while initializeCommand is run on a remote ssh instance. Which means that the

"initializeCommand": ["docker", "build", "--ssh=default", "-f", ".devcontainer/Dockerfile", "."]

workaround doesn't work for me. Note, I'm agent forwarding with AgentForward yes via ssh config. Does anyone know how to access the ssh agent in initializeCommand?

I've been struggling with this today and as far as I can tell, build.args doesn't seem to parse environment variables.

VSCode has "terminal.integrated.inheritEnv": true, I have variables defined and exported in my .zshenv and .zshrc files (macOS), and I have them set in my devcontainer.json as such:

"build": {
	"args": {
		"VAR1": "${VAR1}",
		"VAR2": "${VAR2}"
	}
}

Reopen in Container fails every time with the build failing due to the environment variables not being passed through. Running a docker build from the integrated shell in VSCode works as expected. Am I missing something here or this broken?

My suggestion for you is to use docker compose instead.

@BryanAPEX You can use ${localEnv:VAR1} for using a local variable in the devcontainer.json.

@BryanAPEX You can use ${localEnv:VAR1} for using a local variable in the devcontainer.json.

For some reason, I thought that syntax only applied to working on Windows with PowerShell, but had actually tried it earlier as a test with no success. Something else must have been misconfigured at that point as I just tried it again with fresh eyes and it worked. Embarrassing, but I'll leave this here in hopes it helps anyone else going through this with the same bad assumption. Thank you!

For some cases (such as mine), the following workaround can be useful:

// pre build image to leverage --cache-from
"initializeCommand": [
  "docker",
  "build",
  "--target=devcontainer",
  "--cache-from=armdocker.rnd.ericsson.se/proj-river/cicd-devcontainer",
  "."
],

This will build the image the way I want, and later when VS Code tries to build it, it will be already cached and will be almost instantaneous.

Building on this suggestion, we can also use image:

 "initializeCommand": "docker build --network host --tag my-image .",
  "image": "my-image"

This works pretty nicely and requires not so much boilerplate.
Should you have a lot of arguments, you can save building command as a script and call that.

Looking to leverage the --secret flag to mount some credentials at build, doesn't seem to be supported currently (?)

I am trying to use a BLAH_TOKEN in my build environment, but can't seem to get it to work via anything I've googled or found so far.

My suggestion for you is to use docker compose instead.

Quoting again my own suggestion. ;)

dreSte commented

OMG nearly 3 years open
Its a Problem....
I need to pass environment variables to the build for authentication.

Roemer commented

This is seriously limiting us. It is not possible to build a dev-container because we need to access a proxy that is running on the host. We can neither pass --network=host nor --add-host=host.docker.internal:host-gateway when building a container.

Edit: Finally I got the mentioned workaround with initializeCommand working. What they all forgot to mention is that the whole build part needs to be removed and instead, the custom build should tag the image and that tag should be used in image.
Example:

{
	"name": "Debian",
	"initializeCommand": [
		"docker",
		"build",
		"--network=host",
		"--tag=my-project-dev",
		".devcontainer"
	],
	"image": "my-project-dev",
	...
}

#3545 (comment)

As of today, using the pre-release version of the plugin (don't know if available on the release version), there is a new build attribute in devontainer.json with new sub-attributes like args, cacheFrom and target:

"build": {
	"args": {
		"BUILD_ARG1": "value1",
		"BUILD_ARG2": "value2"
	}
},
{
    "build": {
		"dockerfile": "../Dockerfile", 
		"args": {
			"BUILD_ARG_KEY":"BUILD_ARG_VALUE"
		}
    }
}

Field "args" worked for me

Field "args" worked for me

AFAIK that's for docker build --build-arg only, not for any arbitrary option.

Field "args" worked for me

AFAIK that's for docker build --build-arg only, not for any arbitrary option.

Sorry, I didn't read the entire conversation, just replied to "Allow additional build flags when building a container" topic (the main request from marchingphoenix).

Roemer commented

As this is something that is missing in the dev-container specification itself, I started a feature discussion regarding this there: devcontainers/spec#301

appdoo commented

Sometimes it is necessary to pass secrets to the dev container build. While I learned that we can use something like ${localEnv:VAR1}, which is great, it is not sufficient from my point of view.

Is it possible to ask the user for a specific argument, such as:

  1. Specify ${userArg:VAR1} in the devcontainer,json.
  2. Before starting the build, ask the user to pass the value for e.g. VAR1*.
  3. Start the Docker build

*) Ask the user if the value should be stored in a local login store (optional second version).

Use case:
I have a Docker file from a customer that contains vcpkg in a cmake script to pull some libraries from an Azure repository. While the git repo is pulled with a credential manager, vcpkg only works with a pat (personal access token).

While this is a specific use case, it can also apply to many other use cases where secrets should only be stored in a secure repository.

For years I have been using docker compose instead. You can do that too, no?

OMG nearly 3 years open Its a Problem.... I need to pass environment variables to the build for authentication.
How many more years until this has been implemented? Right now this is the last hurdle we have in my organisation to fully using vs code development containers.

For anyone having this trouble I would suggest to use a post-install script called after the build command that allows for user authentication inside docker. ๐Ÿ‘Œ that's how we "workarounded" the issue and works like a charm.

Roemer commented

I added a proposal devcontainers/spec#328 and also the spec change devcontainers/spec#324
Feel free to upvote them to give more visibility.

For years I have been using docker compose instead. You can do that too, no?

@felipecrs Thanks but it's the 3rd time you mention this. This feature should exist without needing to use Docker Compose.

Yes, for sure. I'm not denying that. I was just trying to provide an alternate solution so that users don't need to wait on this to be implemented.

The proposal devcontainers/spec#328 is merged. ๐Ÿ‘

In progress: devcontainers/cli#85 and devcontainers/spec#324.

Available in Dev Containers 0.333.0-pre-release.

This is great being able to specify build arguments now!

Is there a way the user can specify those build arguments (or a script can be run on the host machine)?

I'm thinking something like this.

{
        "name": "Code Build Environment",
        "dockerFile": "/usr/share/dpkg-buildenv/Dockerfile",
        "build": {
                "args": {
                        "DISTRIBUTION" : "${inputs:distribution}"
                }
        },
	"inputs": [
		{
		  "id": "distribution",
		  "type":"promptString",
		  "description": "which base os to use",
		  "default": "debian:12"
		}
	],
}

Using "${inputs:XX}" works in VSCode launch.json however it looks like it isn't support for .devcontainers.json.

@aidan-gallagher Correct, that is not supported at the moment. Seeing your feature request for this at #9397. Thanks.

@aidan-gallagher +1, would love to see this implemented.

Awesome, thanks! Is it possible @chrmarti to also include Docker's official buildx bake tool as well? that would allow passing in a larger build spec file (instead of lots of cli flags)
devcontainers/spec#311

I just tried it with the pre-release of 0.333.0 with the following build:

"build": {
      "dockerfile": "Dockerfile",
      "options": [
        "--add-host=host.docker.internal:host-gateway"
      ]
    },

but I don't see this added to the docker build command in the log and also the hostname cannot be found in the docker container. Am I missing something?

@Roemer That should indeed work. Could you open an issue with the log from rebuilding the container? Thanks!

@c-ameron That is not supported by the feature implemented here. devcontainers/spec#311 is a good place to track it. Thanks!

build: {options: [...]} does NOT work in the latest prerelease version of extension 0.337 and devcontainer cli 0.55

@pmunin Could you open an issue with the log included? (F1 > Dev Containers: Show Container Log)

@chrmarti as i mentioned in that other comment - I discovered after reloading the window that my installed prerelease version was not 0.337, but 0.330 instead which is max available for standard vscode build:
image

So seems like I need VS Code Insider to try it, which I'm not ready to install yet, hope it's ok. But I cannot wait this feature to be released. This --ssh default is an absolute MUST HAVE for companies that have their private repos/packages installed during building an image that require authentication (in my case it's private homebrew packages)

The current pre-release versions of the Dev Containers extension also adopt changes from the upcoming VS Code 1.86 which is why they require VS Code Insiders at the moment. VS Code 1.86 is expected to release some time next week at which point we will also release a new stable version of the Dev Containers extension.