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

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


  1. https://www.cnblogs.com/ztone/articles/10558803.html

  2. https://www.cnblogs.com/zwcry/p/9602756.html

  3. https://www.php.cn/linux-419494.html

  4. https://blog.csdn.net/kkkder/article/details/78317167

  5. https://www.cnblogs.com/20170719log/p/13577877.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容