Как редактировать файлы контейнера Docker с хоста?
Теперь, когда я нашел способ предоставить хост-файлы контейнеру (опция -v), я хотел бы сделать наоборот:
Как я могу редактировать файлы из запущенного контейнера с помощью редактора хоста?
sshfs, вероятно, может выполнить эту работу, но поскольку работающий контейнер уже является своего рода каталогом хоста, мне интересно, есть ли переносимый (между aufs, btrfs и device mapper) способ сделать это?
10 ответов
Хотя это возможно, а другие ответы объясняют, как, вы должны избегать редактирования файлов в файловой системе Union, если можете.
Ваше определение томов не совсем правильное - оно больше касается обхода файловой системы 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
получить оболочку в контейнере и редактировать напрямую, либо использовать docker cp
чтобы скопировать файл, отредактируйте на хосте и скопируйте обратно.
Лучший способ это:
$ docker cp CONTAINER:FILEPATH LOCALFILEPATH
$ vi LOCALFILEPATH
$ docker cp LOCALFILEPATH CONTAINER:FILEPATH
Ограничения с $ docker exec: он может подключаться только к работающему контейнеру.
Ограничения с $ docker run: он создаст новый контейнер.
Мы можем использовать другой способ редактирования файлов внутри рабочих контейнеров (это не будет работать, если контейнер остановлен).
Логика заключается в:
-) скопировать файл из контейнера на хост
-) редактировать файл на хосте, используя его редактор хоста
-) скопировать файл обратно в контейнер
Мы можем сделать все эти шаги вручную, но я написал простой скрипт bash, чтобы сделать это легко одним вызовом.
/ бен /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 / путь / к / файлу / в / контейнере
Сценарий очень прост, но он отлично работает для меня.
Любые предложения приветствуются.
Есть два способа монтировать файлы в ваш контейнер. Похоже, вам нужно привязное крепление.
Привязать маунтов
Это монтирует локальные файлы непосредственно в файловую систему контейнера. Путь на стороне контейнера и путь на стороне хоста указывают на один и тот же файл. Правки, внесенные с любой стороны , будут отображаться на обеих сторонах .
- смонтировать файл:
❯ 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
является более кратким,
--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
(Если имя тома не указано, выбирается случайное.)
Документация пытается убедить вас использовать одно в пользу другого вместо того, чтобы просто рассказать вам, как это работает, что сбивает с толку.
Я использую плагин sftp из моей IDE.
- Установите ssh-сервер для вашего контейнера и разрешите root-доступ.
- Запустите ваш докер-контейнер с -p localport:22
- Установите из вашей IDE плагин sftp
Пример использования превосходного плагина sftp: https://www.youtube.com/watch?v=HMfjt_YMru0
Вот скрипт, который я использую:
#!/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
Если вы думаете, что ваш том - "сетевой диск", это будет проще. Чтобы отредактировать файл, расположенный на этом диске, вам просто нужно включить другой компьютер и подключиться к этому сетевому диску, а затем отредактировать файл как обычно.
Как это сделать чисто с помощью докера (без FTP/SSH ...)?
- Запустите контейнер с редактором (VI, Emacs). Поиск Docker для "Alpine Vim"
Пример:
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
Надеюсь это поможет.
Я использую Emacs с docker
пакет установлен. Я бы порекомендовал Spacemacs версию Emacs. Я бы следовал следующим шагам:
1) Установите Emacs ( Инструкция) и установите Spacemacs ( Инструкция)
2) Добавить docker
в вашем .spacemacs
файл
3) Запустите Emacs
4) Найти файл (SPC+f+f
) и введите /docker:<container-id>:/<path of dir/file in the container>
5) Теперь ваш emacs будет использовать контейнерную среду для редактирования файлов
docker run -it -name YOUR_NAME IMAGE_ID /bin/bash
$>vi path_to_file
Следующее сработало для меня
docker run -it IMAGE_NAME /bin/bash
например. мое изображение называлось ipython/notebook
docker run -it ipython/notebook /bin/bash