China Mirrors

Cover image

Here is how to increase the speed of Debian, Docker, Node, PHP, Python setups, by using mirrors hosted inside China.

Note that regardless of where you are on the planet, you should also consider caching. That will be the topic of an upcoming article.

Debian

As of 2020-08-27, the Debian mirror list mentions the following "Push-Primary" instances:

  • ftp2.cn.debian.org
  • ftp.cn.debian.org
  • mirrors.tuna.tsinghua.edu.cn << my pick since March 2020
  • mirrors.ustc.edu.cn

Rewrite your sources.list with:

sed -i "s#http://deb.debian.org/debian#http://mirrors.tuna.tsinghua.edu.cn/debian#" /etc/apt/sources.list
sed -i "s#http://security.debian.org/debian-security#http://mirrors.tuna.tsinghua.edu.cn/debian-security#" /etc/apt/sources.list

Docker

Docker setup on Debian/Ubuntu

Tuna has a mirror of docker-ce for China

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt-get update -y
apt-get install -y docker-ce docker-ce-cli containerd.io
systemctl start docker
systemctl enable docker

Docker registry

  • As of 2020, Docker once-official registry.docker-cn.com is dead.
  • Azure CN offered a mirror https://dockerhub.azk8s.cn, but it was closed to public access in early 2020 (cf April 22nd 2020 commit "currently .azk8s.cn could only be accessed by Azure China IP, we don't provide public outside access any more.")
  • NetEase mirror https://hub-mirror.c.163.com (thanks https://gist.github.com/y0ngb1n/7e8f16af3242c7815e7ca2f0833d3ea6) still works as of 2020-08-29
echo '{"registry-mirrors": ["https://hub-mirror.c.163.com/"]}' > /etc/docker/daemon.json
systemctl restart docker

Note that if the mirror is unavailable, Docker will fallback to the default address for Docker Hub. The error message on pull makes you believe the mirror is not used:

docker: Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout.

But journalctl -xe reveals it tried the mirror first (thanks https://stackoverflow.com/questions/42143395/docker-registry-mirror-not-used):

Aug 29 14:43:31 mathieu-TM1701 dockerd[1631]: time="2020-08-29T14:43:31.909534014+08:00" level=info msg="Attempting next endpoint for pull after error: error parsing HTTP 403 response body: invalid character '<'
 looking for beginning of value: \"<html>\\r\\n<head><title>403 Forbidden</title></head>\\r\\n<body bgcolor=\\\"white\\\">\\r\\n<center><h1>403 Forbidden</h1></center>\\r\\n<hr><center>nginx/1.14.0 (Ubuntu)</cen
ter>\\r\\n</body>\\r\\n</html>\\r\\n\""
Aug 29 14:43:42 mathieu-TM1701 dockerd[1631]: time="2020-08-29T14:43:42.168132298+08:00" level=warning msg="Error getting v2 registry: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout"
Aug 29 14:43:42 mathieu-TM1701 dockerd[1631]: time="2020-08-29T14:43:42.168255578+08:00" level=info msg="Attempting next endpoint for pull after error: Get https://registry-1.docker.io/v2/: net/http: TLS handsha
ke timeout"
Aug 29 14:43:42 mathieu-TM1701 dockerd[1631]: time="2020-08-29T14:43:42.168351623+08:00" level=error msg="Handler for POST /v1.40/images/create returned error: Get https://registry-1.docker.io/v2/: net/http: TLS
 handshake timeout"

Node

NPM registry

Taobao has a mirror of npm within China

One shot:

npm --registry https://registry.npm.taobao.org install express

To make it persistent on the user:

npm config set registry https://registry.npm.taobao.org

Or by directly writing the configuration file at ~/.npmrc

echo "registry=https://registry.npm.taobao.org" > ~/.npmrc

PHP

Composer setup

Based on How to install Composer programmatically and https://pkg.phpcomposer.com/:

php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');"
php composer-setup.php --quiet
php -r "unlink('composer-setup.php');"

Comparing https://getcomposer.org/installer with https://install.phpcomposer.com/installer out of curiosity:

645c645
<         $this->baseUrl = $uriScheme.'://getcomposer.org';
---
>         $this->baseUrl = $uriScheme.'://install.phpcomposer.com';
827c827
<         $url = $this->baseUrl.'/versions';
---
>         $url = $this->baseUrl.'/versions.json';

Make composer available to the local user with:

mkdir -p ~/.local/bin/
mv composer.phar ~/.local/bin/composer

Packagist mirror

As of 2020-08-27, the Packagist mirror page lists:

  • mirrors.huaweicloud.com/repository/php
  • developer.aliyun.com/composer << works OK
  • php.cnpkg.org
  • packagist.phpcomposer.com
  • packagist.mirrors.sjtug.sjtu.edu.cn
  • mirrors.cloud.tencent.com/help/composer.html << works OK

Apply with the composer config command:

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

Or you can directly write into ~/.config/composer/config.json:

mkdir -p ~/.config/composer/
echo '{"repositories":{"packagist":{"type":"composer","url":"https://mirrors.aliyun.com/composer/"}}}' > ~/.config/composer/config.json

Python

pip / PyPI

pip config set global.index-url "https://pypi.tuna.tsinghua.edu.cn/simple"

Or to avoid running pip (for instance in a Dockerfile, as it would pollute the image), write directly to ~/.config/pip/pip.conf

mkdir -p ~/.config/pip/
echo -e "[global]\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple\n" > ~/.config/pip/pip.conf

Ubuntu cloud images

Equivalent to https://cloud-images.ubuntu.com/


Cover image adapted from https://xkcd.com/303/ ; Creative Commons Attribution-NonCommercial 2.5 License