如何从主机编辑Docker容器文件?
现在,我找到了一种向容器(-v选项)公开主机文件的方法,我想做一些相反的事情: 如何使用主机编辑器编辑运行容器中的文件如何从主机编辑Docker容器文件?,docker,Docker,现在,我找到了一种向容器(-v选项)公开主机文件的方法,我想做一些相反的事情: 如何使用主机编辑器编辑运行容器中的文件 sshfs可能可以完成这项工作,但由于正在运行的容器已经是某种主机目录,我想知道是否有一种可移植(在aufs、btrfs和设备映射器之间)的方法来完成这项工作?我们可以使用另一种方法来编辑工作容器中的文件(如果容器被停止,这将不起作用) 逻辑是: -)将文件从容器复制到主机 -)使用主机编辑器在主机上编辑文件 -)将文件复制回容器 我们可以手动完成所有这些步骤,但我编写了简单的
sshfs可能可以完成这项工作,但由于正在运行的容器已经是某种主机目录,我想知道是否有一种可移植(在aufs、btrfs和设备映射器之间)的方法来完成这项工作?我们可以使用另一种方法来编辑工作容器中的文件(如果容器被停止,这将不起作用) 逻辑是:
-)将文件从容器复制到主机
-)使用主机编辑器在主机上编辑文件
-)将文件复制回容器 我们可以手动完成所有这些步骤,但我编写了简单的bash脚本,只需一次调用即可轻松完成 /bin/dmcedit:
#!/bin/sh
set -e
CONTAINER=$1
FILEPATH=$2
BASE=$(basename $FILEPATH)
DIR=$(dirname $FILEPATH)
TMPDIR=/tmp/m_docker_$(date +%s)/
mkdir $TMPDIR
cd $TMPDIR
docker cp $CONTAINER:$FILEPATH ./$DIR
mcedit ./$FILEPATH
docker cp ./$FILEPATH $CONTAINER:$FILEPATH
rm -rf $TMPDIR
echo 'END'
exit 1;
用法示例:
#!/bin/sh
set -e
CONTAINER=$1
FILEPATH=$2
BASE=$(basename $FILEPATH)
DIR=$(dirname $FILEPATH)
TMPDIR=/tmp/m_docker_$(date +%s)/
mkdir $TMPDIR
cd $TMPDIR
docker cp $CONTAINER:$FILEPATH ./$DIR
mcedit ./$FILEPATH
docker cp ./$FILEPATH $CONTAINER:$FILEPATH
rm -rf $TMPDIR
echo 'END'
exit 1;
dmcedit CONTAINERNAME/path/to/file/in/container
剧本很简单,但对我来说效果很好
非常感谢您的建议。虽然这是可能的,但其他答案说明了如何避免在Union文件系统中编辑文件(如果可以的话) 您对卷的定义不太正确-与其说是在主机上公开文件,不如说是绕过联合文件系统。例如,如果我这样做:
$ docker run --name="test" -v /volume-test debian echo "test"
容器中的目录/volume test
将不是Union文件系统的一部分,而是存在于主机上的某个位置。我没有指定主机上的位置,因为我可能不在乎——我没有公开主机文件,只是创建了一个可在容器和主机之间共享的目录。您可以通过以下方式找到它在主机上的确切位置:
$ docker inspect -f "{{.Volumes}}" test
map[/volume_test:/var/lib/docker/vfs/dir/b7fff1922e25f0df949e650dfa885dbc304d9d213f703250cf5857446d104895]
如果您确实需要对文件进行快速编辑以测试某些内容,可以使用
docker exec
在容器中获取一个shell并直接编辑,或者使用docker cp
将文件复制出来,在主机上编辑并复制回来。
docker run -it -name YOUR_NAME IMAGE_ID /bin/bash
$>vi path_to_file
docker run-it IMAGE\u NAME/bin/bash
我的图像被称为ipython/notebook
docker-run-it-ipython/notebook/bin/bash
以下是我使用的脚本:
#!/bin/bash
IFS=$'\n\t'
set -euox pipefail
CNAME="$1"
FILE_PATH="$2"
TMPFILE="$(mktemp)"
docker exec "$CNAME" cat "$FILE_PATH" > "$TMPFILE"
$EDITOR "$TMPFILE"
cat "$TMPFILE" | docker exec -i "$CNAME" sh -c 'cat > '"$FILE_PATH"
rm "$TMPFILE"
当我修复它但忘记更新这个答案时的要点是:
最好的方法是:
$ docker cp CONTAINER:FILEPATH LOCALFILEPATH
$ vi LOCALFILEPATH
$ docker cp LOCALFILEPATH CONTAINER:FILEPATH
$docker exec的限制:它只能附加到正在运行的容器
$docker run的限制:它将创建一个新容器。我使用IDE中的sftp插件
如果您认为您的卷是一个“网络驱动器”,这会更容易。 若要编辑此驱动器中的文件,只需打开另一台计算机并连接到此网络驱动器,然后像普通一样编辑该文件 如何纯粹使用docker(不使用FTP/SSH…)实现这一点
docker run -d --name shared_vim_editor \
-v <your_volume>:/home/developer/workspace \
jare/vim-bundle:latest
docker run-d——名称共享的_vim_编辑器\
-v:/home/developer/workspace\
jare/vim捆绑包:最新版本
docker exec-it-u root共享\u vim\u编辑器/bin/bash
希望这能有所帮助。我现在的做法是在安装了
docker
软件包的情况下使用Emacs。我会推荐Emacs的版本。我将遵循以下步骤:
1) 安装Emacs()和Spacemacs()
2) 在.spacemacs
文件中添加docker
3) 启动Emacs
4) 查找文件(SPC+f+f
)并键入/docker::/
5) 现在您的emacs将使用容器环境编辑文件有两种方法可以将文件装载到容器中。看起来您需要一个绑定挂载 捆绑坐骑 这会将本地文件直接装载到容器的文件系统中。containerside路径和hostside路径都指向同一个文件。从任意一侧进行的编辑将显示在两侧
- 装载文件:
- 在单独的shell中,编辑文件:
- 回到容器中:
- 装入卷
- 本地文件系统保持不变
- docker看到一个新卷:
- 创建具有相同卷的新容器
-v
vs-mount
它们做同样的事情-v
更简洁,--mount
更明确
绑定挂载
-v /hostside/path:/containerside/path
--mount type=bind,source=/hostside/path,target=/containerside/path
-v /containerside/path
-v volumename:/containerside/path
--mount type=volume,source=volumename,target=/containerside/path
卷装载量
-v /hostside/path:/containerside/path
--mount type=bind,source=/hostside/path,target=/containerside/path
-v /containerside/path
-v volumename:/containerside/path
--mount type=volume,source=volumename,target=/containerside/path
(如果未指定卷名,则选择随机卷名。)
试图说服你用一件事来代替另一件事,而不是仅仅告诉你它是如何工作的,这是令人困惑的。这将在一些容器上起作用,但许多容器只包含一个最小的环境,因此不包含vi。@JensKohl,您可以提供更详细的信息吗?您应该尝试使用
docker cp$FILEPATH$CONTAINER:。。。。etc
@joaqínM Thx!我已经编辑了我的答案。很高兴docker改进了它的功能,并为我们提供了这个新功能。在Windows上,我最终在MINGW64控制台中使用了docker cp
。这对我有用。所以,首先从容器复制到主机,编辑相同的文件,然后再复制回容器。我只是通过保留文件扩展名来改进脚本,让编辑器突出显示文件内容。docker inspect
命令似乎只有在docker 1.7之前才是正确的。有关如何检查更新版本上的映射,请参见能否将此答案推广到其他容器?这在osx上可能吗?@s.matthew.english没有MacOS容器。在MacOS上,Docker在内部运行xhyve Linux VM来托管Docker容器。卷路径只存在于这个虚拟机中(它对您几乎是隐藏的)
❯ docker run --mount type=volume,source=foovolume,target=/foo -it debian:latest
root@containerC:/# cat /foo/data
this is in a volume # data is still available
-v /hostside/path:/containerside/path
--mount type=bind,source=/hostside/path,target=/containerside/path
-v /containerside/path
-v volumename:/containerside/path
--mount type=volume,source=volumename,target=/containerside/path