404 on docker push (to gitlab.com)

I have successfully authenticated with docker to my GitLab.com project with a personal access token, and now when I go to push an image, I get a 404 HTTP error:

$ docker push gitlab.com/foo-the-group/foo-project/foo-ci-image:latest
The push refers to repository [gitlab.com/foo-the-group/foo-project/foo-ci-image]
fccd7e88be6d: Preparing 
b2803670fcde: Preparing 
db14f754ba91: Preparing 
9be3c06ba9b1: Preparing 
bbff2f76b512: Preparing 
66cbf9b5e7d4: Waiting 
093501b0a9e2: Waiting 
b1169e57b139: Waiting 
b3577d595e75: Waiting 
3ee270f20d54: Waiting 
4ef4adca5c3b: Waiting 
error parsing HTTP 404 response body: invalid character '<' looking for beginning of value: "<!DOCTYPE html>\n<html>\n<head>\n  <meta content=\"width=device-width, initial-scale=1, maximum-scale=1\" name=\"viewport\">\n  <title>The page you're looking for could not be found (404)</title>\n  <style>\n    body {\n      color: #666;\n      text-align: center;\n      font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n      margin: auto;\n      font-size: 14px;\n    }\n\n    h1 {\n      font-size: 56px;\n      line-height: 100px;\n      font-weight: 400;\n      color: #456;\n    }\n\n    h2 {\n      font-size: 24px;\n      color: #666;\n      line-height: 1.5em;\n    }\n\n    h3 {\n      color: #456;\n      font-size: 20px;\n      font-weight: 400;\n      line-height: 28px;\n    }\n\n    hr {\n      max-width: 800px;\n      margin: 18px auto;\n      border: 0;\n      border-top: 1px solid #EEE;\n      border-bottom: 1px solid white;\n    }\n\n    img {\n      max-width: 40vw;\n      display: block;\n      margin: 40px auto;\n    }\n\n    a {\n      line-height: 100px;\n      font-weight: 400;\n      color: #4A8BEE;\n      font-size: 18px;\n      text-decoration: none;\n    }\n\n    .container {\n      margin: auto 20px;\n    }\n\n    .go-back {\n      display: none;\n    }\n\n  </style>\n</head>\n\n<body>\n  <a href=\"/\">\n    <img src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjIxMCIgdmlld0JveD0iMCAwIDIxMCAyMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTVsMzguNjQtMTE4LjkyMWgtNzcuMjhsMzguNjQgMTE4LjkyMXoiIGZpbGw9IiNlMjQzMjkiLz4KICA8cGF0aCBkPSJNMTA1LjA2MTQgMjAzLjY1NDhsLTM4LjY0LTExOC45MjFoLTU0LjE1M2w5Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTIuMjY4NSA4NC43MzQxbC0xMS43NDIgMzYuMTM5Yy0xLjA3MSAzLjI5Ni4xMDIgNi45MDcgMi45MDYgOC45NDRsMTAxLjYyOSA3My44MzgtOTIuNzkzLTExOC45MjF6IiBmaWxsPSIjZmNhMzI2Ii8+CiAgPHBhdGggZD0iTTEyLjI2ODUgODQuNzM0Mmg1NC4xNTNsLTIzLjI3My03MS42MjVjLTEuMTk3LTMuNjg2LTYuNDExLTMuNjg1LTcuNjA4IDBsLTIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+CiAgPHBhdGggZD0iTTEwNS4wNjE0IDIwMy42NTQ4bDM4LjY0LTExOC45MjFoNTQuMTUzbC05Mi43OTMgMTE4LjkyMXoiIGZpbGw9IiNmYzZkMjYiLz4KICA8cGF0aCBkPSJNMTk3Ljg1NDQgODQuNzM0MWwxMS43NDIgMzYuMTM5YzEuMDcxIDMuMjk2LS4xMDIgNi45MDctMi45MDYgOC45NDRsLTEwMS42MjkgNzMuODM4IDkyLjc5My0xMTguOTIxeiIgZmlsbD0iI2ZjYTMyNiIvPgogIDxwYXRoIGQ9Ik0xOTcuODU0NCA4NC43MzQyaC01NC4xNTNsMjMuMjczLTcxLjYyNWMxLjE5Ny0zLjY4NiA2LjQxMS0zLjY4NSA3LjYwOCAwbDIzLjI3MiA3MS42MjV6IiBmaWxsPSIjZTI0MzI5Ii8+Cjwvc3ZnPgo=\"\n       alt=\"GitLab Logo\" />\n  </a>\n  <h1>\n    404\n  </h1>\n  <div class=\"container\">\n    <h3>The page could not be found or you don't have permission to view it.</h3>\n    <hr />\n    <p>The resource that you are attempting to access does not exist or you don't have the necessary permissions to view it.</p>\n    <p>Make sure the address is correct and that the page hasn't moved.</p>\n    <p>Please contact your GitLab administrator if you think this is a mistake.</p>\n    <a href=\"javascript:history.back()\" class=\"js-go-back go-back\">Go back</a>\n  </div>\n  <script>\n    (function () {\n      var goBack = document.querySelector('.js-go-back');\n\n      if (history.length > 1) {\n        goBack.style.display = 'inline';\n      }\n    })();\n  </script>\n</body>\n</html>\n"

It appears that docker is interpreting the misinterpreting the image name as a repository path, rather than as <registry URL>/<namespace>/<project>/<image> (see GitLab Container Registry). My docker version is version 20.10.7, build f0df350. Am I invoking docker push incorrectly, or not have my GitLab project set up correctly, or… what?

I have the same issue with my own gitlab self managed server

gitlab.com/foo-the-group/foo-project/foo-ci-image:latest

Targets the https endpoint for the GitLab server, and not the container registry domain endpoint. The Docker client receives a HTTP response and tries to parse that as JSON, which fails with the < bracket at the beginning of the document, <HTML>.

You can verify the container registry path by inspecting an existing project and container registry, for example, Container Registry · GitLab.org / GitLab · GitLab and copy the path to one of the container images using the small copy icon.

registry.gitlab.com/gitlab-org/gitlab

TL;DR - the docker push commands needs to use the registry domain and path. You do not need to hardcode the domain in every CI configuration, I’d suggest using the predefined CI/CD variable instead: CI_REGISTRY.