说说如何基于 Docker 构建并使用 jdk 作为业务工程的基础镜像

·  阅读 169

我们的目标是构建一个业务工程镜像,它是基于 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 镜像

在这里插入图片描述

  1. 首先到 Docker 镜像仓库服务器中获取构建好的 jdk 基础镜像;
  2. 然后在宿主机构建可执行的、基于 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"]

启动成功后,就可以进入业务工程的镜像实例,查看 CentOSjava 的版本号了:

# 查看 CentOS 具体版本信息
cat /etc/redhat-release

# 查看 java 版本号
java -version
复制代码


分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改