• Слоеный интерфейс

    Разработчики, пожалуйста, перестаньте делать интерфейс с тулбарами. Это ужасно. Тулбары остались в нулевых. Не стоит тащить их в современный веб.

    Идея тулбара в следующем: каждый раз, когда нужно меню или набор кнопок, дизайнер фигачит очередной слой в шапке. Выглядит так:

    layer

    Когда я вижу подобное решение, хочется отбить дизайнеру пальцы газовым ключом. Очевидно, что мы потеряли треть экрана на слои. Посмотрите, сколько дырок между кнопками. Не все же сидят за 27-дюймовыми Деллами!

    Отдельный слой для виджета календаря – это вообще жесть.

    Если тупо схлопнуть слои, их останется максимум два. Далее, если мы растягиваем браузер по ширине, то все слои тоже растягиваются, но место справа остается пустым. Поэтому должен быть один слой, а кнопки будут перетекать, пытаясь занять все доступное пространство.

    А самый терминальный случай, за который положен расстрел, это когда слой залипает наверху при перемотке. Вырезается Ад-блоком.

  • Двоемыслие

    Столкнулся с каноничным двоемыслием, прям в точности по Оруэллу.

    Человек на страницах блога утверждает, что США – враг. В личной переписке выясняется, что он работает удаленно на фирму, расположенную – сюрприз! – именно в США.

    При этом фирма – не стартап с модными футболками, а системы управления на производствах. Обслуживают заводы, порты, станции, сети.

    Я теряю ориентиры – как надо самого себя обманывать, как выворачивать мозги, чтобы одновременно стыковать в голове оба факта. Работодатель – враг. Ты на него работаешь. Не клинит?

    Понятно, что все дело в деньгах. Долларовая зарплата удаленщика в США – это 2-3 зарплаты московского специалиста. Для жителя провинции, мягко говоря, очень неплохо.

    Забавный момент: деньги могут не только затуманить мозг, как это часто бывает с ментами или чиновниками, но и протрезвить. Получая такую зарплату, человек напрочь забыл о том, что США – враг. Или, по крайней мере, больше так не пишет.

    Конечно, лучше изначально принять тот факт, что врагов в политике, как и в личной жизни, не бывает. Не дожидаясь удаленки в США.

  • Кложа. Причины успеха

    Я вижу три причины, по которым Кложа стала успешной технологией.

    Новые идеи

    Рич Хики, автор Кложи, предложил радикально новые идеи. Полная неизменяемость структур данных. Специальные типы и операторы для изменяемых ячеек (ссылки, атомы). Транзакционная память. Многозадачность и асинхронность из коробки (core.async ставится отдельно, но пилят ее те же люди).

    Офигительные коллекции и принципы работы с ними. Дополнительные абстракции за счет типов и протоколов. Наконец, расширение всего и вся, что в других языках возможно только обезьяним патчингом.

    Платформа

    Если бы Рич принадлежал академической среде, он бы начал писать реализацию на Си. Возможно, через 20 лет, отрастив бороду до колен, он бы решил проблемы со сборщиком мусора, ГИЛом, общим доступом к ресурсам и так далее.

    К счастью, как человек практичный и с опытом в промышленности, Рич изначально проектировал Кложу гостевой системой. Такая система старается выстроить собственные абстракции поверх платформы, с которой ей повезло работать. Совместимость с JVM разом подарила миллион библиотек и миллионы строк кода, проверенного временем.

    Лисп

    Наконец, S-выражения как способ описать язык. Некоторые думают, что Кложа – это еще один Лисп. Неверно! Каждый месяц на Гитхабе появляется очередной интерпретатор Лиспа на том или ином языке. Но не находит поддержки, потому что решает техническую задачу – как перегнать синтаксис одного языка в другой.

    Кложа – это не Лисп. Это новый язык с инновационными идеями, полный абстракций. Рич мог бы взять за основу синтаксис Джавы или Руби, и получилось бы тоже ОК, что-то вроде Котлина. Но Рич взял Лисп и тем самым добавил в Кложу метапрограммирование, принцип код-как-данные, REPL, декларативный стиль кода, макросы и много чего еще.

    Заключение

    Читали Ерофеева? В человеке есть физическая сторона, духовная сторона и, что самое главное, мистическая, тайная сторона. Вот и Кложа так. Физическая – это JVM, духовная – иммутабельность, коллекции, многозадачность, мистическая – Лисп.

  • Реклама

    У меня очень простое отношение к рекламе: на сайте ее быть не должно.

    Я установил в Хроме Адблок и Гостери, два полезных расширения, которые вырезают до 90% рекламы. Оба периодические подтягивают с серверов информацию о новых рекламных сервисах.

    Если вылазит плашка с просьбой отключить адблок, вырезаю плашку тоже. Аналогично с разными попапами, предложеним подписаться, зафоловить и т.д.

    Если реклама пролазит не смотря на все ухищрения, с сайтом приходится расстаться. Что поделать, не судьба.

    Я искренне не понимаю, почему создатели сайтов кормят посетителей говном, а посетители соглашаются это есть. Например, сайт Эсквайра. Сто лет там не был. Зашел, листаю статью, вдруг вылазит видео. Сперва подумал, что это видос в тему, оказалось такси. Смотал два экрана, а там видео часов.

    Или Нью-Йорк Обсервер, мобильная версия. На каждый экран плашка с половину экрана с какой-то чернухой. Знакомства, дейтинги.

    Ребят, вы не охуели?

    Чтобы зарабатывать деньги с сайта, достаточно ввести платную подписку за контент. Это честно, потому что работает в обе стороны. Потребитель получает именно то, что нужно. Он платит. Деньги поощряют создателей сайта производить более качественный контент, расширять влияние, развивать бизнес.

    Примеры. Сайт со смешными картинками. Самые смешные помещаются в особый раздел, доступный по подписке. Сайт со статьями – аналогично. Вот тебе тизер, понравилось – плати. Можно сформировать закрытое сообщество, как в Снобе, чтобы подписчик чувствовал себя элитой.

    В крупных городах можно устраивать офлайн-мероприятия для платных подписчиков. Подписка есть? Проходи бесплатно в клуб или на конференцию.

    Новостной сайт. На морде подписчику видно больше анонсов. И так далее.

    Мне несколько раз предлагали добавить рекламу на страницу личного проекта за деньги. Зачем? У меня платная подписка. Почему потребитель должен видеть какое-то говно? Он же целенаправленно зашел на мой сайт. Разве правильно показывать левую инфу по результатам вчерашнего гугления?

    Давайте смотреть правде в глаза. Большинство сайтов в сети рекламные уже по своему содержимому. Откройте Хабр. Половина статей на главной – блоги компаний. Цель публикации в коммерческом блоге – лишний раз напомнить о себе и прорекламировать услуги, иногда даже открыто.

    Или Медуза. На морде обязательно висит несколько “партнерских материалов”. А что это другими словами? Реклама, Карл.

    По этой же причине я поддерживаю Лебедева и Варламова, у которых железное правило. Если пост рекламный, об этом должно быть сказано явно: реклама, пост оплачен.

    Так что размещать контекстную рекламу на сайте, где уже рекламные посты, я считаю переходом за грань.

    Мне нравится подход Журнала Тинькова. Там пишут интересные статьи про деньги, экономику, быт. Нет баннеров и рекламы, но в каждой статье врезка с информацией, почему эту услугу выгодно заказать именно у Тинькова. Это честно. Я, хоть и не клиент Тинькова, с большим удовольствием читаю эти статьи, врезка не вызывает отторжения.

    Правила, добавленные в Адблок, я периодически копирую и комичу в приватный репозиторий на Битбакете. Если Адблок слетит, можно быстро восстановить.

  • Правила работы с почтой

    Я очень люблю элекронную почту и стараюсь пользоваться только ей. За несколько лет я выработал и подсмотрел у других набор полезных правил. Вот они ниже.

    Нулевой инбокс. Письмо остается в списке входящих только если на него требуется реакция. Например, написать ответ, проверить баг, зайти на сайт. В остальных случаях после прочтения письмо отправляется либо в архив, либо в особую папку. Пустой инбокс – нереально круто.

    Фильтры и правила. У меня масса правил, чтобы раскладывать почту по нужным папкам. Это позволяет не отвлекаться на рассылки или уведомления, которые не требуют мгновенной реакции. Мне достаточно окинуть взглядом папки, чтобы понять, что меня ожидает. Например, папки yandex (2) и facebook (1) говорят о том, что пришли уведомления, которые можно посмотреть потом.

    Я уж не говорю о том, что в среднем при платеже приходит три письма – от сервиса, с которого вы платили, от сервиса, куда вы платили и реклама. Это говно должно раскладываться автоматом.

    Единая точка сбора. У меня личный ящик, потом почта текущего проекта, личного проекта и два ящика от заказа на стороне. Получается либо пачка аккаунтов в почтовом клиенте, либо вагон вкладок. Проблема решается переадресацией всей почты в один личный ящик. Конечно, добавляем правила, чтобы почта раскладывалась по нужным папкам.

    – “А вот уеду я в отпуск, – говорит коллега, – и не хочу видеть письма с работы”. Не вопрос! Скрой эту папку в настройках интерфейса, по возвращению опять верни.

    Можно добавить параметры авторизации для сторонних ящиков. Тогда если оригинальное письмо пришло на ваш рабочий ящик, то при ответе будет использована учетная запись рабочего ящика. Вы читаете и отвечаете из личного ящика, а собеседник никак об этом не узнает.

    Только Гмейл. Я долго пользовался почтовым клиентом Мака, но все же вернулся к Гуглу и браузеру. Маковый клиент, как любое настольное приложение, временами виснет, падает или грузит систему внезапной индексацией. Кроме того, папки в Маке – это не те папки в Гугле.

    На десктопе плохо сделан поиск. В Гугле он просто охренеть какой классный и работает мгновенно.

    Только плоский текст. Никаких шрифтов, болдов, италиков. Только плейн-текст.

    Никаких подписей. Свое имя в конце письма я вписываю руками. Жирный абзац с должностью, телефонами и ссылками на соцсети – признак неадеквата. Огрызки типа “С ув, Алексей” – тоже.

    Выношу переписку из соцсетей в почту. Если до пользователя можно достучатсья только личным сообщением в каком-то сервисе, обязательно добавляю почту с просьбой отвечать на нее. Если пишут мне в соцсети, добавляю в ответ емейл и прошу, чтобы в следующй раз писали туда.

    Банальности. Стараюсь писать без ошибок, проверять имена, не ставить пробелы перед знаками препинания.

    Не больше одного восклицательного знака на письмо.

    Подумать. Если письмо требует сложного ответа – надо встать, пройтись, попить водички.

  • JSON в 1С на Гитхабе

    Наконец-то дошли руки выложить полезную функцию 1С на Гитхаб. Речь о сериализации любого объекта в JSON. Ранее в блоге я публиковал ссылки на Pastebin, но теперь с этим покончено.

    Ссылка на репозиторий.

    Напомню, функция переводит в джейсон сущности 1С, отталкиваясь от их природы. Например, таблица значений станет списком словарей, дата будет переведена в ISO-формат и т.д.

    Код не требует сторонних модулей и работает с версиями 8.1 и выше. Кажется, в 8.3 грозились добавить аналог в коробку, но я за этим не слежу.

    Пользуйтесь на здоровье.

  • Спорт

    Нет ничего отвратительней большого спорта.

    Все эти олимпиады, циклопические стадионы, взятки и откаты на самых высоких уровнях. Допинги, антидопинговые офицеры. Мерзость.

    Большой спорт не имеет никакого отношения к здоровью. Спортсмены калечат себя нечеловеческими нагрузками и гормонами. На пенисию уходят развалинами. Вкручивают в позвоночнник штифты, чтобы продержаться еще один сезон.

    Коммерческий спорт ничем не отличается от боев в Колизее, когда обученные рабы кромсали друг друга на радость люмпенам. Спортсменов, как и рабов, с детства учат одному линейному делу, пичкая препаратами.

    Спорт высасывает колоссальные деньги из стран в пользу спортивной мафии. Всякие ФИФА и МОК – обычный лохотрон, только разводят не отдельных лиц, а целые страны.

    Нормальный человек понимает, что проводить соревнования каждый раз в новом месте неэффективно. Это же строить с нуля стадионы, проводить инфраструктуру, а потом все стоит никому не нужное. В Бразилии нищета, работы нет, в реку говно сливают, а они стадионы строят.

    Все состязания должны быть в одном месте. Летние – а какой-нибудь Греции, зимние – в странах северной Европы.

    Почему за соревнования платит государство? Все должно быть за счет спортсменов. Хочешь выступить – плати взнос, покупай билеты, проживание. Нет денег – ищи спонсоров, заключай контракты, поддерживай Единую Россию, в конце концов. Разве бывает, чтобы государство готовило нобелевских лауреатов?

    Главной минус большого спорта в том, что он бессмысленный. Ну то есть смысла нет вообще. От того, что ты нечеловеческим усилием пробежал дистанцию на 0.01 секунды быстрее, ничего не изменится. Вообще ничего. В мире не станет больше знаний или меньше болезней. Не откроется новых возможностей молодым специалистам.

    Болелщики – это диагноз. Каким же конченым надо быть, чтобы кататься с флагом, высунувшись из машины. О преданности болельщиков смешно даже говорить. Завтра другой спортсмен пробежит на 0.02 секунды быстрей, а прежнего забудут.

    Большой спорт – безумие. Он оттдает низостью, коррупцией и маргиналами. Брр.

  • Без названия

    bot

  • Восьмая встреча

    Провели восьмую встречу!

    Я рассказал про монады. Читали Булгакова? “Оно, может, умно, да непонятно. Над вами потешаться будут.” Потешались надо мной где-то час:

    Слайды

    Денис Ковалев рассказал про криптографию. Очень хороший доклад получился:

    Слайды

    Напомню, сообщество тусит в группе Фейсбука.

    Скоро анонс девятой встречи. Хотите выступить? Пишите в группу.

  • Докер

    Последний месяц меня дико прет с Докера. Это настоящий прорыв в индустрии. Я подключаю Докер ко всем репозиториям. Решил поделиться впечатлениями, описать плюсы и рассмотреть реальный пример.

    Про Докер написано очень много. Я не собираюсь досканально описывать как он работает. Расскажу лишь кратко о том, что вы, возможно, не слышали.

    Докер – утилита для запуска процесса в изолированном окружении. Технически это работает поверх одной из фич ядра Линукса – Cgroups.

    Преимущество Докера в том, что стирается грань между отдельными машинами. Если вы собрали образ на Линуксе, то он заведется на Маке. При этом понадобится только Докер. Никаких либ или пакетов выкачивать не нужно.

    Этот плюс я уже испытал на практике. Мне пришел из ремонта Мак. За время работы на Линуксе я успел перевести большую часть репозиториев на Докер. На Маке все завелось без проблем.

    Докер идеален, когда нужно передать правильно настроенное приложение заказчику. Вы делаете образ, заказчик запускает контейнер. Достаточно лишь, чтобы у вас и у заказчика были близкие версии Докера.

    Разработка с Докером напоминает идею виртуальной машины с байткодом. Как Джава – однажды скомпилированное работает везде, был бы только рантайм. Преимущество в том, что теперь речь идет не только о коде, а об утилитах, библиотеках, словом, окружении в целом. Стало возможным сделать Линукс-среду кросплатформенной!

    Докер содержит систему в чистоте. Работая нативно, мы ставим сотни и тысячи пакетов, которые оседают в системе как ил. Они занимают место на диске, что особо важно для небольших SSD. Пакеты вызывают коллизии – три версии Руби, два Питона, разные Ноды.

    В случае с Докером все файлы ложатся в образ – единый файл. Удалив его, мы достоверно вернем систему в то состояние, в котором она была до билда.

    Начав работать на свежей системе, я поставил только Гит и Емакс. База, Редис, различные Питоны, Кложа с Джавой крутятся в Докере. Система ничего о них не знает.

    Бытует ошибочное мнение, что Докер – средство вируализации. Это не так. Докер не создает виртуальную машину как это делают Виртуал-Бокс и аналоги. Он запускает процесс через Cgroups с ограничениями в ресурсах и файловой системе.

    На Маке и Винде Докер эмулируется через виртуалку. Вы запускаете терминал Докера, а на самом деле проваливаетесь в Виртуал-Бокс, где работает нативный Докер. Но на Маке он тоже скоро будет нативный, уже есть бета-версия.

    По этой причине я смеюсь над Микрософтом, которые добавили ps и grep в 10 Виноуз. Кому это нужно? В сети тысячи версий юникс-утилит, скомпилированных под Винду. Скорей делайте нативный Докер!

    Докер может стать принципиально иным способом распространения приложений. Вместо того, чтобы собирать бинарник, мы будем делать образ. По клику мышкой Докер будет запускать из него образ, как обычное приложение.

    Докер – это отсутствие состояния. Контейнер может удалить все файлы внутри себя, нагадить в конфиги и аварийно завершиться. Но стоит запустить контейнер из образа, и мы вновь в прежнем состоянии: файлы, конфиги на месте. Иммутабельность – это круто.

    Докер отлично подходит для билдов всего и вся. Собрать проект, который требует миллион пакетов и библиотек – милое дело.

    Докер – это еще и пакетный менеджер. В экосистеме докера выделяют образы и контейнеры. Образ – декларативное описание того, каким будет будущий контейнер. Контейнер – результат запуска из образа. Выражаясь языком ООП, образ это класс, а контейнер – экземпляр.

    Существует официальный хаб образов. Оттуда можно скачать образ ЛЮБОЙ версии Питона, Руби, Постгреса и т.д. Помните, какой это геморрой – на систему с Питоном 2.7 ставить 3.4? Или проверить баг на старой версии БД? Теперь c этим покончено.

    Хранить приватные образы в хабе Докера разрешено за деньги. Альтернативой может стать официальный сервис Амазона ECR, где все операции над образами бесплатны.

    Докер можно использовать и в продакшене для запуска приложений. На работе мы подключили Докер к Дженкинсу для билдов и прогона тестов. Позже мы выкатили приложение на Питоне в Амазон. Оно было разбито на 4 образа. Каждый образ представлял собой микросервис и мог быть заменен независимо от других.

    Теперь рассмотрим реальный пример применения Докера.

    Бложик, что вы сейчас читаете, работает на движке Jekyll. Это утилита на Руби, которая собирает из маркдаун-файлов статический сайт на голом HTML. Jekyll нативно поддерживается Гитхабом – стоит сделать комит, и твой сайт сам обновляется.

    Однако, прожде чем комитить, хочется посмотреть вживую, как выглядит пост. Для этого я ставлю движок и запускаю локальный сервер. При этом Jekyll тянет за собой вагон зависимых пакетов и просит dev-библиотеки для компиляции сишных либ. Тут нам и поможет Докер.

    Установка Докера подробно описана на официальном сайте под каждую операционку в отдельности.

    В корне проекта создаем файлик Dockerfile с содержимым:

    FROM ubuntu:16.04
    
    RUN apt-get update
    RUN apt-get install -y jekyll bundler
    
    RUN mkdir /blog
    WORKDIR /blog
    COPY Gemfile* ./
    RUN bundle install
    RUN rm Gemfile*
    
    CMD ["jekyll", "serve"]
    

    Разберемся построчно:

    • Образ унаследован от официального образа Убунты версии 16.04.
    • При создании образа обновить информацию о пакетах.
    • Установить из пакетов jekyll (движок) и bundler (установщик пакетов для Руби).
    • Создать внутри образа папку blog в корне.
    • Перейти в нее.
    • Скопировать из хост-системы в образ файлы Gemfile и Gemfile.lock. Это аналог питонячьего pip.requirements.txt.
    • Поставить пакеты, специфичные для проекта.
    • Удалить Gem-файлы.
    • При запуске контейнера стартануть локальный сервер.

    Собираем образ Make-командой:

    docker-build:
    	docker build -t blog .
    

    Параметр -t <foo:bar> задает имя и тег для образа.

    Посмотрите, что показывает консоль при сборке:

    The following additional packages will be installed:
      ca-certificates cpp cpp-5 dbus file fontconfig-config fonts-dejavu-core
      fonts-lato ifupdown iproute2 isc-dhcp-client isc-dhcp-common
      javascript-common krb5-locales libasn1-8-heimdal libatm1 libauthen-sasl-perl
      libbsd0 libcap-ng0 libdbus-1-3 libdns-export162 libdrm-amdgpu1 libdrm-intel1
      libdrm-nouveau2 libdrm-radeon1 libdrm2 libedit2 libelf1
      libencode-locale-perl libexpat1 libffi6 libfile-basedir-perl
      libfile-desktopentry-perl libfile-listing-perl libfile-mimeinfo-perl
      libfont-afm-perl libfontconfig1 libfontenc1 libfreetype6 libgdbm3
      libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libglib2.0-0 libglib2.0-data
      libgmp10 libgnutls30 libgssapi-krb5-2 libgssapi3-heimdal libhcrypto4-heimdal
      libheimbase1-heimdal libheimntlm0-heimdal libhogweed4 libhtml-form-perl
      libhtml-format-perl libhtml-parser-perl libhtml-tagset-perl
      libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl
      libhttp-message-perl libhttp-negotiate-perl libhx509-5-heimdal libice6
      libicu55 libidn11 libio-html-perl libio-socket-ssl-perl
      libipc-system-simple-perl libisc-export160 libisl15 libjs-coffeescript
      libjs-jquery libk5crypto3 libkeyutils1 libkrb5-26-heimdal libkrb5-3
      libkrb5support0 libldap-2.4-2 libllvm3.8 liblwp-mediatypes-perl
      liblwp-protocol-https-perl libmagic1 libmailtools-perl libmnl0 libmpc3
      libmpfr4 libmysqlclient20 libnet-dbus-perl libnet-http-perl
      libnet-smtp-ssl-perl libnet-ssleay-perl libnettle6 libp11-kit0 libpciaccess0
      libperl5.22 libpng12-0 libpq5 libpython-stdlib libpython2.7-minimal
      libpython2.7-stdlib libroken18-heimdal libruby2.3 libsasl2-2
      libsasl2-modules libsasl2-modules-db libsm6 libsqlite3-0 libssl1.0.0
      libtasn1-6 libtext-iconv-perl libtie-ixhash-perl libtimedate-perl
      libtxc-dxtn-s2tc0 liburi-perl libuv1 libwind0-heimdal libwww-perl
      libwww-robotrules-perl libx11-6 libx11-data libx11-protocol-perl libx11-xcb1
      libxau6 libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0
      libxcb-shape0 libxcb-sync1 libxcb1 libxcomposite1 libxcursor1 libxdamage1
      libxdmcp6 libxext6 libxfixes3 libxft2 libxi6 libxinerama1 libxml-parser-perl
      libxml-twig-perl libxml-xpathengine-perl libxml2 libxmu6 libxmuu1 libxpm4
      libxrandr2 libxrender1 libxshmfence1 libxt6 libxtables11 libxtst6 libxv1
      libxxf86dga1 libxxf86vm1 libyaml-0-2 mime-support mysql-common netbase
      nodejs openssl perl perl-modules-5.22 python python-chardet python-minimal
      python-pkg-resources python-pygments python2.7 python2.7-minimal rake rename
      ruby ruby-afm ruby-ascii85 ruby-blankslate ruby-classifier-reborn
      ruby-coderay ruby-coffee-script ruby-coffee-script-source ruby-colorator
      ruby-did-you-mean ruby-execjs ruby-fast-stemmer ruby-ffi ruby-hashery
      ruby-jekyll-coffeescript ruby-jekyll-feed ruby-jekyll-gist
      ruby-jekyll-paginate ruby-jekyll-sass-converter ruby-jekyll-watch ruby-json
      ruby-kramdown ruby-liquid ruby-listen ruby-mercenary ruby-mime-types
      ruby-minitest ruby-multi-json ruby-mysql ruby-net-telnet ruby-oj
      ruby-parslet ruby-pdf-core ruby-pdf-reader ruby-pg ruby-posix-spawn
      ruby-power-assert ruby-prawn ruby-prawn-table ruby-pygments.rb
      ruby-rb-inotify ruby-rc4 ruby-rdiscount ruby-redcarpet ruby-rouge
      ruby-safe-yaml ruby-sass ruby-sequel ruby-sequel-pg ruby-stringex
      ruby-test-unit ruby-toml ruby-ttfunk ruby-yajl ruby2.3 rubygems-integration
      sgml-base shared-mime-info ucf unzip x11-common x11-utils x11-xserver-utils
      xdg-user-dirs xdg-utils xml-core zip
    Suggested packages:
      cpp-doc gcc-5-locales dbus-user-session | dbus-x11 ppp rdnssd iproute2-doc
      resolvconf avahi-autoipd isc-dhcp-client-ddns apparmor apache2 | lighttpd
      | httpd libdigest-hmac-perl libgssapi-perl gnutls-bin krb5-doc krb5-user
      libdata-dump-perl coffeescript libcrypt-ssleay-perl pciutils
      libsasl2-modules-otp libsasl2-modules-ldap libsasl2-modules-sql
      libsasl2-modules-gssapi-mit | libsasl2-modules-gssapi-heimdal
      libauthen-ntlm-perl libunicode-map8-perl libunicode-string-perl
      xml-twig-tools perl-doc libterm-readline-gnu-perl
      | libterm-readline-perl-perl make python-doc python-tk python-setuptools
      ttf-bitstream-vera python2.7-doc binutils binfmt-support ri ruby-dev
      libjs-mathjax ruby-activesupport doc-base coderay fonts-arphic-gkai00mp
      ruby-pdf-inspector ruby-prawn-doc ttf-dejavu-core bundler sgml-base-doc
      mesa-utils nickle cairo-5c xorg-docs-core gvfs-bin debhelper
    The following NEW packages will be installed:
      ca-certificates cpp cpp-5 dbus file fontconfig-config fonts-dejavu-core
      fonts-lato ifupdown iproute2 isc-dhcp-client isc-dhcp-common
      javascript-common jekyll krb5-locales libasn1-8-heimdal libatm1
      libauthen-sasl-perl libbsd0 libcap-ng0 libdbus-1-3 libdns-export162
      libdrm-amdgpu1 libdrm-intel1 libdrm-nouveau2 libdrm-radeon1 libdrm2 libedit2
      libelf1 libencode-locale-perl libexpat1 libffi6 libfile-basedir-perl
      libfile-desktopentry-perl libfile-listing-perl libfile-mimeinfo-perl
      libfont-afm-perl libfontconfig1 libfontenc1 libfreetype6 libgdbm3
      libgl1-mesa-dri libgl1-mesa-glx libglapi-mesa libglib2.0-0 libglib2.0-data
      libgmp10 libgnutls30 libgssapi-krb5-2 libgssapi3-heimdal libhcrypto4-heimdal
      libheimbase1-heimdal libheimntlm0-heimdal libhogweed4 libhtml-form-perl
      libhtml-format-perl libhtml-parser-perl libhtml-tagset-perl
      libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl
      libhttp-message-perl libhttp-negotiate-perl libhx509-5-heimdal libice6
      libicu55 libidn11 libio-html-perl libio-socket-ssl-perl
      libipc-system-simple-perl libisc-export160 libisl15 libjs-coffeescript
      libjs-jquery libk5crypto3 libkeyutils1 libkrb5-26-heimdal libkrb5-3
      libkrb5support0 libldap-2.4-2 libllvm3.8 liblwp-mediatypes-perl
      liblwp-protocol-https-perl libmagic1 libmailtools-perl libmnl0 libmpc3
      libmpfr4 libmysqlclient20 libnet-dbus-perl libnet-http-perl
      libnet-smtp-ssl-perl libnet-ssleay-perl libnettle6 libp11-kit0 libpciaccess0
      libperl5.22 libpng12-0 libpq5 libpython-stdlib libpython2.7-minimal
      libpython2.7-stdlib libroken18-heimdal libruby2.3 libsasl2-2
      libsasl2-modules libsasl2-modules-db libsm6 libsqlite3-0 libssl1.0.0
      libtasn1-6 libtext-iconv-perl libtie-ixhash-perl libtimedate-perl
      libtxc-dxtn-s2tc0 liburi-perl libuv1 libwind0-heimdal libwww-perl
      libwww-robotrules-perl libx11-6 libx11-data libx11-protocol-perl libx11-xcb1
      libxau6 libxaw7 libxcb-dri2-0 libxcb-dri3-0 libxcb-glx0 libxcb-present0
      libxcb-shape0 libxcb-sync1 libxcb1 libxcomposite1 libxcursor1 libxdamage1
      libxdmcp6 libxext6 libxfixes3 libxft2 libxi6 libxinerama1 libxml-parser-perl
      libxml-twig-perl libxml-xpathengine-perl libxml2 libxmu6 libxmuu1 libxpm4
      libxrandr2 libxrender1 libxshmfence1 libxt6 libxtables11 libxtst6 libxv1
      libxxf86dga1 libxxf86vm1 libyaml-0-2 mime-support mysql-common netbase
      nodejs openssl perl perl-modules-5.22 python python-chardet python-minimal
      python-pkg-resources python-pygments python2.7 python2.7-minimal rake rename
      ruby ruby-afm ruby-ascii85 ruby-blankslate ruby-classifier-reborn
      ruby-coderay ruby-coffee-script ruby-coffee-script-source ruby-colorator
      ruby-did-you-mean ruby-execjs ruby-fast-stemmer ruby-ffi ruby-hashery
      ruby-jekyll-coffeescript ruby-jekyll-feed ruby-jekyll-gist
      ruby-jekyll-paginate ruby-jekyll-sass-converter ruby-jekyll-watch ruby-json
      ruby-kramdown ruby-liquid ruby-listen ruby-mercenary ruby-mime-types
      ruby-minitest ruby-multi-json ruby-mysql ruby-net-telnet ruby-oj
      ruby-parslet ruby-pdf-core ruby-pdf-reader ruby-pg ruby-posix-spawn
      ruby-power-assert ruby-prawn ruby-prawn-table ruby-pygments.rb
      ruby-rb-inotify ruby-rc4 ruby-rdiscount ruby-redcarpet ruby-rouge
      ruby-safe-yaml ruby-sass ruby-sequel ruby-sequel-pg ruby-stringex
      ruby-test-unit ruby-toml ruby-ttfunk ruby-yajl ruby2.3 rubygems-integration
      sgml-base shared-mime-info ucf unzip x11-common x11-utils x11-xserver-utils
      xdg-user-dirs xdg-utils xml-core zip
    

    А ю факин сириес? Миллион пакетов на установку одной тулзы! Представьте теперь, что ставите ее нативно, без Докера. Колоссальное захламление системы. Вы не сможете потом удалить эти пакеты. Не записывать же их на бумажку.

    Это точка невозврата. Без Докера вы не сможете сделать систему такой, какой она была до установки.

    Ок, образ собрался. Запускаем через Make:

    docker-run:
    	docker run -it --rm -p 4000:4000 -v $(CURDIR):/blog blog
    

    Параметры:

    • -it значит прикрепить STDIN хост-системы к контейнеру. Иначе говоря, считывать пайпы или ввод с клавиатуры.
    • --rm – удалить контейнер по завершении процесса.
    • -p 4000:4000 – пробросить 4000 порт хост-системы на аналогичный порт контейнера.
    • -v $(CURDIR):/blog – смонтировать текущую папку хост-системы в папку /blog образа.

    Make-переменная $(CURDIR) означает текущую папку. К сожалению, при пробросе томов нельзя указать относительный путь, а хардкодить в Гите – моветон.

    Если внутри образа я шагну в папку /blog, то увижу содержимое проекта.

    При старте образа автоматом запустится сборка блога и сервер. Мне останется открыть в браузере http://127.0.0.1:4000/ и посмотреть на результат. При изменении маркдаун-файлов – не важно где, в образе или на хосте – блог автоматом себя перестроит.

    Посмотреть исходники для Make и Докера можно в репозитории блога. Возможно, в следующий раз я расскажу об инструменте Docker Compose. С помощью него мы создадим три контейнера – приложение, база и Редис – и заставим идти в одной упряжке как единое целое.

    Используете ли вы Докер, и если да, то как?

Страница 30 из 52