使用Docker一鍵部署CI、CD環境
使用Docker一鍵部署CI、CD環境
簡介 |
利用 Docker 來建立持續性整合與發佈的環境,並達到「一鍵部署」的目標。 |
作者 |
曾克維 |
使用Docker一鍵部署CI、CD環境
前言
在軟體開發的過程中,我們常常會需要導入 CI(Continuous Integration)、CD(Continuous Delivery) 流程來增加軟體開發的品質、效率。
但每次開始新的專案都需要重新部署設定 CI、CD 環境十分耗時與費力。
因此接下來我們將利用 Docker 來建立持續性整合與發佈的環境,並達到「一鍵部署」的目標。
CI、CD 架構(範例)
以下將以此架構來建立 CI、CD 的環境:
- Bitbucket - 原始碼版本控制
- Jenkins - 自動化流程控制
- Sonarqube - 原始碼掃描工具
- Postgres - 提供 Sonaqube 存取的 DB
- JBoss - Application Server
Jenkins 由 Bitbucket 取得原始碼後,交由 Sonaqube 進行安全性掃描,接者進行打包並部署至 JBoss 上。
NOTE: 此架構為簡單的範例,可依實際需求做調整
開始前準備
開始建置
Step 1:啟動 Docker
執行 Docker,查詢版本確認已啟動
$ docker version
Client:
Version: 17.09.0-ce
API version: 1.32
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:40:09 2017
OS/Arch: darwin/amd64
Server:
Version: 17.09.0-ce
API version: 1.32 (minimum version 1.12)
Go version: go1.8.3
Git commit: afdb6d4
Built: Tue Sep 26 22:45:38 2017
OS/Arch: linux/amd64
Experimental: true
Step 2:從 Docker Hub 上尋找適合的 image
兩種方式搜尋 Docker Hub 上的 image:
- 下指令搜尋
$ docker search jenkins
- 至 Docker Hub 網站搜尋
Jenkins
下圖為搜尋「Jenkins」的結果,通常若有官方提供的 image,會優先選擇。
但 Jenkins 官方提供的 image,已經被棄用不再維護,官方建議使用由 Jenkins 社群維護的 image「jenkins/jenkins:lts」。
因此我們選擇「jenkins/jenkins:lts」作為 Jenkins 的 image。
Image Tags
「jenkins/jenkins:lts」冒號左邊為 image name,右邊即是 image tag,image tag 代表此 image 的某個特定版本,若不特別指定預設為 latest 也就是最新的版本。
此處選擇的 lts 為長期維護的版本(Long Term Support)。
可點選「Tags」查看此 image 提供哪些版本:
Sonaqube
選擇 Sonaqube 官方提供的 image「sonarqube:lts」。
Postgres
選擇 Postgres 官方提供的 image「postgres」,因為沒有特別提供 lts 的版本,所以使用預設的最新版本 latest。
JBoss
因為 JBoss 官方並沒有提供公開的 image,所以接下來將示範如何自製 JBoss image,當然您也可以選擇 JBoss 的開源版本 Wildfly 來取代。
Step 3:Docker Hub 上沒有合適的 image 怎麼辦?
DIY 一個適合自己的 image 吧,以下將自製架構中的 JBoss image。
需要準備三樣東西:
- JBoss 主程式
- Dockerfile
- Docker Repository
JBoss 主程式
可至官方網站註冊開發者帳號下載取得 7.1.0 版的 zip 檔。
Dockerfile
Dockerfile 就像是 image 的設計圖,裡面定義了 image 該如何被建置,通常包含了:
- 基底映像檔資訊
- 維護者資訊
- 映像檔操作指令
- 容器啟動時執行指令
新增一個檔案名稱為 Dockerfile,內容如下:(相關語法參考)
# Use latest jboss/base-jdk:8 image as the base
FROM jboss/base-jdk:8
# Sets the Author field of the generated images
LABEL maintainer="cody.tseng@tpinformation.com.tw"
# Set the JBOSS_VERSION env variable
ENV JBOSS_VERSION 7.1.0
ENV JBOSS_HOME /opt/jboss/jboss-eap-$JBOSS_VERSION
# Checkout user to root
USER root
# Copy jboss zip file from local to container
COPY jboss-eap-$JBOSS_VERSION.zip /opt/jboss
# Add the JBoss distribution to /opt, and make jboss the owner of the extracted tar content
# Make sure the distribution is available from a well-known place
RUN cd /opt/jboss \
&& unzip jboss-eap-$JBOSS_VERSION.zip \
&& rm jboss-eap-$JBOSS_VERSION.zip \
&& chown -R jboss:0 ${JBOSS_HOME} \
&& chmod -R g+rw ${JBOSS_HOME}
# Ensure signals are forwarded to the JVM process correctly for graceful shutdown
ENV LAUNCH_JBOSS_IN_BACKGROUND true
# Checkout user to jboss
USER jboss
# Add a user in administration realm
RUN ${JBOSS_HOME}/bin/add-user.sh admin Admin#007 --silent
# Expose the ports we're interested in
EXPOSE 8080 9990
# Set the default command to run on boot
# This will boot JBoss EAP in the standalone mode and bind to all interface
CMD ${JBOSS_HOME}/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0
Docker Repository
在 Docker Hub 上新增管理 JBoss image 的 repository:
- 登入 Docker Hub,然後點選「Create Repository」
- 輸入 image 名稱「jboss」,然後點選「Create」
- 完成後即可看到頁面如下:
Build image
將寫好的 Dockerfile、JBoss 的 zip 檔放在同目錄下,然後在目錄下輸入指令「docker build -t $NAME:$TAG $DIR_PATH」建立 image,最後輸入「docker push $NAME:$TAG」將建好的 image 推送到我們建好的 Repository
$ ls
Dockerfile jboss-eap-7.1.0.zip
# 根據當前目錄下的 Dockerfile 建立 image
$ docker build -t cody81314/jboss:7.1.0 .
# 將 image 推送至 repository
$ docker push cody81314/jboss:7.1.0
完成後至 Repository 的「Tags」頁籤,即可看到剛剛建立好的 image 已經推送上去了。
Step 4:編輯 docker-compose.yml 檔
Docker Compose 是一個可以定義如何啟動多個容器的工具。
可以藉由定義一個 YAML 檔來配置應用程式服務。
定義完成後即可使用一行指令來創建、啟動這些服務。
主要包含三個部分:
- services
- networks
- volumes
以下就新增一個名為「docker-compose.yml」的 YAML 檔(預設路徑為 ./docker-compose.yml)來配置我們的 CI、CD 架構:
version: "3.3"
services:
jenkins:
image: jenkins/jenkins:lts
container_name: 'DevOps_jenkins'
ports:
- "18080:8080"
- "50000:50000"
networks:
- jenkinsnet
volumes:
- ./jenkins_home:/var/jenkins_home
sonarqube:
image: sonarqube:lts
container_name: 'DevOps_sonarqube'
ports:
- "9000:9000"
networks:
- sonarnet
- jenkinsnet
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- sonarqube_bundled-plugins:/opt/sonarqube/lib/bundled-plugins
db:
image: postgres
container_name: 'DevOps_postgres'
networks:
- sonarnet
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- postgresql:/var/lib/postgresql
# This needs explicit mapping due to https://github.com/docker-library/postgres/blob/4e48e3228a30763913ece952c611e5e9b95c8759/Dockerfile.template#L52
- postgresql_data:/var/lib/postgresql/data
jboss:
image: cody81314/jboss:7.1.0
container_name: 'DevOps_jboss'
ports:
- "28080:8080"
- "9990:9990"
networks:
- jenkinsnet
networks:
sonarnet:
driver: bridge
jenkinsnet:
driver: bridge
volumes:
sonarqube_conf:
sonarqube_data:
sonarqube_extensions:
sonarqube_bundled-plugins:
postgresql:
postgresql_data:
NOTE: 副檔名使用 .yml
或 .yaml
都可以
version
定義 compose 檔的格式版本,詳細「格式版本」與「Docker Engine 版本」的對應如下:
Compose file format | Docker Engine release |
---|---|
3.7 | 18.06.0+ |
3.6 | 18.02.0+ |
3.5 | 17.12.0+ |
3.4 | 17.09.0+ |
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
1. services
定義各個「服務」的配置區塊,在上面範例中我們定義了四個服務分別為:
- jenkins
- sonarqube
- db
- jboss
1-1. image
指定建立 Container 的來源映像檔、Tag(版本)
1-2. container_name
指定自定義的容器名稱,而不是系統自動生成的預設名稱
1-3. ports
設定對外的端口與容器端口的對應,以格式HOST:CONTAINER
做設定:
- HOST:公開釋出的端口
- CONTAINER:容器內的端口
1-4. networks
指定要加入的網路,此處指定的網路需被定義在與services
同層的networks
區塊
1-5. environment
針對各個服務指定環境變數
1-6. volumes
可指定一個「本機位置」或「參考名稱」對單一服務掛載 volumes,但若是要多個服務共用同一個 volumes,則需要在最上層的 volumes 宣告名稱。
範例中,jenkins 服務有指定「本機位置」來掛載容器內的「/var/jenkins_home」,來保存配置設定,確保之後無論將服務搬移至哪台主機都能將原有的 jenkins 配置資料再掛載上去。
2. networks
最上層 networks 的可指定要創建的網路,在上面範例中我們定義了兩個網路分別為:
- sonarnet
- jenkinsnet
2-1. driver
指定應該為此網絡使用哪個驅動程序,若在單一主機上通常使用 bridge
3. volumes
最上層的 volumes,定義可跨多個服務使用的 volumes 名稱
一鍵部署
Step 1:建立 Workspace
在一個空目錄下(此處為 Docker)準備以下內容:
- 編輯完成的 docker-compose.yml
- 目錄 jenkins_home(Jenkins 配置的內容都會同步到此資料夾中)
因此若是想要在一台新主機上部署,但又不想重新設定 Jenkins,只需要將舊主機上的 jenkins_home 目錄複製到新主機並且掛載上去即可。
反之若要重新設定,則新增一個空的 jenkins_home 目錄即可。
Step 2:執行 docker-compose up
在 Workspace 目錄下執行:
$ docker-compose up
就會開始依照 docker-compose.yml 裡的配置的內容進行配置
Step 3:完成部署
- Jenkins
- SonarQube
- JBoss