Учебник. Сохранение данных в приложении-контейнере с помощью томов в VS Code
Из этого учебника вы узнаете, как сохранять данные в приложении-контейнере. При запуске или обновлении данные по-прежнему остаются доступными. Существует два основных типа томов, используемых для хранения данных. В этом учебнике основное внимание уделяется именованным томам.
Кроме того, вы узнаете о подключениях привязок, которые контролируют точку подключения на узле. Подключение привязки можно использовать для хранения данных, однако оно также может привести к добавлению дополнительных данных в контейнеры. При работе с приложением можно использовать подключение BIND для подключения исходного кода к контейнеру, чтобы он мог видеть изменения в коде, реагировать и сразу отображать изменения.
В этом учебнике также рассматриваются слои в образе, кэширование слоев и многоэтапные сборки.
В этом руководстве описано следующее:
- Общие сведения о данных в контейнерах.
- Сохранение данных с помощью именованных томов.
- Использование подключений привязок.
- Просмотр слоя образа.
- Кэширование зависимостей.
- Общие сведения о многоэтапных сборках.
Необходимые компоненты
Этот учебник является продолжением предыдущего — Создание приложения Docker и предоставление к нему общего доступа с помощью Visual Studio Code. Начните с первого учебника, поскольку в нем приводятся предварительные требования.
Общие сведения о данных в контейнерах
В этом разделе вы запустите два контейнера и создайте файл в каждом из них. Файлы, созданные в одном контейнере, недоступны в другом.
-
Запустите контейнер ubuntu с помощью следующей команды:
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"

Эта команда запускает две команды с помощью && . Первая часть выбирает одно случайное число и записывает его в файл /data.txt . Вторая команда наблюдает за файлом, чтобы работа контейнера не прекращалась.
cat /data.txt
В терминале отображается число от 1 до 10000. Чтобы использовать командную строку для просмотра этого результата, получите идентификатор контейнера с помощью команды docker ps и выполните следующую команду.
docker exec cat /data.txt
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
docker run -it ubuntu ls /
Сохранение данных приложения Todo с помощью именованных томов
По умолчанию приложение todo сохраняет данные в базе данных SQLite в /etc/todos/todo.db . База данных SQLite — это реляционная база данных, которая хранит данные в одном файле. Этот подход приемлем для небольших проектов.
Можно сохранить один файл на узле. Когда вы сделаете его доступным для следующего контейнера, приложение сможет продолжить работу с того места, где оно было остановлено. Создавая том и присоединяя его (или подключая) к папке, в которой хранятся данные, можно сохранить данные. Контейнер выполняет запись в файл todo.db, и эти данные сохраняются на узле в томе.
Для выполнения инструкций в этом разделе используется именованный том. Docker сохраняет физическое расположение тома на диске. Укажите имя тома, и Docker предоставит правильные данные.
-
Создайте том с помощью команды docker volume create .
docker volume create todo-db
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started

Параметр volume указывает том для подключения и расположение ( /etc/todos ).
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Именованные тома и подключения привязок, рассматриваемые ниже, являются основными типами томов, поддерживаемыми установкой подсистемы Docker по умолчанию.
| Свойство | Именованные тома | Привязка подключений |
|---|---|---|
| Расположение узла | Выбирает Docker | Указываете вы |
| Пример подключения (с использованием -v ) | my-volume:/usr/local/data | /path/to/data:/usr/local/data |
| Заполняет новый том содержимым контейнера | Да | Нет |
| Поддерживает драйверы томов | Да | Нет |
Существует множество подключаемых модулей драйверов томов для поддержки NFS, SFTP, NetApp и т. д. Эти подключаемые модули особенно важны для запуска контейнеров на нескольких узлах в кластеризованной среде, такой как Swarm или Kubernetes.
Чтобы узнать, где Docker на самом деле хранит ваши данные, выполните следующую команду.
docker volume inspect todo-db
Взгляните на выходные данные, приведенные ниже.
[ < "CreatedAt": "2019-09-26T02:18:36Z", "Driver": "local", "Labels": <>, "Mountpoint": "/var/lib/docker/volumes/todo-db/_data", "Name": "todo-db", "Options": <>, "Scope": "local" > ]
Mountpoint — это фактическое расположение, в котором хранятся данные. На большинстве компьютеров для доступа к этому каталогу с узла необходим доступ с правами root.
Использование подключения BIND
Подключения BIND позволяют указать точную точку подключения на узле. Этот подход сохраняет данные, но часто используется для добавления большого объема данных в контейнеры. Подключение привязки можно использовать для подключения исходного кода к контейнеру, чтобы он мог видеть изменения в коде, реагировать и сразу отображать изменения.
Чтобы запустить контейнер для поддержки рабочего процесса разработки, выполните приведенные ниже действия.
- Удалите все контейнеры getting-started .
- В папке app выполните следующую команду.
docker run -dp 3000:3000 -w /app -v $:/app node:20-alpine sh -c "yarn install && yarn run dev"
- -dp 3000:3000 — то же, что и раньше. Выполните команду в отключенном режиме и создайте сопоставление портов.
- -w /app — рабочий каталог внутри контейнера.
- -v $:/app» — подключение текущего каталога из узла в контейнере к каталогу /app .
- node:20-alpine — используемый образ. Это базовый образ для вашего приложения из Dockerfile.
- sh -c «yarn install && yarn run dev» — команда. Она запускает оболочку, используя sh , и выполняет yarn install для установки всех зависимостей. Затем она выполняет yarn run dev . Если взглянуть на package.json , сценарий dev запускает nodemon .
docker logs -f
$ nodemon src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000

Сохраните изменения.
Просмотр слоев образа
Можно просмотреть слои, составляющие образ. Выполните команду docker image history , чтобы просмотреть команды, которые использовались для создания каждого слоя в образе.
-
Используйте docker image history для просмотра слоев в образе getting-started, созданном ранее в этом учебнике.
docker image history getting-started
Результат должен быть похож на выходные данные, приведенные ниже.
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
docker image history --no-trunc getting-started
Кэширование зависимостей
После изменения слоя все нижестоящие слои также необходимо создать заново. Вот Dockerfile:
FROM node:20-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "/app/src/index.js"]
Каждая команда в Dockerfile становится новым слоем в образе. Чтобы максимально сократить количество слоев, можно изменить структуру Dockerfile для поддержки кэширования зависимостей. Для приложений на основе узлов эти зависимости определяются в файле package.json .
Подход заключается в том, чтобы сначала скопировать только этот файл, установить зависимости и затем скопировать все остальное. Повторное создавать зависимости Yarn нужно будет только в том случае, если было внесено изменение в файл package.json .
-
Сначала измените Dockerfile, чтобы выполнить копирование в package.json , установите зависимости, а затем скопируйте все остальное. Вот новый файл:
FROM node:20-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
docker build -t getting-started .
Вы должны увидеть выходные данные, аналогичные приведенным ниже.
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages. [2/4] Fetching packages. info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies. [4/4] Building fresh packages. Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
Многоэтапная сборка
Многоэтапные сборки — невероятно мощное средство для использования нескольких этапов при создании образа. У них есть несколько преимуществ.
- Отделение зависимостей времени сборки от зависимостей среды выполнения.
- Уменьшение общего размера образа за счет доставки только того, что нужно вашему приложению для работы.
В этом разделе приводятся краткие примеры.
Пример с Maven и Tomcat
При создании приложений на основе Java для компиляции исходного кода в байт-код Java требуется JDK. JDK не требуется в рабочей среде. Для упрощения сборки приложения можно использовать такие средства, как Maven или Gradle. Они также не нужны в окончательном образе.
FROM maven AS build WORKDIR /app COPY . . RUN mvn package FROM tomcat COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
В этом примере один этап ( build ) используется для выполнения фактической сборки Java с помощью Maven. Второй этап (начиная с «FROM tomcat») копирует в файлы с этапа build . Окончательный образ создается только на последнем этапе (что можно переопределить с помощью параметра —target ).
Пример React
При создании приложений React требуется среда Node для компиляции кода JavaScript, таблиц стилей SASS и др. в статический HTML, JavaScript и CSS. Если вы не выполняете отрисовку на стороне сервера, вам даже не нужна среда узла для рабочей сборки.
FROM node:20-alpine AS build WORKDIR /app COPY package* yarn.lock ./ RUN yarn install COPY public ./public COPY src ./src RUN yarn run build FROM nginx:alpine COPY --from=build /app/build /usr/share/nginx/html
В этом примере для выполнения сборки используется образ node:20 , который максимально эффективно кэширует слой, а затем копирует выходные данные в контейнер nginx.
Очистка ресурсов
Чтобы продолжить работу с этой серией учебников, оставьте все настройки, сделанные на данный момент.
Следующие шаги
Вы узнали о вариантах сохранения данных для приложений-контейнеров.
Что вы хотите сделать дальше?
- Работа с несколькими контейнерами с помощью Docker Compose: Создание многоконтейнерных приложений с помощью MySQL и Docker Compose
- Развертывание в приложениях контейнеров Azure:
- Краткое руководство. Развертывание в приложениях контейнеров Azure с помощью Visual Studio Code
- Руководство по развертыванию в приложениях контейнеров Azure
- Развертывание контейнерного приложения в Azure
Сохранить изменения в docker
Запустил docker с образом ubuntu. Обновил, поменял конфиги, вышел, зашел и ничего не сохранилось. Как правильно сохранять изменения в docker? Гугл предлагает сохранение образа, а мне надо сохранять изменения внутри контейнера.

NoobeR ★★★★
30.05.16 18:00:16 MSK
Use volumes, Luke!
theNamelessOne ★★★★★
( 30.05.16 18:02:09 MSK )монтируй вольюм и пиши в него
leave ★★★★★
( 30.05.16 18:02:43 MSK )Но скорее всего ты хочешь странного от докера.
staseg ★★★★★
( 30.05.16 18:03:06 MSK )
Последнее исправление: staseg 30.05.16 18:03:33 MSK (всего исправлений: 1)Ответ на: комментарий от staseg 30.05.16 18:03:06 MSK

я хочу обновить ПО, подредачить конфиги и потом запускать с этими изменениями, а не делать всё с нуля
NoobeR ★★★★
( 30.05.16 18:04:44 MSK ) автор топика
Ответ на: комментарий от NoobeR 30.05.16 18:04:44 MSK
Тащемта, ты запускаешь контейнер на основе какого-то образа, редактируешь в нём конфиги, коммитишь изменения и получаешь уже новый образ, в котором эти изменения зафиксированы.
theNamelessOne ★★★★★
( 30.05.16 18:06:22 MSK )
Ответ на: комментарий от NoobeR 30.05.16 18:04:44 MSK
Смотри эту ссылку, обращай внимания на картинки и описания к ним.
theNamelessOne ★★★★★
( 30.05.16 18:07:40 MSK )
Ответ на: комментарий от NoobeR 30.05.16 18:04:44 MSKОбновлять ПО вручную 99% не надо, просто используй свежий образ. Или создай его сам с помощью docker commit или Dockerfile. Конфиги и персистентные стораджи лучше просовывать с помощью volumes.
staseg ★★★★★
( 30.05.16 18:09:26 MSK )
Ответ на: комментарий от staseg 30.05.16 18:09:26 MSKА, и еще важно понять разницу между контейнером и образом, у многих из-за этого каша в голове.
staseg ★★★★★
( 30.05.16 18:10:25 MSK )
Ответ на: комментарий от staseg 30.05.16 18:10:25 MSK
контейнер это то, что работает, а образ это то, из чего создаем контейнер?
NoobeR ★★★★
( 30.05.16 18:23:29 MSK ) автор топика
Ответ на: комментарий от NoobeR 30.05.16 18:23:29 MSK
Образ — это совокупность неизменяемых “слоев” (layers), представляющих различия (differences) в состояниях файловой системы. Контейнер — это рантайм-инстанс образа. Как я уже сказал, образа сами по себе неизменяемы, однако контейнеры содержат вдобавок к неизменяемым слоям образа содержат доступный для записи слой, в котором отражаются его изменения. Когда ты запустил контейнер и внёс изменения в конфиги, эти изменения записались в этот самый слой контейнера. Чтобы зафиксировать эти изменения, есть команда docker commit , которая создаёт из контейнера новый образ, добавляя его доступный для записи слой поверх неизменяемых слоёв базового контейнера. Можно также описывать изменения базового слоя декларативно с помощью Dockerfile .
theNamelessOne ★★★★★
( 30.05.16 18:34:46 MSK )
Ответ на: комментарий от theNamelessOne 30.05.16 18:34:46 MSK
NoobeR ★★★★
( 30.05.16 18:37:03 MSK ) автор топика
Ответ на: комментарий от theNamelessOne 30.05.16 18:34:46 MSK
Можно также описывать изменения базового слоя декларативно с помощью Dockerfile .
Можно также описывать изменения базового образа декларативно с помощью Dockerfile .
Посмотри ещё на volume’ы, вполне возможно, для твоей задачи они будут предпочтительней.
theNamelessOne ★★★★★
( 30.05.16 18:42:53 MSK )
Ответ на: Fix от theNamelessOne 30.05.16 18:42:53 MSK
я и так использую тома, для хранения самих сайтов (~/www). в контейнере ~/www смонтирован в /var/www/srv. если это правильно..
NoobeR ★★★★
( 30.05.16 18:47:32 MSK ) автор топика
Ответ на: комментарий от NoobeR 30.05.16 18:47:32 MSK
Ну так можно с помощью томов примонтировать конфиги.
theNamelessOne ★★★★★
( 30.05.16 18:54:50 MSK )
Ответ на: комментарий от theNamelessOne 30.05.16 18:54:50 MSK
что-то вроде ~/www/config/:/etc/apache2/sites-available ?
NoobeR ★★★★
( 30.05.16 18:56:46 MSK ) автор топика
Ответ на: комментарий от NoobeR 30.05.16 18:56:46 MSK
Насколько я знаю, в таком случае в типовой конфигурации апача ещё требуется симлинк в sites-enabled , так что лучше сразу монтировать туда.
theNamelessOne ★★★★★
( 30.05.16 19:00:09 MSK )
Ответ на: комментарий от theNamelessOne 30.05.16 19:00:09 MSK
NoobeR ★★★★
( 30.05.16 19:01:59 MSK ) автор топика
Ответ на: комментарий от NoobeR 30.05.16 18:04:44 MSK
я хочу обновить ПО, подредачить конфиги и потом запускать с этими изменениями, а не делать всё с нуля
Если ты хочешь ручками что-то править в системе и работать с контейнером как с отдельным компьютером, то тебе нужно смотреть не на Docker, а на LXC.
В Docker же твоя задача решается так:
— Делаем Dockerfile для твоих изменений (исходный образ + действия в нём)
— Из Dockerfile делаем image (или это сделает автоматом docker-compose)
— Запускаем docker-образ, монтируя внутрь него индивидуальные для контейнера конфиги, сохраняемые данные и т.п.Если тебе требуется сохранять сделанные в Docker изменения, то 99% за то, что ты делаешь что-то не так.
Не могу сохранить изменения в контейнере докера
Я с хоста коппирую файл в докер (docker cp file.txt 4f20e373e04b: / root) захожу в диркторирию докера и там есть этот файл. Но только я перезапускаю докер этот файлик пропадаеа.Запускаю докер командой docker run -p 5000: 5000 lorry- server.Я новичок в докерах , помогите пожалуста)
Отслеживать
задан 6 мар 2019 в 13:42
Андрій Гавриляк Андрій Гавриляк
69 1 1 серебряный знак 9 9 бронзовых знаков2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Данные в контейнере сохраняться, если Вы остановите просто остановите контейнер, а не удалите.
# запуск контейнера (без опции --rm) docker run --name foo . # скопировали туда файлик docker cp . # остановили контейнер docker stop foo # запустили контейнер, файлик еще там docker start foo # остановили и удалили контейнер docker stop foo && docker rm foo # файлик утерян навсегда, надо снова делать docker run и docker cpА вообще, чтоб не делать лишних телодвижений рекомендую использовать опцию -v в команде docker run , тогда Ваш файл будет всегда в контейнере
docker run -v /path/to/file.txt:/path/inside/container/file.txtКак сохранить свои изменения во взятом Docker-образе для последующего повторного использования?
Несмотря на возможность сделать docker commit , то, что Вы получите в результате, будет чёрным ящиком, который непонятно каким образом создан. Хорошая практика в данном случае заключается в том, чтобы описать все изменения, которые Вы производите в контейнере, с помощью Dockerfile -а. Этот Dockerfile можно будет сохранить в системе контроля версий, провести его ревью, модифицировать, воспроизвести в сборочном конвеере.
Да, под капотом на каждую строчку в Dockerfile -е происходит вызов docker commit , но важно то, что в этом случает сохраняется источник этих изменений.
Не знаю, как точно настраивается FreePBX, но Вам может понадобиться, например, использовать envsubst для применения переменных окружения, с которыми запущен контейнер, к конфигурационным файлам. А может потребоваться сделать стартовый .sh-скрипт, который при запуске произведёт нужные
конфигурационные действия.В случае использования переменных окружения также очень полезно в скрипте запуска проверить, заданы ли они, и если нет — упасть с осмысленным сообщением об ошибке:
echo MY_ENV_VAR "$"