Docker折腾记: 构建yapi容器,从构建发布到可用
Posted crper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Docker折腾记: 构建yapi容器,从构建发布到可用相关的知识,希望对你有一定的参考价值。
前言
yapi是什么?
YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台 yapi.ymfe.org
文章会穿插部分相关的知识点,可以节省你爬坑的时间,都是一步一步爬出来的,
从定制构建的思路,优化,实现的姿势, 感兴趣的小伙伴往下走~~~
-
yapi(Docker Hub): crper/yapi
-
Github地址: yapi-docker
效果图
登录
登录成功
项目区域
yapi容器
已经内置了bash
为默认shell
,vim也配置了一些常用的设置
- vim的预设
前置基础
知识储备
Docker
/Linux
/Node
基础, 比如Linux和docker的常用命令,shell
的编写等等
构建基础环境
Docker version 18.03.1-ce
- 基于
alpine
,alpine
是一个非常轻量级的Linux
,裸版本只有5M
- 基于
Docker Compose
(从pip3
安装的默认版本)
构建的目标: 能用/能升级,数据库独立,第一次构建是拉取最新的版本!!!!
实用科普
若是走Docker Hub
自动化构建,因为是在国外服务器构建,不存在慢的问题,
下面的仅限于你本地构建的时候采纳
众所周知国外的资源都比较慢,所以我们构建优先选择境内提供的
尽可能最小化配置,所以不配置什么个性化的东西了,比如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"]
#!/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`识别到
#!/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`识别到
#!/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
commit
:提交你自己写的或者二次定制的镜像
规格: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] [flags]
push
: 推送镜像到远程docker hub
, 啊咧,报错了?
提示我们没有权限,为什么会有这个问题,
docker hub
的提交规范需要我们用自己用户名开头,改一下即可
版本一的镜像体积
版本二的镜像体积
我提交的compress
的版本,所以你在docker hub
看到只有这么大
走完这一步,你的作品就可以在Dock Hub看到了
你可以直接基于本地构建的镜像搭建了,
若是你基于你自己的包再做二次构建,不需要走commit
那一步也可以的,改完直接push
就行了
自动化构建发布
Docker Hub
提供了automated build
,简言之就是自动化构建,
我们可以关联github
仓库来构建,bitbucket
也可以,但是我不用这个;
不管是从这里还是从用户管理那里,都需要提前绑定github
(授权)
授权后,就能读取到你的仓库列表.选择一个仓库来构建,仓库的要求,基本目录如下
├── .dockerignore //docker打包忽略的文件
├── .gitignore //git提交忽略的文件
├── Dockerfile //docker 构建配置文件
├── README.md // 不用多说了
├── config.json // yapi的配置文件
└── entrypoint.sh // 构建入口的脚本
初始化可以设置那些分支会触发构建,亦或者触发endpoint
来构建,
最傻瓜化的就是勾选监听push
事件自动构建
若是你想把镜像上传到国内的阿里云
,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
: 这句话就是非侵入式的进入容器内部,并且调用的shell
为bash
,这个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端口,所以我们宿主机可以用工具链接到数据库内部,
萝卜青菜各有所爱,效果图
喜欢用命令行的也一样
错误汇总
构建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
,这货很流行,有兴趣的可以去看看,一般都是做大厂运维才会用到这货
有不对之处亦或者改善的方案请及时留言,会及时修正和改善.感谢阅读~~~
以上是关于Docker折腾记: 构建yapi容器,从构建发布到可用的主要内容,如果未能解决你的问题,请参考以下文章
.NET ----记Docker部署asp.net mvc项目
在构建期间将文件从 GCS 复制到 Cloud Run docker 容器中