This is the expected behavior, as weird as it seems!
ENTRYPOINT is a list (as in
ENTRYPOINT ["echo", "$USER"]), it is used as-is, without further parsing or interpretation. So
$USER, because there is no shell involved in the process to replace it with the value of the
USER environment variable.
ENTRYPOINT is a string (as in
ENTRYPOINT echo $USER), what is actually executed is
sh -c "echo $USER", and
$USER is replaced with the value of the environment variable (as you would expect).
However, the environment variable
USER is not set by default. It is set by the login process; and when you just run
sh -c ... the login process is not involved.
Compare the environment when running
docker run -t -i ubuntu bash and
docker run -t -i ubuntu login -f root. In the former case, you will get a very basic environment; in the latter case, you will get the complete environment that you are used to (including