一、系统环境
组件 | 版本 |
---|---|
Centos | 7.6.1810 |
Jenkins | 2.319.1 |
Docker | 20.10.12 |
Docker-Compose | 1.29.2 |
HARBOR | 2.4.1 |
二、学习资料
三、Docker安装
1、Docker
2、Docker-Compose
四、HARBOR安装
1、下载安装包
下载地址
【注意】
1、HARBOR分1.0和2.0两个大版本,根据自己需要选择版本
2、安装包分离线和在线安装版,我们选择离线安装包
2、官方文档
3、解压安装包
sudotar -zxvf harbor-offline-installer-v2.4.1.tgz
4、配置文件
进入HARBOR安装目录,对harbor.yml文件进行配置,下面有"配置"注释的行需要修改
# Configuration file of Harbor# The IP address or hostname to access admin UI and registry service.# DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients.# 配置 设定主机名称,可以ip或者域名
hostname: 192.168.x.x# http related config
http:# port for http, default is 80. If https enabled, this port will redirect to https port# 配置 设定http端口号,此处仅启用http方式,如需https方式请查阅相关文档
port: 8182# https related config# https:# https port for harbor, default is 443# port: 443# The path of cert and key files for nginx# certificate: /your/certificate/path# private_key: /your/private/key/path# # Uncomment following will enable tls communication between all harbor components# internal_tls:# # set enabled to true means internal tls is enabled# enabled: true# # put your cert and key files on dir# dir: /etc/harbor/tls/internal# Uncomment external_url if you want to enable external proxy# And when it enabled the hostname will no longer used# external_url: https://reg.mydomain.com:8433# The initial password of Harbor admin# It only works in first time to install harbor# Remember Change the admin password from UI after launching Harbor.# 配置 harbor管理员admin的登录密码
harbor_admin_password: Harbor12345# Harbor DB configuration
database:# The password for the root user of Harbor DB. Change this before any producti
on use.# 配置 harbor数据库密码
password: root123# The maximum number of connections in the idle connection pool. If it <=0, no
idle connections are retained.
max_idle_conns: 100# The maximum number of open connections to the database. If it <= 0, then the
re is no limit on the number ofopen connections.# Note: the default number of connections is 1024 for postgres of harbor.
max_open_conns: 900# The default data volume# 配置 HARBOR的DockerVolume位置
data_volume: ~/opt/harbor/data......
5、安装
# 切换到harbor目录下# 准备阶段
./prepare# 安装阶段
./install.sh
【注意】HARBOR为Docker一键安装,安装成功后会启动相关镜像
6、登录
访问HARBOR地址,如:192.168.x.x:8182,端口号为HARBOR配置文件中指定
7、创建项目
在HARBOR中新建一个项目,如:demo-hello
8、Jenkins部署节点Docker中添加私有镜像库
# 添加私有镜像库
vim /usr/lib/systemd/system/docker.service
ExecStart后添加–insecure-registry 192.168.x.x:8182
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service[Service]
Type=notify# the default is not to use systemd for cgroups because the delegate issues still
l# exists and systemd currently does not support the cgroup feature set required# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sockk
--insecure-registry 192.168.x.x:8182
五、Jenkins Build Docker镜像
1、Dockerfile
# 定制的镜像都是基于 FROM 的镜像,这里的openjdk:8-jdk-alpine就是基础镜像
FROM openjdk:8-jdk-alpine# 构建参数
ARG JAR_FILE# 复制指令,将指定文件复制为app.jar
COPY${JAR_FILE} app.jar# 声明对外暴露的端口
EXPOSE 8214# 配置容器启动时运行的命令
ENTRYPOINT["java","-jar","/app.jar"]
将Dockerfile放到代码目录下,通常和pom.xml在同一目录下
2、Pipeline
pipeline{/*Jenkins节点,any代表所有*/// agent any
agent{
node{//在label为dev1的节点进行部署
label'dev1'}}/*环境变量,类似全局变量*/
environment{
BUILD_USER=""//项目构建者
GIT_COMMIT_MSG=""//GIT提交信息
GIT_COMMIT_ID=""//GIT提交ID,可用于标识版本/*部署配置*/
POM_PATH="${env.WORKSPACE}/pom.xml"//配置文件路径
POM_ARTIFACTID=""//项目名称
POM_VERSION=""//项目版本
POM_PROJECT_NAME=""//项目原名:POM_ARTIFACTID+'-'+POM_VERSION+'.jar',用于杀死上一版本。值为空则读取Pom.xml中上个版本的jar,值不为空则指定杀死进程。
JAR_NAME=""//jar包名称
JAR_PATH="${env.WORKSPACE}/target"//生成的jar包路径/*部署配置*/
JAR_WORK_PATH="~/jenkins/jar/"//运行jar的工作路径,统一管理,并需要提前创建好/*部署配置*/
LOG_PATH="~/jenkins/log"//日志路径/*部署配置*/
DOCKER_PORT="8214"//程序运行端口号}// /*Jenkins自动构建触发器*/// triggers{// //每5分钟判断一次代码是否有变化// pollSCM('H/5 * * * *')// }/*构建阶段*/
stages{/*准备阶段:拉取代码、定义全局变量等*/stage('Preparation'){
steps{//使用build user vars插件,获取构建执行者wrap([$class:'BuildUser']){
script{
BUILD_USER="${env.BUILD_USER}"//将构建执行者注入到环境变量中,方便最后通知使用}}/*部署配置*//** 从Bitbucket上拉取分支
* @url git地址
* @branch 分支名称
* @credentialsId Jenkins凭证Id,用于远程访问
*/git(url:'https://sleetdream@bitbucket.org/sleetdream/demo-hello.git', branch:'master', credentialsId:'sleetdream')
script{//执行Git命令获取Git相关信息赋值给全局变量,returnStdout返回命令结果
GIT_COMMIT_MSG=sh(script:'git log -1 --pretty=%B ${GIT_COMMIT}', returnStdout:true).trim()
GIT_COMMIT_ID=sh(script:'git rev-parse --short HEAD', returnStdout:true).trim()}/*读取pom.xml文件,设置全局变量*/readRom()}}/*构建阶段*/stage('Build'){
steps{/**
* 执行maven打包
* -B --batch-mode 在非交互(批处理)模式下运行(该模式下,当Mven需要输入时,它不会停下来接受用户的输入,而是使用合理的默认值)
* 打包时跳过JUnit测试用例
* -DskipTests 不执行测试用例,但编译测试用例类生成相应的class文件至target/test-classes下
* -Dmaven.test.skip=true,不执行测试用例,也不编译测试用例类
**/
sh'mvn -B -DskipTests clean package'}}stage('Docker Build'){
steps{withEnv(['JENKINS_NODE_COOKIE=background_job']){
sh"""
pid=\$(docker ps -a | grep ${POM_ARTIFACTID} | awk \'{print \$1 }\')
image=\$(docker images | grep ${POM_ARTIFACTID} | awk \'{ print \$3 }\')
if [ -z "\$pid" ]
then
echo container ${POM_ARTIFACTID} is already stopped
else
docker stop \$pid
docker rm \$pid
fi
if [ -z "\$image" ]
then
echo image ${POM_ARTIFACTID}:${POM_VERSION} is already stopped
else
docker rmi \$image
fi
# 创建默认路径
mkdir -p ${JAR_WORK_PATH}
cp -f ${JAR_PATH}/${JAR_NAME} ${JAR_WORK_PATH}
cp -f ${env.WORKSPACE}/Dockerfile ${JAR_WORK_PATH}
cd ${JAR_WORK_PATH}
docker build --build-arg JAR_FILE=${POM_PROJECT_NAME} -t ${POM_ARTIFACTID}:${POM_VERSION} .
docker run --name=${POM_ARTIFACTID} -p ${DOCKER_PORT}:${DOCKER_PORT} -d -v ${LOG_PATH}:/log ${POM_ARTIFACTID}:${POM_VERSION}
"""}}}}}/**
* 读取配置文件,获取信息
* @return
*/defreadRom(){def pom= readMavenPom file:"${POM_PATH}"//使用Jenkins插件pipeline-utility-steps读取pom.xml文件,使用方法详见https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#readmavenpom-read-a-maven-project-file//设置全局变量
POM_VERSION="${pom.version}"
POM_PROJECT_NAME="${pom.artifactId}"+'-'+"${pom.version}"+'.jar'
POM_ARTIFACTID="${pom.artifactId}"
JAR_WORK_PATH+= POM_ARTIFACTID+'/'
JAR_NAME= POM_ARTIFACTID+'-'+ POM_VERSION+'.jar'}
六、镜像推送HARBOR
1、Pipeline
/*在Docker Build的stage后增加Harbor PUSH的stage*/stage('Harbor PUSH'){
steps{// 使用Jenkins凭证Harbor-dev,登录Harbor,并上传镜像withCredentials([usernamePassword(credentialsId:"Harbor-dev", passwordVariable:'password', usernameVariable:'username')]){// 登录HARBOR
sh"docker login -u ${username} -p ${password} http://192.168.x.x:8182/"// 打标签
sh"docker tag ${POM_ARTIFACTID}:${POM_VERSION} 192.168.x.x:8182/demo-hello/${POM_ARTIFACTID}:${POM_VERSION}"// 上传镜像
sh"docker push 192.168.x.x:8182/demo-hello/${POM_ARTIFACTID}:${POM_VERSION}"// 删除本地镜像
sh"docker rmi 192.168.x.x:8182/demo-hello/${POM_ARTIFACTID}:${POM_VERSION}"}}}
2、Jenkins中添加HARBOR凭证
用户名:admin
密码:Harbor12345
3、Jenkins执行构建
在HARBOR中查看Push的镜像
七、参考鸣谢
[Ubuntu 20.04搭建Harbor 2.2.1私有仓库笔记记录]
解决docker删除镜像时image is referenced in multiple repositories
Docker harbor私有仓库部署与管理
Harbor仓库搭建及简单使用
部署Harbor私有镜像仓库(无坑)!
Ubuntu16.04 安装 Docker 及 docker-compose
Docker 添加–insecure-registry 私有镜像仓库
八、常见问题
1、image is referenced in multiple repositories
# 执行如下命令发生错误
docker rmi ee3742b7b6e7
Docker删除镜像时发现,两个镜像tag共用一个镜像id。如:为一个镜像打了两个标签
此时按repository和tag删除镜像即可,如:
docker rmi demo-hello:latest
2、Error response from daemon: Get https://xxxx.xxxx.xxx/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
方法一
# 添加私有镜像库
vim /usr/lib/systemd/system/docker.service
ExecStart后添加–insecure-registry 192.168.x.x:8182
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket containerd.service[Service]
Type=notify# the default is not to use systemd for cgroups because the delegate issues still
l# exists and systemd currently does not support the cgroup feature set required# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sockk
--insecure-registry 192.168.x.x:8182
方法二
# 添加私有镜像库
vim /etc/docker/daemon.json
添加"insecure-registries": [“192.168.x.x:8182”]
{"registry-mirrors":["https://lv6a8e51.mirror.aliyuncs.com"],"insecure-registries":["192.168.x.x:8182"]}
3、OCI runtime exec failed: exec failed: container_linux.go:380: starting container process
# 执行如下命令时报错,原因是有些镜像中可能没有安装bash,可换成sh试一下
dockerexec -it ee3742b7b6e7bash# 可以换如下命令在尝试一下
dockerexec -it ee3742b7b6e7 sh