Лично я не против самого инструмента - если он реально помогает на этапе разработки, то супер.
Вот только в контейнере он не даст никаких преимуществ, потому что внутри docker образа нет никакого кэша пакетов. Во-первых, одно приложение - один образ, значит нет никакого переиспользования. Во-вторых, кэши раздувают размер образа, поэтому в докере они обычно выключены. Поэтому его применение здесь выглядит как натягивание совы на глобус.
А все попытки притащить инструмент костыльными путями (через volume, через монтирование папки node_modules с хоста, и т.п.) приводят к тому, что возникают проблемы с изоляцией зависимостей и воспроизводимостью сборки. На проде это критично, поэтому крайне не рекомендую так делать.
Максимум где такое можно использовать - локальная разработка в докере, но не более. А для ускорения продовой сборки есть другие варианты, один с buildkit я уже описал выше.
то такому контейру очень выгодно иметь актуальный репозиторий без накладных расходов
Для этого есть buildkit и опция RUN --mount=type=cache в Dockerfile. А с внешними симлинками в докере легко напортачить, могут начать вести на несуществующие пути, если ошибиться с монтированием.
Это антипаттерн. Контейнеры - это про изоляцию приложения вместе с его набором зависимостей и окружением от остального мира. Шарить код между контейнерами через volume значит идти против основной идеи докера.
А что не так? Он удобен для воспроизведения prod среды на девелоперских машинках. Нет зависимости от ОС, не надо страдать с установкой СУБД на хост, и т.п.
Почему низкие порты для основных служб
8060 это низкий порт? К тому жеч докер позволяет настроить маппинг портов, какая разница, что там слушает приложение внутри контейнера?
у которого отличительная черта от остальных мессенджеров — это то, что серверную программы вы контролируете сами. Вы можете скачать исходные коды серверной программы и установить на свой сервер
Rocket.Chat, Matrix и другие open-source мессенджеры непонимающе смотрят со стороны
Статья оставляет желать лучшего. Местами полно голословных утверждений и неправильных выводов.
Однако тут есть странность: пользователю без root-прав все равно нужен tty для перенаправления вывода процесса (а, следовательно, и Docker-логов) в stdio.
TTY нужен только для взаимодействия с пользователем в интерактивном режиме, он не является обязательной составляющей для запуска приложений-демонов, вроде СУБД.
Без TTY внутри контейнера /proc/self/fd/{0..2} начинают ссылаться не на /dev/pts/0, а на pipe, который докер-демон на хосте сам читает и раскладывает в файлы с логами:
В Alpine Linux писать в stdio могут только члены группы tty.
Владельцем файловых дескрипторов процесса становится пользователь, под которым он запущен. Например, на скриншоте выше я указал пользователя для запуска контейнера с помощью опции -u, и он стал владельцем stdout, как в случае с TTY, так и без него. И он без проблем может в него писать.
Вот только entrypoint различных СУБД, например mysql и postgres, запускаются под пользователем root. Это нужно, чтобы перед запуском непосредственно самого приложения исправить владельца папки с файлами БД и конфигами, а уже затем выполнить запуск СУБД с помощью su или sudo.
И тут действительно можно столкнуться с issue, на которое ссылается автор - без TTY владельцем pipe будет тот пользователь, под которым был запущен корневой процесс в контейнере, т.е. root. И так как это pipe, а не файл, к нему нельзя применить chown или chmod. Поэтому приходится использовать обходной вариант с TTY и добавлением пользователя в группу tty либо выполнением chmod o+g /dev/pts/0
Специальный Bash-скрипт может извлекать эти обычные файлы из запущенного контейнера с помощью команды копирования — docker cp
Ага, по пути еще и изобретать свой logrotate вместо того, чтобы создать issue в репозиторий MariaDB.
Не тянет это на топ "лучших фреймворков", ну вот совсем ни разу. Ни примера самих тестов не привели, ни адекватного сравнения - только примитивные копирайтные описания.
Из приведенного списка известна на самом деле только пара фреймворков, остальные сделаны на коленке парой энтузиастов, без документации и последний раз релизились в 2016 году. Зачем их использовать? Чтобы потом все переписывать на нормальный pytest? Так проще с самого начала на нем писать. Кому потом будут нужны специалисты, которые использовали эти фреймворки?
С получением из базы ограниченного набора полей есть одна проблема - это плохо сказывается на кэшировании результатах в даталоадерах.
Допустим, запрос был такой:
query {
getUser(id: 123) {
name
posts(first: 5) {
content
created_at
comments(first: 10) {
id
content
created_at
author {
name
role
}
}
}
}
}
В getUser и в поле author результат возвращается одного и того же типа User, у которого есть поля name и role.
Автором комментария к статье может являться и сам автор, так что раз мы его уже запросили из БД, и информация о нем закэширована в dataloader (по id пользователя), то повторный запрос по тому же пользователю выполняться не будет.
Но в корне мы запросили только имя пользователя, без роли. И если формировать для этого случая запрос вида SELECT name FROM users, то в кэше у пользователя не будет заполнено поле роли, потому что его не было необходимости получать. А для получения автора комментария нужно выполнить запрос SELECT name, role FROM users, но т.к. пользователь уже лежит в кэше, он из базы повторно запрашиваться не будет.
Конечно, можно предложить сначала обходить всю схему, и для объектов одного и того же типа получать максимальный запрошенный список полей, а потом уже генерировать запросы к базе. Но если это не даёт существенного выигрыша (например, из-за постоянно изменяющихся запросов СУБД приходится генерировать новые планы выполнения, а не брать готовые из кэша), то зачем?
В любом случае, надо смотреть на конкретную ситуацию и решать, стоит ли овчинка выделки. А то это может вылиться в преждевременную оптимизацию.
Только если это конфиг сервера, вроде nginx. В конфиге клиента пароль не может быть хэшированным по определению - либо в открытом виде, либо зашифрованный.
Ок, допустим наличие файлового кэша в оперативе требует от ОС дополнительных действий по сбросу его части, чтобы выделить нужный объем для нового процесса. Да, процессы не сразу выделяют нужный для своей работы объем, а могут делать это динамически. Но где замеры того, о каких значениях вообще идёт речь? Может быть это считанные микросекунды, а приложение запускается секунд 5 - тогда пляски с увеличением объема гарантированно пустой оперативы вообще не стоят свеч.
Пример - СУБД Oracle. У нее есть два куча разных параметров для выделения оперативы, но рассмотрим два - нижняя граница (MEMORY_TARGET) показывает, сколько будет выделено оперативы сразу при старте, и верхняя (MEMORY_MAX_TARGET) показывает, до какого уровня ее возможно выделить. Постепенно после запуска СУБД пытается выделить себе память до верхней границы, если столько есть в системе, либо если её не хватает из-за запуска других приложений она может ее освободить, вернувшись к нижней границе. Эти значения СУБД использует для расчета размера всяких буферов и кэшей, без которых скорость выполнения запросов будет совсем печальной.
Допустим, у нас была виртуалка на 8ГБ, для Oracle в конфиге указаны значения в 4 и 6Гб соответственно. База растет (допустим, вместо 10Гб стало 100), все чаще приходится лезть за данными на диск, потому что всей оперативы на кэширование часто используемых данных не хватает.
Апгрейдим виртуалку, теперь там 32Гб оперативы. Но параметры оставляем те же. С одной стороны, у базы остались те же самые параметры для выделения оперативы, а значит и значения для размеров внутренних буферов и кэшей, с другой - у нас стало очень много оперативы, которую больше никто не занимает. Но скорость выполнения запросов возрастает в разы, за что спасибо файловому кэшу ОС - самые часто используемые блоки данных уже находятся в оперативе, что позволяет существенно увеличить производительность.
Теперь увеличиваем значения параметров до пропорциональных размеру оперативы - естественно база станет стартовать дольше из-за выделения кучи оперативы за раз, но после старта и прогрева кэша запросы выполняются все то же время, что и до изменения параметров.
Да, там все же будет разница на определенных запросах - некоторые промежуточные или итоговые результаты не влезали в старые буферы, и поэтому либо падали, либо выполнялись вечно (например, дамп базы не снимался), а теперь все станет значительно лучше. Но существенного влияния на производительность запросов в среднем здесь скорее всего не будет. По крайней мере, так было у меня, проводил такую процедуру не один десяток раз, и результат всегда был схожим. А вот с меньшим файловым кэшем базе стало бы ну совсем плохо.
Плюс сервисы перезапускаются не каждую секунду, и большую часть времени они работают с уже выделенным объемом оперативы. Даже если это какой-то процесс активно выполняет операции, которые требуют постоянного выделения и освобождения памяти, он обычно не особо спешит эту память возвращать ОС - он ее потом может и не получить, а она ему может очень скоро пригодиться.
Поэтому я крайне скептически отношусь к идее как-то ограничивать или сбрасывать файловый кэш - а с чего вообще вы решили, что будет положительный эффект хоть где-то? Есть какие-нибудь записи о реальных эффектах, которые этот способ принес? Звучит крайне сомнительно.
Главное не лезть в совсем уж старые или низкоуровневые модули, вроде socket. Их чтение уже не обучает хорошим подходам по написанию кода, местами все становится в точности наоборот.
Зато возможно это хорошая иллюстрация того, почему нужно выделять время на рефакторинг и удаление deprecated кода.
Стили на выходе рендера должны определяться настройками самого рендера, так что тут нужно смотреть на конкретную реализацию. Возможно, это легко настраивается, а может и придется костылить на уровне переопределение CSS стилей через !important. Но в вашей задаче точно не нужно пытаться вынести его в текст.
я как-то писал документацию в reST и там не то чтобы все было очевидно
Возможно он немного непривычен, да. Но ведь не обязательно использовать именно его. Тот же Markdown тоже можно использовать, для него готовых парсеров и рендеров еще больше.
Например, для Python есть библиотека markdown, которая к тому же поддерживает расширение синтаксиса через написание собственных плагинов. Даже вот встроенный плагин metadata есть, сразу с примером указания автора документа и прочих атрибутов. Правда она возвращает не AST, а сразу HTML.
парсится одной регуляркой
О нет, только не парсеры на основе регулярок. Вас ждет тысяча и одна пара граблей на этом пути, оно того не стоит.
Я скорее о том, что можно на вход передавать сразу Markdown или reST файл, чтобы не приходилось придумывать полностью новый стандарт. Из выданного парсером AST легко вытащить текст и творить с ним что угодно, а после перевода и замены автоматом получите текст ровно с тем же оформлением. Ну и да, для их рендера тоже полно готовых инструментов.
Больше. Неявных. Способов. Выстрелить. В. Ногу.
Лично я не против самого инструмента - если он реально помогает на этапе разработки, то супер.
Вот только в контейнере он не даст никаких преимуществ, потому что внутри docker образа нет никакого кэша пакетов. Во-первых, одно приложение - один образ, значит нет никакого переиспользования. Во-вторых, кэши раздувают размер образа, поэтому в докере они обычно выключены. Поэтому его применение здесь выглядит как натягивание совы на глобус.
А все попытки притащить инструмент костыльными путями (через volume, через монтирование папки node_modules с хоста, и т.п.) приводят к тому, что возникают проблемы с изоляцией зависимостей и воспроизводимостью сборки. На проде это критично, поэтому крайне не рекомендую так делать.
Максимум где такое можно использовать - локальная разработка в докере, но не более. А для ускорения продовой сборки есть другие варианты, один с buildkit я уже описал выше.
Вот только на этапе docker build volume не подключаются, они есть только в runtime
Для этого есть buildkit и опция RUN --mount=type=cache в Dockerfile. А с внешними симлинками в докере легко напортачить, могут начать вести на несуществующие пути, если ошибиться с монтированием.
Это антипаттерн. Контейнеры - это про изоляцию приложения вместе с его набором зависимостей и окружением от остального мира. Шарить код между контейнерами через volume значит идти против основной идеи докера.
А что не так? Он удобен для воспроизведения prod среды на девелоперских машинках. Нет зависимости от ОС, не надо страдать с установкой СУБД на хост, и т.п.
8060 это низкий порт? К тому жеч докер позволяет настроить маппинг портов, какая разница, что там слушает приложение внутри контейнера?
Rocket.Chat, Matrix и другие open-source мессенджеры непонимающе смотрят со стороны
Пункт про изменения в новой версии можно было опустить - статья 2017 года, Airflow 1.8 безнадежно устарел, буквально пару дней назад вышел 2.2.
Статья оставляет желать лучшего. Местами полно голословных утверждений и неправильных выводов.
TTY нужен только для взаимодействия с пользователем в интерактивном режиме, он не является обязательной составляющей для запуска приложений-демонов, вроде СУБД.
Без TTY внутри контейнера /proc/self/fd/{0..2} начинают ссылаться не на /dev/pts/0, а на pipe, который докер-демон на хосте сам читает и раскладывает в файлы с логами:
Владельцем файловых дескрипторов процесса становится пользователь, под которым он запущен. Например, на скриншоте выше я указал пользователя для запуска контейнера с помощью опции -u, и он стал владельцем stdout, как в случае с TTY, так и без него. И он без проблем может в него писать.
Вот только entrypoint различных СУБД, например mysql и postgres, запускаются под пользователем root. Это нужно, чтобы перед запуском непосредственно самого приложения исправить владельца папки с файлами БД и конфигами, а уже затем выполнить запуск СУБД с помощью su или sudo.
И тут действительно можно столкнуться с issue, на которое ссылается автор - без TTY владельцем pipe будет тот пользователь, под которым был запущен корневой процесс в контейнере, т.е. root. И так как это pipe, а не файл, к нему нельзя применить chown или chmod. Поэтому приходится использовать обходной вариант с TTY и добавлением пользователя в группу tty либо выполнением
chmod o+g /dev/pts/0
Ага, по пути еще и изобретать свой logrotate вместо того, чтобы создать issue в репозиторий MariaDB.
Не тянет это на топ "лучших фреймворков", ну вот совсем ни разу. Ни примера самих тестов не привели, ни адекватного сравнения - только примитивные копирайтные описания.
Из приведенного списка известна на самом деле только пара фреймворков, остальные сделаны на коленке парой энтузиастов, без документации и последний раз релизились в 2016 году. Зачем их использовать? Чтобы потом все переписывать на нормальный pytest? Так проще с самого начала на нем писать. Кому потом будут нужны специалисты, которые использовали эти фреймворки?
Была бы возможность, поставил бы статье минус.
Внутри bridge сети к контейнерам и так можно обращаться по их имени. А в случае кубера и с хоста тоже.
С чего бы это было хорошо? За нарушение циркадных ритмов организм вам спасибо не скажет.
На этот счёт кстати есть отличное видео:
С получением из базы ограниченного набора полей есть одна проблема - это плохо сказывается на кэшировании результатах в даталоадерах.
Допустим, запрос был такой:
В getUser и в поле author результат возвращается одного и того же типа User, у которого есть поля name и role.
Автором комментария к статье может являться и сам автор, так что раз мы его уже запросили из БД, и информация о нем закэширована в dataloader (по id пользователя), то повторный запрос по тому же пользователю выполняться не будет.
Но в корне мы запросили только имя пользователя, без роли. И если формировать для этого случая запрос вида SELECT name FROM users, то в кэше у пользователя не будет заполнено поле роли, потому что его не было необходимости получать. А для получения автора комментария нужно выполнить запрос SELECT name, role FROM users, но т.к. пользователь уже лежит в кэше, он из базы повторно запрашиваться не будет.
Конечно, можно предложить сначала обходить всю схему, и для объектов одного и того же типа получать максимальный запрошенный список полей, а потом уже генерировать запросы к базе. Но если это не даёт существенного выигрыша (например, из-за постоянно изменяющихся запросов СУБД приходится генерировать новые планы выполнения, а не брать готовые из кэша), то зачем?
В любом случае, надо смотреть на конкретную ситуацию и решать, стоит ли овчинка выделки. А то это может вылиться в преждевременную оптимизацию.
Только если это конфиг сервера, вроде nginx. В конфиге клиента пароль не может быть хэшированным по определению - либо в открытом виде, либо зашифрованный.
"Где пруфы, Билли?"
Ок, допустим наличие файлового кэша в оперативе требует от ОС дополнительных действий по сбросу его части, чтобы выделить нужный объем для нового процесса. Да, процессы не сразу выделяют нужный для своей работы объем, а могут делать это динамически. Но где замеры того, о каких значениях вообще идёт речь? Может быть это считанные микросекунды, а приложение запускается секунд 5 - тогда пляски с увеличением объема гарантированно пустой оперативы вообще не стоят свеч.
Пример - СУБД Oracle. У нее есть два куча разных параметров для выделения оперативы, но рассмотрим два - нижняя граница (MEMORY_TARGET) показывает, сколько будет выделено оперативы сразу при старте, и верхняя (MEMORY_MAX_TARGET) показывает, до какого уровня ее возможно выделить. Постепенно после запуска СУБД пытается выделить себе память до верхней границы, если столько есть в системе, либо если её не хватает из-за запуска других приложений она может ее освободить, вернувшись к нижней границе. Эти значения СУБД использует для расчета размера всяких буферов и кэшей, без которых скорость выполнения запросов будет совсем печальной.
Допустим, у нас была виртуалка на 8ГБ, для Oracle в конфиге указаны значения в 4 и 6Гб соответственно. База растет (допустим, вместо 10Гб стало 100), все чаще приходится лезть за данными на диск, потому что всей оперативы на кэширование часто используемых данных не хватает.
Апгрейдим виртуалку, теперь там 32Гб оперативы. Но параметры оставляем те же. С одной стороны, у базы остались те же самые параметры для выделения оперативы, а значит и значения для размеров внутренних буферов и кэшей, с другой - у нас стало очень много оперативы, которую больше никто не занимает. Но скорость выполнения запросов возрастает в разы, за что спасибо файловому кэшу ОС - самые часто используемые блоки данных уже находятся в оперативе, что позволяет существенно увеличить производительность.
Теперь увеличиваем значения параметров до пропорциональных размеру оперативы - естественно база станет стартовать дольше из-за выделения кучи оперативы за раз, но после старта и прогрева кэша запросы выполняются все то же время, что и до изменения параметров.
Да, там все же будет разница на определенных запросах - некоторые промежуточные или итоговые результаты не влезали в старые буферы, и поэтому либо падали, либо выполнялись вечно (например, дамп базы не снимался), а теперь все станет значительно лучше. Но существенного влияния на производительность запросов в среднем здесь скорее всего не будет. По крайней мере, так было у меня, проводил такую процедуру не один десяток раз, и результат всегда был схожим. А вот с меньшим файловым кэшем базе стало бы ну совсем плохо.
Плюс сервисы перезапускаются не каждую секунду, и большую часть времени они работают с уже выделенным объемом оперативы. Даже если это какой-то процесс активно выполняет операции, которые требуют постоянного выделения и освобождения памяти, он обычно не особо спешит эту память возвращать ОС - он ее потом может и не получить, а она ему может очень скоро пригодиться.
Поэтому я крайне скептически отношусь к идее как-то ограничивать или сбрасывать файловый кэш - а с чего вообще вы решили, что будет положительный эффект хоть где-то? Есть какие-нибудь записи о реальных эффектах, которые этот способ принес? Звучит крайне сомнительно.
Главное не лезть в совсем уж старые или низкоуровневые модули, вроде socket. Их чтение уже не обучает хорошим подходам по написанию кода, местами все становится в точности наоборот.
Зато возможно это хорошая иллюстрация того, почему нужно выделять время на рефакторинг и удаление deprecated кода.
Устоявшийся перевод термина actor - актор, а не актёр. Прям глаза режет.
Стили на выходе рендера должны определяться настройками самого рендера, так что тут нужно смотреть на конкретную реализацию. Возможно, это легко настраивается, а может и придется костылить на уровне переопределение CSS стилей через
!important
. Но в вашей задаче точно не нужно пытаться вынести его в текст.Возможно он немного непривычен, да. Но ведь не обязательно использовать именно его. Тот же Markdown тоже можно использовать, для него готовых парсеров и рендеров еще больше.
Например, для Python есть библиотека markdown, которая к тому же поддерживает расширение синтаксиса через написание собственных плагинов. Даже вот встроенный плагин metadata есть, сразу с примером указания автора документа и прочих атрибутов. Правда она возвращает не AST, а сразу HTML.
О нет, только не парсеры на основе регулярок. Вас ждет тысяча и одна пара граблей на этом пути, оно того не стоит.
Я скорее о том, что можно на вход передавать сразу Markdown или reST файл, чтобы не приходилось придумывать полностью новый стандарт. Из выданного парсером AST легко вытащить текст и творить с ним что угодно, а после перевода и замены автоматом получите текст ровно с тем же оформлением. Ну и да, для их рендера тоже полно готовых инструментов.