用Docker简化Nodejs开发2——开发环境到测试环境

Web应用通常由多个部分组成,包括:前端、后端和基础中间件。前端代码是静态的(html+js),可以放在nginx中运行;后端业务逻辑在nodejs或java容器中运行;mysql、mongodb等通用中间件进行数据持久存储。本文以一个实际项目为例,演示如何利用docker方便运维对应用的多个部分进行发布。

项目概述

image.png

项目地址:https://github.com/jasony62/tms-mongodb-web

项目包括3个部分:

  • ue_admin:前端代码,采用VUE开发,放在nginx中独立运行
  • back:后端代码,采用nodejs开发,独立运行
  • mongodb:数据持久化,独立运行

通过docker要解决两方面问题:1、减轻开发人员个人开发环境的搭建,让项目具备单机开箱即用能力;2、实现代码和运行环境的整体发布,简化并规范运维工作。

问题1通过编写docker-compose.yml解决。相关知识可以参考前一篇文章:用Docker简化Nodejs开发1——开发环境。需要注意的是前端代码独立部署有跨域(CORS)问题,需要在nginx上设置反向代理。

本文的重点是关注问题2,通过docker实现一个完整的从开发到测试的发布流程。

image.png

基本发布流程如下:

  • 开发人员在开发环境将代码发布到git仓库;
  • 运维人员在构建环境从git仓库拉取代码;编译前端代码;分别将不同模块打包成镜像;
  • 构建环境将镜像发布到私有镜像仓库;
  • 测试环境从镜像仓库拉取镜像,启动运行;
  • 测试通过后,生产环境从镜像仓库拉取镜像,启动运行。

为演示上述过程,准备3台机器,开发,构建和测试,都安装好docker和docker-compose。

开发环境

为了让前端运行环境更干净,镜像中只包含编译完的静态内容,所以需要在制作镜像前执行命令生成前端代码(默认在dist目录)

cnpm i

yarn build 或 npm run build

ue_admin目录下的nginx.conf,back目录下的config目录不放在镜像中,它们需要在运行环境中进行指定。

docker-compose.yml

volumes:
      - ./back/config:/usr/src/app/config
volumes:
      - ./ue_admin/nginx.conf:/etc/nginx/nginx.conf:ro

If neither ‘rw’ or ‘ro’ is specified then the volume is mounted in read-write mode.

参考:https://docs.docker.com/engine/reference/run/#volume-shared-filesystems

参考:https://hub.docker.com/_/nginx

参考:https://www.nginx.com/blog/deploying-nginx-nginx-plus-docker/

参考:JS-Web项目常见问题(3)-前后端分离导致的跨域问题分析

构建环境

用树莓派3B+作为构建环境(其他环境也可以),安装docker和docker-compose,建立私有docker仓库,从github上拉取代码,制作镜像,发布镜像到私有仓库。

安装docker

sudo curl -sSL https://get.docker.com | sh

时间有些长,大约等3分钟。

按照提示执行下面的命令,否则会报权限错误。

sudo usermod -aG docker pi

安装docker-compose

通过pyenv安装python,通过pip安装docker-compose。

sudo apt install zlib1g-dev libreadline-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev

curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash

vi ~/.bash_profile

export PATH="/hom/pi/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

source ~/.bash_profile
pyenv install 3.7.0
pyenv global 3.7.0

pip install docker-compose

搭建私有镜像库

拉取(pull)arm版本的registry镜像。

docker pull budry/registry-arm

创建存储镜像文件的目录。

mkdir docker-registry

启动镜像仓库容器。

docker run --name registry-arm -d -p 5000:5000 -v /home/pi/docker-registry:/var/lib/registry --restart always budry/registry-arm

从github拉取代码

安装git(如果没有安装过)

sudo apt-get install git

从git库拉取代码。

git clone https://github.com/jasony62/tms-mongodb-web.git

编译代码

cd tms-mongodb-web/ue_admin

cnpm i

npm run build

检查是否生成dist目录。

制作镜像

官方MongoDb镜像没有树莓派的版本,需要换成rpi3-mongodb3注意,这时并不需要修改docker-compose.yml,docker支持用docker-compose.override.yml文件指定需要覆盖的选项(查看官网文档中关于-f选项的说明)。

version: '3.7'
services:
  mongodb:
    image: andresvidal/rpi3-mongodb3
    logging:
      driver: "json-file"

参考:https://hub.docker.com/r/andresvidal/rpi3-mongodb3

执行命令,生成镜像。

docker-compose build

发布镜像

在发布和获取镜像前,需要让客户端支持以http(非https)访问私库。

客户端直接在界面中设置。

image.png

在树莓派中新建文件/etc/docker/daemon.json,添加如下内容:

{ "insecure-registries": ["192.168.43.30:5000"] }

修改完成后需要重启docker才能生效。

完成上面的工作,在树莓派(私库)上查看已有的镜像。

docker images

REPOSITORY                  TAG                 IMAGE ID            CREATED             SIZE
tms-mw-ue_admin             latest              bb34d5e9ee16        13 hours ago        21.8MB
tms-mw-back                 latest              0abb9b5c6cb6        13 hours ago        162MB
nginx                       alpine              7e9d7b4eafa6        7 days ago          18.4MB
node                        alpine              30bb03f6ec2e        2 weeks ago         96.6MB
andresvidal/rpi3-mongodb3   latest              fca24dc11d8c        23 months ago       366MB
budry/registry-arm          latest              c440ef8a31ab        24 months ago       139MB

tms-mw-ue_admintms-mw-back是应用的镜像,需要发布到私有镜像库。

docker tag tms-mw-back 192.168.43.30:5000/tms-mw-back

docker push 192.168.43.30:5000/tms-mw-back

用开发机或测试机看看是否能够成功拉取镜像。

docker pull 192.168.43.30:5000/tms-mw-back

注意:可以不用tag的操作,直接在docker-compose.override.yml文件中将镜像指定为私有库镜像。

back:
  image: 192.168.43.30:5000/tms-mw-back

ue_admin:
 image: 192.168.43.30:5000/tms-mw-ue_admin

运行命令

docker-compose build

镜像版本

代码更新了就需要生成新的镜像版本,为了方便回滚等需要,可以将现有的镜像版本保留下来。

docker tag 192.168.43.30:5000/tms-mw-ue_admin:latest 192.168.43.30:5000/tms-mw-ue_admin:v1

原则上,每一次生成新版本镜像前,都应该将现有最新版本(latest)标记为一个指定版本号的镜像。

参考:https://docs.docker.com/engine/reference/commandline/tag/

测试环境

安装docker和docker-compose。

复制docker-compose.ymlue_admin/nginx.confback/config到测试环境项目根目录下。修改docker-compose.yml文件中进行的位置和文件的位置。

version: '3.7'
services:
  mongodb:
    image: mongo:latest
    container_name: tms-mw-mongo
    ports:
      - '27017:27017'
    logging:
      driver: none

  back:
    image: 192.168.43.30:5000/tms-mw-back
    container_name: tms-mw-back
    ports:
      - '3000:3000'
    volumes:
      - ./config:/usr/src/app/config
    depends_on:
      - mongodb

  ue_admin:
    image: 192.168.43.30:5000/tms-mw-ue_admin
    container_name: tms-mw-ue_admin
    ports:
      - '8080:80'
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - back

docker-compose up

如果镜像的版本更新了,需要主动拉取新版本的镜像。

docker-compose pull

开发环境

如果开发环境可以连私有仓库,那么开发环境和测试环境的部署就没有什么区别,如果不通,可以采用手工导入导出镜像的方法。

导出镜像

docker save ID > xxx.tar

导入镜像

docker load < xxx.tar

总结

通过docker可以将代码和它依赖的运行环境打包成一个整体进行发布,通过docker-compose.override.yml文件修改镜像制作参数,通过启动容器时用-v选项指定配置文件和数据目录,可以解决设置与特定运行环境相关参数的需求。

按照上面的流程基本可以实现基于docker的版本发布,但是需要手工操作的环节太多,下一步研究如何利用工具将这个过程自动化。

本系列其他文章

用Docker简化Nodejs开发1——开发环境

用Docker简化Nodejs开发3——用webhook实现自动更新

推荐阅读更多精彩内容