Где хранятся файлы docker
I'm using the Windows 10 Home operating system. I have installed Docker toolbox.
Now I want to ship this image, to another machine. But I am not getting the image file.
Can someone please tell me, where my image will get saved? Or is there any way, to specify docker an image path in docker build command.
Have you checked : C:\Users\Public\Documents\Hyper-V\Virtual hard disks\MobyLinuxVM.vhdx? I find mine there. Thank you for asking the question. @purnima-naik
20 Answers 20
All the answers have been outdated or incorrect for me, I found it in "%localappdata%\Docker\wsl"
I dont inderstand it. I expect docker file or something like json or yml file. How can I change config values e.g. for db connection?
Oh my God whole internet is full of people searching where is docker image file. What a pathetic design and support by Docker creators. Finally I found correct answer here. Many thanks.
The answers are really confusing because there is more than one way to run Docker in Windows. The newest way is with Windows 10 Home May 2020 Update. It will use the new version of Windows Subsystem for Linux (WSL2). This answer is about this configuration.
After activating WSL2, you'll install Docker Desktop. Docker Desktop is a client that'll connect to the host inside the WSL.
The image directory is somewhat inconsistent. If you run docker info in your host machine or inside WSL it will give you the path Docker Root Dir: /var/lib/docker which doesn't exist:
You'll find the images in
Or in this Windows Explorer path:
If you are using Windows 10 non-Home versions, it may work differently. Take a look at the other answers. Since I don't have access to this OS, I won't try to answer.
Now the path \\wsl$\docker-desktop-data\mnt\wsl\docker-desktop-data\data\ is empty for me, although docker info says I have 4 images.
@AlexandrZarubkin The correct path in my case was: \\wsl$\docker-desktop-data\version-pack-data\community\docker\image and/or \\wsl$\docker-desktop-data\version-pack-data\community\docker\overlay2 (depending on what you're looking for)
On Windows 10, right click on the docker icon in the system tray (right hand side of task bar) and choose Settings. In the Advanced pane, you'll see something like:
Could get this path location in the Advanced Settings menu, but this path doesn't exist in my file system despite have set to show hidden and system files & folders!
- By using the docker info command.
- In the result - check for Docker Root Dir
This folder will conatins images, containers, .
On my Windows 10 machine, I get this path "Docker Root Dir: /mnt/sda1/var/lib/docker", which doesn't exists on my machine.
Are you running Docker or Docker Toolbox? By the logs, it seems that you are running Docker-Toolbox, which runs the linux VM for docker-machine. In this case - conect to docker-machine, and go to this specified folder
Why is it impossible to get good information about docker?? This is so frustrating! Like the people above, I am running linux containers on a Windows 10 machine and I am unable to figure out what magical location docker stores the containers in.
If you are on windows 10 and running windows containers
In the above image, docker is running windows containers. So its showing switch to linux containers.
First run docker info command (more specific docker info --format “>” ).
You should see root dir as
Docker Root Dir: C:\ProgramData\Docker
Now run a command to pull an image like
After it pulls the image, you can look into the docker root dir.
Notice the current modified date time. In one of the folders you can see the sha of the layers.
Finally, you also have to take a look into the following folder, if you want to know where the images are downloaded. The two folders above and below are
- C:\ProgramData\Docker\image\windowsfilter
- C:\ProgramData\Docker\windowsfilter
Now for linux images.
If your docker is running windows containers, and then if you try to fetch a linux based container such as nginx, like so
you will get a message as follows.
So switch to linux contaners. See the very first image.
Once the docker for linux is running, run the command again.
You can see that image is downloading.
Now where is this image downloaded on your hard disk? docker info command may not help much in this case.
So start again. Click Settings and now "Switch to Windows Containers. "
And now see the path.
On my machine, it's C:\ProgramData\DockerDesktop\vm-data
Note the date modified column. Notice and observe that after you pull or remove a linux based image.
That's a diskspace reserved for linux env, so you will not be able to browse further down to see where the image is.
but if you have to, then launch a linux based VM, install docker and explore the path /var/lib/docker/
У меня redmine установлен на сервере в двух контейнерах:
Хочу перенести их, запустить в другом месте, и сделать резервную копию. В документации ясно написано, что контейнеры создаются в том числе для переноса, однако инструкций как это делается я не нашёл. Нашёл, что docker хранит свои файлы в директории /var/lib/docker однако там у меня много тысяч файлов на 4 GB, а мои контейнеры - намного меньше, не хотелось бы таскать всё что есть в этой директории
Вы изначально при запуске контейнеров не создавали volumes на хостовую машину docker run -v /path/to/host/data::/var/lib/postgresql ?
Да, в доках написано --volume=/srv/docker/redmine/postgresql:/var/lib/postgresql . Когда контейнер запускался директория /srv/docker/redmine/postgresql должна была создаться автоматически. Посмотрите, что там или sudo docker inspect --format '<< .Volumes >>' postgresql-redmine . Достаточно заархивировать её, перенести на новый сервер и разархивировать. Путь разархиварования, не имеет значение, ибо директория, как вы уже заметили, задаётся через volume. Далее, на новой машине подтянуть образ контейнера желательно той же версии: docker pull quay.io/sameersbn/postgresql:latest<>
Собственно, запускаем postgres-контейнер, но без переменных окружения - нам же не нужно вновь создавать БД и пользователя: docker run --name=postgresql-redmine -d --volume=/srv/docker/redmine/postgresql:/var/lib/postgresql quay.io/sameersbn/postgresql:latest . C redmine аналогично. Архивируем /srv/docker/redmine/redmine , переносим и запускаем docker run --name=redmine -d --link=postgresql-redmine:postgresql -p 10083:80 -e 'REDMINE_PORT=10083' -v /srv/docker/redmine/redmine:/home/redmine/data quay.io/sameersbn/redmine
Да, перед архивированием контейнеры необходимо остановить docker stop redmine postgresql-redmine , а потому можно запустить вновь docker stop postgresql-redmine redmine .
2 ответа 2
В приведённой вами инструкции видно, что контейнер запускается с опцией
В момент монтирования происходит затирание данных в контейнере, если те присутствовали по этому пути.
Если опция --volume не была указана, то docker автоматически создаёт volumes исходя из параметров указанных в конфигурационном файле Dockerfile.
Если обратиться к исходникам образа для PostgreSQL, то можно заметить, что это два volumes: /var/lib/postgresql и /run/postgresql . По первому пути расположены данные postgres. Собственно, они нас и интересуют.
Узнать всю информацию про volumes отдельно взятого контейнера можно командой
Данные возвращаются в json-формате, а потому предусмотрена возможность фильтрации/поиска через опцию --format
Все volumes для которых не указан путь расположения на хосте (левая часть /host/path/to/data:/container/to/data ) хранятся в директории /var/lib/docker/volumes//_data/ . Таким образом, можно просто исследовав все директории в /var/lib/docker/volumes/ и найти необходимый.
Если левая часть указана, а правая совпадает с volumes, которые указаны в Dockerfile (volumes by default), то происходит переопределение директории на хосте. Зачем нам два волиума с одинковыми данными на хосте ( /var/lib/docker/volumes//_data/ и /host/path/to/data ), правда?
Как уже было отмечено @dmitrz, пока не существует возможности управлять volumes уже на поднятых контейнерах, также как и линковать. Первая проблема должна уже очень скоро решиться.
▍Удаление тома
Удалить том можно так:
Для того чтобы удалить все тома, которые не используются контейнерами, можно прибегнуть к такой команде:
Перед удалением томов Docker запросит у вас подтверждение выполнения этой операции.
Если том связан с каким-либо контейнером, такой том нельзя удалить до тех пор, пока не удалён соответствующий контейнер. При этом, даже если контейнер удалён, Docker не всегда это понимает. Если это случилось — можете воспользоваться следующей командой:
Она предназначена для очистки ресурсов Docker. После выполнения этой команды у вас должна появиться возможность удалить тома, статус которых до этого определялся неправильно.
Итоги
Вот полезные команды, которыми можно пользоваться при работе с томами Docker:
- docker volume create
- docker volume ls
- docker volume inspect
- docker volume rm
- docker volume prune
- type=volume
- source=volume_name
- destination=/path/in/container
- readonly
Особенности работы контейнеров
Прежде чем перейти к способам хранения данных, вспомним устройство контейнеров. Это поможет лучше понять основную тему.
Контейнер создаётся из образа, в котором есть всё для начала его работы. Но там не хранится и тем более не изменяется ничего важного. В любой момент приложение в контейнере может быть завершено, а контейнер уничтожен, и это нормально. Контейнер отработал — выкидываем его и собираем новый. Если пользователь загрузил в приложение картинку, то при замене контейнера она удалится.
На схеме показано устройство контейнера, запущенного из образа Ubuntu 15.04. Контейнер состоит из пяти слоёв: четыре из них принадлежат образу, и лишь один — самому контейнеру. Слои образа доступны только для чтения, слой контейнера — для чтения и для записи. Если при работе приложения какие-то данные будут изменяться, они попадут в слой контейнера. Но при уничтожении контейнера слой будет безвозвратно потерян, и все данные вместе с ним.
В идеальном мире Docker используют только для запуска stateless-приложений, которые не читают и не сохраняют данные о своём состоянии и готовы в любой момент завершиться. Однако в реальности большинство программ относятся к категории stateful, то есть требуют сохранения данных между перезапусками.
Поэтому нужны способы сделать так, чтобы важные изменяемые данные не зависели от эфемерности контейнеров и, как бонус, были доступными сразу из нескольких мест.
В Docker есть несколько способов хранения данных. Наиболее распространенные:
- тома хранения данных (docker volumes),
- монтирование каталогов с хоста (bind mount).
Особые типы хранения:
- именованные каналы (named pipes, только в Windows),
- монтирование tmpfs (только в Linux).
На схеме показаны самые популярные типы хранения данных для Linux: в памяти (tmpfs), в файловой системе хоста (bind mount), в томе Docker (docker volumes). Разберём каждый вариант.
Работа с томами из командной строки
Ошибка в версии Ruby
В docker существует такое понятие, как entrypoint. Обычно это shell-скрипт, который дёргается при запуске docker run или docker start . Если посмотреть листинг entrypoint.sh для redmine, то можно заметить установку плагинов (bundles) для redmine. Далее, если файла $/tmp/plugins.sha1 не существует, то происходит установка плагинов. Обратите внимание на переменную $ и посмотрите в Dockerfile для redmine, т.е. REDMINE_DATA_DIR входит в волиум. Вспоминаем, что при коммите данные волиума не заносятся в образ. Когда закоммиченый контейнер запускается на новой машине видимо возникает конфликт старой версии redmine и устанавливаемых вновь плагинов.
Если данные redmine критичны ( /srv/docker/redmine/redmine:/home/redmine/data ), то их обязательно нужно перенести на новую машину. Далее, поднять либо закоммиченый образ, либо загрузить контейнер с уже новой версией redmine по той инструкции.
Можете ознакомится со всеми доступными версиями redmine образов от sameersbn.
Что касается PostgreSQL контейнера, то его данные ( /srv/docker/redmine/postgresql:/var/lib/postgresql ) обязательно необходимо перенести.
Флаги --mount и --volume
Для работы с томами вам, при вызове команды docker , часто придётся пользоваться флагами. Например, для того чтобы создать том во время создания контейнера можно воспользоваться такой конструкцией:
В давние времена (до 2017 года) популярен был флаг --volume . Изначально этот флаг (ещё им можно пользоваться в сокращённом виде, тогда он выглядит как -v ) использовался для самостоятельных контейнеров, а флаг --mount — в среде Docker Swarm. Однако, начиная с Docker 17.06, флаг --mount можно использовать в любых сценариях.
Надо отметить, что при использовании флага --mount увеличивается объём дополнительных данных, которые приходится указывать в команде, но, по нескольким причинам, лучше использовать именно этот флаг, а не --volume . Флаг --mount — это единственный механизм, который позволяет работать с сервисами или указывать параметры драйвера тома. Кроме того, работать с этим флагом проще.
В существующих примерах команд, направленных на работу с данными в Docker, вы можете встретить множество примеров употребления флага -v . Пытаясь адаптировать эти команды для себя, учитывайте то, что флаги --mount и --volume используют различные форматы параметров. То есть, нельзя просто заменить -v на --mount и получить рабочую команду.
Главное различие между --mount и --volume заключается в том, что при использовании флага --volume все параметры собирают вместе, в одном поле, а при использовании --mount параметры разделяются.
При работе с --mount параметры представлены как пары вида ключ-значение, а именно, это выглядит как key=value . Эти пары разделяют запятыми. Вот часто используемые параметры --mount :
- type — тип монтирования. Значением для соответствующего ключа могут выступать bind, volume или tmpfs. Мы тут говорим о томах, то есть — нас интересует значение volume .
- source — источник монтирования. Для именованных томов это — имя тома. Для неименованных томов этот ключ не указывают. Он может быть сокращён до src .
- destination — путь, к которому файл или папка монтируется в контейнере. Этот ключ может быть сокращён до dst или target .
- readonly — монтирует том, который предназначен только для чтения. Использовать этот ключ необязательно, значение ему не назначают.
Тома Docker
Том — это файловая система, которая расположена на хост-машине за пределами контейнеров. Созданием и управлением томами занимается Docker. Вот основные свойства томов Docker:
- Они представляют собой средства для постоянного хранения информации.
- Они самостоятельны и отделены от контейнеров.
- Ими могут совместно пользоваться разные контейнеры.
- Они позволяют организовать эффективное чтение и запись данных.
- Тома можно размещать на ресурсах удалённого облачного провайдера.
- Их можно шифровать.
- Им можно давать имена.
- Контейнер может организовать заблаговременное наполнение тома данными.
- Они удобны для тестирования.
Монтирование каталога с хоста (bind mount)
Это более простая концепция: файл или каталог с хоста просто монтируется в контейнер.
Используется, когда нужно пробросить в контейнер конфигурационные файлы с хоста. Например, именно так в контейнерах реализуется DNS: с хоста монтируется файл /etc/resolv.conf.
Другое очевидное применение — в разработке. Код находится на хосте (вашем ноутбуке), но исполняется в контейнере. Вы меняете код и сразу видите результат. Это возможно, так как процессы хоста и контейнера одновременно имеют доступ к одним и тем же данным.
Особенности bind mount:
- Запись в примонтированный каталог могут вести программы как в контейнере, так и на хосте. Это значит, есть риск случайно затереть данные, не понимая, что с ними работает контейнер.
- Лучше не использовать в продакшене. Для продакшена убедитесь, что код копируется в контейнер, а не монтируется с хоста.
- Для успешного монтирования указывайте полный путь к файлу или каталогу на хосте.
- Если приложение в контейнере запущено от root, а совместно используется каталог с ограниченными правами, то в какой-то момент может возникнуть проблема с правами на файлы и невозможность что-то удалить без использования sudo.
Когда использовать тома, а когда монтирование с хоста
Volume | Bind mount |
---|---|
Просто расшарить данные между контейнерами. | Пробросить конфигурацию с хоста в контейнер. |
У хоста нет нужной структуры каталогов. | Расшарить исходники и/или уже собранные приложения. |
Данные лучше хранить не локально (а в облаке, например). | Есть стабильная структура каталогов и файлов, которую нужно расшарить между контейнерами. |
Общие советы по использованию томов
Монтирование в непустые директории
Если вы монтируете пустой том в каталог контейнера, где уже есть файлы, то эти файлы не удалятся, а будут скопированы в том. Этим можно пользоваться, когда нужно скопировать данные из одного контейнера в другой.
Если вы монтируете непустой том или каталог с хоста в контейнер, где уже есть файлы, то эти файлы тоже не удалятся, а просто будут скрыты. Видно будет только то, что есть в томе или каталоге на хосте. Похоже на простое монтирование в Linux.
Монтирование служебных файлов
С хоста можно монтировать любые файлы, в том числе служебные. Например, сокет docker. В результате получится docker-in-docker: один контейнер запустится внутри другого. UPD: (*это не совсем так. mwizard в комментариях пояснил, что в таком случае родительский docker запустит sibling-контейнер). Выглядит как бред, но в некоторых случаях бывает оправдано. Например, при настройке CI/CD.
Монтирование /var/lib/docker
Разработчики Docker говорят, что не стоит монтировать с хоста каталог /var/lib/docker, так как могут возникнуть проблемы. Однако есть некоторые программы, для запуска которых это необходимо.
Ключ командной строки для Docker при работе с томами.
Для volume или bind mount:
Команды для управления томами в интерфейсе CLI Docker:
Создадим тестовый том:
Вот он появился в списке:
Команда inspect выдаст примерно такой список информации в json:
Попробуем использовать созданный том, запустим с ним контейнер:
После самоуничтожения контейнера запустим другой и подключим к нему тот же том. Проверяем, что в нашем файле:
То же самое, отлично.
Теперь примонтируем каталог с хоста:
Docker не любит относительные пути, лучше указывайте абсолютные!
Теперь попробуем совместить оба типа томов сразу:
Отлично! А если нам нужно передать ровно те же тома другому контейнеру?
Вы можете заметить некий лаг в обновлении данных между контейнерами, это зависит от используемого Docker драйвера файловой системы.
Создавать том заранее необязательно, всё сработает в момент запуска docker run:
Посмотрим теперь на список томов:
Ещё немного усложним команду запуска, создадим анонимный том:
Такой том самоуничтожится после выхода из контейнера, так как мы указали ключ –rm.
Если этого не сделать, давайте проверим что будет:
Хозяйке на заметку: тома (как образы и контейнеры) ограничены значением настройки dm.basesize, которая устанавливается на уровне настроек демона Docker. Как правило, что-то около 10Gb. Это значение можно изменить вручную, но потребуется перезапуск демона Docker.
При запуске демона с ключом это выглядит так:
Однажды увеличив значение, его уже нельзя просто так уменьшить. При запуске Docker выдаст ошибку.
Если вам нужно вручную очистить содержимое всех томов, придётся удалять каталог, предварительно остановив демон:
Если вам интересно узнать подробнее о работе с данными в Docker и других возможностях технологии, приглашаем на двухдневный онлайн-интенсив в феврале. Будет много практики.
Автор статьи: Александр Швалов, практикующий инженер Southbridge, Certified Kubernetes Administrator, автор и разработчик курсов Слёрм.
В сегодняшней части перевода серии материалов о Docker мы поговорим о работе с данными. В частности — о томах Docker. В этих материалах мы постоянно сравнивали программные механизмы Docker с разными съедобными аналогиями. Не будем отходить от этой традиции и здесь. Данные в Docker пусть будут специями. В мире существует множество видов специй, а в Docker — множество способов работы с данными.
Данные в Docker могут храниться либо временно, либо постоянно. Начнём с временных данных.
▍Создание тома
Создать самостоятельный том можно следующей командой:
Создание томов
Тома можно создавать средствами Docker или с помощью запросов к API.
Вот инструкция в Dockerfile, которая позволяет создать том при запуске контейнера.
При использовании подобной инструкции Docker, после создания контейнера, создаст том, содержащий данные, которые уже имеются в указанном месте. Обратите внимание на то, что если вы создаёте том с использованием Dockerfile, это не освобождает вас от необходимости указать точку монтирования тома.
Создавать тома в Dockerfile можно и используя формат JSON.
Кроме того, тома можно создавать средствами командной строки во время работы контейнера.
Загрузка образов
, где тег - это, как правило, версия софта, который находится в этом образе.
Запуск контейнера происходит командой
Если образа с таким именем и тегом на локальной машине нет, то прозрачно срабатывает команда docker pull , т.е. образ ищется на удалённых registry.
Если вы не знаете, что такое Docker или не понимаете, как он соотносится с виртуальными машинами или с инструментами configuration management, то этот пост может показаться немного сложным.
Пост предназначен для тех, кто пытается освоить docker cli, понять, чем отличается контейнер и образ. В частности, будет объяснена разница между просто контейнером и запущенным контейнером.
В процессе освоения нужно представить себе некоторые лежащие в основе детали, например, слои файловой системы UnionFS. В течение последней пары недель я изучал технологию, я новичок в мире docker, и командная строка docker показалась мне довольно сложной для освоения.
По-моему, понимание того, как технология работает изнутри — лучший способ быстро освоить новый инструмент и правильно его использовать. Часто новая технология разрабатывает новые модели абстракций и привносит новые термины и метафоры, которые могут быть как будто бы понятны в начале, но без четкого понимания затрудняют последующее использование инструмента.
Хорошим примером является Git. Я не мог понять Git, пока не понял его базовую модель, включая trees, blobs, commits, tags, tree-ish и прочее. Я думаю, что люди, не понимающие внутренности Git, не могут мастерски использовать этот инструмент.
Определение образа (Image)
Визуализация образа представлена ниже в двух видах. Образ можно определить как «сущность» или «общий вид» (union view) стека слоев только для чтения.
Слева мы видим стек слоев для чтения. Они показаны только для понимания внутреннего устройства, они доступны вне запущенного контейнера на хост-системе. Важно то, что они доступны только для чтения (иммутабельны), а все изменения происходят в верхнем слое стека. Каждый слой может иметь одного родителя, родитель тоже имеет родителя и т.д. Слой верхнего уровня может быть использован как UnionFS (AUFS в моем случае с docker) и представлен в виде единой read-only файловой системы, в которой отражены все слои. Мы видим эту «сущность» образа на рисунке справа.
Если вы захотите посмотреть на эти слои в первозданном виде, вы можете найти их в файловой системе на хост-машине. Они не видны напрямую из запущенного контейнера. На моей хост-машине я могу найти образы в /var/lib/docker/aufs.
Определение контейнера (Container)
Контейнер можно назвать «сущностью» стека слоев с верхним слоем для записи.
На изображении выше показано примерно то же самое, что на изображении про образ, кроме того, что верхний слой доступен для записи. Вы могли заметить, что это определение ничего не говорит о том, запущен контейнер или нет и это неспроста. Разделение контейнеров на запущенные и не запущенные устранило путаницу в моем понимании.
Контейнер определяет лишь слой для записи наверху образа (стека слоев для чтения). Он не запущен.
Определение запущенного контейнера
Запущенный контейнер — это «общий вид» контейнера для чтения-записи и его изолированного пространства процессов. Ниже изображен контейнер в своем пространстве процессов.
Изоляция файловой системы обеспечивается технологиями уровня ядра, cgroups, namespaces и другие, позволяют докеру быть такой перспективной технологией. Процессы в пространстве контейнера могут изменять, удалять или создавать файлы, которые сохраняются в верхнем слое для записи. Смотрите изображение:
Чтобы проверить это, выполните команду на хост-машине:
Вы можете найти новый файл в слое для записи на хост-машине, даже если контейнер не запущен.
Определение слоя образа (Image layer)
Наконец, мы определим слой образа. Изображение ниже представляет слой образа и дает нам понять, что слой — это не просто изменения в файловой системе.
Метаданные — дополнительная информация о слое, которая позволяет докеру сохранять информацию во время выполнения и во время сборки. Оба вида слоев (для чтения и для записи) содержат метаданные.
Кроме того, как мы уже упоминали раньше, каждый слой содержит указатель на родителя, используя id (на изображении родительские слои внизу). Если слой не указывает на родительский слой, значит он наверху стека.
Расположение метаданных
На данный момент (я понимаю, что разработчики docker могут позже сменить реализацию), метаданные слоев образов (для чтения) находятся в файле с именем «json» в папке /var/lib/docker/graph/id_слоя:
где «e809f156dc985. » — урезанный id слоя.
Свяжем все вместе
Теперь, давайте посмотрим на команды, иллюстрированные понятными картинками.
docker create
До:
После:
Команда 'docker create' добавляет слой для записи наверх стека слоев, найденного по . Команда не запускает контейнер.
docker start
До:
После:
Команда 'docker start' создает пространство процессов вокруг слоев контейнера. Может быть только одно пространство процессов на один контейнер.
docker run
До:
После:
Один из первых вопросов, который задают люди (я тоже задавал): «В чем разница между 'docker start' и 'docker run'?» Одна из первоначальных целей этого поста — объяснить эту тонкость.
Как мы видим, команда 'docker run' находит образ, создает контейнер поверх него и запускает контейнер. Это сделано для удобства и скрывает детали двух команд.
Продолжая сравнение с освоением Git, я скажу, что 'docker run' очень похожа на 'git pull'. Так же, как и 'git pull' (который объединяет 'git fetch' и 'git merge'), команда 'docker run' объединяет две команды, которые могут использоваться и независимо. Это удобно, но поначалу может ввести в заблуждение.
docker ps
Команда 'docker ps' выводит список запущенных контейнеров на вашей хост-машине. Важно понимать, что в этот список входят только запущенные контейнеры, не запущенные контейнеры скрыты. Чтобы посмотреть список всех контейнеров, нужно использовать следующую команду.
docker ps -a
Команда 'docker ps -a', где 'a' — сокращение от 'all' выводит список всех контейнеров, независимо от их состояния.
docker images
Команда 'docker images' выводит список образов верхнего уровня (top-level images). Фактически, ничего особенного не отличает образ от слоя для чтения. Только те образы, которые имеют присоединенные контейнеры или те, что были получены с помощью pull, считаются образами верхнего уровня. Это различие нужно для удобства, так как за каждым образом верхнего уровня может быть множество слоев.
docker images -a
Команда 'docker images -a' выводит все образы на хост-машине. Это фактически список всех слоев для чтения в системе. Если вы хотите увидеть все слои одного образа, воспользуйтесь командой 'docker history'.
docker stop
До:
После:
Команда 'docker stop' посылает сигнал SIGTERM запущенному контейнеру, что мягко останавливает все процессы в пространстве процессов контейнера. В результате мы получаем не запущенный контейнер.
docker kill
До:
После:
Команда 'docker kill' посылает сигнал SIGKILL, что немедленно завершает все процессы в текущем контейнере. Это почти то же самое, что нажать Ctrl+\ в терминале.
docker pause
До:
После:
В отличие от 'docker stop' и 'docker kill', которые посылают настоящие UNIX сигналы процессам контейнера, команда 'docker pause' используют специальную возможность cgroups для заморозки запущенного пространства процессов. Подробности можно прочитать здесь, если вкратце, отправки сигнала Ctrl+Z (SIGTSTP) не достаточно, чтобы заморозить все процессы в пространстве контейнера.
docker rm
До:
После:
Команда 'docker rm' удаляет слой для записи, который определяет контейнер на хост-системе. Должна быть запущена на остановленном контейнерах. Удаляет файлы.
docker rmi
До:
После:
Команда 'docker rmi' удаляет слой для чтения, который определяет «сущность» образа. Она удаляет образ с хост-системы, но образ все еще может быть получен из репозитория через 'docker pull'. Вы можете использовать 'docker rmi' только для слоев верхнего уровня (или образов), для удаления промежуточных слоев нужно использовать 'docker rmi -f'.
docker commit
До:
или
После:
Команда 'docker commit' берет верхний уровень контейнера, тот, что для записи и превращает его в слой для чтения. Это фактически превращает контейнер (вне зависимости от того, запущен ли он) в неизменяемый образ.
docker build
До:
Dockerfile и
После:
Со многими другими слоями.
Команда 'docker build' интересна тем, что запускает целый ряд команд:
На изображении выше мы видим, как команда build использует значение инструкции FROM из файла Dockerfile как базовый образ после чего:
1) запускает контейнер (create и start)
2) изменяет слой для записи
3) делает commit
На каждой итерации создается новый слой. При исполнении 'docker build' может создаваться множество слоев.
docker exec
До:
После:
Команда 'docker exec' применяется к запущенному контейнеру, запускает новый процесс внутри пространства процессов контейнера.
docker inspect |
До:
или
После:
Команда 'docker inspect' получает метаданные верхнего слоя контейнера или образа.
docker save
До:
После:
Команда 'docker save' создает один файл, который может быть использован для импорта образа на другую хост-систему. В отличие от команды 'export', она сохраняет все слои и их метаданные. Может быть применена только к образам.
docker export
До:
После:
Команда 'docker export' создает tar архив с содержимым файлов контейнера, в результате получается папка, пригодная для использования вне docker. Команда убирает слои и их метаданные. Может быть применена только для контейнеров.
docker history
До:
После:
Команда 'docker history' принимает и рекурсивно выводит список всех слоев-родителей образа (которые тоже могут быть образами)
Я надеюсь, вам понравилась эта визуализация контейнеров и образов. Есть много других команд (pull, search, restart, attach и другие), которые могут или не могут быть объяснены моими сравнениями.
Важная характеристика Docker-контейнеров — эфемерность. В любой момент контейнер может рестартовать: завершиться и вновь запуститься из образа. При этом все накопленные в нём данные будут потеряны. Но как в таком случае запускать в Docker приложения, которые должны сохранять информацию о своём состоянии? Для этого есть несколько инструментов.
В этой статье рассмотрим docker volumes, bind mount и tmpfs, дадим советы по их использованию, проведём небольшую практику.
Команда commit
Volume является отдельной сущностью и потому не попадает в commit. Вот что говорит официальная документация.
The commit operation will not include any data contained in volumes mounted inside the container.
Вообще смущает наличие двух методов создания образов: файлами конфигурации и коммитами.
Временное хранение данные
В контейнерах Docker организовать работу с временными данными можно двумя способами.
По умолчанию файлы, создаваемые приложением, работающим в контейнере, сохраняются в слое контейнера, поддерживающем запись. Для того чтобы этот механизм работал, ничего специально настраивать не нужно. Получается дёшево и сердито. Приложению достаточно просто сохранить данные и продолжить заниматься своими делами. Однако после того как контейнер перестанет существовать, исчезнут и данные, сохранённые таким вот нехитрым способом.
Для хранения временных файлов в Docker можно воспользоваться ещё одним решением, подходящим для тех случаев, когда требуется более высокий уровень производительности, в сравнении с тем, который достижим при использовании стандартного механизма временного хранения данных. Если вам не нужно, чтобы ваши данные хранились бы дольше, чем существует контейнер, вы можете подключить к контейнеру tmpfs — временное хранилище информации, которое использует оперативную память хоста. Это позволит ускорить выполнение операций по записи и чтению данных.
Часто бывает так, что данные нужно хранить и после того, как контейнер прекратит существовать. Для этого нам пригодятся механизмы постоянного хранения данных.
▍Выяснение информации о томах
Для того чтобы просмотреть список томов Docker, воспользуйтесь следующей командой:
Исследовать конкретный том можно так:
Монтирование tmpfs
Tmpfs — временное файловое хранилище. Это некая специально отведённая область в оперативной памяти компьютера. Из определения выходит, что tmpfs — не лучшее хранилище для важных данных. Так оно и есть: при остановке или перезапуске контейнера сохранённые в tmpfs данные будут навсегда потеряны.
На самом деле tmpfs нужно не для сохранения данных, а для безопасности, полученные в ходе работы приложения чувствительные данные безвозвратно исчезнут после завершения работы контейнера. Бонусом использования будет высокая скорость доступа к информации.
Например, приложение в контейнере тормозит из-за того, что в ходе работы активно идут операции чтения-записи, а диски на хосте не очень быстрые. Если вы не уверены, в какой каталог идёт эта нагрузка, можно применить к запущенному контейнеру команду docker diff . И вот этот каталог смонтировать как tmpfs, таким образом перенеся ввод-вывод с диска в оперативную память.
Такое хранилище может одновременно работать только с одним контейнером и доступно только в Linux.
Тома (docker volumes)
Тома — рекомендуемый разработчиками Docker способ хранения данных. В Linux тома находятся по умолчанию в /var/lib/docker/volumes/. Другие программы не должны получать к ним доступ напрямую, только через контейнер.
Тома создаются и управляются средствами Docker: командой docker volume create, через указание тома при создании контейнера в Dockerfile или docker-compose.yml.
В контейнере том видно как обычный каталог, который мы определяем в Dockerfile. Тома могут быть с именами или без — безымянным томам Docker сам присвоит имя.
Один том может быть примонтирован одновременно в несколько контейнеров. Когда никто не использует том, он не удаляется, а продолжает существовать. Команда для удаления томов: docker volume prune.
Можно выбрать специальный драйвер для тома и хранить данные не на хосте, а на удалённом сервере или в облаке.
Для чего стоит использовать тома в Docker:
- шаринг данных между несколькими запущенными контейнерами,
- решение проблемы привязки к ОС хоста,
- удалённое хранение данных,
- бэкап или миграция данных на другой хост с Docker (для этого надо остановить все контейнеры и скопировать содержимое из каталога тома в нужное место).
Постоянное хранение данных
Существуют два способа, позволяющих сделать срок жизни данных большим срока жизни контейнера. Один из способов заключается в использовании технологии bind mount. При таком подходе к контейнеру можно примонтировать, например, реально существующую папку. Работать с данными, хранящимися в такой папке, смогут и процессы, находящиеся за пределами Docker. Вот как выглядят монтирование tmpfs и технология bind mount.
Монтирование tmpfs и bind mount
Минусы использования технологии bind mount заключаются в том, что её использование усложняет резервное копирование данных, миграцию данных, совместное использование данных несколькими контейнерами. Гораздо лучше для постоянного хранения данных использовать тома Docker.
Читайте также: