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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: YApi 是一个可本地部署的、打通前后端及QA的、可视化的接口管理平台 yapi.ymfe.org文章会穿插部分相关的知识点,可以节省你爬坑的时间,都是一步一步爬出来的,从定制构建的思路,优化,实现的姿势, 感兴趣的小伙伴往下走~~~


前言


yapi是什么?


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


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

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



效果图


登录



登录成功



项目区域



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自动化构建,因为是在国外服务器构建,不存在慢的问题,

下面的仅限于你本地构建的时候采纳


众所周知国外的资源都比较慢,所以我们构建优先选择境内提供的


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



  • 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 : 这句话就是非侵入式的进入容器内部,并且调用的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端口,所以我们宿主机可以用工具链接到数据库内部,

萝卜青菜各有所爱,效果图



喜欢用命令行的也一样


错误汇总


构建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…

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
20天前
|
Docker 容器
进入Docker容器中
进入Docker容器中
34 2
|
3天前
|
运维 Kubernetes Devops
构建高效自动化运维体系:DevOps与容器技术融合实践
【4月更文挑战第15天】 在当今快速发展的信息技术时代,传统的IT运维模式已难以满足业务敏捷性的需求。本文旨在探讨如何通过整合DevOps理念和容器技术来构建一个高效的自动化运维体系。文章将详细阐述DevOps的核心原则、容器技术的基础知识,以及两者结合的优势。此外,文中还将分享一系列实践经验,包括持续集成/持续部署(CI/CD)流程的搭建、微服务架构的应用,以及监控和日志管理策略的优化,以期帮助企业实现快速、可靠且安全的软件交付过程。
|
5天前
|
运维 Devops 持续交付
构建高效稳定的云基础设施:DevOps与容器化技术融合实践
【4月更文挑战第13天】 在当今快速迭代和持续部署的软件开发环境中,传统的IT运维模式已难以满足业务发展的需求。本文聚焦于如何通过融合DevOps理念与容器化技术,构建一个高效、稳定且易于管理的云基础设施。文章将探讨持续集成/持续交付(CI/CD)流程的优化、容器化技术的最佳实践、以及微服务架构下的应用管理,以期为企业提供一种改进运维效率、加速产品上市时间,同时保障系统稳定性的解决方案。
|
9天前
|
Linux Docker 容器
docker 容器常用命令
docker 容器常用命令
12 0
|
17天前
|
Kubernetes 网络协议 Docker
Docker 容器的DNS
Docker 容器的DNS
23 1
|
20天前
|
运维 Kubernetes 持续交付
构建高效自动化运维体系:基于Docker和Kubernetes的最佳实践
在现代云计算环境中,自动化运维成为保障系统稳定性与提升效率的关键。本文深入探讨了如何利用Docker容器化技术和Kubernetes容器编排工具构建一个高效、可靠的自动化运维体系。文中不仅介绍了相关的技术原理,还结合具体案例分析了实施过程中的常见问题及解决方案,为读者提供了一套行之有效的最佳实践指南。
|
20天前
|
关系型数据库 MySQL Nacos
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
【深入浅出Nacos原理及调优】「实战开发专题」采用Docker容器进行部署和搭建Nacos服务以及“坑点”
45 1
|
21天前
|
运维 Kubernetes 监控
构建高效稳定的容器化运维环境
在现代IT基础设施中,容器技术以其轻量级、快速部署和易于管理的特性成为企业数字化转型的重要支撑。本文将深入探讨如何构建一个高效且稳定的容器化运维环境,涵盖从容器选择、集群管理到持续集成与持续部署(CI/CD)的最佳实践。文章旨在为运维工程师提供一套系统的解决方案,以应对日益复杂的业务需求和技术挑战。
|
24天前
|
运维 Kubernetes 监控
构建高效稳定的云基础设施:DevOps与容器化技术融合实践
在当今云计算时代,企业追求敏捷性、可扩展性以及成本效益的云基础设施。本文将探讨如何通过DevOps文化与容器化技术的融合,打造一个既高效又稳定的运维环境。文章不仅阐述了DevOps和容器化技术各自的优势,还提供了一个具体的实施案例,展示了这种结合如何优化资源利用、提高部署速度并降低运维复杂性。
|
1月前
|
Java Go 开发者
Docker容器技术简介及其与Go语言的结合点
【2月更文挑战第23天】本文首先概述了Docker容器技术的核心概念和优势,接着探讨了Go语言与Docker容器技术的结合点。通过阐述Docker的轻量级、可移植性和版本控制等特性,以及Go语言在容器化应用中的优势,本文旨在说明两者结合能够实现更高效、灵活的应用开发和部署。