使用数据卷、数据卷容器实现多个容器共享JDK

1. docker基础环境共享数据卷可行性验证

  • 多个容器使用宿主机的JDK
  • 多个容器继承某个容器共享JDK

2. 概念

2.0.1. 数据卷:

数据卷就是在宿主中可以在容器之间进行共享和重用的一系列和文件和文件夹,通过docker run -v命令可以将数据卷挂载到对应的容器目录空间,进行文件读取,容器卷特性如下

  • 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效方便
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作
  • 对数据卷的更新不会影响镜像,解耦了应用和数据
  • 卷会一直存在,直到没有容器使用,可以安全地卸载它

2.0.2. 数据卷容器:

接数据卷,已经存在一个挂载了数据卷的容器;由于数据卷在容器之前是可以共享的,所以此时如果存在其他容器通过docker run --volumes-from [容器别名]命令挂载到该容器上,则该容器可以被称之为数据卷容器,其主要功能是提供数据卷供其他容器挂载。当数据卷容器宕机后,并不会造成数据卷的回收卸载,数据卷会继续挂载在其他容器中。当全部挂载该数据卷的容器全部宕机后,该数据卷才会卸载

CDS

3. 环境准备

  • demo.tar.gz (java打印"hello world")
  • jdk-8u231-linux-x64.tar.gz (JDK8)
  • ubuntu:16.04 (ubuntu官方镜像)
  • jdk-11.0.5_linux-x64_bin.tar.gz (JDK11)

4. 多个容器挂载宿主机的JDK(数据卷)

4.1. 挂载物理机目录

  • 将demo.zip,jdk的安装包上传至服务器
  • 解压jdk-8u231-linux-x64.tar.gz,并将解压得到的jdk1.8.0_231文件夹修改为jdk
$ tar -zxvf jdk-8u231-linux-x64.tar.gz
$ mv jdk1.8.0_231/ ./jdk/
  • 编写Dockerfile制作镜像,将demo.tar.gz拷贝到镜像中,并制定Java环境变量
FROM ubuntu:16.04

COPY demo.tar.gz /
# 这里的/home/xuda/docker/jdk目录只是一个示例可以修改,真正起作用是在启动容器时的-v命令,将这个目录挂载到物理机的某个目录。
ENV JAVA_HOME="/home/xuda/docker/jdk"
ENV PATH="${PATH}:${JAVA_HOME}/bin:${JAVA_HOME}/sbin"
RUN tar -zxvf /demo.tar.gz

ENTRYPOINT  (sleep 20 && java -version) & \
           (sleep 20 && sh /demo/bin/demo.sh) & \
           tail -f /dev/null

需要注意的是,以上镜像是没有jdk环境的,所以在生成容器的时候一定要把宿主机jdk目录挂载到容器中。

  • 构建镜像
$ docker build -t ubuntu_jdk1:v1 .

# 最终构建结果如下
Successfully built 14736288edd6
Successfully tagged ubuntu_jdk1:v1
  • 启动容器,并挂载宿主机上的JDK
$  docker run --name jdktest1  -v /home/xuda/docker/jdk:/home/xuda/docker/jdk ubuntu_jdk1:v1

可以看到容器启动结果如下:

java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
Hello World!
  • 再启动两个同样的容器,可以看到仍然可以运行
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS               NAMES
87ac095fca74        ubuntu_jdk1:v1      "/bin/sh -c '(sleep …"   24 seconds ago       Up 23 seconds                           jdktest3
5452529443c5        ubuntu_jdk1:v1      "/bin/sh -c '(sleep …"   About a minute ago   Up About a minute                       jdktest2
5946a221e19b        ubuntu_jdk1:v1      "/bin/sh -c '(sleep …"   7 minutes ago        Up 7 minutes                            jdktest1

4.2. 更改物理机环境

4.2.1. 用新的包覆盖旧包

  • 在物理机上将jdk-11.0.5_linux-x64_bin.tar.gz解压,将放置jdk1.8的jdk目录,重新命名为jdk1。解压jdk-11.0.5_linux-x64_bin.tar.gz并将解压后的文件夹命名为jdk
  • 进入上一步已经启动好的容器中,执行java -version命令,发现输出仍然是jdk1.8,但是重启容器后正常

4.2.2. 先删除jdk目录下的文件,将jdk11中的文件,拷贝到jdk目录中

$ cd jdk
$ rm -rf *
$ cp jdk-11.0.5/* jdk/
# 进入容器内查看环境是否变化,其中87ac095fca74是容器的id,根据实际修改
$ docker exec -it 87ac095fca74 /bin/bash
$ root@87ac095fca74:/ java -version

java version "11.0.5" 2019-10-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.5+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.5+10-LTS, mixed mode)
  1. 所以得出结论,能够使用挂载卷的方式多个容器共享物理机的 JDK
  2. 更新物理机的环境时,不能使用新的目录覆盖旧的目录,只能将新的环境中的文件复制到旧的目录下
  3. 如果使用新的目录覆盖旧的目录需要重启容器才能生效

各个容器与物理机环境的关系如下图所示
在这里插入图片描述

5. 多个容器挂载数据卷容器(数据卷容器)

  • 起一个上一步构建的容器作为父容器
$ docker run --name jdktest1  -v /home/xuda/docker/jdk:/home/xuda/docker/jdk ubuntu_jdk1:v1
  • 使用ubuntu:16.04作为基础镜像,起动容器继承自jdktest1
$ docker run -it --volumes-from jdktest1 --name con_jdk1 ubuntu:16.04

可以看到目录/home/xuda/docker/查看到jdk,并且执行/home/xuda/docker/jdk/bin/java -version有如下输出,

java version "11.0.5" 2019-10-15 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.5+10-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.5+10-LTS, mixed mode)
  • 在启动一个容器
$ docker run -it --volumes-from jdktest1 --name con_jdk2 ubuntu:16.04

效果相同

5.1. 更改物理机环境

挂载到数据卷容器下,更新物理机环境的操作结果与4.2 更改物理机环境相同

各个容器与物理机环境的关系如下图所示
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值