概述

想着在公司弄一套自动部署测试流程,jenkins + gitee 自动 build 已经测试成功了。

下一步就是 docker + maven + jenkins + git 打包发布了。


dockerfile

dockerfile 可以根据命令定制镜像,用来构建 docker 容器。

语法

注意:dockerfile 命令都必须用大写

  • FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
  • MAINTAINER:维护者,国际惯例:姓名+邮箱。
  • ADD/COPY:两者相似、官方推荐 COPY,将文件复制到容器中。不过 ADD 会自动解压,也蛮不错。
  • RUN:用于执行后面跟着的命令行命令。RUN是构件容器时就运行的命令以及提交运行结果。
  • VOLUME:定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。避免数据丢失、避免容器膨胀。
  • EXPOSE:声明端口。① 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。② 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
  • ENV:设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
  • WORKDIR:指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在
  • CMD:CMD是容器启动时执行的命令,在构件时并不运行,构件时紧紧指定了这个命令到底是个什么样子。如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
  • ENTRYPOINT :类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
# 基础镜像,在此基础上开始构建
FROM centos

# 维护者信息
MAINTAINER shiva

# 将jar包复制到容器指定目录下
COPY /opt/shiva-test.jar /opt/
ADD /usr/local/java/jdk-8u261-linux-x64.tar.gz /opt/

# 运行命令
RUN yum install wget
RUN tar -xzvf redis.tar.gz

# 虚拟映射,用于持久化存储数据。和挂载 -v 一样。映射地址可以通过 docker inspect ID 查看
VOLUME ["/data", "/var"]

# 暴露 8080、6379 两个端口,创建时按顺序映射端口 docker run -p 12345 -p 54321 image
# 12345:8080,54321:6379
EXPOSE 8080 6379

# 后续就可以用 NODE_VERSION 代替 7.2.0
ENV NODE_VERSION 7.2.0

# 指定工作目录,对RUN,CMD,ENTRYPOINT,COPY,ADD生效。如果不存在则会创建,也可以设置多次
WORKDIR /opt/software

PS:Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。命令越少越好。


编写 dockerfile

按需要进行构建,我按自己的需求搞一个,思路大约是:

  1. 基础镜像、维护者信息、设置变量、复制需要的压缩包到容器
  2. 在容器内执行命令,完成环境配置,暴露端口
  3. 构建运行

先准备一个 jar 包,就一个接口,以后 jar 包也会自动生成。

@RestController
public class IndexController {
    @RequestMapping(value = "index")
    public String index(){
        return "服务正在运行......";
    }
}

编写 dockerfile 文件:

FROM openjdk:8-jdk-alpine
MAINTAINER shiva<qianwei4712@163.com>
COPY demo.jar /opt/
EXPOSE 8080
WORKDIR /opt
ENTRYPOINT ["java","-jar","/opt/demo.jar"]

构建运行

当前目录下文件:

[root@kwnswba51515gqdqpz software]# ll
total 16720
-rw-r--r-- 1 root root 17102555 Aug 30 09:45 demo.jar
-rw-r--r-- 1 root root      156 Aug 30 13:34 dockerfile

构建镜像:

docker build -f dockerfile -t test/demo:1.0 .

可以在镜像列表中查看 test/demo : 1.0 的镜像,然后启动:

docker run -itd --name=testDemo -p 8081:8080 test/demo:1.0

测试访问,链接正常运行。

build 常用参数如下:

  • --build-arg=[] : 设置镜像创建时的变量;
  • -f : 指定要使用的Dockerfile路径;
  • --tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
  • --rm : 设置镜像成功后删除中间容器;

jenkins maven 插件

jenkins 先安装插件: Maven Integrationopen in new window

首先,在全局安全配置中:

  • 取消勾选 Agent → Controller Security,可以防止以下问题。这个问题在生成 Gitee WebHook 密码会出错。
HTTP ERROR 403 No valid crumb was included in the request
  • JDK 和 maven 配本地的,把自动安装取消,应该就知道填什么地址了

构建 maven项目,其他都不写了,和 jenkins npm build 一样,看以前的文章。

Goals and options可以填写下面命令。

clean compile package -Dmaven.test.skip=true

清理、编译、打包,不执行测试用例,也不编译测试用例类。

然后执行构建,测试下。

在我的工程目录 /root/.jenkins/workspace/maven test/ 下,已经生成了 target 文件夹。


全套构建测试

上面两步合在一起就行了。

  1. 在本地编写 dockerfile,和代码一起上传 git
  2. jenkins 拉代码,maven 自动打包
  3. Post Steps 中写构建后 shell 命令,执行 docker 构建、启动运行

dockerfile 要根据实际路径和版本修改:

FROM openjdk:8-jdk-alpine
MAINTAINER shiva<qianwei4712@163.com>
COPY target/demo-0.1.jar /opt/
EXPOSE 8080
WORKDIR /opt
ENTRYPOINT ["java","-jar","/opt/demo-0.1.jar"]

构建后 shell 命令也根据实际情况写:

docker build -f dockerfile -t test/demo:1.0 .
docker run -itd --name=testDemo -p 8081:8080 test/demo:1.0

考虑到会多次构建,重复生成镜像,重复创建容器。对命令进行改进:


# 先定义镜像和版本信息
DOCKERNAME='demoTest'
REPOSITORIES='demo/test'
TAG=`date +%Y%m%d-%H%M%S`

# 删除原来的容器
CONTAINER_ID=`docker ps | grep "${DOCKERNAME}" | awk '{print $1}'`
if [ -n "$CONTAINER_ID" ]; then
    docker stop $CONTAINER_ID
    docker rm $CONTAINER_ID
else #如果容器启动时失败了,就需要docker ps -a才能找到那个容器
    CONTAINER_ID=`docker ps -a | grep "${DOCKERNAME}" | awk '{print $1}'`
    if [ -n "$CONTAINER_ID" ]; then  # 如果是第一次在这台机器上拉取运行容器,那么docker ps -a也是找不到这个容器的
        docker rm $CONTAINER_ID
    fi
fi

# 删除原来的镜像
IMAGE_ID=`sudo docker images | grep ${REPOSITORIES} | awk '{print $3}'`
if [ -n "${IMAGE_ID}" ];then
    docker rmi ${IMAGE_ID}
fi

docker build -f dockerfile -t ${REPOSITORIES}:${TAG} .
docker run -itd --name=${DOCKERNAME} -p 8081:8080 ${REPOSITORIES}:${TAG}

最后测试,一切顺利。


参考文章

【狂神说Java】Docker最新超详细版教程通俗易懂_哔哩哔哩_bilibiliopen in new window

Dockerfile命令详解(超全版本) - 大周说测试 - 博客园 (cnblogs.com)open in new window

docker构建jdk1.8镜像_面朝大海,春暖花开-CSDN博客open in new window

Docker 构建jdk8 镜像 - 蓝色土耳其 - 博客园 (cnblogs.com)open in new window

自动化部署(一)jenkins+github+maven+docker(通过Dockerfile脚本部署项目) - jack-jin - 博客园 (cnblogs.com)open in new window

【docker】docker build :镜像_u010900754的专栏-CSDN博客open in new window

Dockerfile部署jar_fishinhouse的专栏-CSDN博客_dockerfile jaropen in new window

jenkins实现maven项目自动化部署tomcat - 夜枫林 - 博客园 (cnblogs.com)open in new window

Maven中-DskipTests和-Dmaven.test.skip=true的区别 - 飘飘雪 - 博客园 (cnblogs.com)open in new window

Jenkins+Docker持续集成_artaganan8的博客-CSDN博客open in new window