准备工作表明,公司近期准备了一台新的开发服务器,刚好用于实践docker的基础应用。docker的好处就不详细说了。具体可以参考阮一峰的这篇介绍。(关于Docker最好的中文介绍没有之一)。公司目前主要采用EggJs+ReactJS的技术组合,前后端分离。使用docker后,一般的部署方式如下:环境主机:阿里云系统:CentOS7.5工具Gitlab-RunnerDockerNginx在新购买的阿里云主机上运行(必须准备好域名并映射到主机的IP),直接使用root用户输入以下命令:root#yuminstallgitlab-ci-multi-runnerroot#yuminstalldockerroot#yuminstallnginx以上三个命令表示需要的软件环境已经安装完成。剩下的任务可以通过docker和gitlab-runner来完成。本文略过的gitlab的使用,请看这里Nginx的配置。nginx安装完成后,需要修改配置文件,添加需要代理的端口设置。配置文件一般放在/etc/nginx/conf.d目录下。在/etc/nginx/nginx.conf中,有这么一段代码:...include/etc/nginx/conf.d/*.conf;...意思是,都在/etc/nginx/conf中。d目录下的配置文件会被自动加载。因此,在该目录下添加一个配置文件如:service.conf。内容如下:server{listen80;server_nameyour.website.com;//这里写你配置的域名//api访问路径(http://your.website.com/api/test)location/api/test{proxy_http_version1.1;client_max_body_size100m;client_body_buffer_size128k;proxy_send_timeout300;proxy_read_timeout300;proxy_buffer_size4k;proxy_buffers1632k;proxy_busy_buffers_size64k;proxy_temp_file_write_size64k;proxy_connect_timeout30s;proxy_redirect关闭;proxy_passhttp://127.0.0.1:18001/;//api的docker转发的内部端口proxy_set_headerHost$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;}//网页访问路径(http://your.website.com/web/test)location/web/test{alias/data/www/test;//web项目文件都放在该目录下,可配置为自己的目录索引index.html;}//gitlab访问路径(http://your.website.com/gitlab),location/gitlab{proxy_http_version1.1;client_max_body_size100米;client_body_buffer_size128k;proxy_send_timeout300;proxy_read_timeout300;proxy_buffer_size4k;proxy_buffers1632k;proxy_busy_buffers_size64k;proxy_temp_file_write_size64k;proxy_connect_timeout30s;proxy_passhttp://127.0.0.1:15080/;//gitlab的docker转发的内部端口proxy_set_headerHost$host;proxy_set_headerX-Real-IP$remote_addr;proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;}}conf配置完成后,重启nginxroot#servicenginxrestartgitlabinstallationandstartup(使用Docker)通过docker安装gitlab,比传统方法简单100多倍。只需要两个简单的命令就可以开始使用:installroot#dockerpullgitlab/gitlab-ce//这里安装的是ce版本,这里没有指定版本,默认安装最新版本。你可以在这里找到你想要的版本并安装它:root#dockerpullgitlab/gitlab-ce:11.3.3-ce.0启动并使用一个简单的命令来运行和使用gitlab。首先编辑启动脚本gitlab-start.sh,比如在/srv/docker中:#!/bin/bashdockerrun--namegitlab\-d\--restartalways\-p15022:22\#暴露给nginx的外部端口,-p15080:80\#暴露给nginx的外部端口(与上面的nginx配置一致)-p15433:433\#对外暴露给nginx的端口,-v/srv/gitlab/config:/etc/gitlab\#gitlab配置文件-v/srv/gitlab/logs:/var/log/gitlab\#gitlab日志file-v/srv/gitlab/data:/opt/lib/gitlab\#gitlab数据文件gitlab/gitlab-ce使用bash执行shell文件,gitlab可以root启动#bash/srv/docker/gitlab-start.sh现在访问your.website.com/gitlab,应该可以正常访问gitlab服务了。就这么简单!使用Gitlab-Runner自动部署api项目和web项目是不一样的,所以runner也是不一样的。api项目运行在docker容器中,将文件复制到docker中即可,executor是shell类型web项目打包后的静态文件需要docker环境,executor是docker类型web项目的自动部署添加runner执行runner的注册命令,按照说明配置参数root#gitlab-ci-multi-runnerregister请输入gitlab-cicoordinatorURL(e.g.https://gitlab.com/ci):#http://your.website.com/gitlab请输入此运行器的gitlab-ci令牌:#xxxxxxxx请输入此运行器的gitlab-ci描述:#web-deploy-runner请输入此运行器的gitlab-ci标签(逗号分隔):#node-web-deployRegisteringrunner...succeededrunner=avuSXASJPleaseentertheexecutor:docker-ssh,parallels,shell,ssh,virtualbox,docker+machine,docker-ssh+machine,docker:#dockerPleaseenterthedefaultDockerimage(例如ruby??:2.1):#node:10Runner注册成功。随意启动它,但如果它已经在运行,配置应该会自动重新加载!说明一下,前两个需要分别输入gitlab的url和对应的token。这两个信息在项目的Settings->CI/CD->Runners中有记录,第三个需要runner的输入名称的第四个名称是要求输入标签。runner决定通过项目gitlab-ci.yml中的tagmark来执行CI流程(见下一步)。runner的执行者指定为docker,所以最后一个需要输入docker镜像,因为是node项目。指定镜像为node:10(版本10节点,也可以指定其他版本)。添加完成后,runner已经开始在服务中运行了。只要提交gitlab项目,相关runner会根据tags决定是否运行自动部署命令。在web项目根目录添加.gitlab-ci.yml,添加.gitlab-ci.yml文件如下:stages:-deploycache:key:${CI_BUILD_REF_NAME}paths:-node_modules/before_script:-exportPATH=/usr/local/bin:$PATH-'哪个ssh-agent||(apt-getupdate-y&&apt-getinstallopenssh-client-y)'-eval$(ssh-agent-s)-ssh-add<(echo"$SSH_PRIVATE_KEY")-mkdir-p~/.ssh-chmod700~/.ssh-echo"$SSH_KNOWN_HOSTS">~/.ssh/known_hosts-chmod644~/.ssh/known_hosts-'[[-f/.dockerenv]]&&echo-e"Host*\\n\\tStrictHostKeyCheckingno\\n\\n">~/.ssh/config'#devbranchbuilddev-deploy:stage:build标签:-node-web-deploy#这只是runner的标签内容:-dev#只有dev分支会被相应的runner脚本执行:-npminstall-npmrunbuild#web项目的打包命令-scp-rdist/*root@your.网站。com:/data/www/test-dev#复制打包的dist到部署目录#uat分支构建uat-deploy:stage:buildtags:-node-web-deploy#Thisistherunner'stagscontentonly:-uat#只有你t分支会被对应的runner脚本执行:-npminstall-npmrunbuild#web项目的打包命令-scp-rdist/*root@your.website.com:/data/www/test-uat#Will被打包的dist复制到部署目录描述文件中声明了两个部署过程,分别针对dev和uat这两个分支。打包后复制到对应的部署目录下(nginx已经映射,见上面的配置文件)。before_script部分是为scp命令做的准备工作,打包在docker内部,不能直接复制到host目录下,所以需要scp命令复制。ssh的设置如上2所述,因为是在docker内部打包的,打包后的文件只能通过scp复制到host目录下。所以需要配置SSH。参考官方例子完成这一步:1.生成SSH密钥官方文档推荐使用ed25519类型的SSH,我还是使用RSA方式root#ssh-keygen-o-trsa-b4096-C"root@your.website.com”按照提示一路回车即可完成配置。记住:不要添加密码。2.添加项目的变量在gitlab的项目设置中(Settings->CI/CD->Variables),添加SSH_PRIVATE_KEY变量,其值为上一步生成的SSH密钥对的私钥。root#vi~/.ssh/id_rsa//私钥保存在这里。复制到SSH_PRIVATE_KEY的值域后,继续添加SSH_KNOWN_HOSTS变量。该变量的值是以下命令的输出:root#ssh-keyscanyour.website.com3。SSH免密码设置上面两步完成后,Runner在运行时还是会报错。原因是虽然设置了SSH登录,但是没有设置登录免密码设置。免密登录的要点是将SSH密钥对的公钥导入到~/.ssh/authorized_keys文件中。对于这个实践,gitlab-runner和gitlab其实是在同一台服务器上完成的。因此,只需将PUBLC_KEY导入本地authorized_keys文件即可。root#cat~/.ssh/id_rsa.pub>>~/.ssh/authorized_keys经过以上3步,WEB项目的自动部署就完成了。转到http://your.website.com/web/test并尝试一下,该网页应该已启动。api项目自动部署添加runner,执行runner的注册命令,根据提示配置参数。(详见:web项目自动部署)root#gitlab-ci-multi-runnerregister请输入gitlab-cicoordinatorURL(例如https://gitlab.com/ci):#http://your.website.com/gitlab请输入此运行器的gitlab-ci令牌:#xxxxxxxx请输入此运行器的gitlab-ci描述:#api-deploy-runner请输入此运行器的gitlab-ci标签(逗号分隔):#node-api-deployRegisteringrunner...succeededrunner=avuSXASJ请输入executor:docker-ssh,parallels,shell,ssh,virtualbox,docker+machine,docker-ssh+machine,docker:#shellRunner注册成功。随意启动它,但如果它已经在运行,配置应该会自动重新加载!在api项目根目录添加.gitlab-ci.yml,添加.gitlab-ci.yml文件如下:/usr/local/bin:$PATH-npminstall#ep-devbranchbuilddeploy_dev:stage:deploytags:-仅node-api-deploy:-开发脚本:-sudodockercp./api-test:/home/service-sudodockerrestartapi-test#ep-releasebranchbuilddeploy_uat:stage:deploytags:-node-api-deployonly:-uat脚本:-sudodockercp./api-test:/home/service-sudodockerrestartapi-test可以看出上面的脚本使用docker命令将新文件复制到docker并重启docker服务来添加docker服务。以上两部分已经配置好gitlab的CI/CD,CI/CD命令中也提到我们需要使用api项目对应的docker服务。这个docker服务需要我们提前打包一个image,docker里面运行的正是api服务需要的环境。1.编辑Dockerfile在api项目根目录下,添加一个新的Dockerfile(不带后缀名)如下:FROMnode:10RUNmkdir-p/home/serviceWORKDIR/home/serviceCOPY。/home/serviceRUNnpminstallEXPOSE8102CMD["npm","start"]表示FROM指的是所使用的node环境对应的dockerimageWORKDIR,指的是docker环境中的工作目录。执行的RUN命令都是在这个目录下执行的。EXPOSE是指API服务暴露的端口号,可以写多个端口号多个EXPOSECMD是docker在启动image时执行的命令。eggjs项目默认在工作目录下执行npmstart2。在根目录下打包docker,执行以下命令打包一个imageroot#dockerbuild-tlynx/test。打包完成后,执行dockerimages可以看到打包好的docker镜像。3、执行docker服务和gitlab的使用类似,先编辑一个启动脚本/srv/docker/start-test.sh,内容如下:#!/bin/bashdockerrun-d--namenr-api-ep-dev\-p18001:8102\-v/data/api/test/logs:/home/service/logs\lynx/test使用bash执行shell文件,node服务可以启动root#bash/srv/docker/start-test.sh启动后,执行dockerps查看启动的docker任务列表。至此,已经自动部署了web和api服务。连接其他docker服务在api服务中,必须使用sql或redis等第三方服务。一种方式是将此服务安装到宿主机环境中,另一种方式是启动redis的docker服务,连接(link)服务请求(docker-compose方式本文不涉及)。使用redis本文使用docker安装redis并启动服务root#dockerpullredis//installredisroot#dockerrun-d--name=redis-p6379:6379-v/srv/redis/data:/var/lib/redisredis:latestredis-server--appendonlyyes//启动redisapi(Docker)连接redis(Docker)如果api服务需要使用redis,那么定义redis的地址为127.0.0.1是不行的,因为这两项服务目前都在docker环境中运行。上面api的docker执行命令,加上--link选项#!/bin/bashdockerrun-d--namenr-api-ep-dev\-p18001:8102\--linkredis:redis\-v/data/api/test/logs:/home/service/logs\lynx/test为了提供服务,docker运行时可以使用参数--link。注意,如果链接后想在api服务中使用redis,服务的地址要改成redis,不要改成127.0.0.1或localhost
