TLDR: Provide the right credentials, otherwise the error message might not tell you what went wrong.
Upfront summary of recommendations:
- Always quote the variables 1, otherwise it is easy to miss if they are unset.
- Provide the password via standard input (stdin), this is a better fit for CI/CD pipelines.
The "Error: Cannot perform an interactive login from a non TTY device" emitted by the docker(1) command for a command like yours in the gitlab job:
docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $CI_REGISTRY
The message is a bit misleading because docker login is quite lax here. Even you specified to read the password as string from the command-line (-p or --password option), if the password is missing or wrong, docker login will ask for it.
As this makes no sense within a gitlab CI automation - there is no interactive terminal (TTY) - the docker login command is at least clever enough to realize that and quits with the bespoken error message.
So if you get that error, you were not able to properly provide the password.
The Missing Credentials Docker Login Situation in Gitlab CI/CD
You can change the docker login command to make it a bit more robust, especially within CI runs.
Let's shortly review the usage and better understand the problem to then make some suggestions how to improve. From docker login --help:
Usage: docker login [OPTIONS] [SERVER]
Log in to a registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
Given your original command-line:
docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $CI_REGISTRY
and considering an error and all those three Gitlab CI/CD variables are empty, the command-line would look like the following:
docker login -u -p
That is login with the username "-p" to the default server.
You can simulate that on your own shell by running this command with standard-input closed:
$ 0<&- docker login -u -p
Error: Cannot perform an interactive login from a non TTY device
Exactly that error message.
Always quote "$VARIABLES"
Looking closer at the actual command-line, the error message is a reminder to always quote the variables1. Also for explicitness use the options delimiter --:
docker login -u "$REGISTRY_USER" -p "$REGISTRY_PASSWORD" -- "$CI_REGISTRY"
In the error case those variables are empty the command then is:
docker login -u "" -p "" -- ""
The behaviour is still the same thought, the docker login command still tries hard, and it's not yet giving a good message.
NOTE: It's not solving any of the problems incl. the messaging but we at least handle the case of empty or undefined variables, thanks to the quoting they do not disappear any longer:
0<&- docker login -u "" -p "" -- ""
Error: Cannot perform an interactive login from a non TTY device
The --password-stdin option
Therefore within a non-interactive session (like the gitlab-runner) it is strongly recommended:
Use the --password-stdin option. Not only to prevent the warning in the case of a successful login but to make docker login to actually complain about the empty username in the first place! Also it allows to specify it before the username argument option to remove another ambiguity:
echo "$REGISTRY_PASSWORD" | docker login --password-stdin -u "$REGISTRY_USER" -- "$CI_REGISTRY"
Now even if the variables are missing, the command still fails in a good way:
echo "" | docker login --password-stdin -u "" -- ""
Must provide --username with --password-stdin
- Always quote the variables 1, otherwise it is easy to miss if they are unset.
- Provide the password via standard input (stdin), this is a better fit for CI/CD pipelines.
Remarks:
- An earlier version of the answer suggested to quote the variables with single-quotes (
'), which turned out to be wrong after Franks' answer with the final conclusion. Better than single-quotes for this Gitlab CI job with a Linux/Unix (shell) script, the variables need to be quoted with double quotes (") instead, as they are substituted by the shell and not - as assumed earlier - when the shell script is generated by the runner for its executor. Under that wrong impression I had considered single-quotes a better fit as their content won't be substituted by the shell then, but substituting within the shell is much better now (and much more stable/safe by the gitlab runner to do it this way now as I think about it).