文章目录
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)
- 所以得出结论,能够使用挂载卷的方式多个容器共享物理机的 JDK
- 更新物理机的环境时,不能使用新的目录覆盖旧的目录,只能将新的环境中的文件复制到旧的目录下
- 如果使用新的目录覆盖旧的目录需要重启容器才能生效
各个容器与物理机环境的关系如下图所示
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 更改物理机环境相同
各个容器与物理机环境的关系如下图所示