Статьи

Начало работы с Docker с точки зрения разработчика: как создать среду, которой вы можете доверять

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

В рамках этого процесса я больше сосредоточился на  непрерывной интеграции  и  методах тестирования . Я думаю, что большая часть хорошего процесса состоит в том, чтобы иметь среду, которую вы можете контролировать, легко настраивать и копировать по своему усмотрению. Вы когда-нибудь обновляли что-то на своей машине для разработки, и все черт побери? Ну, мне это не нравится. Конечно, есть несколько инструментов, которые мы можем использовать:

  • Virtualenv при работе на python, чтобы изолировать библиотеки, к которым вы хотите получить доступ
  • RVM и Gemfiles для работы с разными версиями библиотек Ruby / JRuby + для разных проектов
  • Cabal, который позволяет задавать специфичные для проекта наборы библиотек для проектов на Haskell (и, кстати,  удачи в этом …)
  • Maven, чтобы указать, какую версию компилятора Java вы хотите использовать и какие зависимости

Эти инструменты очень помогают, но их недостаточно. Иногда вам нужен доступ к разделяемым библиотекам, иногда вам нужен определенный инструмент (apache httpd? MySQL? Postgresql?), Установленный и настроенный определенным образом, например:

  • вам может понадобиться настроить apache httpd на определенный порт для определенного доменного имени
  • вам может понадобиться определенный набор пользователей для вашей БД с установленными конкретными разрешениями
  • вам может понадобиться использовать определенный компилятор, может быть, даже определенную версию (C ++ ’11, кто-нибудь?)

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

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

Именно по этим причинам я недавно начал играть с Docker.

Что такое Docker и как его установить

По сути, вы можете представить Docker как своего рода легкую альтернативу VirtualBox или другим подобным гипервизорам. Запустив Linux, вы можете создавать виртуальные машины различного типа, используя ядро ​​«реальной» машины. Однако вы можете полностью изолировать эти виртуальные машины, установить конкретные версии необходимых вам инструментов, определенные библиотеки и т. Д.

Docker изначально работает только в Linux. Чтобы использовать его в Mac OS-X или Windows, вам нужно создать облегченную виртуальную машину под управлением Linux, и Docker будет работать на этой виртуальной машине. Однако весь беспорядок может быть частично скрыт с помощью  boot2docker . Это означает некоторые дополнительные головные боли, но вы можете пережить это, если придется. Если я могу, я предпочитаю ssh на Linux-боксе и запускать там Docker, но иногда это не лучшее решение.

Чтобы установить docker на производную Debian, просто запустите:

# if your system is not recent you could have to use apt-get instead of apt
sudo apt install docker

Наш пример: создание двух взаимодействующих Docker-контейнеров

Давайте начнем с простого примера: предположим, что вы хотите разработать приложение PHP (извините …) и хотите использовать MySQL в качестве базы данных (еще раз извините …).

Мы создадим два docker-контейнера: в первом мы установим PHP, во втором — MySQL. Мы установим связь между двумя контейнерами и получим доступ к приложению из браузера на нашей гостевой машине. Для простоты мы будем запускать PhpMyAdmin вместо разработки какого-либо примера приложения на PHP.

Первый Docker-контейнер: PHP

Давайте начнем с чего-то очень простого: давайте настроим образ Docker для запуска httpd под centos6. Давайте создадим каталог с именем  phpmachine  и создадим файл с именем  Dockerfile .

# Based on an example found at https://github.com/CentOS/CentOS-Dockerfiles
FROM centos:centos6 
MAINTAINER Federico Tomassetti
RUN yum -y update; yum clean all 
RUN yum -y install httpd; yum clean all 
RUN yum -y install php; yum clean all
RUN yum -y install php-mbstring; yum clean all
RUN yum -y install php-mysql; yum clean all
RUN echo "Apache HTTPD" >> /var/www/html/index.html
EXPOSE 80

Обратите внимание, что это очень простой пример: мы  не  указываем определенную версию httpd для установки. При установке какого-либо другого программного обеспечения мы могли бы захотеть это сделать.

Из каталога, содержащего Dockerfile, запустите:

docker build -t phpmachine .

Эта команда создаст контейнер, как описано в инструкциях. Первым делом он загрузит изображение Centos 6, которое будет использоваться в качестве основы этой машины.

Теперь, запустив  образы Docker,  вы должны найти строку, похожую на эту:

~/d/phpmachine ❯❯❯ docker images
REPOSITORY                  TAG                 IMAGE ID            CREATED              VIRTUAL SIZE
phpmachine                  latest              a6f6e10d6834        About a minute ago   236.6 MB

Теперь вы можете запустить этот контейнер и войти в него с помощью этой команды:

docker run -t -i -P phpmachine /bin/bash

После входа в контейнер вы можете запустить Apache и узнать IP-адрес докера, на котором он работает:

~/d/phpmachine ❯❯❯ docker run -t -i -P phpmachine /bin/bash
[root@f9226ce4ca3b /]# /usr/sbin/apachectl start
httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.5 for ServerName
[root@f9226ce4ca3b /]# ifconfig
eth0      Link encap:Ethernet  HWaddr 5A:71:53:91:7C:D2  
          inet addr:172.17.0.5  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::5871:53ff:fe91:7cd2/64 Scope:Link
          UP BROADCAST RUNNING  MTU:1500  Metric:1
          RX packets:7 errors:0 dropped:2 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:558 (558.0 b)  TX bytes:648 (648.0 b)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

[root@f9226ce4ca3b /]# 

Теперь, если вы введете этот IP-адрес в браузере, вы должны увидеть что-то вроде этого:

Скриншот от 2015-03-08 17:13:53

Круто, все работает!

Давайте улучшим процесс так, чтобы 1) мы могли запустить сервер httpd без необходимости использовать консоль док-контейнера 2) нам не нужно выяснять IP-адрес контейнера.

Чтобы решить первую проблему, просто добавьте эту строку в Dockerfile:

CMD exec /usr/sbin/apachectl -D FOREGROUND

Теперь пересоберите контейнер и запустите его так:

docker build -t phpmachine .
docker run -t -p 80:80 -P phpmachine

Таким образом, порт 80 док-контейнера повторно сопоставляется с портом 80 хост-машины. Теперь вы можете открыть браузер и использовать адрес  localhost  или 127.0.0.1.

Замечательно, теперь давайте начнем с сервера MySQL.

Второй Docker-контейнер: MySQL сервер

Мы хотим создать Dockerfile в другом каталоге и добавить в тот же каталог скрипт с именем  config_db.sh .

# Dockerfile
FROM centos:centos6 
MAINTAINER Federico Tomassetti
RUN yum -y update; yum clean all 
RUN yum -y install mysql-server; yum clean all 
EXPOSE 3306

# Run a script to create a DB
ADD ./config_db.sh /config_db.sh
RUN chmod +x /config_db.sh
RUN /etc/init.d/mysqld start && /config_db.sh && /etc/init.d/mysqld stop

# Start Mysql and open a mysql shell just to keep the process alive:
# this is a poor-man trick and you probably want to do something smarter
CMD /etc/init.d/mysqld start && mysql
# config_db.sh
# note that by default we do not need a password to connect to
# mysql as root
mysql -e "CREATE DATABASE mydb"
mysql -e "GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost' IDENTIFIED BY 'myuserpwd'; FLUSH PRIVILEGES;"
mysql -e "GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'%' IDENTIFIED BY 'myuserpwd'; FLUSH PRIVILEGES;"
mysql -e "select user, host FROM mysql.user;"

Примечание: мы никоим образом не сохраняем данные нашей базы данных MySQL, поэтому каждый раз, когда мы перезапускаем контейнер, мы теряем все.

Теперь мы можем построить машину:

docker build -t mysqlmachine .

Тогда мы можем запустить это:

docker run -p 3306:3306 -P -i -t mysqlmachine

И мы можем подключиться с нашего «реального ящика» к серверу mysql, работающему в контейнере Docker:

mysql --host=127.0.0.1 --protocol=TCP -u myuser -pmyuserpwd mydb

Пока все работает как положено? Круто, давай двигаться дальше.

Заставьте два док-контейнера общаться

Давайте присвоим имя контейнеру mysql:

docker run -p 3306:3306 -P --name mysqlcontainer -i -t mysqlmachine

Теперь давайте запустим контейнер PHP, рассказывающий о mysqlcontainer:

docker run -i -t -p 80:80 -P --link mysqlcontainer:dbhost phpmachine /bin/bash

С консоли phpmachine вы сможете пинговать  dbhost  (имя, под которым phpmachine может достигать контейнера mysql). Хороший!

На практике в   файл / etc / hosts phpmachine добавляется строка, связывающая  dbhost  с IP-адресом нашего mysqlmachine .

Установка PHPMyAdmin

Мы используем PHPMyAdmin в качестве заполнителя для некоторого приложения, которое вы можете захотеть разработать. Когда вы разрабатываете приложение, вы хотите отредактировать его на компьютере разработчика и сделать его доступным для контейнера Docker. Итак, загрузите  PhpMyAdmin  версии 4.0.x (более поздние версии требуют mysql 5.5, а centos 6 использует mysql 5.1) и распакуйте его в какой-то каталог, предположим, что он находится в  ~ / Downloads / phpMyAdmin-4.0.10-all-languages . Теперь вы можете запустить Docker-контейнер с php следующим образом:

docker run -v ~/Downloads/phpMyAdmin-4.0.10-all-languages:/var/www/html -i -t -p 80:80 -P --link mysqlcontainer:dbhost phpmachine

Это смонтирует каталог с исходным кодом PhpMyAdmin в  / var / www / html  в * phpmachine *, который является каталогом, который настроен для обслуживания Apache httpd.

На этом этапе вам нужно переименовать  config.sample.inc.php  в  config.inc.php  и изменить эту строку:

# From

$cfg['Servers'][$i]['host'] = 'localhost';

# To

$cfg['Servers'][$i]['host'] = 'dbhost';

Таким образом,  phpmachine  должен использовать базу данных на  mysqlmachine .

Теперь вы должны иметь возможность посетить  localhost  и увидеть форму. Там введите учетные данные для db:  myuser , myuserpwd,  и у вас все будет готово!

Снимок экрана от 2015-03-09 19:59:07

Как Докер связан с Vagrant и Ansible, Chef, Puppet?

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

  • Vagrant — это утилита командной строки для управления виртуальными машинами, но мы говорим о полном моделировании машины, в то время как Docker использует ядро ​​с хоста Docker, что приводит к гораздо более легким «виртуальным машинам» (наши контейнеры Docker)
  • Ansible, Chef и Puppet — это способы управления конфигурацией этих машин (операционные процессы), которые они могут использовать вместе с Docker. Ansible кажется намного легче по сравнению с Chef и Puppet (но чуть менее мощный). Он набирает обороты среди пользователей Docker, и я планирую узнать о нем больше.

Этот пост  дает более подробную информацию об отношениях между этими инструментами.

Выводы

В нашем небольшом примере мы могли бы поиграть с реалистичной имитацией окончательной производственной установки, которая, как мы предполагаем, составлена ​​на двух машинах под управлением CentOS 6. Таким образом, мы выяснили несколько вещей (например, у нас есть пакеты для MySQL 5.1, и это заставляет мы не используем последнюю версию PhpMyAdmin, мы знаем полный список пакетов, которые нам нужно установить, и т. д.). Таким образом, мы можем ожидать, что очень немногие будут удивлены при развертывании в производственной среде. Я твердо верю,  что  меньше сюрпризов — это очень хорошо.

Мы также можем просто развернуть докер-контейнеры, если захотим (я еще никогда не пробовал).