我们的目标是构建一个业务工程镜像,它是基于 JDK
,而 JDK
基于 CentOS
。由于业务工程是 Spring Boot 架构,所以内嵌了 Tomcat。这样的镜像就可以在 k8s
中正常启动运行。
1 构建 jdk 镜像[1]
我们首先基于 centos7 镜像来构建 jdk8 镜像。
(1)启动 docker 服务
安装好 docker 之后,启动 docker 服务:
systemctl start docker
systemctl
是 Systemd 的主命令,用于管理系统。[2]
还有一些常用的管理 docker 服务的命令:
# 停止 docker 服务
systemctl stop docker
# 重启 docker 服务
systemctl restart docker
# 重新加载 docker 服务配置文件
systemctl reload docker
(2)下载 centos
镜像
# 命令,格式:docker pull [name]:[tag]
docker pull centos:centos7
# 输出
centos7: Pulling from library/centos
2d473b07cdd5: Pull complete
Digest: sha256:9d4bcbbb213dfd745b58be38b13b996ebb5ac315fe75711bd618426a630e0987
Status: Downloaded newer image for centos:centos7
(3)下载 jdk 并安装
首先下载 Linux 版本的 jdk,放入虚拟机。
# 把 jdk8 包解压到 /usr/local/src 路径,用于验证该包是否可以正常解压
[root@localhost ~]# cd /usr/local/src
[root@localhost src]# tar axf jdk-8u161-linux-x64.tar.gz
[root@localhost src]# ls
jdk1.8.0_161 jdk-8u161-linux-x64.tar.gz
# 创建 /usr/local/jdk 文件夹,把 jdk8 包放入该文件夹
[root@localhost src]# mkdir /usr/local/jdk
[root@localhost src]# cd /usr/local/jdk
[root@localhost jdk]# cp ../src/jdk-8u161-linux-x64.tar.gz ./
[root@localhost jdk]# ls
jdk-8u161-linux-x64.tar.gz
(4) 配置 Dockerfile
vi Dockerfile
# 以下是 Dockerfile 文件的配置内容
FROM centos:centos7 # 指定基础镜像
MAINTAINER deniro # 镜像创建者
RUN mkdir /usr/local/jdk # 需要执行的命令指令,在基础镜像的 centos7 内部创建 /usr/local/jdk
WORKDIR /usr/local/jdk # 工作目录
ADD jdk-8u161-linux-x64.tar.gz /usr/local/jdk #解压到 /usr/local/jdk
# 下面这一段是设置 JAVA 环境变量,特别要注意版本路径问题
ENV JAVA_HOME /usr/local/jdk/jdk1.8.0_161 #设置 JAVA_HOME 环境变量
ENV JRE_HOME /usr/local/jdk/jdk1.8.0_161/jre #设置 JRE_HOME 环境变量
ENV PATH $JAVA_HOME/bin:$PATH # 把 JAVA_HOME 加入 PATH 路径
(5)构建 jdk 镜像
# 构建命令,-t 用于指定标签的名字,最后的点(.)表示当前路径
docker build -t jdk1.8 .
# 实际命令执行与结果输出
[root@localhost jdk]# docker build -t jdk1.8 .
Sending build context to Docker daemon 189.8MB
Step 1/8 : FROM centos:centos7
---> eeb6ee3f44bd
Step 2/8 : MAINTAINER deniro
---> Running in a08584b223d1
Removing intermediate container a08584b223d1
---> e1d4d654e2dd
Step 3/8 : RUN mkdir /usr/local/jdk
---> Running in 4920ee3498ed
Removing intermediate container 4920ee3498ed
---> ff03d3e32fca
Step 4/8 : WORKDIR /usr/local/jdk
Removing intermediate container c977e7a20c92
---> 136a7ca6d48d
Step 5/8 : ADD jdk-8u161-linux-x64.tar.gz /usr/local/jdk
---> 306dc9ac0d6f
Step 6/8 : ENV JAVA_HOME /usr/local/jdk/jdk1.8.0_201
---> Running in 1d948b3611ee
Removing intermediate container 1d948b3611ee
---> 45a3d77d8906
Step 7/8 : ENV JRE_HOME /usr/local/jdk/jdk1.8.0_201/jre
---> Running in 8cd22a215d8d
Removing intermediate container 8cd22a215d8d
---> e848f6909324
Step 8/8 : ENV PATH $JAVA_HOME/bin:$PATH
---> Running in 4e2caaf182ca
Removing intermediate container 4e2caaf182ca
---> 567d71c1723d
Successfully built 567d71c1723d
Successfully tagged jdk1.8:latest
# 查看目前已有镜像
[root@localhost jdk]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jdk1.8 latest 567d71c1723d About a minute ago 588MB
centos centos7 eeb6ee3f44bd 31 hours ago 204MB
(6)验证镜像是否运行正常
创建一个新的容器:
# -di 就是 -d 与 -i,-d 表示后台运行容器,并返回容器ID;-i 表示以交互模式运行容器。
# --name 指定容器的名称。
docker run -di --name=jdk1.8 jdk1.8
docker run -di --name=191.168.27.xxx:8083/deniro/jdk1.8:1.0.0 jdk1.8
a905240862b0d6e9466a1b5d8e53bd85055e8ebf48d0d2d101a683a22f8006af
在运行的容器中执行命令:
# -i :即使没有附加也保持 STDIN 打开
#-t :分配一个伪终端
[root@localhost jdk]# docker exec -it jdk1.8 /bin/bash
[root@a905240862b0 jdk]# pwd
/usr/local/jdk
[root@a905240862b0 jdk]# ls
jdk1.8.0_161
[root@babd33b3552d jdk]# java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
在linux中经常会看到stdin,stdout和stderr,这3个可以称为终端(Terminal)的标准输入(standard input),标准输出( standard out)和标准错误输出(standard error)[3]。
如果已经停止了实例,但无法启动镜像,可以尝试以下命令[4]:
docker ps -a | grep "Exited" | awk '{print $1 }'|xargs docker rm
(7)为镜像打标签
# 打标签命令模板
# ImageId 镜像 ID
docker tag [ImageId] [镜像库地址]/[文件夹]/[镜像名称]:[镜像版本号]
# 打标签示例
docker tag 567d71c1723d 191.168.27.xxx:8083/deniro/jdk1.8:1.0.0
# 命令输出结果
[root@localhost jdk]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
191.168.27.xxx:8083/deniro/jdk1.8 1.0.0 567d71c1723d
(8)配置 docker 私有仓库
vi /etc/docker/daemon.json
# 以下是配置内容
{
"insecure-registries": ["191.168.27.xxx:8083"]
}
配置后需要重启 docker:
systemctl restart docker
(9)推送镜像
首先登录 docker 私有仓库:
docker login -u admin -p admin@2020 191.168.27.xxx:8083
# 输出结果
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
然后把刚才打好标签的镜像推送到远程镜像库:
docker push 191.168.27.xxx:8083/deniro/jdk1.8:1.0.0
[root@localhost jdk]# docker push 191.168.27.xxx:8083/deniro/jdk1.8:1.0.0
The push refers to repository [191.168.27.xxx:8083/deniro/jdk1.8]
2d5e169356d5: Pushed
d4bb58bcbbca: Layer already exists
174f56854903: Layer already exists
1.0.0: digest: sha256:6c5d64f356f94ebd5dfcee7b48761665c8ba940fbfae68c5bd25589f0970d72d size: 949
推送成功后,就可以在远程镜像仓库看到:
在这里插入图片描述2 使用 jdk 镜像
在这里插入图片描述- 首先到 Docker 镜像仓库服务器中获取构建好的 jdk 基础镜像;
- 然后在宿主机构建可执行的、基于 Spring Boot 的业务工程 jar,创建相应的镜像信息文件,发送到虚拟机的 Docker 服务构建出真正的 Docker 镜像。
2.1 开启 TCP 端口[5]
开启虚拟机 TCP 端口的目的是:宿主机可以连接到虚拟机中的 Docker 服务,构建业务工程镜像包。
# 编辑 docker.service
vi /lib/systemd/system/docker.service
# docker.service 修改内容
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
# 重新加载系统服务配置文件
systemctl daemon-reload
# 重启 docker 服务
systemctl restart docker
# 查看端口是否被 docker 监听
[root@localhost jdk]# ss -tnl | grep 2375
LISTEN 0 128 [::]:2375 [::]:*
# 防火墙添加开放 2375 端口
[root@localhost jdk]#firewall-cmd --zone=public --add-port=2375/tcp --permanent
success
# 重启防火墙
[root@localhost jdk]#firewall-cmd --reload
success
# 查看防火墙是否开放 2375 端口
[root@localhost jdk]# firewall-cmd --zone=public --query-port=2375/tcp
yes
在宿主机的 Windows 系统上测试端口是否可以使用
telnet 192.168.37.120 2375
2.2 配置应用工程
(1)修改 jdk 基础镜像
配置工程的 Dockerfile
,修改 jdk
基础镜像为我们刚才新构建的镜像:
FROM 191.168.27.xxx:8083/deniro/jdk1.8:1.0.0
...
(2)修改业务工程镜像 tag
这里的 tag 对应的就是业务工程镜像在 Docker 容器内的标签。
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-version}</version>
<configuration>
<repository>
${dockerfile.repostory}/${dockerfile.registry.name}/${project.artifactId}
</repository>
<useMavenSettingsForAuth>true</useMavenSettingsForAuth>
<tag>${dockerfile.tag}</tag>
<buildArgs>
<JAR_FILE>${project.artifactId}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
(3)构建镜像
执行镜像构建命令:
mvn dockerfile:build
查看 docker 状态:
service docker status
(4)验证业务工程镜像
docker run 191.168.27.xxx:8083/cc/xxx-sql:1.0.0
注意:如果版本路径配置不正确,那么运行镜像时就会抛出:
[root@localhost usr]# docker run 191.168.27.xxx:8083/cc/xxx-sql:1.0.0
docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"java\": executable file not found in $PATH": unknown.
原因是 java
命令没有加入到环境变量。很可能是之前打 jdk
镜像的脚本中 JAVA_HOME 配置路径不正确导致的。之所以用到 java
命令是因为业务工程使用了 java
命令来启动 jar 包:CMD ["java", "-Xmx2048m","-Duser.timezone=GMT+08", "-jar", "/app/xxx-sql-1.5.0.jar"]
启动成功后,就可以进入业务工程的镜像实例,查看 CentOS
与 java
的版本号了:
# 查看 CentOS 具体版本信息
cat /etc/redhat-release
# 查看 java 版本号
java -version
网友评论