Open dslijepcevic opened 3 years ago
There is "initializeCommand"
, we would then have to reread the devcontainer.json to pick up any changes (we currently don't).
There is
"initializeCommand"
, we would then have to reread the devcontainer.json to pick up any changes (we currently don't).
If I understood you correctly, you mean to have a self-modifying .devcontainer.json
? That would probably not be the best practice since this file is usually stored in a repo, and besides, current initializeCommand
already has a major design flaw that requires hacking around. Maybe something like this:
"linux": {
"runArgsGeneratorCommand": "echo -e '--arg\nvalue'"
}
where the generator would then write run args to stdout, each one on a separate line if you don't want to deal with the quotes. Or even better, you could introduce a similar dynamic envFileGenerator
that would produce VAR=VALUE
pairs for the container and standard runArgs
(and even docker-compose
) to consume.
Currently the whole system is pretty much locked down for any non-static content. Even with docker-compose.yml
where you can specify multiple compose files, you are not able to generate the dynamic ones in a temporary directory via initializeCommand
rather than poluting the source/repo folder because it is not possible to reference /tmp
/$TMPDIR
/%TEMP%
/workspaceHash
in a portable way.
You could add --env-file
to runArgs
for a file you generate in initializeCommand
. Would that work? (It sounds like you mainly need environment variables.)
No, that would not work for mounting an extra volume based on user's environment, for example. This information needs to be passed directly to docker run
.
Also, currently there is no clean way for initializeCommand
to generate a file in platform's temporary directory and then to actually refer to that file path in a portable way in runArgs
or docker-compose.yml
. VSCode lacks some pre-defined variables like ${hostOS}
, ${tmpDir}
, ${workspaceHash}
, etc. You can only leave a mess in the project directory which is what I'd like to avoid if possible.
You could add that file to .gitignore
. What is the extra volume being used for?
One of them is for user's customization of the box itself, we use the same for Vagrant and a dev container. We don't use git or dotfiles repository. Another volume is for some optional app-specific data that the user can mount, if available.
You can specify additional mounts with the "mounts"
property and there are a few variables (${var}
) you can use to make this more dynamic: https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_variables-in-devcontainerjson
Unfortunately, that's not going to work as we need more complex logic for this than a simple variable replacement. Also, mounts
cannot reference any newly calculated dynamic value from the environment and there is no way to specify a "null" volume mount in more complex cases -- docker will report an error. Another issue with this approach is that VSCode cannot provide a default value (e.g. ${localEnv:VARIABLE:-defaultValue}
) if user's environment variable is not set! To me this seems like a really useful feature and if you do a google search you'll see than an astounding number of people is asking for the same thing.
What if we added a "createCommand"
property with which you can implement your own docker run
call? I haven't thought it through entirely, but it would likely need to handle the case where the container already exists (and might be stopped) and would have to print the container id to its stdout as the result.
Hmm, I think that approach would be an overly complicated way to pass a few dynamic args to docker run
. Beside making most of the content of .devcontainer.json
irrelevant, for automatic start/stop of a container to work seamlessly like before the user would probably need to pass all of these manually:
docker run -a STDOUT -a STDERR -l vsch.quality=stable -l vsch.remote.devPort=0 -l vsch.local.folder=\\wsl$\Ubuntu\proj\test ...
I believe that just making runArgs
dynamic in a way similar to what I previously proposed would be simpler. E.g. if runArgs
is given as a string, it specifies a shell command to run to get the arguments on stdout, one argument per line. As simple as that. And you add windows
, linux
and osx
overrides for it, like VSCode tasks do so container can be created portably.
@chrmarti How about something like this?
{
"initializeCommand": [ "${localWorkspaceFolder}/generateArgsFile.sh" ],
"linux": { // override
"initializeCommand": "echo -e '--network\nhost' >${localWorkspaceFolder}/.args",
}
// either static or from file
// "runArgs": [ "--arg", "value" ],
"runArgsFile": "${localWorkspaceFolder}/.args",
...
}
It's using existing initializeCommand
(albeit with new platform overloads) and seems more elegant than previous proposals. Input file format can be whatever, e.g. json array, yaml, shell-style quoted args, one arg per line, etc.
What if we added a
"createCommand"
property with which you can implement your owndocker run
call? I haven't thought it through entirely, but it would likely need to handle the case where the container already exists (and might be stopped) and would have to print the container id to its stdout as the result.
@chrmarti Actually, on second thought, I like your idea. However, I'd expect once the container is created for extension to pick it up and run the exact same commands on it like it would normally do. Extension would perform all checks and call this method only if container does not already exist. Also, since Docker does not allow setting of metadata after container creation, there would have to be a way to pass metadata that the extension itself requires for operation to createCommand
and, ultimately, to docker run
. To keep things simple, if createCommand
is defined only a subset of devcontainer.json
properties would be available to the user (e.g. no need for build
or runArgs
, but workspaceFolder
or containerUser
can be specified, etc.).
Where was this left? I could really use this feature. My specific use case is developing for a USB peripheral in a dev container. Right now my only 2 options are to update the --device
option every time I reconnect the device, or to use --privileged
. Privileged is not preferred for a variety of well documented reasons. I have a command shell script that can look up a device by its name and returns the absolute path to the device. I only need a way to use it through vscode now.
+1
Any progress? We would also like to see the ability to dynamically generate runArgs
Any news on this feature request? Is something been done?
Should It be possible, at least, that VSCode interpolates the environment variables in runArgs before passing the args to docker run?
For example, I want to use:
"runArgs": [
// GPU support (Direct Rendering Manager)
"--device",
"${DRI_DEVICE:-/dev/null}:/dev/dri"
],
that generates:
docker run --device ${DRI_DEVICE:-/dev/null}:/dev/dri ...
that ends with error:
docker: bad mode specified: /dev/dri.
as ${DRI_DEVICE:-/dev/null}
is not interpolated (to DRI_DEVICE value or /dev/null if DRI_DEVICE env variable is not defined).
I also tried with
"runArgs": [
// GPU support (Direct Rendering Manager)
"--device",
"$(echo ${DRI_DEVICE:-/dev/null}):/dev/dri"
],
hopping that it is sent directly to the command line but no luck, the '$(echo ${DRI_DEVICE:-/dev/null})' is not evaluated.
Looks like this is related to the way the runArgs are passed as the generated command works as expected if manually run:
docker run --device $(echo ${DRI_DEVICE:-/dev/null}):/dev/dri ...
@rubensa You can use ${localEnv: DRI_DEVICE:/dev/null}
.
It is quite annoying to request to devs to comment-uncomment multiple sections every time they need to switch from CPU to GPU:
https://github.com/keras-team/keras-cv/pull/946 https://github.com/airo-ugent/airo-ros/issues/17
I'm looking to dynamically enable a passthrough serial device if its plugged in. Since docker will fail to run if you specify a device that doesnt exist, I need to check if the device first exists, then add the device to the runsArgs if it does. Sounds like this would be required for something like that.
In our case, for development a serial device is only needed if dealing with hardware. Might not always have a serial USB plugged in or even need one, so to have to have one plugged in just for the container to boot is not preferred.
Could you somehow support a way of building and passing dynamic arguments to the docker run command? We currently only have
runArgs
array indevcontainer.json
that is static in nature and not suitable for any sort of scripting. One use case could be, for example, to mount some extra volumes conditionally while keeping all the nice automatic devcontainer infrastructure that the remote extension has to offer. It'd be enough just to include a shell call somewhere. For example, you could introduce a string version ofrunArgs
that would be included verbatim in the default docker run command and then the entire command would be executed by the shell. Or you could introduce arunCommand
override with some pre-defined variables that users would then include in the command they specify. You could also support variables like${workspaceFolder}
inremote.containers.dockerPath
so that we can hack our way through :) Thanks