jenkins构建docker镜像上传至私有镜像库Nexus
# 什么是镜像库
字面意思,镜像库就是集中存放镜像的一个文件服务。镜像库在 CI/CD
中,又称 制品库
。构建后的产物称为制品,制品则要放到制品库做中转和版本管理。常用平台有Nexus,Jfrog,Harbor或其他对象存储平台。
在这里,我们选用 Nexus3
作为自己的镜像库。因为其稳定,性能好,免费,部署方便,且支持类型多,是许多制品库的首选选型。
# 部署 Nexus 服务
在部署 Nexus
之前,需要先下载 Nexus
的安装包(这里需要另外找个托管服务)
wget https://dependency-fe.oss-cn-beijing.aliyuncs.com/nexus-3.29.0-02-unix.tar.gz
下载完成后,解压安装包
tar -zxvf ./nexus-3.29.0-02-unix.tar.gz
解压后,我们可以看到有2个文件夹。分别是 nexus-3.29.0-02
和 sonatype-work
。其中,nexus-3.29.0-02
是nexus主程序文件夹,sonatype-work
则是数据文件。
# 启动 Nexus
我们进入 nexus-3.29.0-02
下面的 bin
目录,这里就是 nexus
的主命令目录。我们在 bin
目录下,执行 ./nexus start
命令即可启动 nexus
:
./nexus start
nexus 还支持停止,重启等命令。可以在 bin 目录下执行 ./nexus help 查看更多命令
由于 nexus
默认服务端口是 8081
,稍后我们还需要给镜像库访问单独开放一个 8082
端口。这里将 8081
,8082
端口添加到防火墙放行规则内(没开防火墙则可以略过):
firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --zone=public --add-port=8082/tcp --permanent
2
打开浏览器地址栏,访问 IP:8081
。启动时间比较长,需要耐心等待。在 Nexus
启动后,会进入这个欢迎页面:
# 配置 Nexus
进入欢迎页后,点击右上角的登录,会打开登录框。这里需要我们输入 默认管理员密码
进行初始化配置。
可以在这里找到:
cat /opt/nexus/sonatype-work/nexus3/admin.password
# 0ee35fa5-d773-432b-8e76-6c10c940ccd9
2
将文件中获取到的密码输入进去,登录用户名是 admin
。
接着是修改新密码。修改后,会进入下图这一步。这一步的意思是是否开启匿名访问。匿名访问是指:**我们在没有登录的情况下,拉取(推送)制品到制品库,都算匿名访问。**这是个很便捷,也是个危险的行为。
例如,这个制品库也支持 node
的 npm
私有库。那么我们在没有 npm login
登录这个制品库之前,就可以进行 npm install
npm publish
,其实是不太安全的。那么任何一个知道制品库地址的人,都可以任意进行推送和获取资源。
这里我们为了测试,可以先允许开启匿名访问。选择 Enable anonymous access
,点击下一步。
# 创建一个 Docker 私服
登录完成后,点击页面头部导航栏的齿轮图标,选择左侧菜单中的 Repositories
,点击 Create repository
。
点击后,我们可以看到一个列表,这就是 Nexus
所支持的制品库类型。其中有我们要使用的 Docker
,也有我们熟悉的 Npm
。我们在里面找到 Docker
:
但是 Docker
有三种,该选哪个呢?
# 选择制品库的类型
在 nexus
中,制品库一般分为以下三种类型:
- proxy: 此类型制品库原则上只下载,不允许用户推送。可以理解为缓存外网制品的制品库。例如,我们在拉取
nginx
镜像时,如果通过proxy
类型的制品库,则它会去创建时配置好的外网docker
镜像源拉取(有点像cnpm
)到自己的制品库,然后给你。第二次拉取,则不会从外网下载。起到内网缓存
的作用。 - hosted:此类型制品库和
proxy
相反,原则上只允许用户推送,不允许缓存
。这里只存放自己的私有镜像或制品。 - group:此类型制品库可以将以上两种类型的制品库组合起来。组合后只访问
group
类型制品库,就都可以访问。
在这里,我们其实不需要缓存外网镜像,那么我们只需要 hosted
即可。选择 docker (hosted)
。
我们将启动 Nexus
镜像时,配置好的 Docker
端口(预留了一个 8082
端口)填入 HTTP
输入框内。这里可以先允许匿名拉取镜像。
填写完成后,点击最下方的 **Create repository,**保存创建。
# 给镜像库添加访问权限
在我们创建好镜像库后,还需要配置一步访问权限才可以。
找到页面头部导航栏的 齿轮
图标,选择左侧菜单中的 Realms
。找到右边的 Docker Bearer Token Realm
,将其添加到右边的 Active
内,保存即可。
# 查看获取镜像库地址
找到我们刚刚创建的制品,点击上面的 copy
,查看镜像库地址。
# 登录制品库
私服建设完成后,如果私服对外访问地址为HTTP的话,还需要在服务器配置一下才可以使用(HTTPS不需要配置)。
找到 daemon.json
文件,该文件描述了当前 docker
配置的镜像加速地址,和配置过的私服地址。
vi /etc/docker/daemon.json
找到 insecure-registries
字段,如果不存在就自己添加一个。值是数组类型,将你的制品库地址填写上去。例如:
{
"insecure-registries" : [
"172.16.81.7:8082"
],
}
2
3
4
5
注意,nexus 显示的镜像库端口为 nexus 服务端口,要替换为自己配置的端口才有效。
保存并退出,重启 Docker
systemctl restart docker
接着使用 docker login
命令尝试登录:
docker login 服务IP:端口
如果提示:Login Succeeded 则代表登录成功。
# 推送镜像到制品库
在完成镜像库配置后,我们就可以使用 Jenkins 推送自己的镜像到镜像库了。我们找到 Jenkins 任务中设置 Shell 的编辑框,添加一条推送镜像的命令进去:
注意!
docker
在推送一个镜像时,镜像的 Tag (名称:版本号) 开头必须带着镜像库的地址,才可以推送到指定的镜像库。例如 jenkins-test
是不能推送到镜像库的。而 172.16.81.7:8082/jenkins-test
则可以推送到镜像库。
那我们怎么才能推送镜像上去呢?我们可以重新制作一份带镜像库地址的镜像。找到 Jenkins 的 Shell 编辑框,j将构建的 Shell 脚本修改为以下内容:
#!/bin/sh -l
npm install --registry=https://registry.npm.taobao.org
npm run build
docker build -t 172.16.81.7:8082/jenkins-test .
docker push 172.16.81.7:8082/jenkins-test
2
3
4
5
6
这里将构建的镜像名称加了镜像库的前缀,推送镜像也是一样,这样才可以将镜像推送到指定镜像库。保存后并重新构建一次。
构建后我们发现,报错了。提示信息是没有权限推送
# 利用凭据给 Shell 注入镜像库用户名密码
没有权限怎么办呢?我们可以使用 docker login
在 shell
脚本里面登录下。想直接在命令里写入用户名和密码,可以直接加 -u 用户名 -p 密码
即可。例如:
docker login -u "用户名" -p "密码" 172.16.81.7:8082
但这样,我们需要在命令里面写死用户名和密码,无论是安全和友好性上,都是不太合适的。这里我们可以借助 Jenkins 的凭据功能,添加一条用户名密码凭据,然后利用 Shell 变量写入在终端内。
找到任务的设置界面 => 构建环境 => 勾选 Use secret text(s) or file(s) => 找到左下角的新增按钮,选择 Username and password (separated)
打开后,我们可以添加一条凭据。点击凭据字段下面的添加,弹出以下弹窗,在这里填入你的用户名和密码。ID为凭据名称,描述随意。
添加后,返回下图模块。在这里选择你刚才添加的凭据,用户名变量可以起名为 DOCKER_LOGIN_USERNAME
,密码可以起名为 DOCKER_LOGIN_PASSWORD
。
接着找到下面的构建,找到 docker login
命令,将我们保存的用户名和密码变量填写进去:
docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD 172.16.81.7:8082
接着保存并构建,提示权限通过,构建成功
# 如何推送已有的镜像到仓库呢?
上面是推送我们现场编译的镜像,镜像名称都可以一条龙约定好。可是面对 load /pull 进来的镜像,我们如何推送到自己的镜像库呢?
这里可以使用 docker tag
命令给已有的镜像打个标签。在打新Tag时可以在Tag头部加入镜像库地址。如下面格式。
# docker tag <镜像ID>/<镜像名称> 新镜像名称[:版本]
docker tag bd695e3e4317 172.16.81.150:8082/local/jenkins
2
查看服务器上的docker镜像列表,可以使用 docker images 查看
这样,就可以重新打一个全新的tag,实现 重命名
功能。
接着我们使用 docker push
命令就可以进行推送了:
docker push 172.16.81.150:8082/local/jenkins