2016-06-27

О Docker Compose

Docker вовсю обрастает собственной инфраструктурой.
Docker Engine, чтобы запускать из образов контейнеры, а из контейнеров делать новые образы.
Docker Machine, чтобы запускать Docker под Mac и Windows, в виртуалке.
Dockerfile, чтобы автоматизировать сборку образов из множества слоёв.
Docker Hub, он же Docker Registry, чтобы хранить все нужные образы в одном месте и всегда иметь к ним доступ.
Docker
Образ — это лишь набор файлов, упакованных, готовых для изолированного запуска, и намерение запустить этот набор файлов ради получения какого-то сервиса. Образ — это абстракция. Собственно запуск, т.е. команда docker run, требует дополнительных данных, чтобы получить конкретную реализацию данной абстрации. Нужно указать порты, как они мапятся на порты хоста. Нужно указать тома (volumes), как они связаны с файловой системой хоста. Можно даже указать конкретную команду, которая будет выполнена в контейнере. И это всё для одного контейнера. А если их несколько?
Хочется всё это тоже автоматизировать. И для этого есть штука Docker Compose.
Рекомендуемый способ установки Compose выглядит странным для Linux. Предлагается скачать исполняемый файл, поместить в /usr/local/bin/ и сделать исполняемым. Ну да, Go позволяет не мучаться с зависимостями. В пакетах Xenial тоже есть docker-compose, правда, версии 1.5.2, хотя актуальная уже 1.7.1. В Docker всё меняется быстро, так что имеет место необходимость всё ставить помимо пакетов вашего дистрибутива.
Docker Compose
Покомпозим. Возьмем классический пример. Допустим, у нас есть какое-то Java веб-приложение, которое мы уже собрали в target/mywebapp.jar. Приложение умеет веб само по себе, но ему нужна база данных, Postgres. Рассуём всё по контейнерам.
С точки зрения приложения важно, чтобы базу данных оно искало на хосте с именем postgres.
А потом делаем Dockerfile примерно такого содержания.
FROM java:openjdk-8-jre
COPY target/mywebapp.jar /opt/mywebapp/mywebapp.jar
EXPOSE 8080
CMD ["/usr/bin/java", "-jar", "/opt/mywebapp/mywebapp.jar"]
Можно уже и собрать этот образ и запустить. Но нам нужен еще Postgres.
Поэтому пишем docker-compose.yml. Файлик в формате YAML. В нём мы опишем наши «сервисы», и из каких образов они должны быть запущены.
В начале файла нужно указать его версию. Docker Compose умудрился родить уже вторую, не вполне совместимую с первой, версию своего конфига.
version: '2'
Начинаем список сервисов.
version: '2'
services:
Сервис первый — наше самое веб-приложение. Так как у нас тут же уже есть Dockerfile, попросим Compose собрать образ из текущего каталога.
services:
  mywebapp:
    build: .
Хотим, чтобы порт 8080 этого приложения был виден как порт 80 на хосте. Порт 80 должен быть свободен для прослушивания.
services:
  mywebapp:
    build: .
    ports:
      - '80:8080'
Ну и указываем, что этот сервис слинкован (по сети) с postgres.
  mywebapp:
    build: .
    ports:
      - '80:8080'
    links:
      - postgres
А postgres — это другой сервис, который запускается из готового образа.
  postgres:
    image: postgres:9.5
Этому образу нужно передать пароль от БД через переменную окружения.
  postgres:
    image: postgres:9.5
    environment:
      POSTGRES_PASSWORD: 'postgres'
А если мы хотим, чтобы данные хранились за пределами контейнера, то нужно еще определить тома.
  postgres:
    image: postgres:9.5
    environment:
      POSTGRES_PASSWORD: 'postgres'
    volumes:
      - ./data:/var/lib/postgresql/data
Теперь можно собрать образ нашего приложения командой docker-compose build. Или же просто выполнить docker-compose up. Важно: Compose не пересобирает образ при каждом вызове up, если у вас что-то поменялось, явно дёргайте build.
Compose запустит два контейнера с говорящими именами вида папкагдележитyml_имясервиса_1.
 % docker ps
CONTAINER ID   IMAGE             COMMAND                 CREATED        STATUS        PORTS                 NAMES
8dc2c02cba05   example_mywebapp  "/usr/bin/java -jar /"  3 minutes ago  Up 2 minutes  0.0.0.0:80->8080/tcp  example_mywebapp_1
a1af628ac4cd   postgres:9.5      "/docker-entrypoint.s"  4 minutes ago  Up 3 minutes  5432/tcp              example_postgres_1
Вообще-то надо бы создать всякую базу да таблицы в Postgres. Можно для этого создать отдельный образ, отпочкованный от официального postgres. А можно подключиться к уже запущенному Postgres. Вот только наружу у этого контейнера порты не торчат. Придётся запустить psql прямо внутри контейнера (последние Docker это позволяют).
% docker exec -it example_postgres_1 psql -U postgres
psql (9.5.3)
Type "help" for help.

postgres=# CREATE DATABASE ...
По умолчанию Docker Compose начинает плеваться в консоль логами всех контейнеров, красиво подсвечивая разными цветами разные сервисы. А при нажатии Ctrl+C грамотно зашатдаунит все сервисы.
Чтобы запустить всё в фоне, нужно добавить ключик -d.
 % docker-compose up -d
Starting example_postgres_1
Starting example_mywebapp_1
Чтобы остановить, теперь нужно сделать docker-compose stop.
HAProxy
Пойдем дальше, добавим лоадбалансер. С помощью HAProxy. Можно взять кусочек Docker Cloud в виде готового балансера.
Добавим ещё один сервис.
  balancer:
    image: dockercloud/haproxy
    links:
      - mywebapp
    environment:
      STATS_AUTH: 'stats:stats'
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    ports:
      - '80:80'
      - '1936:1936'
Он собран из образа HAProxy для Docker Cloud. В линках нужно указать тот сервис, который мы собираемся балансировать. Контейнеру нужно передать сокет Docker демона через тома, чтобы он мог извлечь/подкрутить в Docker что ему нужно. Ну и балансер выдаёт 80 порт для приложения и 1936 порт для статистики, пароль на веб мордочку статистики можно передать через переменную окружения.
Немного поправим сервис нашего приложения. Теперь он не выпячивает порты наружу, но утверждает, что внутри у него запущен сервер на порту 8080.
  mywebapp:
    build: .
    expose:
      - '8080'
    links:
      - postgres
Запускаем как обычно docker-compose up. Должно получиться три контейнера, и запросы до нашего приложения должны ходить через балансер.
Теперь — магия.
 % docker-compose scale mywebapp=2
Creating and starting example_mywebapp_2 ... done 
И вот у нас уже два наших веб-приложения. И конфигурация HAProxy изменилась, и он успешно перестартовал. И веб-приложения уютненько спрятались за балансером и успешно балансируются.
Конечно, в рамках одного хоста подобная балансировка почти лишена смысла. Но ведь у нас есть ещё Docker Swarm, чтобы распихать наши контейнеры по нескольким физическим хостам. Впрочем, это, как и UCP, — тема для отдельного разговора.
Кстати, штуку, подобную Docker Compose, чтобы запускать, балансировать и скейлить контейнеры из Docker образов, давненько уже имеет Amazon EC2 Container Service. Да, контейнеры Docker можно запускать напрямую в EC2.

2016-06-14

О социальном

Мы — в Сети. Каждый день, как минимум утром и вечером (догадайтесь, где), я смотрю, что нового написали в четырёх Слаках — это по работе, что наболтали в Телеграме коллеги и знакомые — это для души, что начирикали в Твиттере — это новости, что выложили ВКонтакте — это локальные новости и общественная жизнь, что напостили в Гуглоплюсе — это другие новости, пожалуй, в том формате, в котором я бы наиболее желал их видеть.
Согласно всем заветам Дорофеи уведомления у меня отключены, ну разве что кроме тех случаев, когда по рабочим делам поминают меня лично. Поэтому обращение к чатикам и социалочкам у меня именно что явный просмотр нового.
Messengers
А ведь я ещё помню времена, когда интернетов не то, чтобы совсем не было, но просто в самих интернетах не было ничего интересного. Понятное дело, все делали свои хомяки. Особо продвинутые использовали для этого специальные Personal Home Page Tools. И, о ужас, припоминаю, что примерно тогда же писали мы приложеньице, как сейчас бы его назвали, веб 2.0, на голом JavaScript с прицелом исключительно на самый популярный браузер MSIE 5.
В интернетах ничего не было, а все котики, гифки, тесты, программки и лягушки в миксере качались с BBS, а потом раздавались знакомым на дискетках. Качались модемом. Представляете, где-нибудь с двенадцати до трёх ночи, потому что телефон спаренный с соседями, с разрывами, без докачки, вытягивались крупицы лулзов. А хорошая по нынешним временам фоточка на одну дискетку не влезала. Поэтому популярностью пользовались многотомные архиваторы типа RAR. Даже дистрибутив Виндоуз передавался иногда на дискетках, десятках дискет.
Потом интернеты таки появились. Тоже через диалап. И едва ли не единственным средством общения стала Аська. Там не было групповых чатиков. Там были пароли не длиннее восьми символов. Зато там был поиск людей со всего мира по имени, месту проживания, полу, возрасту и всему такому. Нормуль, в общем.
Конечно, в те времена существовала еще и Ирка. Групповые чатики. Но что-то у меня с нею не сложилось. И клиентов симпатичных было не очень. И дурость в виде разных портов для разных кодировок бесила. В общем, как-то не по-человечески там всё было.
А потом случился Джаббер, он же XMPP. Потрясающий протокол с потрясающими возможностями. Тут вам и личная переписка. И возможность общаться с любыми джаббер пользователями по всему миру, аналогично электропочте. И шифрование сообщений по GPG, если хочется поиграть в шпионов. И групповые чатики. И боты. Помнится, я даже что-то пописывал на эту тему. А главное, это — полностью открытый протокол.
В джаббере даже существуют свои микроблоги. Ну и долгое время, а, может, и до сих пор, все пользователи Gmail, LiveJournal, Facebook, сами того не зная, имели свой джаббер аккаунт и могли общаться по этому протоколу с любыми другими джаббер пользователями.
А самое классное, в джаббере существуют транспорты. Имея джаббер аккаунт и соответствующие транспорты на сервере, можно было общаться в той же Ирке, Аське и прочих. Это была и остаётся единственная сеть общения, которая поощряет соединение с другими сетями.
Много лет я жил с Джаббер. И его было более чем достаточно. Даже сейчас какой-то клиент у меня запущен на планшете, и изредка я смотрю, что там прилетает.
А потом, под грузом производственной необходимости общаться голосом, пришлось начать пользоваться Скайпом. Всегда считал и считаю, что текстовые чаты в Скайп — говно. Теперь, слава богу, текстовая коммуникация по работе перешла в Слаку. Слака хороша, но, имхо, развивается куда-то не туда. Уж сильно много разных дурацких непонятных менюшек.
Пытался пользоваться Хангаутами, но не вышло. Потому что сильно мало нужных людей там.
А буквально с месяц пользуюсь Телеграмом. Ничего особо нового, по сравнению с джаббером, в нём нет. Но, блин, удобно.
Socials
Социальные сети пытался долго игнорировать. Хотя в МоёмКруге, когда он ещё был независимым проектом, регистрировался. И в ЛинкедИне профиль завёл. Но это скорее воспринималось как публикация резюме.
С Фейсбуком я не подружился. Уж больно нелогичным, тормозным, вырвиглазным и бессмысленным он мне показался. Ожидал чего-то такого же от ВКонтакте, но, на удивление, отечественный «аналог» оказался гораздо понятнее и удобнее.
Твиттер. Это такой Жуйк с человеческим лицом :) До сих пор не понимаю, как он жив. Но как источник новостей годится.
Гуглоплюс. Моя любимая социальная сеть. Простая и удобная. К сожалению, без бесплатных популярных аудиозаписей и с маловатой аудиторией.
Jabber
Меня очень печалит, что всякие гуглы стали уходить от открытого протокола XMPP, что многочисленные чатики на удивление плодятся, но совершенно не думают о взаимодействии. Я хотел бы иметь единственного клиента и единый протокол для текстового общения. К сожалению, XMPP с этой ролью не справился. И не видно, кто бы мог справится.
Аналогично социальные сети. Каждая со своими особенностями и своими API. И каждая не очень любит альтернативных клиентов. Соответственно, и нет клиентов для нескольких сетей сразу. Как-то помогают инструменты кросспостинга вроде Friends+Me или IFTTT. Но в целом ситуация печальна.
Средства социального взаимодействия в Сети почему-то не хотят объединить Человечество, объединившись сами. Они тянут одеяло на себя, окучивая аудиторию и затрудняя взаимодействие. Получается, что социальные сети и мессенджеры становятся ещё одним инструментом социальной стратификации.