现在我找到了一种向容器映射主机文件的方法(-v选项),我想做相反的操作:
如何使用主机编辑器编辑正在运行的容器中的文件?
sshfs可能可以完成这项工作,但由于正在运行的容器已经是某种主机目录,因此我想知道是否有一种可移植的方法(适用于aufs、btrfs和device mapper)来实现这一点?
现在我找到了一种向容器映射主机文件的方法(-v选项),我想做相反的操作:
如何使用主机编辑器编辑正在运行的容器中的文件?
sshfs可能可以完成这项工作,但由于正在运行的容器已经是某种主机目录,因此我想知道是否有一种可移植的方法(适用于aufs、btrfs和device mapper)来实现这一点?
最好的方法是:
$ docker cp CONTAINER:FILEPATH LOCALFILEPATH
$ vi LOCALFILEPATH
$ docker cp LOCALFILEPATH CONTAINER:FILEPATH
$ docker exec存在局限性:它只能附加到正在运行的容器。
$ docker run存在局限性:它将创建一个新的容器。
虽然有可能,且其他答案已经解释了如何操作,但如果可以的话,应该避免编辑Union文件系统中的文件。
你对卷的定义不完全正确——更多是绕过Union文件系统而不是在主机上暴露文件。例如,如果我执行以下操作:
$ docker run --name="test" -v /volume-test debian echo "test"
容器内的目录/volume-test
不会成为联合文件系统的一部分,而是存在于主机的某个位置。我没有指定它在主机上的位置,因为我可能不在意 - 我不暴露主机文件,只是创建了一个可在容器和主机之间共享的目录。您可以通过以下命令确定它在主机上的确切位置:
$ docker inspect -f "{{.Volumes}}" test
map[/volume_test:/var/lib/docker/vfs/dir/b7fff1922e25f0df949e650dfa885dbc304d9d213f703250cf5857446d104895]
如果您只是需要快速编辑文件来测试某些内容,可以使用docker exec
在容器中获取shell并直接进行编辑,或使用docker cp
将文件复制出来,在主机上进行编辑,然后再次复制回去。
docker inspect
命令似乎只适用于 docker 1.7 版本。如需了解新版本上的映射检查方法,请参阅 https://www.adelton.com/docs/docker/docker-inspect-volumes-mounts。 - Dirk Vollmar我们可以使用另一种方法来编辑工作容器中的文件(如果容器停止,则此方法将无法使用)。
逻辑如下:
-)从容器中复制文件到主机
-)使用主机编辑器在主机上编辑文件
-)将文件重新复制回容器
我们可以手动执行所有这些步骤,但我编写了一个简单的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;
使用示例:
dmcedit CONTAINERNAME /path/to/file/in/container
该脚本非常简单,但对我来说运行良好。
欢迎提出任何建议。
docker cp $FILEPATH $CONTAINER:...等
命令将文件复制回去。 - Joaquín Mdocker cp
。这对我有用。因此,首先从容器复制到主机,进行编辑,然后将相同的文件复制回容器。 - Mustafa Temiz将文件挂载到容器中有两种方式。看起来你需要使用绑定挂载。
该方式会直接将本地文件挂载到容器的文件系统中,容器端和主机端的路径都指向同一个文件,在任何一侧所做的修改都会在另一侧显示出来。
❯ echo foo > ./foo
❯ docker run --mount type=bind,source=$(pwd)/foo,target=/foo -it debian:latest
# cat /foo
foo # local file shows up in container
❯ echo 'bar' > ./foo # make a hostside change
# cat /foo
bar # the hostside change shows up
# echo baz > /foo # make a containerside change
# exit
❯ cat foo
baz # the containerside change shows up
❯ docker run --mount type=volume,source=foovolume,target=/foo -it debian:latest
root@containerB# echo 'this is in a volume' > /foo/data
❯ docker volume ls
DRIVER VOLUME NAME
local foovolume
❯ 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
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
(如果未指定卷名,则会选择一个随机的卷名。)
文档试图说服您使用某些东西而不是仅仅告诉您它的工作方式,这很令人困惑。
#!/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"
当我修复问题但忘记更新此答案时的要点:
https://gist.github.com/dmohs/b50ea4302b62ebfc4f308a20d3de4213
docker run -d --name shared_vim_editor \
-v <your_volume>:/home/developer/workspace \
jare/vim-bundle:latest
docker exec -it -u root shared_vim_editor /bin/bash
希望这能帮到你。
我使用IDE的sftp插件。
使用sublime sftp插件的示例: https://www.youtube.com/watch?v=HMfjt_YMru0
docker run -it -name YOUR_NAME IMAGE_ID /bin/bash
$>vi path_to_file