Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to dynamically add Volume to a running Docker container

2025-01-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to dynamically add Volume to a running Docker container. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.

I was asked if I could mount the volume after the Docker container was started, and considering how the mnt namespace works, I initially thought it would be difficult to achieve. But now I think it came true.

To put it simply, to mount a disk volume to a running container, we need:

Use nsenter to mount the entire file system containing this disk volume to the temporary mount point

Create a bind mount (bind mount) from the specific folder we want to use as a disk volume to the location of this disk volume

The temporary mount point created in the first step of umount.

Matters needing attention

In the following example, I deliberately include the $symbol to indicate that this is the Shell command line prompt to help you distinguish between what you need to type and which are machine reply. There are some multi-line commands, I also continue to use >. I know that this makes the commands in the example not easy to copy and paste. If you want to copy and paste the code, please see the sample script at the end of the article.

Detailed steps

The following example assumes that you have started a simple container named charlie with the following command:

$docker run-name charlie-ti ubuntu bash

What we need to do is mount the host folder / home/jpetazzo/Work/DOCKER/docker to the / src directory in the container. All right, let's get started.

Nsenter

First, we need nsenter and docker-enter help scripts. Why? Because we are going to mount the file system from the container. The container does not allow us to do this for security reasons. With nsenter, we can break through the above security restrictions and run arbitrary commands in the context of the container (strictly speaking, namespaces). Of course, this must require root permission for the Docker host.

The easiest way to install nsenter is to associate execution with a docker-enter script:

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

For more details, please see the nsenter project home page.

Find the file system

We want to mount the file system that contains the host folder (/ home/jpetazzo/Work/DOCKER/docker) in the container. Then we need to find out which file system contains this directory.

First, we need a canonicalize (or dereferencing) file in case this is a symbolic link, or its path contains a symbolic link:

$readlink-- canonicalize / home/jpetazzo/Work/DOCKER/docker/home/jpetazzo/go/src/github.com/docker/docker

Ha, this is indeed a symbolic link! Let's put it in an environment variable:

$HOSTPATH=/home/jpetazzo/Work/DOCKER/docker$ REALPATH=$ (readlink-- canonicalize $HOSTPATH)

Next, we need to find out which file system contains this path. We use a somewhat unexpected tool to do this, which is df:

$df $REALPATHFilesystem 1K-blocks Used Available Use% Mounted on/sda2 245115308 156692700 86157700 65% / home/jpetazzo

Use the-P parameter (force the POSIX format in case it is exotic df, or the df that someone else runs when installing Docker on Solaris or BSD systems), and put the results in a variable as well:

$FILESYS=$ (df-P $REALPATH | tail-n 1 | awk'{print $6}')

Locate the device of the file system (and sub-root)

Now that there are no bind mounts and BTRFS subvolumes bound in the system, we just need to look at / proc/mounts and find the device that corresponds to the / home/jpetazzo file system. But in my system, / home/jpetazzo is a subvolume of the BTRFS pool, and to get information about the subvolumes (or bind mount information), you need to look at / proc/self/moutinfo.

If you've never heard of mountinfo, check the kernel documentation for proc.txt.

First, get the file system device information:

$while read DEV MOUNT JUNK > do [$MOUNT = $FILESYS] & & break > done do [$MOUNT = $FILESYS] & & break > done

< /proc/self/mountinfo $ echo $SUBROOT/jpetazzo 很好。现在我们知道需要挂载/dev/sda2。在文件系统内部,进入/jpetazzo,从这里可以得到到所需文件的剩余路径(示例中是/go/src/github.com/docker/docker)。 让我们计算出剩余路径: $ SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,) 注意:这个方法只适用于路径里没有符号","的。如果你的路径里有","并且想使用本文方法挂载目录,请告诉我。(我需要调用Shell Triad来解决这个问题:jessie,soulshake,tianon?) 在进入容器之前最后需要做的是找到这个块设备的主和次设备号。可以使用stat: $ stat --format "%t %T" $DEV8 2 注意这两个数字是十六进制的,我们之后需要的是二进制。可以这么转换: $ DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV)) 总结 还有最后一步。因为某些我无法解释的原因,一些文件系统(包括BTRFS)在挂载多次之后会更新/proc/mounts里面的设备字段。也就是说,如果我们在容器里创建了名为/tmpblkdev的临时块设备,并用其挂载我们自己的文件系统,那么文件系统(在宿主机器里!)会显示为/tmpblkdev,而不是/dev/sda2。这听起来无所谓,但实际上这会让之后试图得到文件系统块设备的操作都失败。 长话短说,我们想要确保块设备节点在容器里位于和宿主机器上的同一个路径下。 需要这么做: $ docker-enter charlie -- sh -c \>

"[- b $DEV] | | mknod-- mode 0600$ DEV b $DEVDEC"

Create a temporary mount point to mount the file system:

$docker-enter charlie-- mkdir / tmpmnt$ docker-enter charlie-- mount $DEV / tmpmnt

Ensure that the volume mount point exists, bind mount volume:

$docker-enter charlie-- mkdir-p / src$ docker-enter charlie-- mount-o bind / tmpmnt/$SUBROOT/$SUBPATH / src

Delete temporary mount point:

$docker-enter charlie-- umount / tmpmnt$ docker-enter charlie-- rmdir / tmpmnt

(we do not clear the device node. It may be superfluous to check the existence of the equipment in the first place, but now it is complicated to check it again.)

The great task has been completed!

Automate everything.

The following paragraph can be copied and pasted directly.

#! / bin/shset-eCONTAINER=charlieHOSTPATH=/home/jpetazzo/Work/DOCKER/dockerCONTPATH=/srcREALPATH=$ (readlink-- canonicalize $HOSTPATH) FILESYS=$ (df-P $REALPATH | tail-n 1 | awk'{print $6}') while read DEV MOUNT JUNKdo [$MOUNT = $FILESYS] & & break done

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report