1.为什么需要Docker化
在业务上线的时候,常常会出现这样一个问题,明明在测试环境测试时各项功能都是通过的,但部署到生产环境中就会出现各种问题,这往往是因为测试环境和生产环境不一致导致的。Docker就可以很好的解决这个问题,Docker可以将一整套环境打包封装成镜像,无需重复配置环境,解决环境带来的种种问题。
运行在Docker容器间的应用进程是隔离的,谁也不会影响谁。这样的好处是如果一个应用出现了问题,导致CPU占100%,那其他的应用不会受到影响,因为它们之间运行的环境是相互隔离的。
DockerHub提供了很多镜像,将Docker的镜像运行起来就是一两秒的事情而已,十分方便。
2.环境准备
- 安装依赖包以及Docker
yum -y install wget yum-utils epel-release python-pip
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum -y install gcc gcc-c++ gcc-g77 autoconf automake zlib* fiex* libxml* ncurses-devel libmcrypt* libtool-ltdl-devel* cmake readline-devel openssl openssl-devel
yum -y install automake* autoconfig* pcre-devel openssl-clients libtool bridge-utils iptables-services net-tools device-mapper-persistent-data
yum -y install htop dstat speedtest screen bash-completion ncdu lvm2 lrzsz docker-ce vim
yum -y update
- 修改Docker配置文件
修改 /usr/lib/systemd/system/docker.service 配置文件,添加如下参数。端口参数与地址请按需修改。如果没有防火墙或其他访问控制规则保护,我这里设为0.0.0.0。
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
此文件为 systemctl 控制下的 Docker Daemon 的启动脚本。也可以修改/etc/docker/daemon.json文件,添加如下参数:
{
"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]
}
- 搭建自己的Docker仓库
在前面有提到jenkins通过命令把镜像push到仓库Harbor,所以这里我们需要搭建用来存放镜像的仓库:
docker run -d --restart always -p 5000:5000 --harbor -v /data/registry:/var/lib/registry registry
把新搭建的仓库设置可信赖的仓库:
vim /etc/docker/daemon.json
![image.png](https://upload-images.jianshu.io/upload_images/18025248-28302bf70a7957e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 仓库管理
当我们往仓库里push越来越多镜像的时候,可能会造成磁盘空间紧张,镜像过多不易管理等问题,这个时候我们就需要进入仓库清理一些不必要的镜像。
进入仓库:
docker exec -it --user root harbor sh
查看磁盘使用情况:
du -chs /var/lib/registry
![image.png](https://upload-images.jianshu.io/upload_images/18025248-4ce3e11e3c100100.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
清理不必要的镜像文件:
rm -rf /var/lib/registry/docker/registry/v2/repositories/pro_qqm_area/_manifests/revisions/sha256/<Folder>
- 编写Dockerfile
这是一个标准的Dockerfile示例文件:
FROM tomcat:7.0.63
ENV JAVA_OPTS '-Xms256m -Xmx512m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=128m'
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN rm -rf /usr/local/tomcat/webapps/ROOT
RUN rm -rf /usr/local/tomcat/webapps/docs
RUN rm -rf /usr/local/tomcat/webapps/examples
ADD *.war /usr/local/tomcat/webapps/
EXPOSE 8080
ENTRYPOINT ["/usr/local/tomcat/bin/catalina.sh","run"]
FROM 参数定义了 “从哪个镜像开始构建”,这里选择了现成的tomcat官方镜像。
ENV 参数指定了相对应的环境变量参数
RUN 指定了在构建过程中要执行什么命令,通常是 Linux 命令
ADD 指定了要拷贝什么文件到镜像中的什么目录
EXPOSE 指定了容器要开放哪些端口,比如 tomcat 是 8080,但这个跟 -p 参数的用法并不一样,这里是指定“容器需要开放的端口”,而不是“映射的端口”
ENTRYPOINT 指定了容器的入口点,通常的理解是“靠什么命令来启动这个容器”。因为容器是依托于服务构建的,本质是一个进程,所以 docker start必须根据入口点来启动容器(服务进程),所以这里指定tomcat的运行命令。
3.结合Jenkins和Gitlab完成代码发布
-
流程图
开发在本地修改代码后提交到gitlab —> gitlab通过webhook通知jenkins代码有改变 —> jenkins到gitlab拉取最新的代码 —>通过Sonarqube进行代码检测—>jenkins根据Dockerfile完成容器构建 —> jenkins通过构建命令把镜像push到仓库Harbor —> 在服务器上拉下镜像并运行
-
Jenkins创建任务
打开Jenkins创建一个新任务
选择要执行构建的Jenkins节点,因为我们Jenkins是多节点的,这里我选择slave_1
选git 填入gitlab上边需要持续集成的工程地址
构建触发器,勾选途中三个选项
填写Maven的打包和Build命令
构建那里选择Execute shell
docker tag $(docker images | grep -w "dev_flb_bid" | awk 'NR==1{print }') 仓库地址/dev_flb_bid:0.0.${BUILD_NUMBER}
docker push 仓库地址/dev_flb_bid:0.0.${BUILD_NUMBER}
这里shell命令的作用是,按关键字过滤并打印出IMAGE ID,然后把IMAGE ID 打个标签推送到仓库Harbor,${BUILD_NUMBER}就是Jenkins构建时生成的序列号
这个时候已经把镜像推送到了仓库,接下只需要从仓库上拉取镜像到服务器上运行即可。
构建那里再次选择Execute shell
PROJ=bid-api
IMG=dev_flb_bid
#####log start ###########
docker images;
docker container ls;
docker ps;
#####log end###########
#delete the specific container if its exsist.
if [ $( ssh dev-2 "docker ps -a | grep -w ${IMG} | wc -l" ) -ge 1 ]; then ssh dev-2 "docker rm -f $(ssh dev-2 "docker ps -a | grep "${IMG}" | awk '{print $1}'")"; fi
#启动容器
ssh dev-2 "docker run -e \"SPRING_PROFILES_ACTIVE=fat\" -d --name bid-api -p 端口:端口 -p 端口:端口 --mount type=bind,source=/data/logs,target=/logs 仓库地址/dev_flb_bid:0.0.${BUILD_NUMBER}"
#删除一些无用的image
docker images|grep none|awk '{print }'|xargs docker rmi;
到这里,一个完整的项目配置就完成了,下面就来验证一下自动部署的过程。
-
自动化部署验证
开发提交代码到Gitlab,Jenkins会自动进行一个构建任务
进入到控制台输出,可以看到具体的操作日志,开始主要是进行一些git任务
下载Maven相关的软件包
下载完成后,就开始利用maven BUILD 新的项目包
然后重建Maven容器,构建新的Image并Push到Docker私有库中
最后,重新把Docker容器拉起来
到服务器上查看,可以看到容器已经运行起来了
4.Docker的运维和维护
- 日志管理
在容器启动后,Docker Daemon 会接管容器中的主进程(通常只会在一个容器中运行一个程序)的日志记录。可以使用一下命令来查看某容器的日志
docker log -f <容器名> ####相当于tail -f
docker log --tail=200 -f <容器名> ####相当于tail -200f
- 容器详情
可以使用一下命令查看容器的详细情况:
docker inspect <容器名>
-
Portainer
如果你觉得使用命令行管理Docker不方便,可以通过Portainer来管理容器。
Portainer是一款轻量级的图形化管理工具,通过它我们可以轻松管理不同的docker环境。Portainer部署和使用都非常的简单,它由一个可以运行在任何docker引擎上的容器组成。Portainer提供管理docker的containers、images、volumes、networks等等。它兼容独立的docker环境和swarm集群模式。基本满足中小型单位对docker容器的管理工作。
可以看到,通过Portainer可以对单个或者多个容器进行管理,包括启动、停止、重启、暂停、添加等操作。
Portainer还提供日志查看、容器监控等多功能。在排查问题的时候,开发或者测试可以直接通过普通账号登录Portainer管理界面查看日志。