從Docker 到Jenkins 到Ansible的部署經驗

[TOC]html

從Docker 到Jenkins 到Ansible的部署經驗

工做中,除了開發功能,還負責系統的部署工做。我從頻繁的部署工做中,逐漸找到了一些偷懶的方法。從傳統的Java -jar命令啓動服務,到經過Docker 容器構建部署服務,再後來經過自動化部署工具Jenkins來完成部署,最後再結合Ansible完成遠程部署。一步步的進步極大的減小部署工做,提升了工做效率。前端

Docker

簡介

Docker 是一個開源的應用容器引擎,讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的Linux機器上,也能夠實現虛擬化,容器是徹底使用沙箱機制,相互之間不會有任何接口。java

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

經常使用命令

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文件目錄spring

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鏡像和基本的啓動參數sql

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命令docker

一)、經過gradle的bootJar,將項目打包。同時須要把引入的第三方jar也要一塊兒打入到項目jar中。shell

二)、Windows系統中能夠經過Xftp將jar和Dockerfile文件拷貝同一個目錄下。Linux系統能夠經過scp命令上傳文件。npm

三)、執行docker ps,查看當前運行的容器,執行docker stop和docker rm 關閉和刪除以前舊版本的容器ubuntu

四)、找到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命令。

安裝Ansible

官網地址

$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible

使用場景

第一步:修改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

第三步:調試是否能經過ansible連同遠程服務器

sudo vim /etc/ansible/ansible.cfg
# 打開註釋
inventory = /etc/ansible/hosts
host_key_checking = False

sudo vim /etc/ansible/hosts
# 添加內容
ip ansible_ssh_user=xxx ansible_ssh_pass=xxx

# 檢查是否連同
$ ansible -m ping all              
ip | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

第四步:在Jenkins上構建編譯項目。

先後端項目的部署

到這裏,三種部署的流程就完成了。若是你熟悉Docker的方式構建,再用Jenkins和Ansible的時候,就會簡單不少。我在實際開發中,項目是先後端分離的。公司作了兩個方案,

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

第二種:把先後端放在一個項目中,一次構建完成兩個項目的打包部署。缺點是構建慢,優勢就是保證兩端的代碼都是最新的,適合發佈到預發佈環境和正式環境。

那麼,針對先後端一塊兒部署的需求,Jenkins和Ansible一樣也須要簡單的修改。其思路就是Jenkins負責編譯項目,將資源文件壓縮,再經過Ansible上傳到其餘服務器上。執行解壓,構建,啓動的命令。

看起來視乎很簡單,但有一個坑但願大家跨過去。前端打包須要npm或者其餘工具,可是你的服務器上沒有安裝。此時請務必經過Jenkins控制檯,或者用Jenkins賬號登陸服務器安裝這些工具。筆者就是經過root賬號登陸服務器安裝的npm,經過Jenkins編譯時提示沒有權限。

相關文章
相關標籤/搜索