Docker搭建本地私有仓库
安装部署一个私有的Docker Registry是引入、学习和使用Docker这门技术的必经之路之一。尤其是当Docker被所在组织接受,更多人、项目和产品开始接触和使用Docker时,存储和分发自制的Docker image便成了刚需。Docker Registry一如既往的继承了“Docker坑多”的特点,为此这里将自己搭建”各类”Registry过程中执行的步骤、遇到的问题记录下来,为己备忘,为他参考。
Docker在2015年推出了distribution项目,即Docker Registry 2。相比于old registry,Registry 2使用Go实现,在安全性、性能方面均有大幅改进。Registry设计了全新的Rest API,并且在image存储格式等方面不再兼容于old Registry。去年8月份,docker官方hub使用Registriy 2.1替代了原先的old Registry。如果你要与Registry2交互,你的Docker版本至少要是Docker 1.6。
Docker的开发者也一直在致力于改善Registry安装和使用的体验,通过提供官方Registry Image以及Docker Compose工具等来简化Registry的配置。不过在本文中,我们只是利用Docker以及Registry的官方Image来部署Registry,这样更便于全面了解Registry的部署配置细节。
Registry2在镜像存储方面不仅支持本地盘,还支持诸多主流第三方存储方案。通过分布式存储系统你还可以实现一个分布式Docker Registry服务。这里仅以本地盘以及single node registry2为例。
一、环境
这里还是复用以往文章中的Docker环境:
Docker Registry Server: 10.10.105.71 Ubuntu 14.04 3.16.0-57-generic;docker 1.9.1
其他两个工作Server:
10.10.105.72 Ubuntu 14.04 3.19.0-25-generic; docker 1.9.1
10.10.126.101 Ubuntu 12.04 3.16.7-013607-generic; docker 1.9.1
本次Registry使用当前最新stable版本:Registry 2.3.0。由于镜像采用本地磁盘存储,root分区较小,需要映射使用其他volume。
二、初次搭建
本以为Docker Registry的搭建是何其简单的,甚至简单到通过一行命令就可以完成的。比如我们在Registry Server上执行:
在~/dockerregistry下,执行:
$sudo docker run -d -p 5000:5000 -v `pwd`/data:/var/lib/registry --restart=always --name registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
f32095d4ba8a: Pull complete
9b607719a62a: Pull complete
973de4038269: Pull complete
2867140211c1: Pull complete
8da16446f5ca: Pull complete
fd8c38b8b68d: Pull complete
136640b01f02: Pull complete
e039ba1c0008: Pull complete
c457c689c328: Pull complete
Digest: sha256:339d702cf9a4b0aa665269cc36255ee7ce424412d56bee9ad8a247afe8c49ef1
Status: Downloaded newer image for registry:2
e9088ef901cb00546c59f89defa4625230f4b36b0a44b3713f38ab3d2a5a2b44
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry            2                   c457c689c328        9 days ago          165.7 MB
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                    NAMES
e9088ef901cb        registry:2          "/bin/registry /etc/d"   About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp   registry
Registry container已经跑起来了,其启动日志可以通过:docker logs registry查看。
我们在71本地给busybox:latest打一个tag,并尝试将新tag下的image push到Registry中去:
$ docker tag busybox:latest 10.10.105.71:5000/tonybai/busybox:latest
$ docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry                            2                   c457c689c328        9 days ago          165.7 MB
busybox                             latest              65e4158d9625        9 days ago          1.114 MB
10.10.105.71:5000/tonybai/busybox   latest              65e4158d9625        9 days ago          1.114 MB
... ...
push到Registry中:
$ docker push 10.10.105.71:5000/tonybai/busybox
The push refers to a repository [10.10.105.71:5000/tonybai/busybox] (len: 1)
unable to ping registry endpoint https://10.10.105.71:5000/v0/
v2 ping attempt failed with error: Get https://10.10.105.71:5000/v2/: Tunnel or SSL Forbidden
 v1 ping attempt failed with error: Get https://10.10.105.71:5000/v1/_ping: Tunnel or SSL Forbidden
出错了!简单分析了一下,可能是71上docker daemon配置中加了http代理的缘故,导致无法ping通registry endpoint。于是在/etc/default/docker中注释掉export http_proxy=”xxx”的设置,并重启docker daemon。
再次尝试push:
$ docker push 10.10.105.71:5000/tonybai/busybox
The push refers to a repository [10.10.105.71:5000/tonybai/busybox] (len: 1)
unable to ping registry endpoint https://10.10.105.71:5000/v0/
v2 ping attempt failed with error: Get https://10.10.105.71:5000/v2/: tls: oversized record received with length 20527
 v1 ping attempt failed with error: Get https://10.10.105.71:5000/v1/_ping: tls: oversized record received with length 20527
虽然还是失败,但错误信息已有所不同了。这次看来连接是可以建立的,但client端通过https访问server端,似乎想tls通信,但这一过程并未完成。
在其他机器上尝试push image到registry也遇到了同样的错误输出,如下:
10.10.105.72:
$ docker push 10.10.105.71:5000/tonybai/ubuntu
The push refers to a repository [10.10.105.71:5000/tonybai/ubuntu] (len: 1)
unable to ping registry endpoint https://10.10.105.71:5000/v0/
v2 ping attempt failed with error: Get https://10.10.105.71:5000/v2/: tls: oversized record received with length 20527
 v1 ping attempt failed with error: Get https://10.10.105.71:5000/v1/_ping: tls: oversized record received with length 20527
从错误信息来看,client与Registry交互,默认将采用https访问,但我们在install Registry时并未配置指定任何tls相关的key和crt文件,https访问定然失败。要想弄清这个问题,只能查看Registry Manual。
三、Insecure Registry
Registry的文档还是相对详尽的。在文档中,我们找到了Insecure Registry,即接收plain http访问的Registry的配置和使用方法,虽然这不是官方推荐的。
实际上对于我们内部网络而言,Insecure Registry基本能满足需求,部署过程也避免了secure registry的那些繁琐步骤,比如制作和部署证书等。
为了搭建一个Insecure Registry,我们需要先清理一下上面已经启动的Registry容器。
$ docker stop registry
registry
$ docker rm registry
registry
修改Registry server上的Docker daemon的配置,为DOCKER_OPTS增加–insecure-registry:
DOCKER_OPTS="--insecure-registry 10.10.105.71:5000 ....
重启Docker Daemon,启动Registry容器:
$ sudo service docker restart
docker stop/waiting
docker start/running, process 6712
$ sudo docker run -d -p 5000:5000 -v `pwd`/data:/var/lib/registry --restart=always --name registry registry:2
5966e92fce9c34705050e19368d19574e021a272ede1575385ef35ecf5cea019
尝试再次Push image:
$ docker push 10.10.105.71:5000/tonybai/busybox
The push refers to a repository [10.10.105.71:5000/tonybai/busybox] (len: 1)
65e4158d9625: Pushed
5506dda26018: Pushed
latest: digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892 size: 2739
这回push ok!
我们将本地的tag做untag处理,再从Registry pull相关image:
$ docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry                            2                   c457c689c328        9 days ago          165.7 MB
10.10.105.71:5000/tonybai/busybox   latest              65e4158d9625        9 days ago          1.114 MB
busybox                             latest              65e4158d9625        9 days ago          1.114 MB
ubuntu                              14.04               6cc0fc2a5ee3        5 weeks ago         187.9 MB
$ docker rmi 10.10.105.71:5000/tonybai/busybox
Untagged: 10.10.105.71:5000/tonybai/busybox:latest
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry            2                   c457c689c328        9 days ago          165.7 MB
busybox             latest              65e4158d9625        9 days ago          1.114 MB
ubuntu              14.04               6cc0fc2a5ee3        5 weeks ago         187.9 MB
$ docker pull 10.10.105.71:5000/tonybai/busybox
Using default tag: latest
latest: Pulling from tonybai/busybox
Digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892
Status: Downloaded newer image for 10.10.105.71:5000/tonybai/busybox:latest
$ docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
registry                            2                   c457c689c328        9 days ago          165.7 MB
10.10.105.71:5000/tonybai/busybox   latest              65e4158d9625        9 days ago          1.114 MB
busybox                             latest              65e4158d9625        9 days ago          1.114 MB
ubuntu                              14.04               6cc0fc2a5ee3        5 weeks ago         187.9 MB
可以看到:Pull过程也很顺利。
在Private Registry2中查看或检索Repository或images,将不能用docker search:
$ docker search 10.10.105.71:5000/tonybai/busybox/
Error response from daemon: Unexpected status code 404
但通过v2版本的API,我们可以实现相同目的:
$curl  http://10.10.105.71:5000/v2/_catalog
{"repositories":["tonybai/busybox"]}
$ curl  http://10.10.105.71:5000/v2/tonybai/busybox/tags/list
{"name":"tonybai/busybox","tags":["latest"]}
在其他主机上,我们尝试pull busybox:
10.10.105.72:
$docker pull 10.10.105.71:5000/tonybai/busybox
Using default tag: latest
Error response from daemon: unable to ping registry endpoint https://10.10.105.71:5000/v0/
v2 ping attempt failed with error: Get https://10.10.105.71:5000/v2/: tls: oversized record received with length 20527
 v1 ping attempt failed with error: Get https://10.10.105.71:5000/v1/_ping: tls: oversized record received with length 20527
我们发现依旧不能pull和push!在Registry手册中讲到,如果采用insecure registry的模式,那么所有与Registry交互的主机上的Docker Daemon都要配置:–insecure-registry选项。
我们按照上面的配置方法,修改105.72上的/etc/default/docker,重启Docker daemon,再执行pull/push就会得到正确的结果:
$ sudo vi /etc/default/docker
$ sudo service docker restart
docker stop/waiting
docker start/running, process 10614
$ docker pull 10.10.105.71:5000/tonybai/busybox
Using default tag: latest
latest: Pulling from tonybai/busybox
5506dda26018: Pull complete
65e4158d9625: Pull complete
Digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892
Status: Downloaded newer image for 10.10.105.71:5000/tonybai/busybox:latest
$ docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                              14.04               36248ae4a9ac        8 days ago          187.9 MB
10.10.105.71:5000/tonybai/ubuntu    14.04               36248ae4a9ac        8 days ago          187.9 MB
10.10.105.71:5000/tonybai/busybox   latest              65e4158d9625        9 days ago          1.114 MB
$ docker push 10.10.105.71:5000/tonybai/ubuntu
The push refers to a repository [10.10.105.71:5000/tonybai/ubuntu] (len: 1)
36248ae4a9ac: Pushed
8ea5373bf5a6: Pushed
2e0188208e83: Pushed
e3c70beaa378: Pushed
14.04: digest: sha256:72e56686cb9fb38438f0fd68fecf02ef592ce2ef7069bbf97802d959d568c5cc size: 6781
四、Secure Registry
Docker官方是推荐你采用Secure Registry的工作模式的,即transport采用tls。这样我们就需要为Registry配置tls所需的key和crt文件了。
我们首先清理一下环境,将上面的Insecure Registry停掉并rm掉;将各台主机上Docker Daemon的DOCKER_OPTS配置中的–insecure-registry去掉,并重启Docker Daemon。
如果你拥有一个域名,域名下主机提供Registry服务,并且你拥有某知名CA签署的证书文件,那么你可以建立起一个Secure Registry。不过我这里没有现成的证书,只能使用自签署的证书。严格来讲,使用自签署的证书在Docker官方眼中依旧属于Insecure,不过这里只是借助自签署的证书来说明一下Secure Registry的部署步骤罢了。
1、制作自签署证书
如果你有知名CA签署的证书,那么这步可直接忽略。
$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout certs/domain.key -x509 -days 365 -out certs/domain.crt
Generating a 2048 bit RSA private key
..............+++
............................................+++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Liaoning
Locality Name (eg, city) []:shenyang
Organization Name (eg, company) [Internet Widgits Pty Ltd]:foo
Organizational Unit Name (eg, section) []:bar
Common Name (e.g. server FQDN or YOUR name) []:mydockerhub.com
Email Address []:bigwhite.cn@gmail.com
2、启动Secure Registry
启动带证书的Registry:
$ docker run -d -p 5000:5000 --restart=always --name registry \
  -v `pwd`/data:/var/lib/registry \
  -v `pwd`/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2
35e8ce77dd455f2bd50854e4581cd52be8a137f4aaea717239b6d676c5ea5777
由于证书的CN是mydockerhub.com,我们需要修改一下/etc/hosts文件:
10.10.105.71 mydockerhub.com
重新为busybox制作一个tag:
$docker tag busybox:latest mydockerhub.com:5000/tonybai/busybox:latest
Push到Registry:
$ docker push mydockerhub.com:5000/tonybai/busybox
The push refers to a repository [mydockerhub.com:5000/tonybai/busybox] (len: 1)
unable to ping registry endpoint https://mydockerhub.com:5000/v0/
v2 ping attempt failed with error: Get https://mydockerhub.com:5000/v2/: x509: certificate signed by unknown authority
 v1 ping attempt failed with error: Get https://mydockerhub.com:5000/v1/_ping: x509: certificate signed by unknown authority
push失败了!从错误日志来看,docker client认为server传输过来的证书的签署方是一个unknown authority(未知的CA),因此验证失败。我们需要让docker client安装我们的CA证书:
$ sudo mkdir -p /etc/docker/certs.d/mydockerhub.com:5000
$ sudo cp certs/domain.crt /etc/docker/certs.d/mydockerhub.com:5000/ca.crt
$ sudo service docker restart //安装证书后,重启Docker Daemon
再执行Push,我们看到了成功的输出日志。由于data目录下之前已经被push了tonybai/busybox repository,因此提示“已存在”:
$docker push mydockerhub.com:5000/tonybai/busybox
The push refers to a repository [mydockerhub.com:5000/tonybai/busybox] (len: 1)
65e4158d9625: Image already exists
5506dda26018: Image already exists
latest: digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892 size: 2739
3、外部访问Registry
我们换其他机器试试访问这个secure registry。根据之前的要求,我们照猫画虎的修改一下hosts文件,安装ca.cert,去除–insecure-registry选项,并重启Docker daemon。之后尝试从registry pull image:
$ docker pull mydockerhub.com:5000/tonybai/busybox
Using default tag: latest
latest: Pulling from tonybai/busybox
Digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892
Status: Downloaded newer image for mydockerhub.com:5000/tonybai/busybox:latest
$ docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
10.10.105.71:5000/tonybai/ubuntu       14.04               36248ae4a9ac        9 days ago          187.9 MB
ubuntu                                 14.04               36248ae4a9ac        9 days ago          187.9 MB
10.10.105.71:5000/tonybai/busybox      latest              65e4158d9625        9 days ago          1.114 MB
mydockerhub.com:5000/tonybai/busybox   latest              65e4158d9625        9 days ago          1.114 MB
这样来看,如果使用自签署的证书,那么所有要与Registry交互的Docker主机都需要安装mydockerhub.com的ca.crt(domain.crt)。但如果你使用知名CA,这一步也就可以忽略。
五、Registry的鉴权管理
Registry提供了一种基础的鉴权方式。我们通过下面步骤即可为Registry加上基础鉴权:
在Register server上,为Registry增加foo用户,密码foo123:(之前需要停掉已有的Registry,并删除之)
//生成鉴权密码文件
$ mkdir auth
$ docker run --entrypoint htpasswd registry:2 -Bbn foo foo123  > auth/htpasswd
$ ls auth
htpasswd
//启动带鉴权功能的Registry:
$ docker run -d -p 5000:5000 --restart=always --name registry \
   -v `pwd`/auth:/auth \
   -e "REGISTRY_AUTH=htpasswd" \
   -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
   -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
   -v `pwd`/data:/var/lib/registry \
   -v `pwd`/certs:/certs \
   -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
   -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
   registry:2
199ad0b3591fb9613b21b1c96f017267f3c39661a7025d30df636c6805e7ab50
在105.72上,我们尝试push image到Registry:
$ docker push mydockerhub.com:5000/tonybai/busybox
The push refers to a repository [mydockerhub.com:5000/tonybai/busybox] (len: 1)
65e4158d9625: Image push failed
Head https://mydockerhub.com:5000/v2/tonybai/busybox/blobs/sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4: no basic auth credentials
错误信息提示:鉴权失败。
在72上执行docker login:
$docker login mydockerhub.com:5000
Username: foo
Password:
Email: bigwhite.cn@gmail.com
WARNING: login credentials saved in /home/baiming/.docker/config.json
Login Succeeded
login成功后,再行Push:
$ docker push mydockerhub.com:5000/tonybai/busybox
The push refers to a repository [mydockerhub.com:5000/tonybai/busybox] (len: 1)
65e4158d9625: Image already exists
5506dda26018: Image already exists
latest: digest: sha256:800f2d4558acd67f52262fbe170c9fc2e67efaa6f230a74b41b555e6fcca2892 size: 2739
Push ok!
六、Registry中images的管理
前面提到过,通过V2版Rest API可以查询Repository和images:
$ curl --cacert domain.crt  --basic --user foo:foo123 https://mydockerhub.com:5000/v2/_catalog
{"repositories":["tonybai/busybox","tonybai/ubuntu"]}
但如果要删除Registry中的Repository或某个tag的Image,目前v2还不支持,原因见Registry的roadmap中的说明。
不过如果你的Registry的存储引擎使用的是本地盘,倒是有一些第三方脚本可供使用,比如:delete-docker-registry-image。
七、小结
Registry2发布不到1年,目前还有许多问题待解决,就比如delete image的问题,相信在2.4以及后续版本这些问题会被逐个解决掉或能找到一个相对理想的方案。
Docker搭建本地私有仓库的更多相关文章
- docker 搭建本地私有仓库
		
1.使用registry镜像创建私有仓库 安装docker后,可以通过官方提供的 registry 镜像来简单搭建一套本地私有仓库环境: docker run -d -p : registry: 这将 ...
 - docker使用registry搭建本地私有仓库
		
参考链接来自:http://blog.csdn.net/wangtaoking1/article/details/44180901/ 和Mavan的管理一样,Dockers不仅提供了一个中央仓库,同时 ...
 - Docker容器之搭建本地私有仓库
		
Docker容器之搭建本地私有仓库 本地私有仓库搭建的具体步骤 首先下载 registry 镜像 docker pull registry 在 daemon.json 文件中添加私有镜像仓库的地址并重 ...
 - Docker基础-搭建本地私有仓库
		
1.使用registry镜像创建私有仓库 安装Docker后,可以通过官方提供的registry镜像来简单搭建一套本地私有仓库环境: docker run -d -p 5000:5000 regist ...
 - 利用docker搭建本地私有镜像仓库
		
主机名 角色 sht-sgmhadoopcm-01 Docker Repository sht-sgmhadoopnn-01 Docker Client 1. 在两台节点分别安装docker http ...
 - 使用verdaccio+docker搭建npm私有仓库以及使用
		
公司内部前端组件或库的共享等,搭建一个npm私有库就很方便,现在中大型公司也基本都有自己的npm私有库,这篇文章,和大家一起共同搭建一个npm私有库,共同学习 前置条件 一台电脑 可以联网 一.安装d ...
 - Docker学习笔记六:Docker搭建企业级私有仓库
		
前言 Docker不仅是一个强大的服务器部署工具,而且它还有一个官方的Docker Hub registry用于储存Docker镜像.上传镜像到Docker Hub是免费的,上传的镜像文件同时也对公共 ...
 - 基于Docker搭建pypi私有仓库
		
一.搭建 1.准备htpasswd.txt文件 该文件内容包含上传包至仓库时验证的用户名和密码 pip install htpasswd htpasswd -sc htpasswd.txt <u ...
 - Docker本地私有仓库实战
		
Docker仓库主要用于存放Docker镜像,Docker仓库分为公共仓库和私有仓库,基于registry可以搭建本地私有仓库,使用私有仓库的优点如下: 1)节省网络带宽,针对于每个镜像不用去Dock ...
 
随机推荐
- 后端程序员写的前端js代码模板
			
看几天的javascript面向对象和基础等之类相关javascript的知识,因为自己是写php的,也写过java,所以想在写javascript代码的时候也能用上面向对象的思想, 折腾了一整天的j ...
 - FAQ:如何修改领域模型?
			
问答部分 问: 如何修改领域模型? 答: 一般来说我们有两种选择,这两种选择也是两种价值观的体现(乐观和悲观). 第一种:使用UI传递过来的DTO在应用层重建Domain Model,然后执行修改,D ...
 - Android  onConfigurationChanged 不执行
			
自从Android 3.2(API 13),screen size也开始跟着设备的横竖切换而改变. 所以,在AndroidManifest.xml里设置的MiniSdkVersion和 TargetS ...
 - 7.volatile关键字
			
volatile:一个线程修改了某一个共享变量的值,其他线程也是否能够立即知道这个修改的 1.主要是让该“变量”在多个线程中可见,在java中每一个线程都有一块自己的工作区,其中就存放着所有线程“共享 ...
 - 数学图形(1.41)super spiral超级螺线
			
一种很酷的螺线,看着有种分形学的感觉.参考自http://www.2dcurves.com/spiral/spirallos.html 其数学的极坐标表达式如下: 我的脚本代码如下: #http:// ...
 - ChartView与LineSeries搭配实现曲线局部缩放功能
			
效果图: 上一篇文章实现的时候还不知道有QtChart这个模块......好好看了下资料就想做个例子实现一下这功能,比较了下代码量...恩,直接看代码: Rectangle { id: view_re ...
 - C++构造函数、析构函数、虚析构函数
			
1.构造函数 C++中的构造函数是用于初始化类的各种变量以及分配资源等.主要的注意事项是: (1)在继承关系中先初始化父类对象后初始化子类对象. (2)在一个类中按照变量的声明顺序,对类中的变量进行初 ...
 - log4net 使用笔记
			
一.Log4net特征 1.自定义日志输出级别 Log4net将日志分为五个级别优先级从高到低依次:FATAL > ERROR > WARN > INFO > DEBUG,此外 ...
 - [C#.NET] X509 數位電子簽章
			
摘自: http://www.dotblogs.com.tw/yc421206/archive/2012/06/30/73140.aspx 在上篇[C#.NET] 字串及檔案,利用 RSA 演算法加解 ...
 - Thinkphp学习笔记1-URL模式
			
PATHINFO模式 PATHINFO模式是系统的默认URL模式,提供了最好的SEO支持,系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境.对应上面的URL模式,PATHINFO模式下面的 ...