Trailing underscore in repo name causes HTTP 500 error at Container Registry page + breaks docker
### Summary It all started with this config: ```yaml version: '3.0' services: api: build: context: . dockerfile: Dockerfile image: registry.gitlab.com/remak_team/not-open-source/tbe_/ci/tbe-http-api:${IMAGE_TAG-latest} ports: - 9999:9999 volumes: - .:/app - ..:/src ``` `docker-compose` returned strange error: ```shell $ docker-compose --verbose up --build compose.config.config.find: Using configuration files: ./docker-compose.yml docker.auth.find_config_file: Trying paths: ['~/.docker/config.json', '~/.dockercfg'] docker.auth.find_config_file: Found file at path: ~/.docker/config.json docker.auth.load_config: Found 'auths' section docker.auth.parse_auth: Found entry (registry='https://index.docker.io/v1/', username='webknjaz') docker.auth.parse_auth: Found entry (registry='registry.gitlab.com', username='webknjaz') urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/version HTTP/1.1" 200 222 compose.cli.command.get_client: docker-compose version 1.15.0, build e12f3b9 docker-py version: 2.5.1 CPython version: 3.6.0 OpenSSL version: OpenSSL 1.0.2e 3 Dec 2015 compose.cli.command.get_client: Docker base_url: http+docker://localunixsocket compose.cli.command.get_client: Docker version: Version=17.06.0-ce, ApiVersion=1.30, MinAPIVersion=1.12, GitCommit=02c1d87, GoVersion=go1.8.3, Os=linux, Arch=amd64, KernelVersion=4.10.1-gentoo, BuildTime=2017-07-16T18:30:12.627667545+03:00 compose.cli.verbose_proxy.proxy_callable: docker info <- () urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/info HTTP/1.1" 200 None compose.cli.verbose_proxy.proxy_callable: docker info -> {'Architecture': 'x86_64', 'BridgeNfIp6tables': True, 'BridgeNfIptables': True, 'CPUSet': True, 'CPUShares': True, 'CgroupDriver': 'cgroupfs', 'ClusterAdvertise': '', 'ClusterStore': '', 'ContainerdCommit': {'Expected': 'cfb82a876ecc11b5ca0977d1733adbe58599088a', 'ID': 'd24f39e203aa6be4944f06dd0fe38a618a36c764'}, ... compose.cli.verbose_proxy.proxy_callable: docker inspect_network <- ('tbe_default') urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/networks/tbe_default HTTP/1.1" 200 512 compose.cli.verbose_proxy.proxy_callable: docker inspect_network -> {'Attachable': True, 'ConfigFrom': {'Network': ''}, 'ConfigOnly': False, 'Containers': {}, 'Created': '2017-09-19T08:42:08.644435409+03:00', 'Driver': 'bridge', 'EnableIPv6': False, 'IPAM': {'Config': [{'Gateway': '172.18.0.1', 'Subnet': '172.18.0.0/16'}], 'Driver': 'default', 'Options': None}, ... compose.cli.verbose_proxy.proxy_callable: docker containers <- (all=False, filters={'label': ['com.docker.compose.project=tbe', 'com.docker.compose.oneoff=False']}) urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/containers/json?limit=-1&all=0&size=0&trunc_cmd=0&filters=%7B%22label%22%3A+%5B%22com.docker.compose.project%3Dtbe%22%2C+%22com.docker.compose.oneoff%3DFalse%22%5D%7D HTTP/1.1" 200 3 compose.cli.verbose_proxy.proxy_callable: docker containers -> (list with 0 items) compose.cli.verbose_proxy.proxy_callable: docker containers <- (all=True, filters={'label': ['com.docker.compose.project=tbe', 'com.docker.compose.service=api', 'com.docker.compose.oneoff=False']}) urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/containers/json?limit=-1&all=1&size=0&trunc_cmd=0&filters=%7B%22label%22%3A+%5B%22com.docker.compose.project%3Dtbe%22%2C+%22com.docker.compose.service%3Dapi%22%2C+%22com.docker.compose.oneoff%3DFalse%22%5D%7D HTTP/1.1" 200 1489 compose.cli.verbose_proxy.proxy_callable: docker containers -> (list with 1 items) compose.cli.verbose_proxy.proxy_callable: docker inspect_container <- ('c28db222b5478157f6c76348a0905d30cf7ceb2bee75ac30ef824456e6ad1e60') urllib3.connectionpool._make_request: http://localhost:None "GET /v1.25/containers/c28db222b5478157f6c76348a0905d30cf7ceb2bee75ac30ef824456e6ad1e60/json HTTP/1.1" 200 None compose.cli.verbose_proxy.proxy_callable: docker inspect_container -> {'AppArmorProfile': '', 'Args': ['--server-host=0.0.0.0', '--server-port=9999'], 'Config': {'ArgsEscaped': True, 'AttachStderr': False, 'AttachStdin': False, 'AttachStdout': False, 'Cmd': [], 'Domainname': '', 'Entrypoint': ['entrypoint.sh', '--server-host=0.0.0.0', ... compose.service.build: Building api compose.cli.verbose_proxy.proxy_callable: docker build <- (path='~/src/gitlab/remak_team/not-open-source/tbe_', tag='registry.gitlab.com/remak_team/not-open-source/tbe_/ci/tbe-http-api:latest', stream=True, rm=True, forcerm=False, pull=False, nocache=False, dockerfile='Dockerfile', cache_from=None, labels=None, buildargs={}, network_mode=None) docker.api.build._set_auth_headers: Looking for auth config docker.api.build._set_auth_headers: Sending auth config ('https://index.docker.io/v1/', 'registry.gitlab.com') ERROR: compose.cli.errors.exit_with_error: Couldn't connect to Docker daemon at http+docker://localunixsocket - is it running? If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable. ``` At first, I thought it was an error with `docker-compose`, then I thought it's `docker` itself is broken (because I ran out of storage just before the issue with other container). But then I went to https://gitlab.com/remak_team/not-open-source/tbe_/container_registry and saw *HTTP 500:* Whoops, something went wrong on our end. I've changed `tbe_` to `tbe` and it built and ran the container as expected. It's also important to note that other projects having `_` in the middle of their names don't produce such error. I'm going to guess that it's related to what's described in gitlab-ce#26089: `/` is replaced with `__`, which means producing `___` sequence and `_/` might be restored into `/_` after encode/decode. ### Steps to reproduce 1. Create a repo with trailing underscore in its name. 2.1. Try using that as image name in docker. 2.2. Try accessing `/container_registry` subpage. 3. That's it. ### Example Project https://gitlab.com/remak_team/not-open-source/tbe_ but it's private. ### What is the current *bug* behavior? Impossible to use Registry from within docker app and web browser. ### What is the expected *correct* behavior? No errors. ### Relevant logs and/or screenshots See summary. ### Output of checks This bug happens on GitLab.com ### Possible fixes Fix URL processing?
issue