目的
先前用 Powershell 遠端建置測試機的 DockerDesktop,開發人員一多後,發現太麻煩了,最後還是弄了Jenkins,並整合 Github 憑證及遠端佈署 DockerDesktop
開發環境說明
預期開發者 Push Commit 後,Jenkins 自動將 Github Repo 拉下來,並自動建置,最後佈署到最終的 Windows Docker Desktop 主機。
首先,建立 Jenkins 環境
開啟 Powershell ,建立資料夾作為 Jenkins 的工作目錄
$workspacePath = "C:\jenkins_workspace"
New-Item -ItemType Directory -Path $workspacePath -Force | Out-Null
執行以下指令,Docker 運行 Jenkins 容器,並將 workspace 掛載到本地磁碟
docker run -d -p 8080:8080 -p 50000:50000 -v ${hostWorkspacePath}:/var/jenkins_home/workspace -v /var/run/docker.sock:/var/run/docker.sock --name jenkins --restart=always jenkins/jenkins:lts
P.S. hostWorkspacePath 為宿主主機的資料夾路徑
看到這畫面,要進去容器拿這密碼

接著,安裝建議的插件

等待安裝完成,就能使用 localhost:8080 進入 Jenkins 網頁

Manage Jenkins > Plugins >Available plugins,安裝常用套件
- SSH
- Publish Over SSH
- Msbuild
- .NET SDK Support
- Office 365 Connector Version
- PowerShell
- Docker
- Docker Pipeline
- HTTP Request
- Stage View
- Pipeline Utility Steps
- Pipeline: Input Step
因為我比較熟 docker 指令,用以下指令在 Jenkins 容器中安裝 Docker
docker logs -f jenkins // 獲得 init password
docker exec -it -uroot jenkins bash
apt-get update && apt-get -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common && curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg > /tmp/dkey; apt-key add /tmp/dkey && add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable" && apt-get update && apt-get -y install docker-ce
Jenkins Github 全域憑證設定
首先,透過 docker 指令連入 Jenkins 容器
docker exec -it -uroot jenkins bash
安裝 docker
apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
echo "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y docker-ce-cli
接著,產生ssh key,一直按 Enter 就好
ssh-keygen -t rsa -C "root"
讀取產生的公鑰,複製到github SSH and GPG keys 設定
cat /root/.ssh/id_rsa.pub
讀取產生的私鑰,複製到 Jenkins 全域設定,Manage Jenkins > Credentials > System > Global credentials (unrestricted) > Add credentials ( -----BEGIN OPENSSH PRIVATE KEY-----也要一起複製) > Create
cat /root/.ssh/id_rsa

Create 後會取得一個 ID 之後會將複製到 pipeline 中

Manage Jenkins > Security > Git Host Key Verification Configuration > No verification
到 Jenkins 的宿主主機,賦與相關資料夾
sudo chmod -R 777 /var/jenkins_home/
sudo chown $USER /var/run/docker.sock
sudo gpasswd -a $USER docker
newgrp docker
建立新的建置工作
回到 Dashboard > New Item > Pipeline

設定 Github hook trigger

撰寫
properties([pipelineTriggers([githubPush()])])
pipeline {
agent any
environment {
tag = ':latest'
imageShortName = 'next-ap'
imageName = "${imageShortName}${tag}"
containerName = "${imageShortName}-1"
containerUrl = "192.168.50.49:2375"
dockerfile = "./Dockerfile"
port = "30000:80"
}
stages {
stage("GitHub Pull") {
steps {
git branch: 'main',
credentialsId: 'b2ef50dd-xxxx-xxx-a4ef-xxx',
url: '[email protected]:markku636/ec.git/'
}
}
stage('Stop containers') {
steps {
script {
containerStatus = sh(script: "docker -H=\"${containerUrl}\" ps -a --filter=name=${containerName} -q", returnStdout: true).trim()
if (containerStatus != '') {
echo "Stopping container ${containerName}"
sh "docker -H=\"${containerUrl}\" stop ${containerName}"
} else {
echo "Container ${containerName} does not exist"
}
}
}
}
stage('Remove containers') {
steps {
script {
containerStatus = sh(script: "docker -H=\"${containerUrl}\" ps -a --filter=name=${containerName} -q", returnStdout: true).trim()
if (containerStatus != '') {
echo "Removing container ${containerName}"
sh "docker -H=\"${containerUrl}\" rm -f ${containerName}"
} else {
echo "Container ${containerName} does not exist"
}
}
}
}
stage('Remove image') {
steps {
script {
existingImages = sh(script: "docker -H=\"${containerUrl}\" images --filter=reference='${imageName}' -q", returnStdout: true).trim()
if (existingImages != '') {
echo "[Removing image] Removing the existing image.."
sh "docker -H=\"${containerUrl}\" rmi -f '${imageName}'"
} else {
echo "[Removing image] The image does not exist"
}
}
}
}
stage('Build image remotely') {
steps {
sh 'docker -H="${containerUrl}" build -t "${imageName}" . -f "${dockerfile}"'
}
}
stage('Create and start container application') {
steps {
sh 'docker -H="${containerUrl}" run -d --name "${containerName}" --restart=always -p "${port}" "${imageShortName}"'
}
}
}
}
設定這麼久,終於大功告成,自從有了容器化,建置開發環境,越來越簡單及方便遷移。

補充 - 解决Linux环境非root用户无法运行docker报错unix:///var/run/docker.sock: connect: permission denied
-
新增服務文件:
sudo vim /etc/systemd/system/docker-sock-permissions.service -
添加以下內容:
[Unit] Description=Set permissions for Docker socket After=docker.service [Service] Type=oneshot ExecStart=/bin/chmod 666 /var/run/docker.sock RemainAfterExit=true [Install] WantedBy=multi-user.target -
啟用服務:
sudo systemctl enable docker-sock-permissions.service -
啟動服務(或等待下次開機自動執行):
sudo systemctl start docker-sock-permissions.service
參考資料
備忘錄 - 找回 admin 初始密碼
cat /var/jenkins_home/secrets/initialAdminPassword






















留言