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