假设存在这样的一个情形:

当前运行了一个 Jenkins 的 Docker 容器,在这个 Docker 容器内部有我们下载好的插件或者我们上传进去的插件。当需重新创建一个新的 Jenkins 的 Docker 容器时,这个时候不想对这些插件进行重新安装,我们需要将这些数据导出来,那么该怎么办?

首先我们要知道 Docker 是通过 volumes 来将容器内部的数据挂载到容器外部的,据此提供以下几种解决办法。

方法一

步骤一:打包镜像

通过 commit 命令将运行的容器打包成一个镜像,这个时候之前的数据就在这个镜像内部。

  1. [root@centos ~]# docker ps | grep jenkins
  2. d20be9dc983e 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
  3. [root@centos ~]# docker commit d20be9dc983e test_jenkins
  4. sha256:d2fc250902c0312d4fccda33cad98a31fe89a5e7cc717d8428a7dc3c9753ba96
  5. [root@centos ~]# docker images | grep test_jenkins
  6. test_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

  1. [root@centos var]# docker ps | grep test_jenkins
  2. 30305b5b915e 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目录,查看文件是否复制成功。

  1. [root@centos tmp]# ls
  2. hsperfdata_jenkins jenkins_home jetty-0.0.0.0-8080-war-_-any-2586948396343471552.dir _MEIGp4rD1 winstone2749678798752227523.jar
  3. [root@centos tmp]# cd jenkins_home/
  4. [root@centos jenkins_home]# ls
  5. config.xml hudson.model.UpdateCenter.xml jenkins.install.UpgradeWizard.state jobs nodeMonitors.xml plugins secret.key.not-so-secret tini_pub.gpg userContent war
  6. copy_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 命令,如方法一,备份完毕后,我们得先停止容器,然后删除容器,才能实现资源回收,如下所示:

  1. [root@centos ~]# docker ps | grep test_jenkins
  2. 30305b5b915e test_jenkins "/sbin/tini -- /usr/…" 23 hours ago Up 23 hours 8080/tcp, 50000/tcp frosty_mendel
  3. [root@centos ~]# docker stop frosty_mendel
  4. frosty_mendel
  5. [root@centos ~]# docker rm frosty_mendel
  6. frosty_mendel
  7. [root@centos ~]# docker ps | grep test_jenkins
  8. [root@centos ~]#

进入宿主机的 /tmp/backup 目录,解压tar xvf backup.tar压缩包,即可获得备份好的文件目录jenkins_home

注:
这里牵扯到两个容器,要理清楚:

  • 一是要备份的并且正在运行的jenkins_test容器;
  • 二是ubuntu容器,即 docker run 命令运行的新的容器。该容器在完成打包任务后会自动删除。

方法三(最简单方案)

先获取容器ID。

  1. [root@centos tmp]# docker ps | grep jenkins_test
  2. d20be9dc983e 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/ 目录下。

  1. [root@centos tmp]# docker cp d20be9dc983e:/var/jenkins_home /tmp/
  2. [root@centos tmp]# ls
  3. hsperfdata_jenkins jenkins_home _MEIGp4rD1