1. 程式人生 > >從Docker 到Jenkins 到Ansible的部署經驗

從Docker 到Jenkins 到Ansible的部署經驗

從Docker 到Jenkins 到Ansible的部署經驗

工作中,除了開發功能,還負責系統的部署工作。我從頻繁的部署工作中,逐漸找到了一些偷懶的方法。從傳統的Java -jar命令啟動服務,到通過Docker 容器構建部署服務,再後來通過自動化部署工具Jenkins來完成部署,最後再結合Ansible完成遠端部署。一步步的進步極大的減少部署工作,提高了工作效率(增加了許多划水時間)。

Docker

簡介

Docker 是一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的Linux機器上,也可以實現虛擬化,容器是完全使用沙箱機制,相互之間不會有任何介面。

Docker給我的印象很深,沒有什麼環境是docker pull 解決不了的,

常用命令

docker ps           , docker ps 預設顯示執行中的容器,-a 顯示所有,-l顯示近期建立的容器

docker start xxx    , 啟動xxx容器

docker restart xxx  , 重啟xxx容器

docker run xxx      , 建立並執行xxx容器

docker build -t xxx .   ,使用 Dockerfile 建立映象

docker stop xxx     , 關閉容器

docker rm xxx       , 刪除容器

docker images       , 檢視所有映象

docker rmi xxx      , 刪除xxx映象

docker exec -it xxx sh          , 進入xxx容器中,用quit退出

docker logs -f xxx --tail 500   , 檢視xxx容器的日誌,顯示最後500行,常用命令

docker inspect xxxx             , 檢視容器配置資訊

docker-compose -f app.yml up -d , 按照app.yml檔案配置以debug形式啟動

docker-compose -f app.yml down  , 按照app.yml檔案配置形式關閉

使用場景

第一步:在gradle專案加入docker外掛,即在gradle.build 檔案中加入以下程式碼。需要注意的有外掛的版本,專案打包後的名稱,Dockerfile檔案目錄

dependencies {
    classpath("se.transmode.gradle:gradle-docker:1.2")
}

apply plugin: 'docker'

task buildDocker(type: Docker, dependsOn: build) {
    push = false
    applicationName = "專案名"
    dockerfile = file('src/main/docker/Dockerfile檔案目錄')
    doFirst {
        copy {
            from jar
            into stageDir
        }
    }
}

第二步:建立Dockerfile檔案,檔案目錄要和第一步中設定的保持一致。需要配置jdk映象和基本的啟動引數

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD 專案jar名稱.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENV PORT="6666"
ENV DB_CONNECTION="jdbc:mysql://ip:port/database"
ENV DB_USER="user"
ENV DB_PASSWORD="password"
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.datasource.url=$DB_CONNECTION --spring.datasource.usernam=$DB_USER --spring.datasource.password=$DB_PASSWORD --port=$PORT"]

第三步:將jar拷貝到伺服器上,然後執行編譯,執行的docker命令

一)、通過gradle的bootJar,將專案打包。同時需要把引入的第三方jar也要一起打入到專案jar中。

二)、Windows系統中可以通過Xftp將jar和Dockerfile檔案拷貝同一個目錄下。Linux系統可以通過scp命令上傳檔案。

三)、執行docker ps,檢視當前執行的容器,執行docker stop和docker rm 關閉和刪除之前舊版本的容器

四)、找到jar的目錄,並在當前目錄下,執行 docker build -t 映象名稱 . 的命令編譯專案,注意後面的點不要漏了。

五)、編譯成功後執行 docker run --name 容器名 -v /tmp:/tmp -p 對外開發的埠:專案啟動的埠 映象名:latest 。啟動容器

六)、執行docker ps,檢視容器啟動是否正常啟動。同時執行docker logs -f 容器名 --tail 500,檢視容器啟動日誌,檢查是否有異常

七)、最後瀏覽器訪問一下,已確保部署成功。

全稱大概需要幾分鐘的時間,雖然不算麻煩。可次數多了,就很麻煩了。有沒有什麼好的工具幫助我們完成這一系列操作呢?答案是肯定的。

Jenkins

簡介

The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.

Jenkins 的logo是一個管家的形象,很貼切。對它的理解比較膚淺。他通過管理Git上的專案,來確保每次打包的jar都是最新的。同時在構建成功後執行我們輸入的shell命令,來達到自動化部署的工作。

使用場景

第一步:建立一個負責編譯的Jenkins專案,

在Jenkins控制檯頁面,點選頁面左上角的“新建”按鈕。再輸入專案名後,可以選擇建立一個空專案,也可以在頁面最下面選擇copy from 其他專案。不管如何建立,我們需要Jenkins管理專案的原始碼,構建和構建後的操作。


第二步:建立一個負責執行的Jenkins專案

以同樣的方式建立專案,在構建觸發器上,選擇第一步建立的專案,構建的Shell命令是先刪除之前的容器,然後在重新執行容器。若之前的容器不存在,則會構建失敗。所以第一次構建的時候把第一行命令刪掉。解決方案傻乎乎的,只是因為沒有花時間去處理。


第三步:選擇編譯專案,點選立即構建,當第一個專案構成成功後,會自動觸發執行專案。等待兩個專案都成功後,就可以訪問瀏覽器,檢查功能。

有了Jenkins,一切變得輕鬆很多。但他也有一個較大的弊端,就是使用前必須要先安裝。特別是在客戶的伺服器上,也許別人就只跑這一個服務,你給別人整了一個Jenkins,似乎有點大材小用了。有沒有好的解決方法?答案是肯定的。

Ansible

簡介

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

從接觸到使用Ansible大概有一天的時間,對它的理解也是比較膚淺。我單純的認為,他可以幫助我們在伺服器之間傳輸檔案,同時還可以執行一些shell命令。抱著這樣的想法,我們可以通過Jenkins完成自動化編譯,再通過Ansible傳輸資原始檔到部署的環境中,同時執行啟動Shell命令。

使用場景

第一步:修改Jenkins執行專案的構建Shell,將之前的docker run改成

ansible-playbook ansible命令檔案路徑/app.yaml

第二步:建立Ansible指令碼檔案app.yaml,目錄和第一步中設定的儲存一致,模版大致如下

- hosts: '需要部署的遠端服務ip'
  tasks:
   - name: "關閉舊版本的容器"
     shell: docker stop xxx
     ignore_errors: true
   - name: "刪除舊版本的容器"
     shell: docker rm xxx
     ignore_errors: true
   - name: "刪除之前的舊檔案"
     shell: rm -rf /舊檔案路徑/*
   - name: "傳輸Dockerfile檔案"
     copy:
       src=/檔案目錄/Dockerfile
       dest=/遠端服務指定目錄
   - name: "傳輸Jar檔案"
     copy:
       src=/jar目錄/xxx.jar
       dest=/遠端服務指定目錄
   - name: "構建docker 映象"
     shell: chdir=/jar所在目錄 nohup docker build -t 映象名 .
   - name: "啟動容器"
     shell: nohup docker run --name 容器名 -v /掛載路徑/:/掛載路徑/ -p 對外埠:服務埠 -d 映象名:latest

第三步:在Jenkins上構建編譯專案。

前後端專案的部署

到這裡,三種部署的流程就完成了。如果你熟悉Docker的方式構建,再用Jenkins和Ansible的時候,就會簡單很多。我在實際開發中,專案是前後端分離的。公司做了兩個方案,

第一種:前後端分開部署,即Jenkins上有四個專案。前端和後端各兩個專案。這樣的好處就是前後端互不影響。不會因為對方的錯誤而從新編譯。缺點也是有的,很難保證對方部署的環境是最新的。

第二種:把前後端放在一個專案中,一次構建完成兩個專案的打包部署。缺點是構建慢,優點就是保證兩端的程式碼都是最新的,適合釋出到預釋出環境和正式環境。

那麼,針對前後端一起部署的需求,Jenkins和Ansible同樣也需要簡單的修改。其思路就是Jenkins負責編譯專案,將資原始檔壓縮,再通過Ansible上傳到其他伺服器上。執行解壓,構建,啟動的命令。

看起來視乎很簡單,但有一個坑希望你們跨過去。前端打包需要npm或者其他工具,但是你的伺服器上沒有安裝。此時請務必通過Jenkins控制檯,或者用Jenkins帳號登入伺服器安裝這些工具。筆者就是通過root帳號登入伺服器安裝的npm,通過Jenkins編譯時提示沒有許可權。