欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Docker折腾记: (1)构建yapi容器,从构建发布到可用

程序员文章站 2024-03-15 18:15:24
...

前言

yapi是什么?

YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台 yapi.ymfe.org

文章会穿插部分相关的知识点,可以节省你爬坑的时间,都是一步一步爬出来的,

从定制构建的思路,优化,实现的姿势, 感兴趣的小伙伴往下走~~~


更新日志

  • 2018/7/20:
    • 初始化成功的情况下会自动启动yapi,不需要重启yapi容器来达到启动的效果
    • 移除shadow包,不需要用到usermod来设置默认shell了,用不到
    • 全局npm模块增加aaa@qq.com, 不然会报旧版本有安全隐患
    • 替换构建的源为各自官方源,在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 = 'aaa@qq.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 = 'aaa@qq.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 = 'aaa@qq.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版本

传送门: https://docs.docker.com/v17.09/compose/compose-file/


总结

写这文章各种截图,复现过程(修改文件,打包,运行,调试依次重复)问题花了挺多时间(前后花了一周),

为什么会有这个教程, 感觉能帮助挺多想试水docker的小伙伴,

所谓的”微服务”就是基于docker来实现的,保持容器功能的单一,方便维护测试

本来还想继续写基于docker-compose的版本,这样文章的篇幅就太长了…抽空再写一篇

docker-compose部署的书写很优雅,配置一目了然,而且可以做比较复杂的容器编排…

有人肯定会提到Kubernetes,这货很流行,有兴趣的可以去看看,一般都是做大厂运维才会用到这货

有不对之处亦或者改善的方案请及时留言,会及时修正和改善.感谢阅读~~~