Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to launch .devcontainer project from command line #2133

Open
AlJohri opened this issue Jan 8, 2020 · 46 comments
Open

Ability to launch .devcontainer project from command line #2133

AlJohri opened this issue Jan 8, 2020 · 46 comments
Labels
cli containers Issue in vscode-remote containers feature-request Request for new features or functionality

Comments

@AlJohri
Copy link

AlJohri commented Jan 8, 2020

This issue was closed last time with no resolution: #1084

How do I use the code CLI to launch into the devcontainer? I have a folder with a .devcontainer folder. Running code . prompts me to re-open as a devcontainer but I want to do it in one shot in my Makefile.

@hatchermarie2
Copy link

#2141

@egamma egamma added feature-request Request for new features or functionality containers Issue in vscode-remote containers cli labels Jan 15, 2020
@AlJohri
Copy link
Author

AlJohri commented Feb 3, 2020

I was able to sort of get it to work using the following invocation:

code --folder-uri vscode-remote://dev-container+2f55736572732f6a6f687269612f446576656c6f706d656e742f70726f71756573742d646f776e6c6f61646572/app

which I found by grepping through cat ~/Library/Application\ Support/Code/storage.json.

Unfortunately I can't find how to get the mapping of my folder to this random hash: 2f55736572732f6a6f687269612f446576656c6f706d656e742f70726f71756573742d646f776e6c6f61646572.

@bhack
Copy link

bhack commented Mar 16, 2020

I am also interested in this to support CI requests. See tensorflow/addons#1309 (comment) /cc @Chuxel

@ghost
Copy link

ghost commented Apr 23, 2020

Unfortunately I can't find how to get the mapping of my folder to this random hash: 2f55736572732f6a6f687269612f446576656c6f706d656e742f70726f71756573742d646f776e6c6f61646572.

actually that is your path represented as hex encoded. The upper string decodes to:
/Users/johria/Development/proquest-downloader

seems that splits the part outside and inside the container.

Fyi for attaching to existing containers on a remote docker host this snippet might help:

remote_description = json.dumps(
    {"containerName":"/containername","settings":{"host":"ssh://remote-host"}}
)

remote_uri = urlunparse(('vscode-remote', f'attached-container+{remote_description.encode("utf8").hex()}', '/path/inside/container', '', '', ''))
print(remote_uri)

I guess that should be most of the stuff one could need at some point. But since Microsoft did not document any of this. I expect this might be subject to change at any point.

@tschaub
Copy link

tschaub commented Nov 5, 2020

I'm finding that the "reopen in container" dialog is getting harder and harder to pin down. Recently when I open my project, I get enough other dialogs about things to do (use Pylance, install a linter, install a test framework) that the "reopen in container" dialog gets hidden until I dismiss some of the other dialogs.

The movie below shows how the dialog shows up initially and then gets hidden. It is also a bit unsettling to have another dialog/prompt immediately take its place after clicking the "reopen in container" button (but this is another issue).

jumpy-dialogs

@ghost
Copy link

ghost commented Nov 6, 2020

@tschaub I'd open a new issue for this. Cause it is unrelated to this issue here.
You can always see all notifications when clicking on the bell at the lower right corner of the application.
But I do agree that this is not a perfect user experience.

@takekazuomi
Copy link

takekazuomi commented Nov 13, 2020

I wrote a simple posh script. It works on the Windows side. It doesn't work run form wsl2. I don't know why.

$p = "\\wsl$\Ubuntu\home\takekazu\projects\hoge".ToCharArray() | %{$h=''}{$h += ('{0:x}' -f [int]$_)}{$h}
code --folder-uri "vscode-remote://dev-container+$p/workspaces/hoge"

@Yehonal
Copy link

Yehonal commented Dec 2, 2020

Based on @takekazuomi script I've managed to create single-line scripts that work on every environments.

Just replace <hostfolder> and <containerfolder> with your absolute paths
NOTE: you can use --file-uri instead of --folder-uri if you want to open a .code-workspace file instead of a folder

Powershell

$path = "<hostfolder>"; $p = $path.ToCharArray() | %{$h=''}{$h += ('{0:x}' -f [int]$_)}{$h}; code --folder-uri "vscode-remote://dev-container+$p/<containerfolder>"

Bash

path='<hostfolder>' && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}<containerfolder>"

WSL

For WSL you can just use the bash script above using the "\wsl$" prefixed path, however, if you really need to open the devcontainer within the WSL shell, then you can use this command:

/mnt/c/Windows/System32/cmd.exe /C path='<hostfolder>' && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}/<containerfolder>"

@ilyasotkov
Copy link

ilyasotkov commented Dec 5, 2020

@Yehonal Your Bash code is actually PowerShell, you probably made a mistake while copypasting.

For anyone interested in streamlining this as much as possible, I wrote a Python script that fully automates the process of assembling a --folder-uri for any directory containing .devcontainer.json or .devcontainer/devcontainer.json:

https://gist.github.com/ilyasotkov/27e77fd4a1a045bb17f5bcf7f20c1f2e

You may put the script to e.g. your user home directory, then run

code --folder-uri $(python3 ~/make_devcontainer_folder_uri.py)

or to avoid typing so many characters, create an executable script in your $PATH with these contents

#!/usr/bin/env bash

set -e

uri="$(python3 ~/make_devcontainer_folder_uri.py)"
code --folder-uri $uri

@Yehonal
Copy link

Yehonal commented Dec 5, 2020

Thanks! I've just fixed it

@yuusakuri
Copy link

If the GUI Open Folder in Container is used, the workspaceFolder written in devcontainer.json will be opened, but the above method must be specified separately.

@fardolieri
Copy link

Thanks to the work of you guys, I created a js script that opens my container and prints the vscode command (in color, why not). I then added it to my package.json script section for easy access

"container:shortcut": "node ./.devcontainer/open-container-workspace.js",

I thought I'd share, if it helps someone.

const { exec } = require('child_process');

const printColor = (...args) => console.log('\x1b[36m%s\x1b[0m', ...args);

const workingDirectory = process.cwd().replace(/\\/g, '/');

const hostWorkspaceFileHex = Buffer.from(
  `${workingDirectory}/my.code-workspace`,
).toString('hex');

const containerWorkspaceFile = '/workspace/myProject/my.code-workspace';

const command = `code --file-uri "vscode-remote://dev-container+${hostWorkspaceFileHex}${containerWorkspaceFile}"`;

printColor(command);
exec(command);

@benjaminwood
Copy link

benjaminwood commented Jun 14, 2021

Building off of @Yehonal's bash one-liner shared above ☝️

If you're using zsh, you can add this function to your ~/.zshrc.

function code-remote {
  p=$(printf "%s" "$1" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}/$2"
}

Usage: code-remote ~/local/path/to/project /remote/path/to/open

Example: code-remote ~/projects/foo/bar /app

Where ~/projects/foo/bar is the path to the project containing a .devcontainer folder and /app is the directory I want to open in the container.

Be sure to note what @Yehonal said about .devcontainer folder vs file:

NOTE: you can use --file-uri instead of --folder-uri if you want to open a .code-workspace file instead of a folder

@JPustkuchen
Copy link

JPustkuchen commented Jul 1, 2021

Hi all and thank you very much for the discussion. I tried several of the examples but couln't make it work. Perhaps someone can help.

I'd like to start vscode from a shell script attached to a running docker container NOT created by a .devcontainer definition. The container is selectable within the VSCode UI, but I can't make it work in bash.
Can I do that by container name? Is there any official documentation about these shell parameters?

For example:
code --remote dev-container+my_docker_containername_1

Sorry and thank you for your help!

EDIT: Finally I created a feature request as it seems there's no option to attach to a running container from CLI by anything else than the cryptic ascii ID, which is unusable for typical cases: #5278

@stuartleeks
Copy link

Hi all, I'm happy to report that there is a new CLI released as part of the 0.188.0 release (currently insiders only).

With this version, you can use the "Remote-Containers: Install devcontainer CLI" command to install the CLI. After that you can use devcontainer-insiders open [path] to launch a folder as a dev container without the prompt and reload experience. If the path argument is omitted it uses the current directory.

@metaskills
Copy link

Is there a way to install the devcontainer-insiders CLI via NPM?

@baruchiro
Copy link

I think this issue can be closed:

https://code.visualstudio.com/docs/remote/devcontainer-cli

@metaskills
Copy link

I think this issue can be closed

So when I install the latest NPM package there is no open command. Also, I still can not see in that page you listed how to install the insider version. I am assuming that one has the open command?

> devcontainer --help
devcontainer <command>

Commands:
  devcontainer build [path]  Build a dev container image

Options:
  -h, --help               Show help                                                                           [boolean]
      --disable-telemetry  Disable telemetry                                                  [boolean] [default: false]

@baruchiro
Copy link

@metaskills I installed it from within VSCode:

image

@Chuxel
Copy link
Member

Chuxel commented Oct 12, 2021

@baruchiro @metaskills When installing via the extension, open is available. This also makes sure that the version of the CLI is in sync with the currently installed version of the extension in stable / insiders (no functional differences).

When installing via npm (npm install -g @vscode/dev-container-cli), only build is available currently since its primary scenario was for CI where VS Code would typically not be present. This also would not automatically update as the extension updates if you installed it on the same machine VS Code was running in local scnearios.

Is there a scenario you had in mind for using the CLI from npm where open is needed? Certainly could be something we look at doing there too.

@davidpcaldwell
Copy link

Doesn't this already exist? https://code.visualstudio.com/docs/remote/devcontainer-cli

@BrumGB
Copy link

BrumGB commented Mar 17, 2022

Doesn't this already exist? https://code.visualstudio.com/docs/remote/devcontainer-cli

Great, thank you!

TLDR

  1. Install devcontainer CLI by running VS Code command palette - Remote-Containers: Install devcontainer CLI
  2. After installation from run command devcontainer open instead of code . from directory (Or alternatively devcontainer open *path*) to open the current folder in its corresponding dev container.

@onattech
Copy link

onattech commented Aug 11, 2022

Based on @takekazuomi script I've managed to create single-line scripts that work on every environments.

Just replace <hostfolder> and <containerfolder> with your absolute paths NOTE: you can use --file-uri instead of --folder-uri if you want to open a .code-workspace file instead of a folder

Powershell

$path = "<hostfolder>"; $p = $path.ToCharArray() | %{$h=''}{$h += ('{0:x}' -f [int]$_)}{$h}; code --folder-uri "vscode-remote://dev-container+$p/<containerfolder>"

Bash

path='<hostfolder>' && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}<containerfolder>"

WSL

For WSL you can just use the bash script above using the "\wsl$" prefixed path, however, if you really need to open the devcontainer within the WSL shell, then you can use this command:

/mnt/c/Windows/System32/cmd.exe /C path='<hostfolder>' && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}/<containerfolder>"

If you are using Docker desktop on Linux, path needs to be like below.

Bash

path='{"hostPath":"<hostfolder>","localDocker":false,"settings":{"context":"desktop-linux"}}' && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}<containerfolder>"

@jamesdbrock
Copy link

When I have a vscode devcontainer in a repository, I want the README instructions for how to use VS Code in the repository to go like this:

  1. Clone the repository.
  2. cd to the repository directory.
  3. Run code --devcontainer ..

If there’s a bunch of stuff about first “installing the devcontainer CLI” or “clicking on the Reopen in container pop-up window” then that ruins the simplicity of the instructions.

code should have that --devcontainer command-line argument.

@metaskills
Copy link

I did something like that here. Is that helpful to folks? https://github.com/customink/crypteia#dev-container-cli

@ruslanguns
Copy link

Also interested in this functionality as like the proposed one by @jamesdbrock

@brad-jones
Copy link

Came here because all of a sudden devcontainer open stopped working from inside WSL.
I'm guessing there is some issues with code moving off over into the new https://containers.dev project.
Or perhaps it's related to me no longer running docker desktop & just running the docker engine in my WSL distro.

Anyway thankfully I remembered using these little shell aliases back before the devcontaner CLI was actually a thing.
My current alias looks like this:

path="$(wslpath -w $PWD)" && p=$(printf "%s" "$path" | xxd -p) && code --folder-uri "vscode-remote://dev-container+${p//[[:space:]]/}/workspaces/$(basename $PWD)"

I don't think wslpath was a thing way back when but does the job nicely now.

also: #7189 & #7297 hopefully it's gets sorted soonish.

@CodeMan99
Copy link

CodeMan99 commented Feb 2, 2023

@brad-jones Thank you! I've been wanting use @devcontainers/cli instead of the one from $env:APPDATA\Code\User\globalStorage\ms-vscode-remote.remote-containers\cli-bin\.

I also made a bash function from your command with a refactor to read up to 256 bytes at a time, eliminating the need for whitespace manipulation. 😃

function devopen() {
    local workspace_folder="$(readlink -f "$1")"

    if [ -d "$workspace_folder" ]; then
        local wsl_path="$(wslpath -w "$workspace_folder")"
        local path_id=$(printf "%s" "$wsl_path" | xxd -ps -c 256)

        code --folder-uri "vscode-remote://dev-container%2B${path_id}/workspaces/$(basename "$workspace_folder")"
    else
        echo "Usage: devopen <directory>" 1>&2
        echo "" 1>&2
        echo "Error: Directory ${1@Q} does not exist" 1>&2
        false
    fi
}

@felipecrs
Copy link

Just to mention, the function above only works if the workspace folder is mounted at /workspaces/${workspaceFolderBasename}.

@CodeMan99
Copy link

CodeMan99 commented Feb 15, 2023

@felipecrs The value of workspaceFolder and workspaceMount can be read from the output of devcontainer read-configuration --workspace-folder .

$ devcontainer read-configuration --workspace-folder . | json
[4 ms] @devcontainers/cli 0.30.0. Node.js v18.12.1. linux 5.15.79.1-microsoft-standard-WSL2 x64.
{
  "configuration": {
    "name": "nodejs",
    "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18-bullseye",
    "remoteUser": "node",
    "configFilePath": {
      "$mid": 1,
      "path": "/home/user/dev/project/.devcontainer/devcontainer.json",
      "scheme": "vscode-fileHost"
    }
  },
  "workspace": {
    "workspaceFolder": "/workspaces/project",
    "workspaceMount": "type=bind,source=/home/user/dev/project,target=/workspaces/project"
  }
}

However, I do not have any devcontainer using something other than the default workspaceFolder. So I will not be writing that functionality.

@felipecrs
Copy link

That's a great suggestion, thank you!

@felipecrs
Copy link

Any ideas on what would be the URI for opening the devcontainer from within a SSH target?

felipecrs added a commit to felipecrs/dotfiles that referenced this issue Feb 20, 2023
felipecrs added a commit to felipecrs/dotfiles that referenced this issue Feb 23, 2023
However it does not work for devcontainers within SSH remotes.

Thanks to microsoft/vscode-remote-release#2133 (comment)
@felipecrs
Copy link

Any ideas on what would be the URI for opening the devcontainer from within a SSH target?

BTW, adding --remote=ssh-remote+<hostname> to the command does not help (thanks @CodeMan99 for the suggestion though).

@felipecrs
Copy link

Unfortunately I can't find how to get the mapping of my folder to this random hash: 2f55736572732f6a6f687269612f446576656c6f706d656e742f70726f71756573742d646f776e6c6f61646572.

actually that is your path represented as hex encoded. The upper string decodes to: /Users/johria/Development/proquest-downloader

seems that splits the part outside and inside the container.

Fyi for attaching to existing containers on a remote docker host this snippet might help:

remote_description = json.dumps(
    {"containerName":"/containername","settings":{"host":"ssh://remote-host"}}
)

remote_uri = urlunparse(('vscode-remote', f'attached-container+{remote_description.encode("utf8").hex()}', '/path/inside/container', '', '', ''))
print(remote_uri)

I guess that should be most of the stuff one could need at some point. But since Microsoft did not document any of this. I expect this might be subject to change at any point.

Actually I just realized this. I'll try to reimplement it in Bash.

@michidk
Copy link

michidk commented Mar 5, 2023

I am currently working on a CLI tool for this, written in Rust - since this is a functionality that I use multiple times a day and I want it to work absolutely reliably with some more features that I need.

You can try it out here: https://github.com/michidk/vscli (binaries available - also on cargo and homebrew)

Just do vscli or vscli <path> and it will open the current folder as devcontainer. Other options:

USAGE:
    vscli [FLAGS] [OPTIONS] <path> [args]...

FLAGS:
    -h, --help        Prints help information
    -i, --insiders    Whether to launch the insiders version of vscode
    -V, --version     Prints version information

OPTIONS:
    -b, --behaviour <behaviour>    Launch behaviour [default: detect]  [possible values: detect, force-container, force-
                                   classic]
    -v, --verbosity <verbosity>    The verbosity of the output [default: info]

ARGS:
    <path>       The path of the vscode project to open
    <args>...    Additional arguments to pass to vscode

It works similarly to the bash function from @CodeMan99 but with more error checking and functionality. Also, it reads the workspaceFolder from the .devcontainer/devcontainer.json file if set and uses that to start the devcontainer properly.

In future, I also want add a small TUI that will list the recently opened projects and allow to quickly launch them.

@jamesgecko
Copy link

Doesn't this already exist? https://code.visualstudio.com/docs/remote/devcontainer-cli

Great, thank you!

TLDR

  1. Install devcontainer CLI by running VS Code command palette - Remote-Containers: Install devcontainer CLI
  2. After installation from run command devcontainer open instead of code . from directory (Or alternatively devcontainer open *path*) to open the current folder in its corresponding dev container.

This has actually been pretty confusing for my team! Some of us installed the devcontainers CLI from the VSCode Remote-Containers extension. Some of us installed @devcontainers/cli via npm. They appear to be two versions of the same command with the same version number and different behavior. The npm one doesn't have open, and requires specifying --workspace-folder with build.

@AceHack
Copy link

AceHack commented May 9, 2023

When can I have devcontainer open? It will be very helpful.

@anphung
Copy link

anphung commented Aug 12, 2023

@AceHack devcontainer open is already available if you install devcontainer via VS Code UI command palette "Remote-Containers: Install devcontainer CLI"

Issue I have with --folder-uri is it keeps open "new" session. After open the same folder a few times, in vscode Remote explorer, it will shows many of that folder there.

I prefer to use --remote. Some change on top of benjaminwood's code-remote to use --remote:

function code_remote {
  p=$(printf "%s" "$1" | xxd -p) && code --remote "dev-container+${p//[[:space:]]/}" "$2"
}

Usage: code-remote ~/local/path/to/project /remote/path/to/open

Example: code-remote ~/projects/foo/bar /app

Where ~/projects/foo/bar is the path to the project containing a .devcontainer folder and /app is the directory you want to open in the container.

This can open both file and folder.

@felipecrs
Copy link

For some reason --remote doesn't work on Windows when launching from WSL. $2 somehow opens in the local VS Code window rather than opening with the devcontainer window.

@ecourreges-orange
Copy link

Thanks @brad-jones !
FWIW, here's a command that works from wsl2 without having to install yet another program like xxd, where hexdump is mostly preinstalled, also not using variable name "path" which potentially breaks you path (at least on zsh)

mypath="$(wslpath -w $PWD)" && p=$(printf "%s" "$mypath" | hexdump -v -e '/1 "%02x"') && code --folder-uri "vscode-remote://dev-container+${p}/workspaces/$(basename $PWD)"

or as an alias with proper escaping:

alias devcode='mypath="$(wslpath -w $PWD)" && p=$(printf "%s" "$mypath" | hexdump -v -e "/1 \"%02x\"") && code --folder-uri "vscode-remote://dev-container+${p}/workspaces/$(basename $PWD)"'

@felipecrs
Copy link

I was able to get it working for Remote SSH and Remote Tunnel, the secret is to add @ssh-remote+hostname or @tunnel+tunnelname after path_id.

Finding out such information is hard though. I am parsing the output of code --status | grep "^Remote:" to find it.

I put this all together in my code shim:

Originally posted by @felipecrs in #5957 (comment)

I built my own code wrapper that has a --devcontainer flag. Usage:

code --devcontainer ~/repos/myproject

It works for when VS Code is running on Linux, when running from within a remote SSH session (in or out of the vscode integrated terminal) and even within a remote tunnel session.

https://github.com/felipecrs/dotfiles/blob/master/home/dot_local/bin/executable_code
felipecrs/dotfiles#118

It is immensely useful and timesaving for me, so I expect other people to benefit from it too. Simply install it to your ~/.local/bin/code and you should be good to go.

WindowsTerminal_yAF02SU1CR.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cli containers Issue in vscode-remote containers feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests