假设存在这样的一个情形:
当前运行了一个 Jenkins 的 Docker 容器,在这个 Docker 容器内部有我们下载好的插件或者我们上传进去的插件。当需重新创建一个新的 Jenkins 的 Docker 容器时,这个时候不想对这些插件进行重新安装,我们需要将这些数据导出来,那么该怎么办?
首先我们要知道 Docker 是通过 volumes 来将容器内部的数据挂载到容器外部的,据此提供以下几种解决办法。
方法一
步骤一:打包镜像
通过 commit 命令将运行的容器打包成一个镜像,这个时候之前的数据就在这个镜像内部。
[root@centos ~]# docker ps | grep jenkinsd20be9dc983e jenkins/jenkins:lts "/sbin/tini -- /usr/…" 9 hours ago Up 9 hours 0.0.0.0:42041->8080/tcp, 0.0.0.0:42042->50000/tcp jenkins_test[root@centos ~]# docker commit d20be9dc983e test_jenkinssha256:d2fc250902c0312d4fccda33cad98a31fe89a5e7cc717d8428a7dc3c9753ba96[root@centos ~]# docker images | grep test_jenkinstest_jenkins latest d2fc250902c0 16 seconds ago 592MB
注:
命令 docker commit d20be9dc983e test_jenkins,其中 d20be9dc983e 为容器ID,test_jenkins 为自定义镜像名称。
步骤二:运行镜像
使用 docker run 命令运行这个镜像,并且使用 -v 命令将容器内部的/tmp 目录映射到容器外部(即宿主机)的/tmp目录。
docker run -itd -v /tmp:/tmp test_jenkins
- 第一个
/tmp是宿主机上的目录,第二个/tmp是容器内部的目录。
镜像运行成功后还需获取当前 Docker 容器名称,如下所示,容器名称为frosty_mendel:
[root@centos var]# docker ps | grep test_jenkins30305b5b915e test_jenkins "/sbin/tini -- /usr/…" 23 hours ago Up 23 hours 8080/tcp, 50000/tcp frosty_mendel
步骤三:链接容器,并复制文件
通过交互式终端方式链接到 Docker 容器frosty_mendel,并在该容器内部使用cp命令将/var/jenkins_home目录下的文件复制到的容器的/tmp目录下。
docker exec -it frosty_mendel cp -r /var/jenkins_home /tmp
由于在步骤二中对 Docker 容器的/tmp目录做了映射,所以相当于将文件复制到宿主机的/tmp目录下。进入宿主机的/tmp目录,查看文件是否复制成功。
[root@centos tmp]# lshsperfdata_jenkins jenkins_home jetty-0.0.0.0-8080-war-_-any-2586948396343471552.dir _MEIGp4rD1 winstone2749678798752227523.jar[root@centos tmp]# cd jenkins_home/[root@centos jenkins_home]# lsconfig.xml hudson.model.UpdateCenter.xml jenkins.install.UpgradeWizard.state jobs nodeMonitors.xml plugins secret.key.not-so-secret tini_pub.gpg userContent warcopy_reference_file.log identity.key.enc jenkins.telemetry.Correlator.xml logs nodes secret.key secrets updates users
通过ls命令,我们可以看到jenkins_home目录已经拷贝出来。进入jenkins_home目录,这个时候发现数据都已存在。
步骤四:迁移文件
接下来使用 mv 命令将文件移到home目录下、或者opt目录、或者srv目录下,让数据进行持久化。因为tmp目录下的文件,当Linux重启的时候,会删除tmp目录下的文件,这点需要注意下。
方法二
可采用官方推荐的方式进行备份,命令如下:
docker run —rm —volumes-from jenkins_test -v /tmp/backup:/backup ubuntu tar cvf /backup/backup.tar /var/jenkins_home
--volumes-from命令用于指定从哪个容器中将数据提取出来。jenkins_test表示要备份的Jenkins容器名称;/tmp/backup是宿主机的目录,目录可以随意指定。后面的/backup是容器内部的目录。此处通过-v命令将容器内部的/backup目录映射到宿主机的/tmp/backup目录;ubuntu tar cvf /backup/backup.tar /var/jenkins_home表示将/var/jenkins_home下面的文件打包存储至/backup/backup.tar文件下,其中ubuntu是容器;--rm命令表示当docker把任务(即打包任务)执行完毕后,会将当前产生的容器(即容器ubuntu)删除掉。使用这个命令不要担心资源的回收。
若没有
--rm命令,如方法一,备份完毕后,我们得先停止容器,然后删除容器,才能实现资源回收,如下所示:
[root@centos ~]# docker ps | grep test_jenkins30305b5b915e test_jenkins "/sbin/tini -- /usr/…" 23 hours ago Up 23 hours 8080/tcp, 50000/tcp frosty_mendel[root@centos ~]# docker stop frosty_mendelfrosty_mendel[root@centos ~]# docker rm frosty_mendelfrosty_mendel[root@centos ~]# docker ps | grep test_jenkins[root@centos ~]#
进入宿主机的 /tmp/backup 目录,解压tar xvf backup.tar压缩包,即可获得备份好的文件目录jenkins_home。
注:
这里牵扯到两个容器,要理清楚:
- 一是要备份的并且正在运行的
jenkins_test容器; - 二是
ubuntu容器,即docker run命令运行的新的容器。该容器在完成打包任务后会自动删除。
方法三(最简单方案)
先获取容器ID。
[root@centos tmp]# docker ps | grep jenkins_testd20be9dc983e jenkins/jenkins:lts "/sbin/tini -- /usr/…" 32 hours ago Up 32 hours 0.0.0.0:42041->8080/tcp, 0.0.0.0:42042->50000/tcp jenkins_test
将容器内部的 /var/jenkins_home 文件复制到宿主机的 /tmp/ 目录下。
[root@centos tmp]# docker cp d20be9dc983e:/var/jenkins_home /tmp/[root@centos tmp]# lshsperfdata_jenkins jenkins_home _MEIGp4rD1
