erp项目自动发布流程容器化设计
前言
由于公司ERP后端API项目基于Laravel框架编写,开发语言为PHP,此次记录是把现有的自动化发布流程容器化,原先自动发布流程基于 Gtilab+Jenkins+Nginx 直接发布至开发与测试环境。运行了一个月,发现还是存在一些缺点的,比如代码在开发环境运行得好好的,测试人员使用Jenkins把代码部署到测试环境时就出现了错误。测试完后,发布至生产环境又出现一些如权限、配置文件、变量等一系列问题。每换一个环境,总是有这样那样的问题,所以为了彻底解决这一问题,解放传统运维人员的双手,决定容器化整个发布流程。
一、发布流程设计
1.获取代码
2.编译(可选)
3.配置文件
4.构建镜像
5.上传镜像
6.启动容器
画张图,让大家容易理解些。
首先是,开发人员完成开发任务后,push提交代码------代码同步到Gitlab仓库后,触发Webhook通知Jenkins----Jenkins负责构建Docker镜像并推送到远程Docker仓库,推送完成后,通过SSH连接到节点服务器(Node)----在节点服务器拉取远程docker仓库的镜像,然后指定启动哪个配置文件来启动容器。整个发布流程大概就这样子,实战过程如下。
图中自己搭建的为Harbor私有仓库,不想搭建,大家可以使用阿里云提供docker仓库,功能也很强大,目前免费使用。
二、环境规划
首先整个环境确保已经部署完成Gitlab、Jenkins、Docker Registry、Docker、Nginx。部署方法不在叙述,请看百度或翻看我Blog。
角色 IP 域名 Gitlab 192.168.1.22 git.leiyan.com Jenkins/Docker 192.168.1.23 jenkins.leiyan.com Docker Registry 192.168.1.27 docker.leiiyan.com Docker/Nginx 192.168.1.31 dev.leiyan.com
.
[root@jenkins-server]# cat /etc/redhat-release && uname -a CentOS Linux release 7.5.1804 (Core) Linux jenkins-server 3.10.0-862.14.4.el7.x86_64 #1 SMP Wed Sep 26 15:12:11 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux [root@jenkins-server]# docker -v Docker version 18.09.0, build 4d60db4
三、Docker客户端配置
Docker仓库我使用的是Vmware开源的Harbor,官网,使用域名:docker.leiyan.com
部署与当前内网,因为docker 默认以https方式登陆,不支持http方式登录,所以所有Docker客户端要以http方式登陆,则需修改下配置文件。(阿里云仓库默认是https模式,不需要做此步骤)
方法一:
vim /usr/lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd \ --insecure-registry docker.leiyan.com \ #增加镜像地址
方法二:
创建/etc/docker/daemon.json
文件,在文件中指定仓库地址
cat > /etc/docker/daemon.json << EOF { "insecure-registries":["docker.leiyan.com"] } EOF
完成后从载配置,重启docker
systemctl daemon-reload systemctl restart docker
登录仓库
docker login docker.leiyan.com Username: admin Password: Login Succeeded
四、构建基础镜像
构建一个PHP代码须要环境,我直接在gitbug上找了一个: 项目地址
这个PHP+NGINX的环境镜像还不错,适合大多数PHP环境,它使用supervisord启动守护NGINX
和PHP
进程,具体使用指南可以看: https://www.qinzc.me/post-204.html
Dockerfile 内容
FROM centos:7 MAINTAINER Skiychan <dev@skiy.net> ENV NGINX_VERSION 1.15.7 ENV PHP_VERSION 7.2.13 RUN set -x && \ yum install -y gcc \ gcc-c++ \ autoconf \ automake \ libtool \ make \ cmake && \ #Install PHP library ## libmcrypt-devel DIY rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm && \ yum install -y zlib \ zlib-devel \ openssl \ openssl-devel \ pcre-devel \ libxml2 \ libxml2-devel \ libcurl \ libcurl-devel \ libpng-devel \ libjpeg-devel \ freetype-devel \ libmcrypt-devel \ openssh-server \ python-setuptools && \ #Add user mkdir -p /data/{www,phpextini,phpextfile} && \ useradd -r -s /sbin/nologin -d /data/www -m -k no www && \ #Download nginx & php mkdir -p /home/nginx-php && cd $_ && \ curl -Lk http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz | gunzip | tar x -C /home/nginx-php && \ curl -Lk http://php.net/distributions/php-$PHP_VERSION.tar.gz | gunzip | tar x -C /home/nginx-php && \ #Make install nginx cd /home/nginx-php/nginx-$NGINX_VERSION && \ ./configure --prefix=/usr/local/nginx \ --user=www --group=www \ --error-log-path=/var/log/nginx_error.log \ --http-log-path=/var/log/nginx_access.log \ --pid-path=/var/run/nginx.pid \ --with-pcre \ --with-http_ssl_module \ --without-mail_pop3_module \ --without-mail_imap_module \ --with-http_gzip_static_module && \ make && make install && \ #Make install php cd /home/nginx-php/php-$PHP_VERSION && \ ./configure --prefix=/usr/local/php \ --with-config-file-path=/usr/local/php/etc \ --with-config-file-scan-dir=/data/phpextini \ --with-fpm-user=www \ --with-fpm-group=www \ --with-mysqli \ --with-pdo-mysql \ --with-openssl \ --with-gd \ --with-iconv \ --with-zlib \ --with-gettext \ --with-curl \ --with-png-dir \ --with-jpeg-dir \ --with-freetype-dir \ --with-xmlrpc \ --with-mhash \ --enable-fpm \ --enable-xml \ --enable-shmop \ --enable-sysvsem \ --enable-inline-optimization \ --enable-mbregex \ --enable-mbstring \ --enable-ftp \ --enable-mysqlnd \ --enable-pcntl \ --enable-sockets \ --enable-zip \ --enable-soap \ --enable-session \ --enable-opcache \ --enable-bcmath \ --enable-exif \ --enable-fileinfo \ --disable-rpath \ --enable-ipv6 \ --disable-debug \ --without-pear && \ make && make install && \ #Install php-fpm cd /home/nginx-php/php-$PHP_VERSION && \ cp php.ini-production /usr/local/php/etc/php.ini && \ cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf && \ cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf && \ #Install supervisor easy_install supervisor && \ mkdir -p /var/{log/supervisor,run/{sshd,supervisord}} && \ #Clean OS yum remove -y gcc \ gcc-c++ \ autoconf \ automake \ libtool \ make \ cmake && \ yum clean all && \ rm -rf /tmp/* /var/cache/{yum,ldconfig} /etc/my.cnf{,.d} && \ mkdir -p --mode=0755 /var/cache/{yum,ldconfig} && \ find /var/log -type f -delete && \ rm -rf /home/nginx-php && \ #Change Mod from webdir chown -R www:www /data/www #Add supervisord conf ADD supervisord.conf /etc/ #Create web folder # WEB Folder: /data/www # SSL Folder: /usr/local/nginx/conf/ssl # Vhost Folder: /usr/local/nginx/conf/vhost # php extfile ini Folder: /usr/local/php/etc/conf.d # php extfile Folder: /data/phpextfile VOLUME ["/data/www", "/usr/local/nginx/conf/ssl", "/usr/local/nginx/conf/vhost", "/data/phpextini", "/data/phpextfile"] ADD index.php /data/www/ #Add ext setting to image #ADD extini/ /data/phpextini/ #ADD extfile/ /data/phpextfile/ #Update nginx config ADD nginx.conf /usr/local/nginx/conf/ #Start ADD start.sh / RUN chmod +x /start.sh #Set port EXPOSE 80 443 #Start it ENTRYPOINT ["/start.sh"] #Start web server #CMD ["/bin/bash", "/start.sh"]
开始构建
docker build -t docker.leiyan.com/erp-api/nginx .
注意:后边的点.
是Dockerfile 所在路径,Dockerfile所在路径为文件ADD进容器的根路径。
镜像构建完成后上传至Docker 仓库。
docker push docker.leiyan.com/erp-api/nginx
五、Jenkins 环境准备
1.Jenkins上,/code/data/
文件夹目录结构
2.拉取第四步构建好好的基础镜像
[root@jenkins-server ~]# docker pull docker.leiyan.com/erp-api/nginx:latest latest: Pulling from erp-api/nginx a02a4930cb5d: Pull complete af7170ef0b85: Extracting [==================================================>] 96.14MB/96.14MB 72dff1e1a3e5: Download complete 473619a99d5b: Download complete 31a15d353075: Download complete 7ded69bed07f: Download complete 2bdee6428e36: Download complete
3.jenkins执行的脚本:功能很简单,就是把,php代码,配置文件,容器运行脚本,做成镜像,并上传至Docker仓库
#!/bin/bash #Author:覃子城 #Blog:http://www.qinzc.me #Time:2019-01-09 09:30:55 #Name:devops.sh #Version:V1.0 #Description: jenkins CI shell CODEDIR=/data/code if [ -d /data/code ];then echo "-----目录存在------" else mkdir /data/code -p echo "创建目录成功" fi #拉取gitlab上的代码至当前Jenkins(请根据自身业务去做) echo "############git pull new code....#############" cd $CODEDIR rm -fr ${CODEDIR}/erp-backend git clone git@git.leiyan.com:erp/erp-backend.git #pull新代码下来后进入代码目录,,并编译更新代码(请根据自身业务去做) cd $CODEDIR/erp-backend/src /usr/local/bin/composer update #生成Dockerfile文件 echo "----------编写Dockerfile-------------" cat > $CODEDIR/Dockerfile <<EOF #基础镜像来源 FROM docker.leiyan.com/erp-api/nginx #镜像信息 MAINTAINER Qinzicheng "542129333@qq.com" #1.添加nginx.conf配置文件 #2.添加start.sh启动的脚本 #3.复制所有环境配置文件至站点目录 #4.复制PHP代码到站点目录 ADD nginx.conf /usr/local/nginx/conf/nginx.conf ADD start.sh /start.sh COPY deploy /data/ COPY "erp-backend/src" /data/www #暴露 80、443端口 EXPOSE 80 443 #运行 ENTRYPOINT "/start.sh" EOF # 开始构建镜像 docker build -t docker.leiyan.com/erp-api/nginx:$Tag $CODEDIR/. # 打印当前镜像,查看是否构建成功 echo "--------------print docker images 当前镜像 --------------" docker images # 上传到Docker 仓库 echo "-----------start push Harbor--------------" docker push docker.leiyan.com/erp-api/nginx:$Tag # 把容器删除,释放空间 echo "-------------删除镜像--------------" docker rm -f docker.leiyan.com/erp-api/nginx:$Tag docker rmi -f docker.leiyan.com/erp-api/nginx:$Tag
start.sh脚本内容如下:
https://github.com/skiy/nginx-php7/blob/master/start.sh
此脚本为原项目里的脚本,按照发布流程设计思路,我会在此脚本后面添加上,以下几行内容:
功能:就是运行容器时指定的环境变量-e CONF=xxx
,把相应的配置文件拷贝至站点目录。
代码:
if [ $CONF == "dev" ];then mv /data/dev.conf /data/www/.env elif [ $CONF == "test" ];then mv /data/test.conf /data/www/.env elif [ $CONF == "pro" ];then mv /data/pro.conf /data/www/.env fi
六、Jenkins创建项目并构建测试
1.构建一个自由风格的软件项目,创建Git Parameter 参数化构建
2.源码管理
3.构建:执行shell
4.构建测试
这里我选个我们项目最新的版本
控制台日志,显示我们构建成功啦。
镜像也传到了Docker仓库。
七、 发布
上边步骤都调通后,剩下的事情就简单了。Jenkins SSH连接进入节点,下载远程镜像仓库上对应版本的容器。启动。Game Over!
1.JenKins上增加构建步骤
上边代码:
#删除上一版本的容器 docker rm -f erp-api #下载新构建的容器 docker pull docker.leiyan.com/erp-api/nginx:$Tag #启动新容器 docker run --name erp-api -d -e CONF=dev -p 83:80 -v docker.leiyan.com/erp-api/nginx:$Tag #CONF=dev 为使用dev.conf配置文件,在步骤五中目录结构中的3个配置文件之一。 #如果写城CONF=test 就是使用test.conf配置文件
2.打开验证
知识扩展
容器启动正常后,作为后端服务使用,所以生产环境上,我是用nginx反向代理的功能,把请求都转发到对应的Docker容器上。Nginx配置我就不贴上来了,能看懂,看到这的兄嘚,Nginx反向配置不用我多说,都会的。
还有就是没有做版本回滚优化,所以按现在的情景下使用,回滚版本耗时较长需要1-3分钟,有时间大家可写个脚本优化下,大概思路就是,Jenkins上选择回滚的版本,写个判断脚本,如果本地镜像仓库存在这个版本,就启动,不存在就去远程镜像仓库上拉取后再启动。
请登录后查看评论内容