docker实践(3) 仓库registry和Nexus3作为私有镜像仓库

 

一. docker 官方仓库


1.1 下载官方的 CentOS 镜像到本地

   docker pull centos

1.2  搜索官方的 CentOS 镜像

[root@iZ235fz06auZ docker]# docker search centos
INDEX       NAME                                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/centos                         The official build of CentOS.                   3476      [OK]       
docker.io   docker.io/jdeathe/centos-ssh             CentOS-6 6.9 x86_64 / CentOS-7 7.3.1611 x8...   77                   [OK]
docker.io   docker.io/tutum/centos                   Simple CentOS docker image with SSH access      32                   
docker.io   docker.io/kinogmt/centos-ssh             CentOS with SSH                                 15                   [OK]

STARS:星级( 表示该镜像的受欢迎程度)

OFFICIAL:是否官方创建

AUTOMATED:是否自动创建。 

官方的镜像说明是官方项目组创建和维护的,automated资源允许用户验证镜像的来源和内容。


根据是否是官方提供, 可将镜像资源分为两类。 一种是类似centos这样的基础镜像, 被称为基础或根镜像。这些基础镜像是由Docker公司创建、验证、 支持、 提供。这样的镜像往往使用单个单词作为名字。
 

还有一种类型, 比如 tianon/centos 镜像, 它是由 Docker 的用户创建并维护的, 往往带有用户名称前缀。 可以通过前缀user_name/来指定使用某个用户提供的镜像, 比如tianon 用户。

另外, 在查找的时候通过-s N 参数可以指定仅显示评价为N星以上的镜像。

 

 

二. docker 私有仓库


    有时候使用 Docker Hub 这样的公共仓库可能不方便, 用户可以创建一个本地仓库供私人使用。

   Registry在github上有两份代码:老代码库新代码库。老代码是采用python编写的,存在pull和push的性能问题,出到0.9.1版本之后就标志为deprecated,不再继续开发。从2.0版本开始就到在新代码库进行开发,新代码库是采用go语言编写,修改了镜像id的生成算法、registry上镜像的保存结构,大大优化了pull和push镜像的效率。

2.1  私有仓库镜像安装

    官方在Docker hub上提供了registry的镜像(详情),我们可以直接使用该registry镜像来构建一个容器,搭建我们自己的私有仓库服务。Tag为latest的registry镜像是0.9.1版本的,我们直接采用2.1.1版本。

1、docker run -d -p 5000:5000 registry
1)指定私有仓库位置:

用户可以通过指定参数来配置私有仓库位置, 例如配置镜像存储到Amazon S3 服务。
$ sudo docker run \
   -e SETTINGS_FLAVOR=s3 \
   -e AWS_BUCKET=acme-docker \
   -e STORAGE_PATH=/registry \
   -e AWS_KEY=AKIAHSHB43HS3J92MXZ \
   -e AWS_SECRET=xdDowwlK7TJajV1Y7EoOZrmuPEJlHYcNP2k4j49T \
   -e SEARCH_BACKEND=sqlalchemy \
   -p 5000:5000 \
  registry
2)配置文件:

还可以指定本地路径( 如/home/user/registry-conf) 下的配置文件
docker run -d -p 5000:5000 -v /etc/docker/registry/config.yml:/etc/docker/registry/config.yml registry

3)仓库本地:

之前老版Register,默认上传的镜像保存在容器的位置是/tmp/registry 。新registry的仓库目录是在/var/lib/registry,所以运行时挂载目录需要注意。

docker run -d -p 5000:5000 -v /data/registry:/var/lib/registry registry
     我们将主机的/data/registry目录挂载到该目录,即可实现将镜像保存到主机的/data/registry目录了。

 

2.2  上传pull

创建好私有仓库之后, 就可以使用 docker tag 来标记一个镜像, 然后推送它到本地仓库,别的机器上就可以载下来了。 例如私有仓库本地地址为127.0.0.1:5000。

$ docker tag java8  127.0.0.1:5000/java8

使用 docker push 上传标记的镜像使用 docker push 上传标记的镜像


$ docker push 127.0.0.1:5000/java8

当使用curl http://192.168.0.100:5000/v2/_catalog能看到json格式的返回值时,说明registry已经运行起来了。   

 

2.3  远程访问

   到目前为止,docker registry 已经可以正常使用,且可以指定数据存储位置。但也只能在本地使用,要想在远程使用该 registry,就必须使用 TLS 来确保通信安全,就像使用 SSL 来配置 web 服务器。也可以强制 docker registry 运行在 insecure 模式,这种模式虽然配置起来要简单一些,但很不安全,一般不建议使用。
这里偷懒使用这个简单的 insecure 模式,假设你在一个域名为 test.docker.midea.registry.hub 的主机上运行 docker registry,步骤如下:
1,在你要远程访问 docker registry 的机器上,修改文件 /etc/default/docker 或 /etc/sysconfig/docker,具体是哪个取决于你的系统。
2,编辑里面的 DOCKER_OPTS 选项,如果没有这个选项字段,就添加一个。改成下面这样的:
 

ADD_REGISTRY='--add-registry test.docker.midea.registry.hub:5000'  
DOCKER_OPTS="--insecure-registry test.docker.midea.registry.hub:5000"  
INSECURE_REGISTRY='--insecure-registry test.docker.midea.registry.hub:5000'

3、重启你的 docker 守护进程

通过以上3步,你的这个机器就能远程从 test.docker.midea.registry.hub 上运行的 docker registry 拉取镜像了

2.4 本地安装运行


有时候需要本地运行仓库服务,可以通过源码方式进行安装。首先安装Golang环境支持,以Ubuntu为例,可以执行如下命令:
$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable
$ sudo apt-get update
$ sudo apt-get install golang
确认Golang环境安装成功,并配置$GOPATH环境变量,例如/go。
创建$GOPATH/src/github.com/docker/目录,并获取源码,如下所示:


$ mkdir -p $GOPATH/src/github.com/docker/
$ cd $GOPATH/src/github.com/docker/
$ git clone https://github.com/docker/distribution.git
$ cd distribution
将自带的模板配置文件复制到/etc/docker/registry/路径下,创建存储目录/var/lib/registry:


$ cp cmd/registry/config-dev.yml /etc/docker/registry/config.yml
$ mkdir -p /var/lib/registry
然后执行安装操作:
$ make PREFIX=/go clean binaries
编译成功后,可以通过下面的命令来启动:
$ registry server /etc/docker/registry/config.yml
此时使用访问本地的5000端口,看到返回成功(200 OK),则说明运行成功:
$ curl -i 127.0.0.1:5000/v2/
HTTP/1.1 200 OK

 

 

三. Registry v2认证模式


Docker Registry v2的认证模式和v1有了较大的变化,降低了系统的复杂度、减少了服务之间的交互次数,其基本工作模式:

 

具体交互过程包括如下步骤:
1)Docker Daemon或者其他客户端尝试访问Registry服务器,比如pull、push或者访问manifiest文件;
2)在Registry服务器开启了认证服务模式时,就会直接返回401 Unauthorized错误,并通知调用方如何获得授权;
3)调用方按照要求,向Authorization Service发送请求,并携带Authorization Service需要的信息,比如用户名、密码;
4)如果授权成功,则可以拿到合法的Bearer token,来标识该请求方可以获得的权限;
5)请求方将拿到Bearer token加到请求的Authorization header中,再次尝试步骤1中的请求;
6)Registry服务通过验证Bearer token以及JWT格式的授权数据,来决定用户是否有权限进行请求的操作。
当启用认证服务时,需要注意以下两个地方:

  •  
  • 对于Authentication Service,Docker官方目前并没有放出对应的实现方案,需要自行实现对应的服务接口;
  • Registry服务和Authentication服务之间通过证书进行Bearer token的生成和认证,所以要保证两个服务之间证书的匹配。


除了使用第三方实现的认证服务(如docker_auth、SUSE Portus等)外,还可以通过Nginx代理方式来配置基于用户名密码的认证。

 

四. Nexus3作为私有镜像仓库


使用nexus3作为私有仓库是最简单的方式。

4.1 、安装

1.下载Nexus:
  下载最新版的nexus下载地址: https://www.sonatype.com/oss-thank-you-tar.gz
2.创建nexus文件夹并解压:
  mkdir /nexus && cd /nexus
  tar -xvf   nexus-3.15.2-01-unix.tar.gz
3.使用java8启动:
  修改bin/nexus :
  INSTALL4J_JAVA_HOME_OVERRIDE=/usr/java8/
  进入nexus-3.15.2-01/bin目录下,执行./nexus start 命令启动
  启动成功后要等一会儿,8081端口才会起来 ,可以使用lsof -i:8081 命令查看端口占用情况。

4.安全起见,我们建立一个nexus用户用来启动nexus
   adduser nexus
   更改nexus文件夹的访问权限更改为nexus用户
   sudo chown -R nexus:nexus  /nexus
   打开/nexus/bin/nexus.rc 文件, 修改启动用户如下
   run_as_user=”nexus”

5.如果你想更改默认的数据目录,可以打开nexus的配置文件,修改-Dkaraf.data属性。
   vi /nexus/nexus/bin/nexus.vmoptions
下面来一个例子

-Xms1200M
-Xmx1200M
-XX:+UnlockDiagnosticVMOptions
-XX:+UnsyncloadClass
-Djava.net.preferIPv4Stack=truer
-Dkaraf.home=.
-Dkaraf.base=.
-Dkaraf.etc=etc
-Djava.util.logging.config.file=etc/java.util.logging.properties
-Dkaraf.data=/nexus/nexus-data
-Djava.io.tmpdir=data/tmp
-Dkaraf.startLocalConsole=false

6. 修改端口号: etc/nexus-default.properties

 

 7:  supervisor启动:

 [program:turing-nexus2]
command=/mnt/app/nexus/bin/nexus run
process_name=%(program_name)s
numprocs=1
directory=/mnt/app/nexus
umask=022
user=appuser
stdout_logfile=/mnt/logs/turing-nexus2/server.log
stderr_logfile=/mnt/logs/turing-nexus2/error.log
environment=
serverurl=AUTO

 

4.2 、配置使用

访问地址:http://192.168.10.50:18082/

使用域名:http://nexus.xxxxx.com  admin admin123

首次默认登陆账号:admin admin123

nexus可以作用yum的私库,maven私库、nuget等,可以参见官方说明,我们这里只是针对docker的私有镜像进行配置

代理镜像库(proxy repository)的配置和访问:在内网总是有下载hub.docker.com 的需求,可以通过配置nexus的代理模式来实现

3、nginx代理

配置host repository的HTTPS访问:nginx代理

 

设置Docker Bearer Token Realm可用:

 

五、docker使用私有registry仓库


 1、登陆:

     docker login xxxx.com#登陆
      需要输入创建repository时指定的账号和密码 登陆成功后可以pull私有库的镜像。

 2、拉取镜像:

       docker pull xxxx.com/nginx # 拉取xxxx.com上的nginx镜像,如果没有则拉取失败
 3、提交本地镜像nexus仓库:

       创建好私有仓库之后, 就可以使用 docker tag 来标记一个镜像, 然后推送它到本地仓库,别的机器上就可以下载下来了。 例如 标记镜像:

     docker tag java8  xxxx.com/java8

         使用 docker push 上传标记的镜像使用 docker push 上传标记的镜像
4、上传镜像:

       docker push xxxx.com/java8

5、测试:

    1)使用curl http://xxxx.com/v2/_catalog能看到json格式的返回值时,说明registry已经运行起来了。

     2)# docker search  registry.xxxx.com/java8        
     INDEX     NAME      DESCRIPTION   STARS     OFFICIAL   AUTOMATED

6、保存私有仓库的登陆信息文件位置:

     我们在命令行方式下,输入docker login登陆成功后,会在 ~/.docker/目录下生成一个config.json文件。打开后可以看到如下的内容:

# cat ~/.docker/config.json

{
        "auths": {
                "registry.xxxx.com": {
                        "auth": "cmVnaXN0cnktYWRtaW46cmVnaXN0cnktYWRtaW4="
                }
        }

}     

    如果不logout ,下次拉取镜像就不再需要输入账号和密码:

    这种方式,在kubernetes 中使用deployment定义一个pod,是不能下载镜像成功的。

 

六、k8s使用私有仓库


(后续章节我们讲到)

通常情况下,在私有云环境中使用kubernetes时,我们要从docker registry拉取镜像的时候,都会给docker daemo配置--insecure-registry属性来告诉docker daemo我们所使用的docker registry是可信的,这样才能从私有的docker registry中拉取镜像,但是如果要使用nexus作为kubernetes的镜像仓库的话,这种方式就不适用了,下面让我们看看如何来使用nexus作为kubernetes的镜像仓库。

1、kubenetes设置pause镜像

由于在Kubenetes中是以pod而不是Docker容器管理单元,在kubelet创建pod的时候,还通过启动一个名为google_containers/pause的镜像来实现pod概念。

Pause容器 全称infrastucture container(又叫infra)基础容器。其使用c语言编写,官方使用的镜像为gcr.io/google_containers/pause-amd64:3.1

kubernetes中的pause容器主要为每个业务容器提供以下功能:

PID命名空间:Pod中的不同应用程序可以看到其他应用程序的进程ID。

网络命名空间:Pod中的多个容器能够访问同一个IP和端口范围。

IPC命名空间:Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信。

UTS命名空间:Pod中的多个容器共享一个主机名;Volumes(共享存储卷):

Pod中的各个容器可以访问在Pod级别定义的Volumes。

 

我们可以给每台node的kubelet服务启动参数加上--pod_infra_container_image参数,指定pause镜像地址。例如指定为官方基础镜像:

 kubelet --kubeconfig=/mnt/app/kubernetes/conf/kubelet.yaml --hostname-override=192.68.10.37 --logtostderr=false --log-dir=/mnt/logs/k8s-kubelet/ --v=2 --cgroup-driver=systemd --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice  --pod_infra_container_image=docker.io/mirrorgooglecontainers/pause-amd64:3.1

由于我们使用私有仓库,需要将其下载,导出或者标记,再push到私有Docker registry中去。

docker pull mirrorgooglecontainers/pause-amd64:3.1

docker tag  da86e6ba6ca1 registry.xxxx.com/pause-amd64

docker push  registry.xxxx.com/pause-amd64

 

之后修改--pod_infra_container_image参数指定为私有仓库镜像:

--pod_infra_container_image=registry.xxx.com/pause-amd64

然后重启kubelet服务

 

2、设置k8s的Secret

k8s的Secret类型

Kubernetes提供了Secret来处理敏感信息,目前Secret的类型有3种:

  • Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。
  • kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息,作用于Docker registry(nexus),用户下载docker镜像认证使用。
  • kubernetes.io/service-account-token:用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。

3、k8s的registry认证Secret

当pod从私用仓库拉取镜像时,k8s集群使用类型为docker-registry的Secret来提供身份认证,创建一个名为registry-key的Secret,执行如下命令:

$ kubectl delete secret registry-key
$ kubectl -n k8s-dev create secret docker-registry registry-key-secret \
--docker-server=registry.xxxx.com.com \
--docker-username=registry-admin \
--docker-password=registry-admin \
[email protected]

        


注意 -n k8s-dev为指定命名空间,一般搭建k8s集群时,建议新建一个命名空间来隔离资源。
检查Secret: kubectl get secret registry-key-secret  -o yaml

通过 base64 对 secret 中的内容解码:

也可以直接读取 ~/.dockercfg 的内容来创建:

$ kubectl create secret docker-registry registry-key-secret   --from-file="~/.dockercfg"

 

4、配置和部署Pod

imagePullSecrets标签指定拉取镜像时的身份验证信息

在创建 Pod 的时候,通过 imagePullSecrets 来引用registry-key-secret:指定拉取镜像时的身份验证信息

springboot-deployment.yml: 

apiVersion: v1
kind: Pod
metadata:
  name: springbootweb1
spec:
  containers:
    - name: springbootweb1
      image: registry.xxxx.com/springboot:latest
  imagePullSecrets:
    - name: registry-key-secret

 

 

问题


问题1:登陆出现401 Unauthorized

Error response from daemon: login attempt to https://registry.xxxx.com/v2/ failed with status: 401 Unauthorized

解决:Docker Bearer Token Realm可用:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章