Как редактировать файлы контейнера 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.

  1. Установите ssh-сервер для вашего контейнера и разрешите root-доступ.
  2. Запустите ваш докер-контейнер с -p localport:22
  3. Установите из вашей 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 ...)?

  1. Запустите контейнер с редактором (VI, Emacs). Поиск Docker для "Alpine Vim"

Пример:

docker run -d --name shared_vim_editor \
 -v <your_volume>:/home/developer/workspace \
jare/vim-bundle:latest
  1. Запустите интерактивную команду:

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

Другие вопросы по тегам