欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Docker为运行容器动态添加卷Volume

程序员文章站 2022-05-11 14:05:07
...

前言

最近因为考虑数据支持化问题,需要将docker容器中的数据绕过Union File System然后持久化到本地,想到一种方式就是共享物理机的硬盘,故需要为容器绑定卷组。正常情况下,绑定卷组在容器创建之前完成,常规做法有如下:

  • Dockerfile添加
  • 命令创建容器时指定

这个由于容器已创建好并且处于运行中,需要在不重建容器的前提下进行动态添加卷组。

步骤

1. 安装nsenter

nsenter是一个可以进入容器的工具, 它可以输入现有的名称空间,也可以将进程生成为一组新的名称空间,安装如下:

 $ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter

2. 编写卷组脚本

新建可执行文件dynamic_mount_docker_volume,并键入:

#!/bin/bash
#This script is dynamic mount docker volumens
#Author Deng Lei
#https://github.com/pushiqiang/utils/blob/master/docker/dynamic_mount_docker_volume

if [ -z $1 ] || [ -z $2 ] || [ -z $3 ]; then
    echo "Usage: container_name physics_volumes container_volumes"
    echo "Example: I want mount physics /tmp/test to container /src in test"
    echo "The command is: bash `basename $0` test_container_id /tmp/test /src "
    exit 1
fi
which nsenter &>>/dev/null
if [ $? -ne 0 ];then
    echo "plsease install nsenser,command is:yum install util-linux"
    exit 1
fi
set -e
CONTAINER=$1
HOSTPATH=$2
CONTPATH=$3
if [ ! -d $HOSTPATH ];then
    echo "physics $HOSTPATH is not exist!"
    exit 1
fi
REALPATH=$(readlink --canonicalize $HOSTPATH)
FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}')
while read DEV MOUNT JUNK
    do
        [ $MOUNT = $FILESYS ] && [ $DEV != "rootfs" ] && break
    done </proc/mounts
[ $MOUNT = $FILESYS ] # Sanity check!
while read A B C SUBROOT MOUNT JUNK
    do [ $MOUNT = $FILESYS ] && break
    done < /proc/self/mountinfo
[ $MOUNT = $FILESYS ] # Moar sanity check!
SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,)
DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV))
PID=$(docker inspect --format "{{.State.Pid}}" "$CONTAINER")
run_command="nsenter --target $PID --mount --uts --ipc --net --pid -- sh -c"
if  [ `$run_command "mount|grep $CONTPATH|wc -l"` -ne 0 ];then
    echo "container $CONTAINER mount dir $CONTPATH is mounting!"
    exit 1
fi
$run_command "[ -b $DEV ] ||mknod --mode 0600 $DEV b $DEVDEC"
$run_command "mkdir /tmpmnt"
$run_command "mount $DEV /tmpmnt"
$run_command "mkdir -p $CONTPATH"
$run_command "mount -o bind /tmpmnt/$SUBROOT/$SUBPATH $CONTPATH"
$run_command "umount /tmpmnt"
$run_command "rmdir /tmpmnt"
check_result=`$run_command "mount|grep $CONTPATH|wc -l"`
if [ $check_result -ne 0 ];then
    echo "dymainc mount physics $HOSTPATH on $CONTAINER $CONTPATH is success!"
else
    echo "dymaninc mount physics $HOSTPATH on $CONTAINER $CONTPATH is fail!"
fi

3. 添加容器卷组

确定容器ID,运行的容器挂载卷,使用docker命令docker ps查看正在进行的容器,以jenkins为例:

[[email protected]_0_13_centos data]# docker ps |grep jenkinsci|awk '{print $1}'
8c342301f47b

获得容器id后,执行脚本dynamic_mount_docker_volume并将容器外内的映射目录当做参数更随其后,如下将本地/data/jenkins目录映射到容器ID8c342301f47b的目录/data

./dynamic_mount_docker_volume 8c342301f47b /data/jenkins /data

后记

来一招狠的,修改docker配置文件,这个非特殊情况不建议

步骤总结

$ touch dynamic_mount_docker_volume
$ #vi dynamic_mount_docker_volume 写入脚本
$ chmod +x dynamic_mount_docker_volume
$ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter
$ ./dynamic_mount_docker_volume 8c342301f47b /data/jenkins /data

挂载卷好处

  • 数据卷可以在容器之间共享或重用数据
  • 卷中的更改可以直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命令周期默认会一直存在,即使容器被删除。
相关标签: Kubernetes