使用Docker和Jenkin進行自動化測試、部署、回滾
沒有安裝docker的可以通過docker install進行安裝。
docker jenkins
運行jenkins
首先創建一個目錄存儲容器中的信息mkdir jenkins-blue,然后執行命令sudo chown -R 1000:1000 ./jenkins-blue/,否則可能會報錯touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied,
其中用來改變./jenkins-blue/目錄下所有文件和子目錄的所有者和所屬組。1000:1000代表所有者和所屬組的用戶ID和組ID。
- 創建network
docker network create jenkins - 創建jenkins-docker
docker run --name jenkins-docker --rm --detach \
--privileged --network jenkins --network-alias docker \
--env DOCKER_TLS_CERTDIR=/certs \
--volume ./jenkins-blue/jenkins-docker-certs:/certs/client \
--volume ./jenkins-blue/jenkins-data:/var/jenkins_home \
--publish 2376:2376 \
docker:dind --insecure-registry test.com
注意一下映射的目錄是否存在。--insecure-registry test.com參數沒有配置https才需要。
3. Dockerfile
FROM jenkins/jenkins:2.426.2-jdk17
USER root
RUN apt-get update && apt-get install -y lsb-release
RUN curl -fsSLo /usr/share/keyrings/docker-archive-keyring.asc \
https://download.docker.com/linux/debian/gpg
RUN echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/docker-archive-keyring.asc] \
https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list
RUN apt-get update && apt-get install -y docker-ce-cli
USER jenkins
RUN jenkins-plugin-cli --plugins "blueocean docker-workflow"
- 構建docker鏡像
docker build -t myjenkins-blueocean:2.426.2-1 .
- 運行jenkins
docker run --name jenkins-blueocean --restart=on-failure --detach \
--network jenkins --env DOCKER_HOST=tcp://docker:2376 \
--env DOCKER_CERT_PATH=/certs/client --env DOCKER_TLS_VERIFY=1 \
--volume ./jenkins-blue/jenkins-data:/var/jenkins_home \
--volume ./jenkins-blue/jenkins-docker-certs:/certs/client:ro \
--publish 8080:8080 --publish 50000:50000 myjenkins-blueocean:2.426.2-1
通過ip:8080(記得開放一下服務器端口),訪問Jenkins,密碼保存在/path/to/jenkins-blue/jenkins-data/secrets/initialAdminPassword中。
安裝Git plugin、Pipeline和PipelineView。
點擊New Item添加一個多分支流水線的項目,在Branch Sources -> Add source -> Git中添加我們的項目git地址。
Jenkins會掃描分支中包含Jenkinsfile的分支,進行操作。
安裝Jenkins 插件
- Pipeline Utility Steps,使用其中的readJson解析json字符串。
- Git plugin
- Pipeline: Stage Step
- Pipeline: Stage View Plugin
Jenkinsfile
// 可以用來聲明全局變量
import groovy.transform.Field
String buildNumber = env.BUILD_NUMBER;
String timestamp = new Date().format('yyyyMMddHHmmss');
String projectName = env.JOB_NAME.split(/\//)[0];
userInputRegistryInfo = input(
id: 'userInputRegistryInfo', message: 'Enter path of test reports:?',
parameters: [
string(description: 'Host of docker registry',
name: 'host'),
string(description: 'dockerImage of docker registry',
name: 'dockerImage')
])
host = userInputRegistryInfo.host
dockerImage = userInputRegistryInfo.dockerImage
String version = "${buildNumber}-${timestamp}-${projectName}";
node {
checkout scm;
if(params.BuildType=='Rollback') {
return rollback()
} else if(params.BuildType=='Normal'){
return normalCIBuild(version)
} else {
setScmPollStrategyAndBuildTypes(['Normal', 'Rollback']);
}
}
def setScmPollStrategyAndBuildTypes(List buildTypes) {
def propertiesArray = [
// 構建參數
parameters([choice(choices: buildTypes.join('\n'), description: '', name: 'BuildType')]),
pipelineTriggers([[$class: "SCMTrigger", scmpoll_spec: "* * * * *"]]),
// 禁止并行構建
disableConcurrentBuilds()
];
properties(propertiesArray);
}
@Field def inputAuthValue
def normalCIBuild(String version) {
stage ('test & package') {
sh('chmod +x ./mvnw && ./mvnw clean package')
}
stage('docker build') {
inputAuthValue = getInputAuth()
echo inputAuthValue.password
sh("docker login ${host} -u ${inputAuthValue.username} -p ${inputAuthValue.password}")
sh("docker build . -t ${host}/${dockerImage}:${version}")
sh("docker push ${host}/${dockerImage}:${version}")
}
stage('deploy') {
input 'deploy?'
deployVersion(version)
}
}
def deployVersion(String version) {
// 鏈接服務器使用docker發版
sh """ssh -o StrictHostKeyChecking=no root@${host.split(':')[0]} 'docker login ${host} -u ${inputAuthValue.username} -p ${inputAuthValue.password} && \
docker rm -f container-name && \
docker run --name container-name -d -p 8081:8080 ${host}/${dockerImage}:${version}'"""
}
def rollback() {
stage('do rollback') {
def getAllTagsUri = "/v2/${dockerImage}/tags/list";
inputAuthValue = getInputAuth()
sh("docker login ${host} -u ${inputAuthValue.username} -p ${inputAuthValue.password}")
println "http://${host}${getAllTagsUri}"
def responseJson = sh(script: "curl -u ${inputAuthValue.username}:${inputAuthValue.password} --url ${host}${getAllTagsUri}", returnStdout: true)
// {name:xxx,tags:[tag1,tag2,...]}
def response = readJSON text: responseJson
def versionsStr = response.tags.join('\n');
def rollbackVersion = input(
message: 'Select a version to rollback',
ok: 'OK',
parameters: [choice(choices: versionsStr, description: 'version', name: 'version')])
println rollbackVersion
deployVersion(rollbackVersion)
}
}
// 為Docker registry設置了認證,需要手動輸入
def getInputAuth() {
def inputAuth = input(
id: 'getInputAuth', message: 'Enter username and password:?',
parameters: [
string(description: 'username of auth',
name: 'username', trim: true),
string(description: 'password of auth',
name: 'password', trim: true )
])
return inputAuth
}
Docker registry
- 安裝 htpasswd生成一個登錄registry用的賬號密碼
yum install -y httpd-tools - 生成
mkdir -p /opt/registry-var/auth/用以保存密碼 - 生成密碼保存到htpasswd中
htpasswd -Bbn username password >> /opt/registry-var/auth/htpasswd
大B - 生成
mkdir -p /opt/registry-var/config用來映射registry的config - 啟動registry
docker run -p 5001:5000 --restart=always --name=registry \
-v /opt/registry-var/config/:/etc/docker/registry/ \
-v /opt/registry-var/auth/:/auth/ \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-v /opt/registry-var/:/var/lib/registry/ registry:2.8
如果沒有配置https還需要修改一下vim /etc/docker/daemon.json,
vim中按下i變為插入模式,使用esc輸入:wq保存內容并退出。
{
"insecure-registries": [
"xxx:port"
]
}
sudo deckerd 可以啟動docker
插曲
- 服務器鏈接github慢,可以考慮
521github.com,不過生產環境應該不考慮這種,可能不安全。 - xxx.pem文件使用
mvcp命令移動到~/.ssh/目錄下并命名為id_rsa可以實現ssh role@host連接到服務器。 - 運行
ssh-add id_rsa.pem時可能沒有啟動ssh-add,可以運行
eval `ssh-agent -s`
啟動一個ssh-agent進程,-s選項告訴ssh-agent將其相關信息輸出到標準輸出。
4. Docker registry如果沒有配置https,可以在啟動容器時在命令最后加--insecure-registry test.com,或者使用命令vim /etc/docker/daemon.json(見上描述)。
5. 使用ssh鏈接服務器如提示Warning: unprotected private key file!代表用戶對私鑰權限過大,可以使用命令chmod 400 ~/.ssh/id_rsa, 400代表所有者具有只讀權限,其他用戶沒有任何權限。如需其他權限,可自行查閱。
6. 使用root用戶操作Docker容器,windowsdocker exec -ti --user root {容器名} /bin/bash,linux可以嘗試docker exec -ti --user root {容器名} sh
7. 使用PuTTY和pem文件鏈接服務器,可以在安裝目錄下尋找PuTTYgen將pem文件轉換為ppk。PuTTY添加ppk文件的路徑為 Connection -> SSH -> Auth -> Credentials -> Privite key file。然后點擊sava。
8. 在上述第7條配置后使用WinSCP可以檢測到配置進行利用。
浙公網安備 33010602011771號