一. 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 127.0.0.1:5000/java8
当使用curl http://192.168.0.100:5000/v2/_catalog能看到json格式的返回值时,说明registry已经运行起来了。
2.3 远程访问
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可用: