假设存在这样的一个情形:
当前运行了一个 Jenkins 的 Docker 容器,在这个 Docker 容器内部有我们下载好的插件或者我们上传进去的插件。当需重新创建一个新的 Jenkins 的 Docker 容器时,这个时候不想对这些插件进行重新安装,我们需要将这些数据导出来,那么该怎么办?
首先我们要知道 Docker 是通过 volumes
来将容器内部的数据挂载到容器外部的,据此提供以下几种解决办法。
方法一
步骤一:打包镜像
通过 commit
命令将运行的容器打包成一个镜像,这个时候之前的数据就在这个镜像内部。
[root@centos ~]# docker ps | grep jenkins
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
[root@centos ~]# docker commit d20be9dc983e test_jenkins
sha256:d2fc250902c0312d4fccda33cad98a31fe89a5e7cc717d8428a7dc3c9753ba96
[root@centos ~]# docker images | grep test_jenkins
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
:
[root@centos var]# docker ps | grep test_jenkins
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
目录,查看文件是否复制成功。
[root@centos tmp]# ls
hsperfdata_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]# ls
config.xml hudson.model.UpdateCenter.xml jenkins.install.UpgradeWizard.state jobs nodeMonitors.xml plugins secret.key.not-so-secret tini_pub.gpg userContent war
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
命令,如方法一,备份完毕后,我们得先停止容器,然后删除容器,才能实现资源回收,如下所示:
[root@centos ~]# docker ps | grep test_jenkins
30305b5b915e test_jenkins "/sbin/tini -- /usr/…" 23 hours ago Up 23 hours 8080/tcp, 50000/tcp frosty_mendel
[root@centos ~]# docker stop frosty_mendel
frosty_mendel
[root@centos ~]# docker rm frosty_mendel
frosty_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_test
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/
目录下。
[root@centos tmp]# docker cp d20be9dc983e:/var/jenkins_home /tmp/
[root@centos tmp]# ls
hsperfdata_jenkins jenkins_home _MEIGp4rD1