Mark Ku's Blog
首頁 關於我
整合Windows Docker Desktop、Jenkins in Docker、GitHub SSH憑證與Docker Image建置佈署的開發環境
DevOps
整合Windows Docker Desktop、Jenkins in Docker、GitHub SSH憑證與Docker Image建置佈署的開發環境
Mark Ku
Mark Ku
July 02, 2023
1 min

目的

先前用 Powershell 遠端建置測試機的 DockerDesktop,開發人員一多後,發現太麻煩了,最後還是弄了Jenkins,並整合 Github 憑證及遠端佈署 DockerDesktop

開發環境說明

開發者 Push Commit 後,Github 會知 Jenkins 執行Job,並將 Github Repo 拉下來,並自動建置,最後佈署到最終的 Windows Docker Desktop 主機。

兩種常見的Jenkins 佈署Docker 的方式
兩種常見的Jenkins 佈署Docker 的方式
P.S. Watch tower 並不會主動建建立容器應用,只會抽換容器應用,第一次得自己手動建立。

首先,建立 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

  1. 新增服務文件

    sudo vim /etc/systemd/system/docker-sock-permissions.service
    
  2. 添加以下內容

    [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
    
  3. 啟用服務

    sudo systemctl enable docker-sock-permissions.service
    
  4. 啟動服務(或等待下次開機自動執行):

    sudo systemctl start docker-sock-permissions.service
    

參考資料

參考資料1
參考資料2

備忘錄 - 找回 admin 初始密碼

cat /var/jenkins_home/secrets/initialAdminPassword

Tags

Mark Ku

Mark Ku

Software Developer

10年以上豐富網站開發經驗,開發過各種網站,電子商務、平台網站、直播系統、POS系統、SEO 優化、金流串接、AI 串接,Infra 出身,帶過幾次團隊,也加入過大團隊一起開發。

Expertise

前端(React)
後端(C#)
網路管理
DevOps
溝通
領導

Social Media

facebook github website

Related Posts

透過 Jenkins pipeline 排程自動清除 Docker registry
透過 Jenkins pipeline 排程自動清除 Docker registry
November 18, 2024
1 min

Quick Links

關於我

Social Media