Vscode-remote-release: [Dev Container] allow passing another user to "docker-compose exec" command when connecting to a container

Created on 31 May 2019  路  31Comments  路  Source: microsoft/vscode-remote-release

Currently, when I connect VSCode to my laradock worspace container, it seems to run just docker-compose exec workspace .... However, it would be convenient to my work if I could pass docker-compose the user I want to exec within the container, namely: docker-compose exec -u laradock workspace ...

It would be valuable if there was an option in devcontainer.json to speficy the user to pass to docker-compose exec command.

containers feature-request

Most helpful comment

... We lookup the user on the image, you can set that with USER laradock in your Dockerfile.

... We use docker exec which by default uses the last USER from the Dockerfile.

This is not enough.

The __user associated with container application__ and the __user who owns the files being used and edited__ are different entities. So, there must be settings that allow you explicitly set the name/UID of the user to connect to the container.

Particularly, there should be default user setting for the option "Attaching to running containers":

docker exec -u USER ...  

Without such settings the extension "Remote-Containers" is essentially incomplete.

All 31 comments

We lookup the user on the image, you can set that with USER laradock in your Dockerfile.

As you can see in laradock workspace default Dockerfile, it alternates between USER root (for running system-wide tasks like apt-get install) and USER laradock (for running user-side tasks like composer install) while building image. How does vscode-remote extension decide about which user to choose in image?

We use docker exec which by default uses the last USER from the Dockerfile.

Unfortunately, appending USER laradock to laradock workspace Dockerfile didn't work for me, due to issue https://github.com/laradock/laradock/issues/1889, fixed in PR https://github.com/laradock/laradock/pull/1893.

Maybe @lanphan / @bestlong could provide more info here.

... We lookup the user on the image, you can set that with USER laradock in your Dockerfile.

... We use docker exec which by default uses the last USER from the Dockerfile.

This is not enough.

The __user associated with container application__ and the __user who owns the files being used and edited__ are different entities. So, there must be settings that allow you explicitly set the name/UID of the user to connect to the container.

Particularly, there should be default user setting for the option "Attaching to running containers":

docker exec -u USER ...  

Without such settings the extension "Remote-Containers" is essentially incomplete.

@chrmarti It looks it's possible to change the exec USER through runArgs of .devcontainer.json in the case of docker however this isn't supported in runArgs when doing docker-compose.

Since docker exec and docker-compose exec both support the -u / --user flag it would be great if we could use runArgs to specify the USER when using docker-compose

It looks it's possible to change the exec USER through runArgs of .devcontainer.json in the case of docker ...

runArgs setting in .devcontainer.json is for docker run - not for docker exec.

In my use case containers are started via special bash script, so i can't use .devcontainer.json at all. I just need to attach to the running container as certain user.

For example, i start PHP-FPM in the container as user www-data, but i run PHP Composer and edit mounted files in this container as another user.

@jrseliga docker-compose can be configured to use a different user in the docker-compose.yml: https://docs.docker.com/compose/compose-file/#domainname-hostname-ipc-mac_address-privileged-read_only-shm_size-stdin_open-tty-user-working_dir

@vlad-vinogradov Have you tried setting overrideCommand to false in the devcontainer.json (this will make it use the CMD from the Dockerfile, works for the single container case)?

Let's explain a little more on particular example:

Suppose we use docker containers as a runtime environment for developing and testing web applications. At the developer鈥檚 workstations we run in containers the set of application services we need (web server, database, etc. - the same set as in the production-environment) and these services and tools handle persistent source code files that are mounted in bind-mode to the appropriate containers.

Source code files can be modified both in the containers and in the host system, so all container's images have additional DEV-USER, whose UID & GID match the host user's UID & GID. It is the user that we connect to the containers via docker exec -u DEV-USER ..., when we need to perform some actions and modify source code in the container environment (where some application service is already running).

In this use case USER settings in the Dockerfile and in docker-compose.yml are used to run container's ENTRYPOINT/CMD (web-server, database, etc.), but container-side VS Code Server must be running as different DEV-USER.

So, we really need from Remote-Containers the following base features (with appropriate settings):

  • install/upgrade and run container-side VS Code Server as some DEV-USER via docker exec -u DEV-USER ... (and re-using previously installed software on new sessions - it seems already supported);

  • open remote folders and run terminal sessions in VS Code as some DEV-USER;

Other features - such as selecting the user by default (based on Dockerfile or docker-compose.yml) and launching containers based on .devcontainer.json - must be kind of add-ons above the base features, which simplifies the use of the extension in some common use cases.

@lbssousa
Hi, relating to workspace container in laradock, this image is based on phusion/baseimage (https://github.com/laradock/workspace), and its default CMD '/sbin/my_init' requires root user to execute, that's why you will get error if setting user laradock at the end of workspace image.

Thanks for pointing me, I'm using vscode to develop my laravel project using laradock too :), but just use some basic functions of vscode. Very interested in how to setup and take advantage of vscode to execute docker commands and whole things.

@chrmarti ... (see above)
The extension should allow working in the running container concurrently with the application service which is started via ENTRYPOINT/CMD in the same container.

Launching containers and everything related is an auxiliary option, which is far from being necessary for all users and which may not be used at all.

@chrmarti the user the container is defined to run as is correct and shouldn't be changed. Just need to exec into the container as a specific user, effectively the explanation @vlad-vinogradov provided.

Got it, we are tracking this as a feature request.

Any progress?

Does there exist a workaround for this problem? I added "overrideCommand": false to devcontainer.json but nothing changed. Is running container looking into this file?

Just to add a use case here: this is also important for containers that start as root to perform initialization but drop down to a different user to run the actual application.

In this scenario vscode will attach as root, which is undesirable. It's not just about vscode having way too much privilege inside the container, it messes up file ownership as well.

Being able to start a container via existing scripts but still being able to configure how vscode attaches to it is the number one remaining feature I need to be able to use vscode with containers.

@FilatovArtm for laradock specific case, a workaround I'm using here is enabling SSH server in workspace container and accessing it via Remote SSH rather than Remote Containers extension.

@lbssousa @FilatovArtm @rvolgers Unlike the Docker CLI, Docker Compose has a way to override values by extending it with another compose file. You can add the "user" directive for the service in question in a separate Docker Compose file that "extends" your primary one. The same goes for overriding the command.

See https://code.visualstudio.com/docs/remote/containers#_extending-your-docker-compose-file-for-development

https://code.visualstudio.com/docs/remote/containers-advanced#_adding-a-nonroot-user-to-your-dev-container

Any devcontainer.json property we added would effectively be doing this since you cannot override as much from the command line with Docker Compose as you can from the Docker CLI (particularly from docker-compose up which spins up the containers).

@Chuxel
And what if we cannot change/override the main user (service user) of the container? - it suits us and should be just that! (you have read the posts very inattentively).

Unfortunately, when developing this extension, the author made a significant mistake at the initial stage of design.

@Chuxel AFAIK, the "user" directive in docker-compose.yml makes docker-compose pass this user to docker run command, not docker exec (which is the object of this issue). Docker-compose current file reference has no directive that can be used to customize docker-compose exec command line.

To be clear: the subject of this issue is that VSCode Remote Dev Container should provide a way to start a container (docker run or docker-compose up) as its main user (normally root) and then connect to it (docker exec bash or docker-compose exec bash) as another user (e.g. laradock).

Why is this needed? For example, laradock workspace container must be started as root, but we wish to connect to it as laradock user.

@Chuxel ... In many containers, CMD/ENTRYPOINT command is just some bash-script that __must be executed as root__...

@lbssousa Interesting, yeah I had expected it would use the user from the compose file, but if not that makes sense. I can also see that in the scenario where you're not overriding the entry point, you could get into a situation where you need to leave this as root - thanks for clarifying.

One question, however: I'd like to bubble this up one level and step aside from the solution and talk a bit about what needs to be done. Am I correct that the goal would be to have all VS Code operations run as a different user than the default? Or just certain ones?

The reason I'm asking some of these questions is we've been talking about whether devcontainer.json needs a first class concept of a user. Because of bind mounts on Linux, there's challenges that also result from docker run starting with root (even w/o Docker Compose). We've been talking about the idea of needing a first-class user concept, possibly with some automation behind it (e.g. for UID/GIDs).

If I'm understanding correctly, what we would need to support here abstractly is specifying two separate things:

  1. The user that starts the container
  2. The user VS Code remote runs as

In many cases, these two would be the same. In some, like this one, they would be different.

Does that accurately summarize the need?

I worry that just adding exec support (e.g. execArgs) may not cover things if we use an alternate approach to spin up VS Code server over time. There's a general trend of user issues we need to think through - I want to be sure we've got the specifics of this one in mind.

Edit: removed a lot of text here as I misremembered some of the context of this ticket. Carry on.

@Chuxel Yes, you got the point. When using VSCode Remote Dev Container, we have the following scenario:

  1. VSCode starts the container (if not already running) via docker run or docker-compose up. It's normally done using the container default user (usually root). For some cases (e.g. laradock workspace container) this user should be left untouched, or the container may fail to start.

  2. VSCode attaches to the container via docker exec bash or docker-compose exec bash. Here lies the subject of this issue: we wish to be able to pass argument -u <another-user> to docker exec here, so we can attach to the container as an user other than the one who has started the container. Taking the laradock workspace container example, we wish to attach to it as user laradock, although this container has been started as root.

In my particular case I want vscode packages to look at env variables of another user, not root.

@lbssousa Makes sense.

@rvolgers I'd been wondering if there were two subtlety different conversations going on - you summed it up nicely. There's the "config" flow we have now and this needs to be covered there as @lbssousa mentions, then there's the straight "attach" flow where VS Code doesn't manage the containers.

That scenario is pretty common since it's probably the easiest way to get started if you already have a Docker-based dev setup. ... This issue is specifically about connecting to a container that is already running.

Agree entirely. There's actually a second feature request (#633) that is all about effectively devcontainer.json-enabling the attach workflow. Beyond not being able to set the user, there's also having to reinstall extensions, expose ports, etc.

The Docker Compose flow allows you to attach to an already running container, which provides a workaround of sorts.

So to recap, the needs appear to be:

  • devcontainer.json flow:

    1. Allow you to specify the user that starts the container

    2. Allow you to specify the user that VS Code remote runs as

  • Attach flow:

    1. Allow you to specify an alternate user when attaching

    2. As an improvement, find a way to support devcontainer.json features to speed this up (which is #633).

@FilatovArtm To clarify, I assume you mean local env vars not env vars inside the container, correct? (You can already do this using Docker Compose files using ${env:VARNAME} in devcontainer.json, but there's no way to start the container with a different user today.)

In my use case containers start without the help of VSCode. For this purpose a special wrapper script is used for docker-compose up, which, depending on the current working directory,
selects the folder with the necessary settings and forms the necessary launch parameters (--project-name and etc). Something like vagrant up ...

So, only the second step is required (VSCode attaches to the container via docker exec bash ...) and some convenient procedure for selecting a user to attach to the container.

This is a feature I need badly to use vscode in an already running docker container.

By default when I connect to a running container vscode is in root user(same applies to attach shell).
The design of the vscode to have the ability to connect to any running container is AWESOME, but this missing feature really makes it impossible to use for people who just want to config user setting via -u in front of container id in the cmd.

The process of launching the docker could be complicated that people might already have a bash scripts. Rewriting all the configuration to the vscode devcontainer json file might not be a good solution.

Would love to have this feature.

I'm currently unable to use a lot of VS Code's features (integrated terminal, git staging, file creation), because all of these operations happen with the root user when connected to a container, ending up with the wrong permissions for files.

I already have a script for launching a container, so like to just use the "Connect to an existing container" rather than re-creating the entire script in a devcontainer.json

Thank you @lbssousa
This would be a super awesome feature for our setup. We have a shell script that starts a bunch of docker containers as root and then uses entry point script to setup a few things based on arguments passed to docker run and then does gosu -u <user> $@.
Currently, vscode attaches to the container as root user and messes up file permissions and git.
Any ETA on when this will be available?

Fixed with #1155. There is now a remoteUser property in the config file.

Was this page helpful?
0 / 5 - 0 ratings