关于docker:为了实现CICD先来定制一个Docker镜像实战精华篇

3次阅读

共计 5243 个字符,预计需要花费 14 分钟才能阅读完成。

背景

打算把手头的我的项目逐渐革新为基于 Docker 容器的形式公布,同时,我的项目中曾经采纳了云厂商提供的 CI/CD 自动化公布流水线。因而,为配合 CI/CD 操作,须要先针对我的项目构建一些公布的脚本,通过脚本来自动化操作 Docker 镜像定制、Docker 的启动和进行。

在浏览和实际本篇文章之前,如果你还未搭建 Docker 的环境,可参考上篇文章《Linux 装置 Docker 残缺教程》,先把整个环境搭建起来,同时相熟一下 Docker 的基本操作命令。

这篇文章就配合具体的实际案例来为大家讲讲如何定制一个 Docker 镜像,并通过脚本来执行镜像的构建、我的项目的公布、容器的启动与进行等。

什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容蕴含了一条条构建镜像所需的指令和阐明。常见的指令比方有:FROM、RUN、ADD、COPY、CMD、ENV 等。

在镜像构建时,须要留神的一点是:镜像的构建是一层层构建的,前一层是后一层的根底。每一层构建完就不会再产生扭转,后一层上的任何扭转只产生在本人这一层。

像下面提到的指令,每一次操作都会构建一层。比方删除前一层的文件,在最终容器运行时,尽管看不到这个文件,然而实际上该文件会始终追随镜像。因而,在构建镜像时,须要额定小心,每一层尽量只蕴含该层须要增加的货色,任何额定的货色应该在该层构建完结前清理掉。

另外,为了缩小构建层的数量,在编写 Dockerfile 文件时尽量将多层的指令合并成一层执行,比方两个 RUN 命令能够通过 && 将其合并成一条。

不倡议的镜像制作形式

制作 Docker 镜像通常有两种形式:基于 docker commit 和基于 Dockerfile 的模式。

Docker 提供了一个 docker commit 命令,能够将容器的存储层保留下来成为镜像。换句话说,就是在原有镜像的根底上,再叠加上容器的存储层,并形成新的镜像。后续运行这个新镜像时,就会领有原有容器最初的文件变动。

docker commit的形式除了学习之外,还能够用于一些非凡的场景,比方被入侵后保留现场等。然而不要应用 docker commit 定制镜像,定制镜像应该应用 Dockerfile 来实现。

这是因为在应用 docker commit 制作镜像时,除了咱们想要批改的内容(文件)之外,该命令还会批改一些其余的文件,而且所有对镜像的操作都是黑箱操作,生成的镜像也被称为 黑箱镜像

除了制作镜像的人晓得执行过什么命令、怎么生成的镜像,他人基本无从得悉。即便制作镜像的人,一段时间后可能也无奈记清具体的操作。这种黑箱镜像的保护工作是十分苦楚的。

另外,如果应用 docker commit 制作镜像,以及前期批改的话,每一次批改都会让镜像更加臃肿一次,所删除的上一层的货色并不会失落,会始终如影随形的跟着这个镜像,即便根本无法拜访到。这会让镜像更加臃肿。

因而,这里咱们不采纳 docker commit 的形式制作镜像,如果大家感兴趣的话,能够在网络上查问一下该形式的制作流程。本文重点介绍基于 Dockerfile 的形式来制作镜像,上面就以实例展现一下如何构建一个 Docker 镜像。

Dockerfile 指令编写

在 /opt 目录下创立一个业务目录 /opt/channel/docker(这里部署的我的项目为渠道我的项目,取名 channel),在该目录下寄存 Dockerfile、待发布的 jar 包等资源文件。

$ cd /opt/channel/docker
$ touch Dockerfile

上述指令先进入 /opt/channel/docker 目录、创立了一个空的 Dockerfile(文本)文件。

编辑 Dockerfile 内容如下:

FROM java:8
COPY ./hqy-service-channel.jar ./app.jar
ENV spring.profiles.active prod
EXPOSE 8190
ENTRYPOINT ["java", "-jar","-Duser.timezone=GMT+08", "./app.jar"]

Dockerfile 中波及到 FROM、COPY、ENV、EXPOSE、ENTRYPOINT 五个指令,上面逐个解说。

FROM 指令

所谓制作镜像,就是在曾经存在的镜像的根底上进行定制。根底镜像是必须指定的,而 FROM 就是指定 根底镜像,因而一个 DockerfileFROM 是必备的指令,并且必须是第一条指令。

这里的FROM java:8,也就是采纳 openjdk 在 Docker 镜像源中的镜像,版本为 8。能够通过 search 命令查看一下这个镜像:

[docker]# docker search java
NAME                                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
node                                 Node.js is a JavaScript-based platform for s…   11734     [OK]
tomcat                               Apache Tomcat is an open source implementati…   3368      [OK]
openjdk                              "Vanilla" builds of OpenJDK (an open-source …   3362      [OK]
java                                 DEPRECATED; use "openjdk" (or other JDK impl…   1976      [OK]

第 4 个 name 为 java 的便是,为了不便前面操作,这里间接将镜像 pull 到本地。

docker pull java:8

查看本地 pull 之后,本地的镜像列表:

[root@iZ2zehx0enix3i0aiea7p0Z docker]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
java         8         d23bdf5b1b1b   5 years ago     643MB

后续执行镜像制作时便以该镜像为根底进行构建。

COPY 指令

COPY,复制指令,从上下文目录中复制文件或者目录到容器里指定门路。

COPY ./hqy-service-channel.jar ./app.jar

其中第一个参数为源文件门路,第二个参数为容器内指标文件门路。这里是将当前目录下的 Spring Boot 我的项目 jar 包 hqy-service-channel.jar,复制到容器内并命名为 app.jar。在执行创立镜像命令之前,须要把我的项目 jar 包放到 Dockerfile 同级目录下。

ENV 指令

ENV指令,用于设置环境变量,定义了环境变量,那么在后续的指令中,就能够应用这个环境变量。

根本格局为:

ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...

第一个参数为变量 key,第二个参数为变量值,这里用于设置 SpringBoot 我的项目的配置文件的 profile 为 prod(生产配置文件)。

EXPOSE 指令

EXPOSE指令,仅仅只是申明端口。作用是帮忙镜像使用者了解这个镜像服务的守护端口,以不便配置映射。另外,在运行时应用随机端口映射时,也就是 docker run -P 时,会主动随机映射 EXPOSE 的端口。

根本格局:

EXPOSE < 端口 1 > [< 端口 2 >...]

这里采纳了 8190 端口。

ENTRYPOINT 指令

ENTRYPOINT指令,相似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所笼罩,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。在执行 docker run 时能够指定 ENTRYPOINT 运行所需的参数。

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

这里应用 ENTRYPOINT 指令来执行 jar -jar 启动 SpringBoot 我的项目。

RUN 指令

RUN指令尽管在实例中没用到,但也是十分常见的一个指令,于执行前面跟着的命令行命令,有以下两种格局。

shell 格局:

RUN < 命令行命令 >
# < 命令行命令 > 等同于,在终端操作的 shell 命令。

exec 格局:

RUN ["可执行文件", "参数 1", "参数 2"]
# 例如:# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

通过上述一系列的操作,Dockerfile 文件编写结束。在构建命令时值得注意的是:依照 Docker 最佳实际的要求,容器不应该向其存储层内写入任何数据,容器存储层要放弃无状态化。所有的文件写入操作,都应该应用数据卷(Volume)、或者绑定宿主目录,在这些地位的读写会跳过容器存储层,间接对宿主(或网络存储)产生读写,其性能和稳定性更高。

构建镜像

下面筹备好了 Dockerfile 文件,再把对应的 jar 包放在指定的地位,可在 Dockerfile 文件的目录执行构建命令,比方:

docker build -t channel .

其中 -t channel 指定了构建镜像的名称,当然也能够同时指定版本编号-t channel:v1。前面的“.”指的是当前目录。

执行成果如下:

[docker]# docker build -t channel .
Sending build context to Docker daemon  82.31MB
Step 1/5 : FROM java:8
 ---> d23bdf5b1b1b
Step 2/5 : COPY ./hqy-service-channel.jar ./app.jar
 ---> 10cb376c7572
Step 3/5 : ENV spring.profiles.active test
 ---> Running in ca70651b21b6
Removing intermediate container ca70651b21b6
 ---> ec420f94df51
Step 4/5 : EXPOSE 8190
 ---> Running in 318e718d552a
Removing intermediate container 318e718d552a
 ---> 6746bad4a990
Step 5/5 : ENTRYPOINT ["java", "-jar","-Duser.timezone=GMT+08", "./app.jar"]
 ---> Running in 135de4d42ec8
Removing intermediate container 135de4d42ec8
 ---> 1720afb4fec7
Successfully built 1720afb4fec7
Successfully tagged channel:latest

执行 docker images 可查看到镜像构建结束:

[docker]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
channel      latest    1720afb4fec7   51 seconds ago   725MB
java         8         d23bdf5b1b1b   5 years ago      643MB

后续便能够通过 docker run 命令来启动容器了。

这里为了不便 CI/CD 操作,咱们能够通过脚本来实现整个容器进行、容器移除、镜像的移除、镜像的从新制作以及容器的重新启动,这样 CI/CD 的零碎只用调用对应的脚本即可。

示例脚本 start.sh 如下:

#!/bin/bash
# 进行容器
docker stop channel
echo "进行容器 success!"
# 移除容器
docker rm channel
echo "移除容器 success!"
# 移除镜像
docker rmi channel
echo "移除镜像 success!"
# 制作镜像
docker build -t channel /opt/channel/docker/
echo "制作镜像 success!"
# 启动容器
docker run -d --name channel -p 8190:8190 -v /opt/channel/logs/:/opt/channel/logs/ channel channel:latest
echo "启动 success!"

执行上述脚本之后,查看容器执行后果:

[bin]# docker ps
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                    NAMES
e9eff75cdb6f   channel   "java -jar -Duser.ti…"   30 seconds ago   Up 28 seconds   0.0.0.0:8190->8190/tcp   channel

能够看到容器曾经胜利启动。当从新构建新的 jar 包时,只需对目录中的 jar 包进行替换,而后再执行一遍 start.sh 命令即可。

小结

本文带大家以具体的实例演示了如何制作 Docker 镜像,在制作 Docker 镜像过程中须要留神的事项,以及制作之后用于 CI/CD 的脚本编写。大家可参考以上实例,依据本人的业务场景所需进行对应的革新。

博主简介:《SpringBoot 技术底细》技术图书作者,热爱钻研技术,写技术干货文章。

公众号:「程序新视界」,博主的公众号,欢送关注~

技术交换:请分割博主微信号:zhuan2quan

正文完
 0