Docker

Containerization is the new virtualization
The Docker Book

Что такое Docker?

В отличии от классических систем виртуализации, которые эмулируют работу компьютерного железа и ядра операционной системы поверх него, Docker использует виртуализацию на уровне ядра: все виртуализируемые им процессы делят ядро операционной системы хоста, что позволяет значительно сократить как требуемые ресурсы, так и время, необходимое на запуск/обслуживание таких систем. В идеале, каждый процесс изолируется в собственном контейнере (linux container, lxc), который содержит набор необходимых ему библиотек, что позволяет забыть о dependecy hell, а также легко переносить стек проекта между серверами. В статье ниже я проиллюстрирую, как можно использовать Docker для настройки среды разработчика, повторяющей среду продакшена: предположим, что там используется Ubuntu LTS, PHP 5.4, Nginx.

Установка Docker

Почитать об установке Docker на разные ОС можно на официальном сайте проекта: https://docs.docker.com/installation/#installation

Настройка контейнера

Прежде всего, мы должны написать инструкцию, по которой Docker должен сформировать образ (image), на основе которого будет работать наше приложение — Dockerfile.

src: build/backend/Dockerfile


# Используем за основу контейнера Ubuntu 14.04 LTS
FROM ubuntu:14.04
# Переключаем Ubuntu в неинтерактивный режим — чтобы избежать лишних запросов
ENV DEBIAN_FRONTEND noninteractive 
# Устанавливаем локаль
RUN locale-gen ru_RU.UTF-8 && dpkg-reconfigure locales 

# Добавляем необходимые репозитарии и устанавливаем пакеты
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y ppa:ondrej/php5-5.6
RUN add-apt-repository -y ppa:nginx/stable
RUN sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4F4EA0AAE5267A6C
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y wget curl php5-fpm php5-mysql php5-gd php5-curl php-pear php-apc php5-mcrypt php5-imagick php5-memcache supervisor nginx

# Добавляем описание виртуального хоста
ADD astgo.ru /etc/nginx/sites-enabled/astgo.ru 
# Отключаем режим демона для Nginx (т.к. запускать будем сами) 
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf 
# Отключаем режим демона для php-fpm
RUN sed -i -e "s/;daemonize\s*=\s*yes/daemonize = no/g" /etc/php5/fpm/php-fpm.conf 
# Добавляем конфиг supervisor (описание процессов, которые мы хотим видеть запущенными на этом контейнере)
ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf 

# Объявляем, какие директории мы будем подключать
VOLUME ["/var/www"] 
# Объявляем, какой порт этот контейнер будет транслировать
EXPOSE 80 
# Запускаем supervisor
CMD ["/usr/bin/supervisord"] 

src: build/backend/supervisord.conf


[supervisord]
nodaemon=true
loglevel=debug

[program:nginx]
command=/usr/sbin/nginx
autorestart=true

[program:php5-fpm]
command=/usr/sbin/php5-fpm
autorestart=true

  • FROM — указывает название образа (image), который будет взят за основу.
  • ENV — устанавливает переменную среды
  • RUN — запустить команду в контейнере (все команды исполняются с полными правами в пределах контейнера)
  • ADD — добавить файл в контейнер
  • VOLUME — указать монтируемые директории (их можно монтировать на хост машину или на другие контейнеры)
  • EXPOSE — указать транслируемые порты (их можно транслировать на хост машину или на другие контейнеры)
  • CMD — запустить процесс (это и будет процесс, вокруг которого построен контейнер)

С полным списком инструкций, допустимых в Dockerfile, можно обратиться к руководству.

Сборка образа

По написанной нами инструкции необходимо собрать образ. Назовем его astgo.ru/dev


$ sudo docker build -t astgo.ru/dev ~/PATH_TO_DOCKERFILE_DIR

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


$ sudo docker images | grep 'astgo.ru/dev'
astgo.ru/dev          latest              d2444af3ee61        3 minutes ago       387.2 MB

Запуск контейнера

Теперь создадим контейнер, запустив образ. Мы будем запускать образ astgo.ru/dev, свяжем 80 порт хоста с 80 портом контейнера, а также директорию /var/www хоста с /var/www контейнера. Последнее позволяет нам хранить код проекта на самой хост машине, не теряя его каждый раз, когда мы, по каким-то причинам, пересоздаем контейнер.


$ sudo docker run -v /var/www:/var/www -p 80:80 -t astgo.ru/dev

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


$ sudo docker ps | grep 'astgo.ru/dev'
d8429cc192c0    astgo.ru/dev:latest    "/usr/bin/supervisor 20 seconds ago  
Up 19 seconds  0.0.0.0:80->80/tcp  reverent_fermi 

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

Подключение к запущенному контейнеру

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


$ sudo docker exec -i -t reverent_fermi bash
root@d8429cc192c0:/# 

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


comments powered by Disqus