上一篇《Docker之自定义镜像制作与运行(一)》我们已经知道怎么运行自定义镜像了,但是我们的项目运行环境一般都是会带有配置文件的,那么这么将这些配置文件拷贝到镜像中呢?我们就来实践一下:
首先启动自定义镜像容器:jpress
docker run -d -p 8888:8080 jpress
查看容器进程
docker ps
进入容器内部
至此,我们已经看到容器内部的情况了,接下来我们把自己自定义的文件拷贝到/usr/local 目录下,首先我们看下/usr/local目录下有哪些文件
cd /usr/local
拷贝单个文件到docker容器中:
因为我的系统是Windows的,所以在F盘下创建一个文件copy.txt,内容为:
之前安装docker是我安装在D:\java_dev目录下的,可以在docker终端查看
那么我们就要先把docker终端目录切换到F盘下:
我们已经看到了copy.txt的文件了,接下来就准备将这个文件拷贝到容器的/usr/local目录下
docker cp copy.txt 7a25b276ce7e:/usr/local/
说明一下:7a25b276ce7e是指Jpress容器的ID或者name
然后我们再看一下docker容器中是不是多了一个copy.txt文件
我们看到jpress容器已经在第二次执行的时候多了一个copy.txt文件了,那么我们来查看是不是确实是我们主机上的文件呢?
cat copy.txt
可以看出就是我本机上的文件,为什么会出现不一样呢,那是因为cat显示中文异常问题,小伙伴可以通过设置cat编码集解决。
拷贝文件夹到docker容器中:
首先我们还是在F盘中有一个logs文件夹,里面有相关日志的几个文件
然后还是在docker终端切换到F盘下,执行命令
docker cp logs 7a25b276ce7e:/usr/local/
然后我们看下/usr/local/目录下是否拷贝成功
可以看到我们已经把文件成功的拷贝到/usr/local目录下面了。
注意:通过上面的方法将文件拷贝到容器有一个很大的缺点,那就是当容器stop之后,然后再启动运行,之前拷贝的文件都已经不存在了,这个是为什么呢?
Docker镜像是由多个文件系统(只读层)叠加而成.当我们启动一个容器的时候,Docker会加载镜像层并在其上添加一个读写层.如果运行中的容器修改了现有的一个已存在的文件,那该文件将会从读写层下的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏.当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失.在Docker中,只读层以及在顶部的读写层的组合被称为Union File System(联合文件系统)
解决方案:通过Docker Volume修改docker的文件挂载,后续我会说明怎么使用它。
第二种拷贝文件方案:
那有没有什么可以直接一点呢?当然有,那就是在构建的时候就拷贝进去,那么就需要修改Dockerfile 文件,我们来操作一下。
首先我们把之前的docker容器服务停止一下
我们先把之前的copy.txt和logs文件拷贝到Dockerfile文件目录下,这样便于文件拷贝,该文件在docker默认安装目录下:
然后我们来编辑Dockerfile文件
vi Dockerfile
接下来就是重新构建镜像
docker build -t jpress:latest .
由于我本地已经把jpress.war文件删除了,所以构建失败,但是正因为失败,我们可以发现为什么之前拷贝的文件在重启之后会消失,因为镜像容器是构建在/tmp 临时文件下的,你一旦重启服务之后,这个tmp就会刷新到最初状态,所以文件就不存在了。
文件不存在了,要么参照我之前一篇文章《Docker之自定义镜像制作与运行(一)》去github上下载,要么参照下一篇文件从docker容器中拷贝出来。
文件已经准备好,重新构建镜像:
docker build -t jpress:latest .
可以看到我们的镜像已经重新构建成功了,那我们再看一下本地的镜像有哪些
docker images
可以看出jpress就是我们刚才构建的镜像,从构建时间可以看出,接下来我们再看下刚才构建的镜像是否把我们所需要的文件都拷贝到我们知道的目录下了呢?
我们先运行一下容器,然后进入容器内部查看各个文件所在的位置是否存在
好了,我们已经看到所有的文件已经完全拷贝到镜像之中了,那么再也不怕丢失,即使是重启服务也没事了。