Dotnet-docker: Ensure global tools dir is on the PATH

Created on 6 May 2018  路  20Comments  路  Source: dotnet/dotnet-docker

https://github.com/dotnet/cli/issues/9208

After installation of global tools, you need to restart session to let its dir be on PATH. However, in docker image. This should be exported to PATH beforehand. Or the docker user has to restart the session which could lose state.

area-dockerfiles bug

Most helpful comment

@MichaelSimons Can ya'll please revisit and solve this one? It is a annoying to have to use the full path.

PS C:\Users\taggac\github\Nerdbank.GitVersioning> docker run --name nbgv -it --rm -v ${PWD}:/src -w /src mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview4
root@21dc03dea40b:/src# dotnet tool install -g nbgv --add-source bin/nbgv/Release --version 2.3.149-g68e1675534
Tools directory '/root/.dotnet/tools' is not currently on the PATH environment variable.
If you are using bash, you can add it to your profile by running the following command:

cat << \EOF >> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:/root/.dotnet/tools"
EOF

You can add it to the current session by running the following command:

export PATH="$PATH:/root/.dotnet/tools"

You can invoke the tool using the following command: nbgv
Tool 'nbgv' (version '2.3.149-g68e1675534') was successfully installed.

I then want to just run it, but that doesn't work:

root@21dc03dea40b:/src# nbgv
bash: nbgv: command not found

I must specify the full path:

root@21dc03dea40b:/src# $HOME/.dotnet/tools/nbgv get-version
Version:                      0.0.351.47106
AssemblyVersion:              0.0.0.0
AssemblyInformationalVersion: 0.0.351+02b843d9a9
NuGet package Version:        0.0.351-02b843d9a9
NPM package Version:          0.0.351-02b843d9a9

All 20 comments

Ping @richlander. It'd be nice to have this for the 2.1 RTM SDK images.

Users will expect that /root/.dotnet/tools to be on PATH if they're playing around with global tools from the SDK images.

This is not as straight forward as I initially thought. I don't think we want to add ENV PATH="${PATH}:/root/.dotnet/tools" as this will affect all users. Having /root/.dotnet/tools on the path for non-root users seems wrong. We could try to add it to the root user's path only but that won't help scenarios where users are running as non-root. Additionally, user specific paths in general purpose Dockerfiles is not a common practice.

@richlander - What are your thoughts on this?

Perhaps we could use /etc/profile.d like we do when you install the SDK via the installer?

It creates /etc/profile.d/dotnet-cli-tools-bin-path.sh with the contents:

export PATH="$PATH:~/.dotnet/tools"

@peterhuene - yes - good suggestion. I think we can _dockerize_ this by using ENV PATH="${PATH}:~/.dotnet/tools". Thanks

Either suggestion should work provided bash is the shell being used 馃憤 I forgot that bash does expand tilde when searching PATH (zsh does not, which is what I use).

The native installers support a bash specific solution. A similar bash specific solution could be implemented within the microsoft/dotnet Dockerfiles via ENV PATH="${PATH}:~/.dotnet/tools". A bash specific solution is not ideal within Docker. For example a common use case that would not work is 'docker run --rm dotnet-myglobaltool`. Additionally this solution would not work for 'out of the box' with the Alpine based images. While there are other solutions that could be implemented, they would not be natural to Docker. After discussing with @richlander, we both agree that we will not fix this.

The natural usage for global-tools within a Dockerfile would be:

FROM microsoft/dotnet:2.1-sdk

RUN dotnet tool install -g dotnet-serve
ENV PATH="${PATH}:/root/.dotnet/tools"

or

FROM microsoft/dotnet:2.1-sdk
...
USER containeruser
...
RUN dotnet tool install -g dotnet-serve
ENV PATH="${PATH}:/containeruser/.dotnet/tools"

When comparing the existing ENVs set in the SDK images such as ASPNETCORE_URLS vs adding the global tools dir to the path, why wouldn't the global tools dir be added to the path? The principle difference is the interaction with an open-ended external system. ASPNETCORE_URLS is a configuration setting for ASP.NET Core only.

Reopening as this is something we should be providing a better experience around.

Discussing w/folks further another solution has been formulated. The 2.1.4xx CLI supports a new DOTNET_CLI_HOME environment variable that tells dotnet (and NuGet) where to create .dotnet (and .nuget, respectively). The intention behind this was to make dotnet work for users without a HOME directory and to only affect dotnet.

Setting DOTNET_CLI_HOME seems appropriate within the context of a container. It could be set to /usr/share/dotnet within Linux containers and C:\Program Files\dotnet within Windows containers. This will allow the non-user specific tools directory to be added to the path thus making the global tools easily accessible with no further configuration. See changes here.

FROM microsoft/dotnet-nightly:2.1-sdk

RUN dotnet tool install -g dotnetsay
RUN dotnetsay

There is a question of when this change could be made. It should considered a breaking change. Users can have on a dependency on where global tools are currently installed. The safe time frame is 2.2. There is however a string desire to get this into 2.1 as it will be designated LTS.

@richlander, @dleeapho

Do we want /usr/share/dotnet instead of perhaps /var/cache/dotnet? To me, the former is not something we'd want users to delete to "clear out" because it is the install directory for .NET Core itself. With the latter, /var/cache/dotnet/.dotnet/tools would need to be on the path. Users would then be able to delete /var/cache/dotnet to clear their installed tools and NuGet cache.

That's a fair suggestion. On Windows would ProgramData make sense?

I think so.

A decision was made to do this in 2.2. The thought is to set DOTNET_CLI_HOME to /var/cache and C:\Users\Public for linux/windows.

Upon following the proposed fix above, on Linux, /var/cache/.dotnet/tools is missing in PATH and thus, prompts user to manually set it.

dotnet tool install -g dotnetsay  //prompts user to manually set the /var/cache/.dotnet/tools path to PATH
dotnetsay

@peterhuene , @wli3 - Please confirm if above observation is expected.

The observation is expected when using DOTNET_CLI_HOME, since the installers will, at best, add ~/.dotnet/tools only to the PATH.

If we've set DOTNET_CLI_HOME to /var/cache, then I'd also add /var/cache/.dotnet/tools to PATH. Since this directory is no longer user-dependent, I think it should no longer be a problem to do so in the base image.

There are primarily three user scenario for global tools in dockerized environment :

  1. Default user ( root ) should be able to install global tool and run it. Dotnet global tools path should be available in PATH by default.
  2. A non-root user should be able to install global tool and run it .
  3. A non-root user should be able to run global tool installed by root user.

1 is straight forward and works fine.

2 is achievable by granting full rwx permission to /var/cache/.dotnet/tool and /var/cache/.nuget dir recursively. However, is this viable to grant full rwx permission here to cover this scenario ?

3 is blocked because CLI installs global tool with -rwxrw-rw- permission and thus, is unavailable to non-root user. Not sure if there is any workaround here.

Any thoughts here ?
cc @wli3 , @peterhuene @MichaelSimons

Talked to Rakesh offline. We realize if we consider root-nonroot case, and set DOTNET_CLI_HOME for all user we would end up with permission denied for template engine cache.

run dotnet new as root
login non root
run dotnet new, it should error. Since non root want to use the same template engine cache location as root. But that user doesn't have access.

the down side of not setting DOTNET_CLI_HOME is if the admin want to remove dotnet, the admin need to delete the files under /usr/share and all user's ~/.dotnet and ~/.nuget and it might be big and admin doesn't have the access.

Although DOTNET_CLI_HOME would not affect ~/.nuget location anyway I just realize

cc @peterhuene and @MichaelSimons on sharing their thoughts. Setting DOTNET_CLI_HOME to /var/cache regresses non-root user to build and run a new app.

@MichaelSimons Can ya'll please revisit and solve this one? It is a annoying to have to use the full path.

PS C:\Users\taggac\github\Nerdbank.GitVersioning> docker run --name nbgv -it --rm -v ${PWD}:/src -w /src mcr.microsoft.com/dotnet/core/sdk:3.0.100-preview4
root@21dc03dea40b:/src# dotnet tool install -g nbgv --add-source bin/nbgv/Release --version 2.3.149-g68e1675534
Tools directory '/root/.dotnet/tools' is not currently on the PATH environment variable.
If you are using bash, you can add it to your profile by running the following command:

cat << \EOF >> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:/root/.dotnet/tools"
EOF

You can add it to the current session by running the following command:

export PATH="$PATH:/root/.dotnet/tools"

You can invoke the tool using the following command: nbgv
Tool 'nbgv' (version '2.3.149-g68e1675534') was successfully installed.

I then want to just run it, but that doesn't work:

root@21dc03dea40b:/src# nbgv
bash: nbgv: command not found

I must specify the full path:

root@21dc03dea40b:/src# $HOME/.dotnet/tools/nbgv get-version
Version:                      0.0.351.47106
AssemblyVersion:              0.0.0.0
AssemblyInformationalVersion: 0.0.351+02b843d9a9
NuGet package Version:        0.0.351-02b843d9a9
NPM package Version:          0.0.351-02b843d9a9

Still having this issue when trying to install a global tool on an Ubuntu-based image.

Workaround exists, but is annoying:

RUN dotnet tool install -g mlnet

# doesn't get added to path
ENV PATH="${PATH}:/root/.dotnet/tools"

cc @eerhardt

+1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MichaelSimons picture MichaelSimons  路  5Comments

jamesstow picture jamesstow  路  6Comments

TheYorkshireDev picture TheYorkshireDev  路  5Comments

galvesribeiro picture galvesribeiro  路  7Comments

wu-yafeng picture wu-yafeng  路  6Comments