Docker для Mac v17.12: изменилась ли скорость доступа при монтировании томов
Долгое время пользователи Mac страдали от низкой производительности в контейнерах докера, где использовались тома. К примеру, если вы монтируете ваше приложение в виде тома в папку /app, то получите деградацию производительности по операциям I/O в контейнере. Дело тут в использовании формата qcow (реализация copy-on-write механизма) внутри образа виртуальной машины докера для Mac OS и использовании виртуальной машины самим докером.
Низкая производительность
Многие, наверно, натыкались на различные обсуждения при поиске решения данной проблемы:
Способ, который реально помогает — сбросить sync при flush'е:
$ cd ~/Library/Containers/com.docker.docker/Data/database/
$ git reset --hard
HEAD is now at cafabd0 Docker started 1475137831
$ cat com.docker.driver.amd64-linux/disk/full-sync-on-flush
true
$ echo false > com.docker.driver.amd64-linux/disk/full-sync-on-flush
$ git add com.docker.driver.amd64-linux/disk/full-sync-on-flush
$ git commit -s -m "Disable flushing"
[master dc32fcc] Disable flushing
1 file changed, 1 insertion(+), 1 deletion(-)
Скорость работы с диском увеличилась в несколько раз, но всё равно оставалась недостаточной. Для примера — сравнение скоростей.
Скорость внутри докер-контейнера:
time dd if=/dev/zero of=file.img bs=1024 count=100000
102400000 bytes (102 MB) copied, 15.9318 s, 6.4 MB/s
real 0m15.934s
user 0m0.130s
Скорость на MacBook:
102400000 bytes transferred in 0.905395 secs (113099833 bytes/sec)
dd if=/dev/zero of=file.img bs=1024 count=100000 0,02s user 0,87s system 97% cpu 0,914 total
Видно, что скорость записи медленнее в 16 раз.
Другой популярный способ борьбы с проблемой — docker-sync. Желающие могут почитать подробнее на странице проекта.
Docker 17.12
С выходом версии 17.12 ситуация изменилась. Теперь можно изменять размер образа VM в настройках. Docker теперь использует linuxkit.
Дефолтный формат образа теперь «raw» вместо «qcow». Прежние образы сохранят свой формат при обновлении — переконвертировать их не получится, придётся всё удалить и создать заново.
Если перейти в папку ~/Library/Containers/com.docker.docker/Data, теперь вместо папки com.docker.driver.amd64-linux будет папка vm, в которой содержится образ в «raw» формате (по факту у автора папка com.docker.driver.amd64-linux осталась на месте).
Сначала может показаться, что «raw» образы занимают очень много места. Дело тут в поддержке разреженных файлов (sparse files) файловой системой Apple — логический размер файла может быть больше физического. Подробнее можно прочитать по ссылке.
Посмотреть образ с реальным размером можно командой:
ls -klsh Docker.raw
Напомню, что у формата qcow дефолтный максимальный размер равен 64 Gb.
Освобождение места — поддержка TRIM
В версии Docker 1.13 появится поддержка TRIM, которая поможет освободить место на хост-машине. Размер файла Docker.qcow2 не будет изменён мгновенно — каждые 15 минут будет запускаться задача cron. Однако процесс можно ускорить, запустив контейнер:
docker run --rm -it --privileged --pid=host walkerlee/nsenter -t 1 -m -u -i -n fstrim /var
После этого необходимо сделать restart. Также можно почистить место командой (появится в 1.13):
docker system prune
Подробнее о различии форматов: https://docs.docker.com/docker-for-mac/faqs/#disk-usage
Отступление: новое DNS-имя
Ещё одно нововведение — DNS-имя docker.for.mac.host.internal. Оно теперь должно использоваться вместо docker.for.mac.host.localhost (всё ещё валидная настройка). Это позволит сделать правильный резолвинг хостов внутри контейнеров. Подробнее о проблеме: https://tools.ietf.org/html/draft-west-let-localhost-be-localhost-06
Полный список изменений: https://docs.docker.com/docker-for-mac/release-notes/
Сравнение скорости при использовании томов в новой версии Docker
Возвращаясь к томам в докере — рекомендую сначала сделать бэкапы ваших данных.
Удалите неиспользуемые образы:
docker rmi $(docker images -f dangling=true -q)
Сделайте бэкап необходимых данных, затем удалите файл Docker.qcow2 и перезапустите докер. Либо зайдите в настройки и удалите данные или сбросьте настройки на дефолтные.
После этого можно пользоваться «raw» форматом для образа. Проверим скорость внутри контейнеров:
root@28718ae8cc37:/app# time dd if=/dev/zero of=file.img bs=1024 count=100000
100000+0 records in
100000+0 records out
102400000 bytes (102 MB) copied, 14.4795 s, 7.1 MB/s
real 0m14.484s
user 0m0.180s
sys 0m1.700s
В данном случае скорость не изменилась. Для docker machine ситуация выглядит получше:
root@3ee44d3e4b67:/app# time dd if=/dev/zero of=file.img bs=1024 count=100000
100000+0 records in
100000+0 records out
102400000 bytes (102 MB) copied, 6.28926 s, 16.3 MB/s
real 0m6.300s
user 0m0.000s
sys 0m2.890s
Пока что рекомендуется использовать настройки cached и delegated для томов:
volumes:
- ./:/app:delegated
а также docker-sync.
P.S.
У кого скорость осталась прежней — сначала проверьте, что у вас используется APFS, а не старая HFS+. Для преобразования можно использовать Дисковую Утилиту: зайдите в раздел Правка → Преобразовать в APFS.
Update
Raw формат играет роль только при операциях внутри файловой системы контейнера. Ни raw, ни qcow не влияют на производительность при использовании томов. Обещают улучшить в следующих релизах.