dotnet / dotnet-docker

Docker images for .NET and the .NET Tools.
https://hub.docker.com/_/microsoft-dotnet
MIT License
4.5k stars 1.94k forks source link

Ensure global tools dir is on the PATH #520

Open wli3 opened 6 years ago

wli3 commented 6 years ago

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.

peterhuene commented 6 years ago

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.

MichaelSimons commented 6 years ago

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?

peterhuene commented 6 years ago

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"
MichaelSimons commented 6 years ago

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

peterhuene commented 6 years ago

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).

MichaelSimons commented 6 years ago

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 <image w/global tool> 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.

MichaelSimons commented 6 years ago

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

MichaelSimons commented 6 years ago

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

peterhuene commented 6 years ago

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.

MichaelSimons commented 6 years ago

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

peterhuene commented 6 years ago

I think so.

MichaelSimons commented 6 years ago

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.

rakeshsinghranchi commented 6 years ago

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.

peterhuene commented 6 years ago

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.

rakeshsinghranchi commented 6 years ago

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

wli3 commented 6 years ago

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

rakeshsinghranchi commented 6 years ago

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.

ctaggart commented 5 years ago

@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
gvashishtha commented 4 years ago

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

wkrea commented 4 years ago

+1

tehmufifnman commented 3 years ago

I am having the toughest time transitioning to the new Microsoft.Playwright setup. Here is my current Docker file (before any new Microsoft.Playwright package updates), using <PackageReference Include="PlaywrightSharp" Version="0.192.0" />

Everything I have tried with the new tools doesn't work, including all the suggestions above.

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
WORKDIR /app

# Copy csproj and restore as distinct layers
COPY .nuget/NuGet.Config ./

# Copy everything else and build
COPY . ./
ARG RELEASE_CONFIG=Debug
RUN dotnet restore --configfile .nuget/NuGet.Config
RUN dotnet publish --framework net5.0 Foo.Bar/Foo.Bar.csproj -c ${RELEASE_CONFIG} -o out \
    && mkdir /app/out/.playwright \
    && cp -r /app/Foo.Bar/bin/${RELEASE_CONFIG}/net5.0/.playwright/unix /app/out/.playwright

# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:5.0
ARG DEFAULT_ENV=DEV
ENV ASPNETCORE_ENVIRONMENT=${DEFAULT_ENV}
WORKDIR /app
COPY --from=build-env /app/out/ .
RUN apt-get update \
    && apt-get install libglib2.0-0 -y \
    && apt-get install libnss3 -y \
    && apt-get install libnspr4 -y \
    && apt-get install libatk1.0-0 -y \
    && apt-get install libatk-bridge2.0-0 -y \
    && apt-get install libcups2 -y \
    && apt-get install libdrm2 -y \
    && apt-get install libdbus-1-3 -y \
    && apt-get install libexpat1 -y \
    && apt-get install libxcb1 -y \
    && apt-get install libxkbcommon0 -y \
    && apt-get install libx11-6 -y \
    && apt-get install libxcomposite1 -y \
    && apt-get install libxdamage1 -y \
    && apt-get install libxext6 -y \
    && apt-get install libxfixes3 -y \
    && apt-get install libxrandr2 -y \
    && apt-get install libgbm1 -y \
    && apt-get install libgtk-3-0 -y \
    && apt-get install libpango-1.0-0 -y \
    && apt-get install libcairo2 -y \
    && apt-get install libasound2 -y \
    && apt-get install libatspi2.0-0 -y \
    && apt-get install libxshmfence1 -y \
    && .playwright/unix/native/playwright.sh install

CMD ["dotnet","Foo.Bar.dll"]
MichaelSimons commented 3 years ago

@tehmufifnman, please consider creating a new discussion topic for your question.

jinek commented 3 years ago

The suggestion to do any additional steps to configure dotnet inside the container is not user-friendly. Basically, I believe, dotnet commands should work out of the box.