Docker折騰記: (1)構建yapi容器,從構建釋出到可用

CRPER發表於2018-07-18

前言

yapi是什麼?

YApi 是一個可本地部署的、打通前後端及QA的、視覺化的介面管理平臺 yapi.ymfe.org

文章會穿插部分相關的知識點,可以節省你爬坑的時間,都是一步一步爬出來的,

從定製構建的思路,優化,實現的姿勢, 感興趣的小夥伴往下走~~~


更新日誌

  • 2018/7/20:
    • 初始化成功的情況下會自動啟動yapi,不需要重啟yapi容器來達到啟動的效果
    • 移除shadow包,不需要用到usermod來設定預設shell了,用不到
    • 全域性npm模組增加npm@latest, 不然會報舊版本有安全隱患
    • 替換構建的源為各自官方源,在Docker Hub自動化構建,不需要考慮網速問題

效果圖

  • 登入

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • 登入成功

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • 專案區域

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • yapi容器

已經內建了bash為預設shell,vim也配置了一些常用的設定

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • vim的預設

Docker折騰記: (1)構建yapi容器,從構建釋出到可用


前置基礎

知識儲備

Docker/Linux/Node基礎, 比如Linux和docker的常用命令,shell的編寫等等

構建基礎環境

  • Docker version 18.03.1-ce
    • 基於alpine ,alpine是一個非常輕量級的Linux,裸版本只有5M
  • Docker Compose(從 pip3 安裝的預設版本)

構建的目標: 能用/能升級,資料庫獨立,第一次構建是拉取最新的版本!!!!

實用科普

若是走Docker Hub自動化構建,因為是在國外伺服器構建,不存在慢的問題,

下面的僅限於你本地構建的時候採納

眾所周知國外的資源都比較慢,所以我們構建優先選擇境內提供的

Docker中國源:

Linux映象源用的科大源

alpine的倉庫列表,官方的且支援查詢

隔天同步Github的碼雲

儘可能最小化配置,所以不配置什麼個性化的東西了,比如oh my zsh,neovim這些

通過這篇文章,你能大體學會docker的簡單部署,基本的dockerfile編寫, 以及如何釋出自己定製化的容器

我提供的yapi 映象走自動化構建,所以內部依賴的還是國際源,不在本地打包,不會有慢之說

所以要拉取的小夥伴,只要考慮docker拉取源就行啦


常規構建yapi

我這裡選擇的是基於alpine來構建, 構建的姿勢很多,

你可以從一個空容器也能從別人打包好的node容器

映象的功能儘可能保持單一化,這樣有利於編排,

若是一個映象提供多個服務,維護起來是比較麻煩的.

特別是更新亦或者需要暫停某些服務的時候,要考慮的東西很多

版本一:中規中矩

Dockfile

# 基於 alpine映象構建
FROM alpine:3.8
# 映象維護者的資訊
LABEL MAINTAINER = 'crper@outlook.com(https://github.com/crper)'
# 基礎環境構建
# - 替換國內源,速度槓槓的
# - 更新源
# - 安裝基礎環境包
# - 更改使用者的預設shell , 因為容器只是給yapi用,所以就不考慮建立使用者組和獨立使用者這種東西,所以只有root使用者了
#   ,若是容器包括多功能就需要使用者組這些好一些(不推薦容器有太多功能),儘可能保持容器功能的單一性
# - 最後是刪除一些快取
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
  && apk update \
  && apk add --no-cache shadow git nodejs nodejs-current-npm bash vim tar curl python python-dev py-pip gcc libcurl make\
  && usermod -s /bin/bash root \
  && rm -rf /var/cache/apk/*
# 克隆專案以及初始化專案
# yapi 官方的內網部署教程: https://yapi.ymfe.org/devops/index.html
# install-server會初始化資料庫索引和管理員賬號,管理員賬號名可在 config.json 配置
RUN npm i -g node-gyp --registry https://registry.npm.taobao.org \
  && npm install -g yapi-cli --registry https://registry.npm.taobao.org \
  && mkdir /yapi && cd /yapi \
  && git clone https://github.com/YMFE/yapi.git vendors  \
  && cd vendors \
  && npm install --production --registry https://registry.npm.taobao.org
# 工作目錄
WORKDIR /yapi/vendors
# 配置yapi的配置檔案
COPY config.json /yapi/
# 複製執行指令碼到容器的執行目錄
COPY entrypoint.sh /usr/local/bin/

# 向外暴露的埠
EXPOSE 3000

# 指定配置檔案
ENTRYPOINT ["entrypoint.sh"]



複製程式碼

entrypoint.sh


#!/bin/sh

# yapi初始化後會有一個init.lock檔案
lockPath="/yapi/init.lock"

# 如果初始化檔案檔案存在,則直接執行,否則初始化
if [ ! -f "$lockPath" ]; then
  node /yapi/vendors/server/install.js
else
  node /yapi/vendors/server/app.js
fi

複製程式碼

.dockerignore

這個檔案是個好東西,跟.gitignore類似的,就是專門用來忽略提交檔案的,不至於讓我們映象帶上一些不必要的東西

.git/
node_modules/
複製程式碼

本地打包映象後才發現,雖可以用,但有兩個問題暴露出來(體積,構建速度)

所以我考慮下能不能優化,


版本二:減小映象體積,減少構建時間

選一個好的父容器,一個是減少構建的層數,一個是減少依賴包

第一步不能改了,雖然也有node-alpine這些,只能從後面兩個入手

Dockfile


# 基於 alpine映象構建
FROM alpine:3.8
# 映象維護者的資訊
LABEL MAINTAINER = 'crper@outlook.com(https://github.com/crper)'
# 基礎環境構建
# - 替換國內源,速度槓槓的
# - 更新源
# - 安裝基礎環境包
# - 更改使用者的預設shell , 因為容器只是給yapi用,所以就不考慮建立使用者組和獨立使用者這種東西,所以只有root使用者了
#   ,若是容器包括多功能就需要使用者組這些好一些(不推薦容器有太多功能),儘可能保持容器功能的單一性
# - 最後是刪除一些快取
# - 克隆專案
# !! yapi 官方的內網部署教程: https://yapi.ymfe.org/devops/index.html
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories \
  && apk update \
  && apk add --no-cache shadow git nodejs nodejs-current-npm bash vim tar curl python python-dev py-pip gcc libcurl make\
  && usermod -s /bin/bash root \
  && rm -rf /var/cache/apk/* \
  && mkdir /yapi && cd /yapi && git clone https://gitee.com/mirrors/YApi.git vendors
# 工作目錄
WORKDIR /yapi/vendors
# 配置yapi的配置檔案
COPY config.json /yapi/
# 複製執行指令碼到容器的執行目錄
COPY entrypoint.sh /usr/local/bin/
# 寫好的vim配置檔案複製進去
COPY .vimrc /root/
# 向外暴露的埠
EXPOSE 3000

# 指定配置檔案
ENTRYPOINT ["entrypoint.sh"]


# `shadow`: `alpine`預設不整合`usermod`,所以需要這個額外包,因為要用來更改預設`shell`
# `vim` : 編輯神器
# `tar` : 解壓縮
# `make`: 編譯依賴的
# `gcc`:  GNU編譯器套裝
# `python`: `python python-dev py-pip`這三個包包括了基本開發環境
# `curl` 可以測試連線也能下載內容的命令列工具
# `git` : 不用說了
# `nodejs` : node
# `nodejs-current-npm` : `alpine`Linux版本需要依賴這個版本,才能讓`npm`識別到

複製程式碼

entrypoint.sh

#!/bin/sh

# yapi初始化後會有一個init.lock檔案
lockPath="/yapi/init.lock"

# 設定源為淘寶源
npm config set registry http://registry.npm.taobao.org/;

# 進入yapi專案
cd /yapi/vendors


# 如果初始化檔案檔案存在,則直接執行,否則初始化
if [ ! -f "$lockPath" ]; then
  # 全域性安裝用來更新yapi的cli
  npm i -g node-gyp yapi-cli;
  # 安裝初始化的依賴模組
  npm i --production;
  # 啟動Yapi初始化
  node server/install.js
else
  node server/app.js
fi
複製程式碼

從500多M的映象減小到400出頭,百分之二十還是挺可觀,能不能再優化下呢!!!

vim,tar,bash,shadow,py-pip都能去掉了,其他都是構建需要的(比如yapi初始化依賴python這些)

emm..... 去掉了這些,打包出來就減少了40多M,還是還原吧,優化下構建時間


版本三: 降低初始化失敗的概率

因為用了dockerhub 的自動化構建,所以npm直接在構建的時候選擇官方源

Dockerfile

# 基於 alpine映象構建
FROM alpine:latest
# 映象維護者的資訊
LABEL MAINTAINER = 'crper@outlook.com(https://github.com/crper)'
# 基礎環境構建
# - 更新源
# - 安裝基礎環境包
# - 不用更改預設shell了,只要進入的映象的時候指定shell即可
# - 最後是刪除一些快取
# - 克隆專案
# - 採用自動化構建不考慮國內npm源了 , 可以降低初始化失敗的概率
# !! yapi 官方的內網部署教程: https://yapi.ymfe.org/devops/index.html
RUN apk update \
  && apk add --no-cache  git nodejs nodejs-current-npm bash vim  python python-dev gcc libcurl make\
  && rm -rf /var/cache/apk/* \
  && mkdir /yapi && cd /yapi && git clone https://github.com/YMFE/yapi.git vendors \
  && npm i -g node-gyp yapi-cli \
  && cd /yapi/vendors && npm i --production;
# 工作目錄
WORKDIR /yapi/vendors
# 配置yapi的配置檔案
COPY config.json /yapi/
# 複製執行指令碼到容器的執行目錄
COPY entrypoint.sh /usr/local/bin/
# 寫好的vim配置檔案複製進去
COPY .vimrc /root/
# 向外暴露的埠
EXPOSE 3000

# 指定配置檔案
ENTRYPOINT ["entrypoint.sh"]


# `vim` : 編輯神器
# `tar` : 解壓縮
# `make`: 編譯依賴的
# `gcc`:  GNU編譯器套裝
# `python`: `python python-dev py-pip`這三個包包括了基本開發環境
# `curl` 可以測試連線也能下載內容的命令列工具
# `git` : 不用說了
# `nodejs` : node
# `nodejs-current-npm` : `alpine`Linux版本需要依賴這個版本,才能讓`npm`識別到

複製程式碼

entrypoint.sh

#!/bin/sh

# yapi初始化後會有一個init.lock檔案
lockPath="/yapi/init.lock"



# 進入yapi專案
cd /yapi/vendors


# 如果初始化檔案檔案存在,則直接執行,否則初始化
if [ ! -f "$lockPath" ]; then
  # 啟動Yapi初始化
  node server/install.js
else
  # 執行yapi管理系統
  node server/app.js
fi
複製程式碼

打包映象

格式: docker build [option] tagName path

docker build -t yapi .;

預設不帶:來獨立版本號,打包出來為latest

這裡的意思就是在當前目錄下,基於Dockfile構建一個映象,

你也可以自己構建你的維護版本號,比如

docker build -t yapi:0.0.1 .

若需要壓縮映象為gz格式,帶上--compress


釋出映象

常規終端手動釋出

登入賬號

這裡的賬號就是docker官方註冊的賬號,整體的過程很類似git

  • 開啟終端-> docker login

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • commit:提交你自己寫的或者二次定製的映象

規格: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] [flags]

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

  • push : 推送映象到遠端docker hub , 啊咧,報錯了?

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

提示我們沒有許可權,為什麼會有這個問題,

docker hub的提交規範需要我們用自己使用者名稱開頭,改一下即可

版本一的映象體積

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

版本二的映象體積

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

我提交的compress的版本,所以你在docker hub看到只有這麼大

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

走完這一步,你的作品就可以在Dock Hub看到了

你可以直接基於本地構建的映象搭建了,

若是你基於你自己的包再做二次構建,不需要走commit那一步也可以的,改完直接push就行了


自動化構建釋出

Docker Hub提供了automated build,簡言之就是自動化構建,

我們可以關聯github倉庫來構建,bitbucket也可以,但是我不用這個;

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

不管是從這裡還是從使用者管理那裡,都需要提前繫結github(授權)

授權後,就能讀取到你的倉庫列表.選擇一個倉庫來構建,倉庫的要求,基本目錄如下

├── .dockerignore  //docker打包忽略的檔案
├── .gitignore     //git提交忽略的檔案
├── Dockerfile     //docker 構建配置檔案
├── README.md      // 不用多說了
├── config.json    // yapi的配置檔案
└── entrypoint.sh   // 構建入口的指令碼

複製程式碼

初始化可以設定那些分支會觸發構建,亦或者觸發endpoint來構建, 最傻瓜化的就是勾選監聽push事件自動構建

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

若是你想把映象上傳到國內的阿里雲,dao這些,

有些需要註冊開發者賬號,根據他們的文件要求來提交


映象部署

寫完的作品沒法部署那就搞笑了.現在跟著我來部署你的映象以及初始化;

部署yapi

第一次初始化預設拉取的最新的版本,所以不用指定版本,

若是yapi程式碼不嚴謹,連新版本初始化都會報錯則無解!

建立volume

  • docker volume create yapi-mongo

建立一個儲存卷,用來專門存放yapi使用的mongodb的資料

為什麼要獨立出來,這是為了以後升級的著想,資料庫保留,只要啟動的時候關聯一下就行了


啟動mongodb

  • docker run -d --name yapi-mongo -v yapi-mongo:/data/db mongo

為什麼要先啟動mongodb,因為yapi初始化的時候依賴mongodb,比如建立使用者表這些

這條命令是什麼意思呢?


-d : 是啟動的時候輸出容器的id
--name : 是給容器設定一個名字,方便我們控制,比如start,stop
-v : 指定關聯的卷 => 本地卷:容器內儲存位置 , 就是對映資料儲存的地方

複製程式碼

若是需要外部管理這個資料庫的話,最好也暴露出來埠, mongodb容器預設也暴露了27017埠

  • docker run -d --name yapi-mongo -v yapi-mongo:/data/db -p 27017:27017 mongo

初始化Yapi和啟動Yapi

初始化yapi

  • docker run -d --name yapi -p 3000:3000 --link yapi-mongo crper/yapi

這裡比上面多的一個引數就是--link,用來使連個容器通訊的,過時命令,官方已經不推薦

啟動yapi

  • docker restart yapi

過程均可用docker logs details 容器ID或者name來看到內部的情況

就是shell執行過程,比如這個專案就可以在初始化的時候,看到初始化的賬號密碼(成功)

不管是mongo還是crper/yapi ,當你請求一個容器不存在的時候,

會嘗試往dockhub上面找,預設拉取映象latest版本,找不到才會報錯

以下就是基本的初始化資訊

訪問連結: 127.0.0.1:3000
預設的賬戶名: config.json =>  adminAccount 這個欄位的值
密碼: ymfe.org
複製程式碼

-----而可能發生的錯誤,就是npm掛了------

在初始化的時候,執行

docker logs --details 容器ID

檢視內部終端的執行過程,npm的一些源也不一定靠譜,

若是提示npm安裝報錯了,就需要進去換其他源了

先啟動crper/yapi映象,然後跟著教程走

// npm config set registry [url]
// npm ---- https://registry.npmjs.org/
// cnpm --- http://r.cnpmjs.org/
// taobao - http://registry.npm.taobao.org/
// eu ----- http://registry.npmjs.eu/
// au ----- http://registry.npmjs.org.au/
// sl ----- http://npm.strongloop.com/
// nj ----- https://registry.nodejitsu.com/


// 進入到vendors目錄
// 若是有node_modules目錄,
// 我們都應該先幹掉node_modules
// 這樣重新安裝依賴才會比較乾淨

// 進到vendors目錄, 比如設定回官方源
npm config set registry https://registry.npmjs.org/;

// 安裝全域性升級工具和依賴編譯的npm模組
npm i -g node-gyp yapi-cli \
npm i --production;

// 初始化 yapi
node server/install.js

複製程式碼

依賴安裝完成就可以再重新初始化,然後重啟容器即可


進入容器操作

  • docker ps : 從這個看到你的映象執行容器的資訊列表
  • docker exec -it 容器ID bash : 這句話就是非侵入式的進入容器內部,並且呼叫的shellbash,這個exit不會幹掉容器

docker attach這個命令慎用,會在終端退出的會把容器停止,這條命令是看情況使用的!!!!


升級yapi

因為不涉及到容器處理..只是單純的檔案替換,官方也提供了方案,那個cli已經預設整合到容器裡面

// https://yapi.ymfe.org/devops/index.html
cd  {專案目錄}
yapi ls //檢視版本號列表
yapi update //升級到最新版本
yapi update -v v1.1.0 //升級到指定版本
複製程式碼

升級完畢重啟node程式亦或者重啟容器即可!!

Github地址: yapi-docker


GUI管理資料庫

我們暴露了27017埠,所以我們宿主機可以用工具連結到資料庫內部,

蘿蔔青菜各有所愛,效果圖

Docker折騰記: (1)構建yapi容器,從構建釋出到可用

喜歡用命令列的也一樣


錯誤彙總

構建yapi過程發生的一些錯誤

  • /bin/sh: npm: not found , 構建的時候安裝nodejs-current-npm
  • usermod not found : 構建的時候安裝shadow
  • gyp ERR! stack Error: Can't find Python executable "python", you can set the PYTHON env variable.
    • 這個是初始化yapi遇到的,需要補全python的基礎環境,構建的時候加入相關安裝包
  • mongodb沒法訪問,就是當你配置檔案設定127.0.0.1的時候..
    • docker中,容器名預設對映容器的訪問ip,所以config.json必須指定為mongo的容器名(這個坑浪費了賊多的時間,國外的社群都蒐羅了一遍,基本都是說什麼--network這些)

還有一些錯誤忘記截圖收錄了

------------溫馨提示------------

為什麼看到的dockerfile用了大量的\來連結命令 ,

那是因為RUN一次是構建一個映象,再以此為基礎傳遞給下面二次編排,

若是裡面大量的使用了RUN,那就相當於你這個映象從頭到尾要構建很多層(體積也會變大)...官方推薦是不超過七層!!

構建層目前最多不能超過127層!

對於--link來連結容器(互相訪問),這個docker官方已經不推薦了,屬於過時特性,新的網路模式很健全,

提供了橋接,宿主,子網這些模式,但是這些並不適用於--link結合

所以,對於多容器的編排,更推薦用docker-compose來配置,可配置的東西賊多而且好維護,比如最新的3.6版本

傳送門: docs.docker.com/v17.09/comp…


總結

寫這文章各種截圖,復現過程(修改檔案,打包,執行,除錯依次重複)問題花了挺多時間(前後花了一週),

為什麼會有這個教程, 感覺能幫助挺多想試水docker的小夥伴,

所謂的"微服務"就是基於docker來實現的,保持容器功能的單一,方便維護測試

本來還想繼續寫基於docker-compose的版本,這樣文章的篇幅就太長了...抽空再寫一篇

docker-compose部署的書寫很優雅,配置一目瞭然,而且可以做比較複雜的容器編排...

有人肯定會提到Kubernetes,這貨很流行,有興趣的可以去看看,一般都是做大廠運維才會用到這貨

有不對之處亦或者改善的方案請及時留言,會及時修正和改善.感謝閱讀~~~

相關文章