使用GitHub+Travis-CI+Docker打造自動化流水線


全文采用的是阿里雲的ESC服務器,系統是CentOS 7

示例項目是NodeJS編寫,本文主要是Docker的使用,在文章前2/3都是Docker命令介紹,最后我們會完成一個自動化的示例。

准備

注冊賬號

  1. GitHub賬號

    發布項目到GitHub

  2. Travis-CI賬號

    監聽GitHub上項目改變,將其打包發布到DockerHub

  3. DockerHub賬號

    Travis-CI將項目發布到DokcerHub時需要登陸DockerHub賬號

以上賬號自行注冊

關於如何讓Travis-CI監聽到GitHub上項目的改變,請參考這篇文章

安裝環境

  1. Git環境

  2. Docker環境

    安裝請參考官方文檔

    安裝完成后,運行下面的命令,驗證是否安裝成功。

    $ docker version
    # 或者
    $ docker info
    

    Docker 需要用戶具有 sudo 權限,為了避免每次命令都輸入sudo,可以把用戶加入 Docker 用戶組(如果你是root用戶的話就不需要了

    $ sudo usermod -aG docker $USER
    

    Docker 是服務器----客戶端架構。命令行運行docker命令的時候,需要本機有 Docker 服務。如果這項服務沒有啟動,可以用下面的命令啟動,這是Linux下啟動服務方式。

    # service 命令的用法
    $ sudo service docker start
    
    # systemctl 命令的用法
    $ sudo systemctl start docker
    

正文

了解Docker

首先學習下Docker的兩個核心知識點

container(容器)和image(鏡像)

Docker的整個生命周期由三部分組成:鏡像(image)+容器(container)+倉庫(repository

每台宿主機(電腦),他下載好了Docker后,可以生成多個鏡像,每個鏡像,可以創建多個容器。發布到倉庫(比如DockerHub)時,以鏡像為單位。可以理解成:一個容器就是一個獨立的虛擬操作系統,互不影響,而鏡像就是這個操作系統的安裝包。想要生成一個容器,就用安裝包(鏡像)生成一次,這就是Docker的核心概念。

# 列出本機的所有 image 文件。
$ docker image ls

# 刪除 image 文件
$ docker image rm [imageName]

image 文件是通用的,一台機器的 image 文件拷貝到另一台機器,為了方便共享,image 文件制作完成后,可以上傳到網上的倉庫。Docker 的官方倉庫 Docker Hub 是最重要、最常用的 image 倉庫。

image

國內連接 Docker 的官方倉庫很慢,還會斷線,需要將默認倉庫改成國內的鏡像網站

推薦使用官方鏡像 registry.docker-cn.com 。下面是 CentOS 系統的默認倉庫修改方法,其他系統的修改方法參考官方文檔

打開/etc/default/docker文件(需要sudo權限),在文件的底部加上一行,如果沒有該文件可以自己創建。

DOCKER_OPTS="--registry-mirror=https://registry.docker-cn.com"

然后,重啟 Docker 服務。

$ sudo service docker restart

現在就會自動從鏡像倉庫下載 image 文件了。

container

image 文件生成的容器實例,本身也是一個文件,稱為容器文件。也就是說,一旦容器生成,就會同時存在兩個文件: image 文件和容器文件。而且關閉容器並不會刪除容器文件,只是容器停止運行而已。

# 列出本機正在運行的容器
$ docker container ls

# 列出本機所有容器,包括終止運行的容器
$ docker container ls --all

上面命令的輸出結果之中,包括容器的 ID。很多地方都需要提供這個 ID,

使用docker container kill 命令可終止容器運行

$ docker container kill [containID]

終止運行的容器文件,依然會占據硬盤空間,可以使用docker container rm刪除。

$ docker container rm [containerID]

運行上面的命令之后,再使用docker container ls --all命令,就會發現被刪除的容器文件已經消失了。

Dockerfile 文件

學會使用 image 文件以后,接下來的問題就是,如何可以生成 image 文件?如果你要推廣自己的軟件,勢必要自己制作 image 文件,這就需要用到 Dockerfile 文件。它是一個文本文件,用來配置 image。Docker 根據 該文件生成二進制的 image 文件。

下面通過一個實例,介紹什么是 Dockerfile 文件。

實例

下面我以 這個項目 為例,介紹什么是 Dockerfile 文件,實現讓用戶在 Docker 容器里面運行 Koa 框架。

在你的服務器上克隆該項目(如果沒有Git環境記得安裝)

$ git clone https://github.com/RopeHuo/travis-ci
$ cd travis-ci

.dockerignore文件

.git
node_modules
npm-debug.log

上面代碼表示,這三個路徑要排除,不要打包進入 image 文件。如果你沒有路徑要排除,這個文件可以不要

Dockerfile文件

# 該 image 文件繼承官方的 node image,冒號表示標簽,這里標簽是8.4,即8.4版本的 node。
FROM node:8.4
# 將當前目錄下的所有文件(除了.dockerignore排除的路徑),都拷貝進入 image 文件的/app目錄。
COPY ./ /app
# 指定接下來的工作路徑為/app。
WORKDIR /app
# 在/app目錄下,運行npm install命令安裝依賴。注意,安裝后所有的依賴,都將打包進入 image 文件。
RUN npm install --registry=https://registry.npm.taobao.org
# 將容器 3000 端口暴露出來, 允許外部連接這個端口。
EXPOSE 3000
# 這一行表示等運行image時在shell中自動輸入的命令,不用我們自己再去node文件了。
CMD node hello.js

現在我們服務器上有Dokcer環境,我們通過下面的命令創建image文件

# -t參數用來指定 image 文件的名字,后面還可以用冒號指定標簽。如果不指定,默認的標簽就是latest。
$ docker image build -t travis-ci ./
# 或者
$ docker image build -t travis-ci:0.0.1 ./

如果運行成功,就可以看到新生成的 image 文件travis-ci了。

$ docker image ls

生成容器

docker container run命令會從 image 文件生成容器。

# 3000端口是上面Dockerfile文件中暴露的,8000端口是自定義的可以通過外網訪問
# -p參數:容器的 3000 端口映射到本機的 8000 端口
# -it參數:容器的 Shell 映射到當前的 Shell,然后你在本機窗口輸入的命令,就會傳入容器
# travis-ci:0.0.1:image 文件的名字(如果有標簽,還需要提供標簽,默認是 latest 標簽)
# /bin/bash:容器啟動以后,內部第一個執行的命令。這里是啟動 Bash,保證用戶可以使用 Shell
# /bin/bash也屬於CMD命令他會覆蓋我們Dockerfile文件中的CMD命令,兩者只能選一
$ docker container run -p 8000:3000 -it travis-ci /bin/bash
# 或者
$ docker container run -p 8000:3000 -it travis-ci:0.0.1 /bin/bash

如果一切正常,運行上面的命令以后,就會返回一個命令行提示符。

[你的服務器名稱]:/app#

這表示你已經在容器里面了,返回的提示符就是容器內部的 Shell 提示符。執行下面的命令。

node hello.js

這時,Koa 框架已經運行起來了。打開瀏覽器,訪問 [你的域名/ip]:8000,網頁顯示"hello world"

這個例子中,Node 進程運行在 Docker 容器的虛擬環境里面,進程接觸到的文件系統和網絡接口都是虛擬的,與本機的文件系統和網絡接口是隔離的,因此需要定義容器與物理機的端口映射(map)。

現在,在容器的命令行,按下 Ctrl + c 停止 Node 進程,然后按下 Ctrl + d (或者輸入 exit)退出容器。此外,也可以用docker container kill終止容器運行。

# 列出所有容器,不加 -a 僅列出正在運行的,像退出了的或者僅僅只是創建了的就不列出來
$ docker ps -a

# 在本機的另一個終端窗口,列出當前運行的容器,查出容器的 ID
$ docker container ls

# 停止指定的容器運行
$ docker container kill [containerID]

容器停止運行之后,並不會消失,用下面的命令刪除容器文件。

# 查出容器的 ID
$ docker container ls --all

# 刪除指定的容器文件
$ docker container rm [containerID]

CMD 命令

容器啟動以后,需要手動輸入命令node hello.js。我們可以把這個命令寫在 Dockerfile 里面,這樣容器啟動以后,這個命令就已經執行了,不用再手動輸入了。

FROM node:8.4
COPY ./ /app
WORKDIR /app
# RUN
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
# CMD
CMD node hello.js

上面有RUN命令和CMD命令,RUN命令與CMD命令的區別在哪里?簡單說,RUN命令在 image 文件的構建階段執行,執行結果都會打包進入 image 文件;CMD命令則是在容器啟動后執行。另外,一個 Dockerfile 可以包含多個RUN命令,但是只能有一個CMD命令。

注意,指定了CMD命令以后,docker container run命令就不能附加命令了(比如前面的/bin/bash),否則它會覆蓋Dockerfile中的CMD命令。現在,啟動容器可以使用下面的命令。

# 這里多了一個--rm,意思是在容器終止運行后自動刪除容器文件。
$ docker container run --rm -p 8000:3000 -it travis-ci:0.0.1

發布image

手動發布

首先,去 hub.docker.comcloud.docker.com 注冊一個賬戶。然后,用下面的命令登錄。

$ docker login

接着,為本地的 image 標注用戶名和版本。

$ docker image tag [image名稱] [你的用戶名]/[倉庫名]:[標簽]
# 例子
$ docker image tag travis-ci:0.0.1 rope/travis-ci:0.0.1

也可以不標注用戶名,重新構建一下 image 文件即可。

# 記得進入項目目錄后再操作
$ docker image build -t [username]/[repository]:[tag] ./

最后,發布 image 文件。

$ docker image push [username]/[repository]:[tag]

發布成功以后,登錄 hub.docker.com,就可以看到已經發布的 image 文件。

自動發布

我們使用gitHub+travis+docker來形成一套完整的自動化流水線

只要我們push新的代碼到gitHub上,自動幫我們構建出新的代碼發布到DockerHub,然后我們拉取新的鏡像即可

首先我們先進入 Travis CI 官網配置,注冊綁定自己的gitHub賬號,然后在左側將自己需要git push后自動構建鏡像的倉庫加入可參考這篇文章

我們繼續使用上面用到的travis-ci項目,為了驗證我們下面的操作是成功的可以將項目中的hello.js顯示的hello world改成其他內容。

查看 .travis.yml 文件

language: node_js
node_js:
  - '12'
services:
  - docker

before_install:
  - npm install

script:
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
  - docker build -t mufengsm/travis-ci:latest .
  - docker push mufengsm/travis-ci:latest

注意 :mufengsm/travis-ci應該換成你的用戶名/包名,再push代碼

每次push代碼到GitHub,Travis-CI都會下載,然后根據package.json文件下載所需包,再登陸DockerHub賬戶,再打包並發布到DockerHub,這樣你下載的鏡像就是有最新的代碼。

打開travis-ci中所監聽GitHub項目的設置頁面,然后添加兩個環境變量,這個用戶名和密碼和你的DockerHub賬戶是對應的:

DOCKER_USERNAME和DOCKER_PASSWORD

img

特別提示:這里的Docker容器,想要后台運行,就必須有一個前台進程。容器運行的命令如果不是那些一直掛起的命令(比如tcp,ping,node),就是會自動退出的,通過 docker ps -a 可以看到容器關閉的原因

當配置成功,代碼被推送到GitHub上后,travis-ci幫我們自動構建發布新鏡像

一定要學會使用: docker ps -a 查看容器的狀態

至此,發布,自動構建鏡像已經完成

拉取新的鏡像

正式開始拉取鏡像,啟動容器

我們剛才發布的鏡像名稱是:mufengsm/travis-ci

清除鏡像和容器

如果在此之前你創建了很多鏡像和容器,一個個刪除又太麻煩,下面的命令可以幫到你。

# docker中 啟動所有的容器命令
docker start $(docker ps -a | awk '{ print $1}' | tail -n +2)

#docker中 關閉所有的容器命令
docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)

#docker中 刪除所有的容器命令
docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)

#docker中 刪除所有的鏡像
docker rmi $(docker images | awk '{print $3}' |tail -n +2)
#tail -n +2 表示從第二行開始讀取

然后使用:

$ docker image pull mufengsm/travis-ci:latest

拉取鏡像,這時候需要下載,拉取完成后,使用docker images

可以看到mufengsm/travis-ci:latest鏡像已經存在了

我們使用

# --rm參數,在容器終止運行后自動刪除容器文件。
$ docker container run --rm -p 8000:3000 -it mufengsm/travis-ci:latest

創建這個鏡像的容器,並且綁定在端口號8000

瀏覽器輸入 [你的域名/ip]:8000 發現,訪問成功。

最后

我們再梳理下整個流程,創建項目,創建Dockerfile文件,創建travis.yml文件,發布到GitHub,Travis-CI監聽項目,自動打包發布到DockerHub,拉取新的鏡像,再運行。


參考文章

https://segmentfault.com/a/1190000020676601

http://www.ruanyifeng.com/blog/2018/02/docker-tutorial.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM