Учебник. Сохранение данных в приложении-контейнере с помощью томов в 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
. Вторая команда наблюдает за файлом, чтобы работа контейнера не прекращалась.В VS Code в области Docker щелкните правой кнопкой мыши контейнер Ubuntu и выберите команду Присоединить оболочку.
Откроется терминал с запущенной оболочкой в контейнере Ubuntu.
Выполните следующую команду, чтобы просмотреть содержимое файла
/data.txt
.cat /data.txt
В терминале отображается число от 1 до 10000.
Чтобы использовать командную строку для просмотра этого результата, получите идентификатор контейнера с помощью команды
docker ps
и выполните следующую команду.docker exec <container-id> cat /data.txt
Запустите другой контейнер
ubuntu
.docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
Используйте эту команду для просмотра содержимого папки.
docker run -it ubuntu ls /
Там не должно быть файла
data.txt
, так как он был записан в область временных файлов только для первого контейнера.Выберите эти два контейнера Ubuntu. Щелкните правой кнопкой и выберите Удалить. Контейнеры можно удалить из командной строки с помощью команды
docker rm -f
.
Сохранение данных приложения Todo с помощью именованных томов
По умолчанию приложение todo сохраняет данные в базе данных SQLite в /etc/todos/todo.db
.
База данных SQLite — это реляционная база данных, которая хранит данные в одном файле.
Этот подход приемлем для небольших проектов.
Можно сохранить один файл на узле. Когда вы сделаете его доступным для следующего контейнера, приложение сможет продолжить работу с того места, где оно было остановлено. Создавая том и присоединяя его (или подключая) к папке, в которой хранятся данные, можно сохранить данные. Контейнер выполняет запись в файл todo.db, и эти данные сохраняются на узле в томе.
Для выполнения инструкций в этом разделе используется именованный том. Docker сохраняет физическое расположение тома на диске. Укажите имя тома, и Docker предоставит правильные данные.
Создайте том с помощью команды
docker volume create
.docker volume create todo-db
В разделе "КОНТЕЙНЕРЫ" выберите пункт "Начало работы " и щелкните правой кнопкой мыши. Выберите Остановить, чтобы остановить контейнер приложения.
Чтобы остановить контейнер из командной строки, используйте команду
docker stop
.Запустите контейнер getting-started, выполнив следующую команду.
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Параметр volume указывает том для подключения и расположение (
/etc/todos
).Обновите браузер, чтобы перезагрузить приложение. Если вы закрыли окно браузера, перейдите по адресу
http://localhost:3000/
. Добавьте несколько элементов в список дел.Удалите контейнер getting-started для приложения Todo. Щелкните правой кнопкой мыши контейнер в области Docker и выберите Удалить либо используйте команды
docker stop
иdocker rm
.Запустите новый контейнер с помощью той же команды:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
Эта команда подключает тот же диск, что и раньше. Обновите свой браузер. Добавленные элементы останутся в списке.
Снова удалите контейнер 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 ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
Эта команда содержит следующие параметры
-dp 3000:3000
— то же, что и раньше. Выполните команду в отключенном режиме и создайте сопоставление портов.-w /app
— рабочий каталог внутри контейнера.-v ${PWD}:/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
.docker logs -f <container-id>
$ 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
Если вы видите последнюю запись в этом списке, значит приложение выполняется.
Завершив просмотр журналов, нажмите любую клавишу в окне терминала или нажмите сочетание клавиши CTRL+C во внешнем окне.
В VS Code откройте файл src/static/js/app.js. Измените текст кнопки Добавить элемент в строке 109.
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
Сохраните изменения.
Обновите свой браузер. Вы должны увидеть изменение.
Просмотр слоев образа
Можно просмотреть слои, составляющие образ.
Выполните команду 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 <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
Каждая строка представляет слой в образе. В выходных данных внизу показана основа, а вверху — самый новый слой. С помощью этих сведений можно просмотреть размер каждого слоя, что помогает диагностировать большие образы.
Несколько строк усечены. После добавления параметра
--no-trunc
вам будут доступны полные выходные данные.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
.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
Все слои были перестроены. Этот результат является ожидаемым, так как вы изменили Dockerfile.
Измените файл src/static/index.html. Например, измените заголовок на "The Awesome Todo App" (Прекрасное приложение Todo).
Снова создайте образ Docker, используя
docker build
. На этот раз выходные данные должны выглядеть немного иначе.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
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по