И снова здравствуйте! Почти пять лет уже не писал здесь новых статей, хотя, если честно, всегда знал, что рано или поздно начну это делать снова. Не знаю как вам, а мне все таки это дело всегда казалось довольно увлекательным.


Начинать написание нового материала после столь продолжительного отдыха от этого дела — труднее всего. Но раз цель поставлена — надо идти до конца. Начну немного издалека.


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


Под хабракатом вы найдете Quick Start по использованию Docker на уровне, необходимом для решения конкретных задач, обозначенных ниже, без углубления в "дебри" виртуализации и прочих сопутствующих тем. Если вы до сих пор хотите начать успешно использовать эту современную технологию, тем самым значительно упростив целый ряд процессов: от разработки веб-продуктов и до разворачивания и переноса оных под какое-либо современное оборудование — прошу под кат!


Opening Illustration - Docker


Преамбула


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


С самого начала я заинтерисовался Docker'ом с целью быстрого создания небольшого, но довольно универсального кластера под собственные проекты (рабочие, учебные, etc). Так как системным администрированием я профессионально заниматься не собирался — я решил, что должен обучиться основам кластеризации ровно до того момента, когда я смог бы без особых затруднений разворачивать любой популярный программный стек для веб-проекта. Далее я рассмотрю разворачивание на Docker следующих конфигураций:


  • LAMP;
  • LEMP;
  • MEAN.

Первые две в представлении, думаю, не нуждаются. Третяя же состоит из MongoDBExpress.jsNode.js. MEAN я чаще всего использовал для написания RESTful API, например, для дальнейшего разрабатывания на его основе мобильного приложения.


После этого я сам себе немного усложнил задачу, добавив следующие требования:


  1. Возможность без затруднений использовать различные домены (или, зачастую, поддомены) для каждого отдельного контейнера (по принципу виртуальных хостов).
  2. Использование HTTPS-протокола по-умолчанию. Более того, хотелось бы организовать бесплатное генерирование SSL-сертификатов, не уступающих при этом платным аналогам.
  3. Разворачивание на одном и том же сервере GitLab CE — в качестве основной CVS-системы для работы над проектами не только в одиночку, но и в команде.

Основные определения:


  • Docker — программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы.


  • Letsencrypt — Бесплатный автоматический центр авторизации (CA). Предоставляет бесплатные сертификаты для включения поддержки HTTPS (SSL / TLS) на любом веб-сайте.


  • GitLab Community Edition — Open Source аналог GitHub. Обеспечивает управление Git-репозиториями, анализ кода, отслеживание ошибок, работу с каналами активности, создание Wiki и т.д.

Установка и настройка


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


Сразу уточню, что в этой статье я рассматриваю настройку Docker и всех сопутствующих программ на дистрибютиве CentOS 7, так как на этой ОС я уже давно привык работать, как на основной серверной системе. В целом на любом другом Linux-дистрибютиве действия будут примерно аналогичные, с той лишь разницей, что, например, для Ubuntu вы будете использовать apt-get вместо yum / dnf (для CentOS / Fedora).


Docker + Docker Compose:


Подготовка:


$ sudo yum update
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF


Установка Docker Engine:


$ sudo yum install docker-engine
$ sudo systemctl enable docker.service
$ sudo systemctl start docker


Создание группы пользователей 'docker' и добавление туда текущего пользователя (это необходимо для того, чтобы работать с Docker без использования 'sudo' или root-доступа):


$ sudo groupadd docker
$ sudo usermod -aG docker your_username


Проверка успешности установки:


$ docker run --rm hello-world


Установка Docker Compose (утилита для объединения нескольких контейнеров в одно веб-приложение):


$ sudo curl -L "https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version


Certbot (официальный сайт):


Утилита для автоматического получения/обновления SSL-сертификатов от Letsencrypt:


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


$ sudo yum install certbot


Основы работы с Docker Engine


Docker Engine


Базовые принципы:


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


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

From Wikipedia

Основные преимущества использования Docker:


  • Изолированность отдельных кластеров друг от друга;
  • Один и тот же Docker-контейнер может работать без изменений на множестве различных машин (с разными конфигурациями);
  • Docker оптимизирован для развертывания приложений (application-centric);
  • Автоматизация сборки приложений;
  • Повторное использование одних и тех же компонентов;
  • Open Source реестр готовых контейнеров (Docker Hub);
  • Единый API для автоматизации пользовательской настройки контейнера и его разворачивания.

Далее расмотрим основные команды, которые нам понадобятся для создания кластера:


$ docker run


По сути основная команда, выполняющая запуск нового контейнера.


Основные параметры:


  1. --name: UUID идентификатор: уникальное имя контейнера;
  2. --volume (-v): том, связанный с контейнером: задается в форме абсолютного пути к директории;
  3. --env (-e): переменная окружения: позволяет дополнительного настраивать запускаемый контейнер;
  4. --publish (-p): настройка определенных портов, необходимых для работы контейнера (например, 80 для http, 443 для https).

$ docker ps


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


$ docker stop container-name


Команда, останавливающая работу контейнера.


$ docker rm container-name


Удаление определенного контейнера.


Внимание: прежде, чем удалить контейнер, его необходимо остановить (docker stop)!


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


Конкретные примеры использования docker run вы увидите в этой статье немного далее.


Настройка виртуальных хостов


Nginx Reverse Proxy


Проблема: определенная сложности реализации кластера с использованием виртуальных хостов в различных контейнерах заключается в том, что один порт может "прослушиваться" только одним контейнером (настраивается через --publish). Получается, что по-умолчанию мы можем создать только один контейнер, который будет отвечать на запросы к серверу через порт 80 и/или 443 (http и https протоколы, соответственно).


Решение: в принципе, довольно очевидно использовать для решения этой проблемы Reverse Proxy, инкапсулированный в один контейнер, который и будет "прослушивать" порты 80 и 443. Функционал данного контейнера будет заключаться в автоматическом перенаправлении запросов, в соответствии с используемыми виртуальными хостами.


Такой контейнер существует в открытом доступе в Docker Hub — nginx-proxy.


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


Прежде, чем запустить данный Reverse Proxy контейнер, давайте получим SSL-сертификаты для доменов, которые мы хотим использовать в качестве виртуальных хостов.


Получение бесплатного SSL-сертификата


Для получения SSL-сертификата будем использовать бесплатный сервис letsencrypt. Для этого на предыдущих этапах мы уже установили утилиту certbot. Я не буду останавливаться на подробностях использования этой утилиты (это все есть в официальной документации).


Приведу лишь готовую команду для автоматического получения бесплатного SSL-сертификата для вашего домена:


$ sudo certbot certonly -n -d yourdomain.com --email your@email.com --standalone --noninteractive --agree-tos


--standalone --noninteractive --agree-tos — данные параметры необходимы для того, чтобы certbot с одной стороны отработал в фоновом режиме, а с другой — сгенерировал сертификат без конкретной привязки к определенному веб-серверу.


В результате успешного выполнения данной команды будут сгенерированы два файла:


/etc/letsencrypt/live/yourdomain.com/fullchain.pem


/etc/letsencrypt/live/yourdomain.com/privkey.pem


Для корректной работы nginx-proxy нам необходимо поместить все файлы сертификатов в одну директорию, при этом используя для каждого доменного имени по два файла в формате: yourdomain.com.crt (файл сертификата) и yourdomain.com.key (приватный ключ).


В данном случае логично воспользоваться символьными ссылками. Пример:


$ mkdir ssl-certs


$ cd ssl-certs


$ ln -s /etc/letsencrypt/live/yourdomain.com/fullchain.pem ./yourdomain.com.crt


$ ln -s /etc/letsencrypt/live/yourdomain.com/privkey.pem ./yourdomain.com.key


На расширение .pem не стоит обращать особого внимания — суть файлов от этого не меняется.


Аналогичным образом мы можем получить сертификаты для любых, принадлежащих нам, доменных имен и далее использовать их в качестве виртуальных хостов. Единственное требование заключается в том, что A-записи этих доменных имен должны быть направленны на внешний IP-адрес сервера, на котором вы и выполняете certbot certonly ...


Сгенерировав сертификаты для каждого домена, мы готовы к запуску nginx-proxy контейнера.


$ docker run -d -p 80:80 -p 443:443     ?-v /full/path/to/ssl-keys:/etc/nginx/certs     ?-v /var/run/docker.sock:/tmp/docker.sock:ro     ?jwilder/nginx-proxy

Рассмотрим эту команду более подробно:


  1. -p 80:80 -p 443:443 — привязываем к контейнеру порты 80 и 443. При чем 80-ый порт сервера отвечает 80-ому порту внутри контейнера и аналогично с портом 443. В формате PORT:PORT2 выполняется создание соответствий между реальным портом всей машины и портами внутри отдельного виртуального контейнера.
  2. -v /full/path/to/ssl-keys:/etc/nginx/certs — первый volume, необходимый для настройки данного контейнера. Здесь мы выполняем связь стандартной директории /etc/nginx/certs внутри самого контейнера с директорией, в которую мы вручную поместили символьные ссылки на файлы сертификатов и приватных ключей для наших доменов (на предыдущем этапе).
  3. jwilder/nginx-proxy — идентификатор контейнера внутри Docker Hub. Docker Engine автоматически скачает изображение данного контейнера, если оно еще не было загруженно ранее.

Вот и все — первый контейнер запущен! И этим контейнером является Reverse Proxy, через который мы сможем далее задать любому контейнеру-приложению VIRTUAL_HOST.


Примеры работы с различными стеками


LAMP


Итак, наконец-то мы можем перейти к запуску контейнеров, в которых мы уже сможем разрабатывать наши веб-приложения.


В базе Docker Hub довольно много разных вариантов LAMP-контейнеров. Лично я использовал этот: tutum-docker-lamp.


Ранее, помимо Docker Engine, мы установили утилиту Docker Compose. И вот только с этого момента мы начинаем ее использовать. Docker Compose удобен для создания приложений, в которых несколько контейнеров объединены и именно совместно представляют собой разрабатываемое приложение.


Для того, чтобы запустить этот контейнер в связке с нашим nginx-proxy необходимо:


  1. Загрузить в отдельную директорию исходники tutum-docker-lamp (удобнее всего это сделать с помощью git clone);


  2. Создать в этой рабочей директории файл docker-compose.yml с примерно таким содержанием:

web:
    ?build: .
    volumes:
        - ./www:/var/www/html
    environment:
        - MYSQL_PASS=yourmysqlpassword
        - VIRTUAL_HOST=yourdomain.com   

  1. Выполнить запуск с помощью docker-compose:


    $ docker-compose up



Как видите в данном примере, управление виртуальными хостами при использовании nginx-proxy выполняется с помощью всего одной переменной окружения VIRTUAL_HOST.


Внимание на связку ./www:/var/www/html. Очевидно, что рабочей директорией вашего сайта становится папка www (ее необходимо создать вручную). Все файлы в этой директории автоматически попадают и в /var/www/html внутри запущеного контейнера.


Разобраться более детально с синтаксисом файла настроек docker-compose.yml вы можете в официальной документации.


LEMP


Запуск LEMP-контейнера принципиально ничем не отличается от примера выше.


Сначала находим контейнер в Docker Hub. Например: docker-lemp.


Скачиваем исходники контейнера и добавляем docker-compose.yml. Внутри этого файла настроек уже нашего кастомного контейнера вы можете не только задавать переменную окружения VIRTUAL_HOST, но и настраивать всё, что позволяет файл Dockerfile. Например в Dockerfile определено:


VOLUME /var/www/


Следовательно вы можете в docker-compose.yml выполнить связку с этим томом примерно так:


volumes:
? - ./www:/var/www


NodeJS + ExpressJS + MongoDB


Пример такой конфигурации: docker-nodejs-mongodb-example.


Файл docker-compose.yml выглядит следующим образом:


web:  
  ?  build: .  
  ?  volumes:
  ?      - "./api:/src/app"
  ?  environment:
  ?      - VIRTUAL_HOST=yourdomain.com
  ?  links:
  ?      - "db:mongo"
db:
    ?image: mongo
    ?ports:
    ?     - "27017:27017"
    ?volumes:
        ? - ./data/db:/data/db

В данном случае будет создано два связанных контейнера. Один — для базы (mongoDB), второй собственно для NodeJS приложения.


Для запуска этой связки контейнеров используется все та же команда docker-compose up.


Тонкости в работе с gitlab/gitlab-ce


GitLab CE on Docker Engine


Некоторые, более сложные контейнеры, требуют дополнительной настройки для запуска с использованием nginx-proxy. К таким контейнерам относится и gitlab-ce.


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


Итак:


$ docker run --detach     --hostname gitlab.yourdomain.com     --publish 2289:22     --restart always     --name custom-gitlab     --env GITLAB_OMNIBUS_CONFIG="nginx['listen_port'] = 80; nginx['listen_https'] = false; nginx['proxy_set_headers'] = {  \"X-Forwarded-Proto\" => \"https\", \"X-Forwarded-Ssl\" => \"on\" }; gitlab_rails['gitlab_shell_ssh_port'] = 2289; external_url 'https://gitlab.yourdomain.com'; gitlab_rails['smtp_enable'] = true; gitlab_rails['smtp_address'] = 'smtp.mailgun.org'; gitlab_rails['smtp_port'] = 2525; gitlab_rails['smtp_authentication'] = 'plain'; gitlab_rails['smtp_enable_starttls_auto'] = true; gitlab_rails['smtp_user_name'] = 'postmaster@mg.yourdomain.com'; gitlab_rails['smtp_password'] = 'password'; gitlab_rails['smtp_domain'] = 'mg.yourdomain.com';"     --env VIRTUAL_HOST="gitlab.yourdomain.com"     --volume /srv/gitlab/config:/etc/gitlab     --volume /srv/gitlab/logs:/var/log/gitlab     --volume /srv/gitlab/data:/var/opt/gitlab     gitlab/gitlab-ce:latest

Запуск через NGINX Reverse Proxy + HTTPS


Для того, чтобы схема с Reverse Proxy работала в данном случае, необходимо добавить:


nginx['listen_port'] = 80;
nginx['listen_https'] = false;
nginx['proxy_set_headers'] = {  \"X-Forwarded-Proto\" => \"https\", \"X-Forwarded-Ssl\" => \"on\" };

Причина заключается в том, что nginx-proxy при работе с контейнерами обращается внутри них к порту 80, а не 443. Без дополнительных заголовков в настройке nginx внутри контейнера gitlab-ce (proxy_set_headers) запрос проходить не будет (ошибка 502 "Bad Gateway").


Кроме этого важно добавить:


external_url 'https://gitlab.yourdomain.com';


Порт 22


Суть в данных строках:


--publish 2289:22


Если работа с рабочей машиной производится через SSH-протокол, то мы не можем создавать связку напрямую "22:22", так как порт 22 уже занят сервисом sshd.


Решение этой проблемы описано в официальной документации gitlab-ce. Все просто: мы привязываем любой другой (кроме 22) порт внутри сервера к 22 порту внутри контейнера. В данном примере используется порт 2289.


Параллельно с этим важно не забыть добавить


gitlab_rails['gitlab_shell_ssh_port'] = 2289;


В настройки самого GitLab.


Таким образом после запуска gitlab-ce и создания в нем самом какого-либо репозитория работа с ним будет производится по адресу в стиле:


ssh://git@gitlab.yourdomain.com:2289/username/repository_name.git


Настройка SMTP-сервера


Здесь тоже необходимо использовать специальные переменные окружения самого GitLab.


В моем случае (я использую Google Cloud Engine) по-умолчанию закрыты порты 25, 465 (т.е. стандартные порты SMTP-протокола). Одним из вариантов решения этой проблемы является использование стороннего сервиса (как например MailGun) в качестве SMTP-сервера. Для этого используем настройки:


gitlab_rails['smtp_enable'] = true;
gitlab_rails['smtp_address'] = 'smtp.mailgun.org';
gitlab_rails['smtp_port'] = 2525;
gitlab_rails['smtp_authentication'] = 'plain';
gitlab_rails['smtp_enable_starttls_auto'] = true;
gitlab_rails['smtp_user_name'] = 'postmaster@mg.yourdomain.com';
gitlab_rails['smtp_password'] = 'password';
gitlab_rails['smtp_domain'] = 'mg.yourdomain.com';

Ну и наконец не забываем о --env VIRTUAL_HOST="gitlab.yourdomain.com" \ — переменной окружения для самого nginx-proxy.


Вот и все. После выполнения этой инструкции Docker запустит полностью функционирующий контейнер с GitLab CE.


Стандартный процесс обновления gitlab-ce


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


Процесс обновления GitLab с помощью Docker упрощается до нескольких команд:


  1. docker stop custom-gitlab — останавливаем работающий контейнер;


  2. docker rm custom-gitlab — удаляем контейнер GitLab CE.


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


  3. docker pull gitlab/gitlab-ce — собственно обновление изображения контейнера;


  4. выполняем длинную команду (пример выше), с помощью которой мы изначально запускали контейнер.

Вот и все. Выполнив эти 4 команды, GitLab автоматически обновится до последний версии и запустится через Docker Engine.


Итоги


Итак, в результате выполнения этого гайда должен получится Docker-кластер, в основе которого лежит NGINX Reverse Proxy; каждое веб-приложение имеет свой виртуальный хост, который при этом поддерживает защищенный HTTPS-протокол.


Вместе с веб-приложениями функционирует GitLab-кластер, полностью настроенный, вплоть до доступа к SMTP-серверу.


Я очень надеюсь, что это моё небольшое исследование окажется полезным или, хотя бы, интересным, для многих читателей ХабраХабра. Конечно же, буду рад выслушать критику профессионалов, дополнения или усовершенствования к статье!


Спасибо за внимание!

Поделиться с друзьями
-->

Комментарии (26)


  1. RouR
    15.12.2016 13:11
    +1

    Я так понял что всё запускалось на одном сервере. Как насчёт сценария с тремя серверами — на одном nginx-proxy, на двух других — контейнер с веб-сервисом. Как это сконфигурировать? Как сделать так, чтобы nginx видел что один контейнер с веб-сервисом умер, и на него не надо перенаправлять веб-запросы?


    1. kafeman
      15.12.2016 14:03
      +2

      Думаю, что вам нужно посмотреть в сторону Docker Swarm или Kubernetes.

      Для мониторинга бекендов в Nginx вроде был health check. Но я думаю, что в облаке он вам не понадобится.


      1. neumeika
        15.12.2016 14:06

        имхо, Kubernetes поудобнее, если не хочется отдельную сущность ковырять в виде консула


        1. kafeman
          15.12.2016 14:14
          +2

          Во-первых, он медленнее. Во-вторых, мне лично не нравится, что у него свой API и свои абстракции. В итоге, когда вы работаете с Kubernetes, вам нужно знать и о нем, и о докере. В случае с Docker Swarm вы вообще можете не заметить разницы, потому что он полностью эмулирует Docker Remote API.


          1. neumeika
            15.12.2016 14:50

            Т.е. меньше документации читать? «Соррян», я об этом не подумал.
            Прошу прощения за оффтоп. А ежели рассматривать в разрезе API, сие удобство рассматривается в каком ключе? интеграция с CI и CD?


            1. kafeman
              15.12.2016 15:10

              В плане API. Вы можете использовать любое приложение, которое было изначально написано для локального докера, с Docker Swarm. Например, есть у вас какой-нибудь красивый GUI, который выводит табличкой список контейнеров. После того, как вы перейдете на Docker Swarm, вы можете продолжить пользоваться своим любимым софтом так, что последний может даже не знать ни о каких «облаках». В случае с примером выше, программа будет показывать вам список всех запущенных контейнеров облака, как будто они все запущены локально. Для Kubernetes вам бы пришлось искать альтернативу, или патчить имеющийся софт (если есть такая возможность).

              image


              1. neumeika
                15.12.2016 15:25
                +1

                просто у Kubernetes всё в одном (веб, сервис дисковери, HA)
                а у Docker Swarm всё надо руками собирать и выбирать компоненты. Хотя с HA я может и не прав и он мультимастер научился.
                Я вас понял, в плане однообразности всё-таки лучше Swarm. Пойду почитаю, что там за год изменилось.


                1. kafeman
                  15.12.2016 15:31

                  Рад, что мы друг друга поняли. Возможно, Kubernetes и может в чем-то выиграть на гигантском количестве нод (при том, что Docker Swarm достаточно масштабируется). Но изначально вопрос был о трех серверах, один из которых load-balancer. И тут нельзя забывать о том, что Docker Swarm можно… банально запустить как контейнер в докере! ;-)


                1. renskiy
                  15.12.2016 18:13

                  Таки изменилось, коллеги. Swarm чуть менее года как является частью самого Docker. Так что руками ничего поднимать более не надо.

                  kafeman, и к сожалению «какой-нибудь красивый GUI», предназначенный для контейнеров, не будет без доработки работать с новым Swarm, увы.


                  1. kafeman
                    15.12.2016 18:24

                    Конечно, никакого «красивого GUI» у меня нет, но я не вижу причин, почему абстрактный сторонний клиент не сможет работать в swarm mode. Документация по API говорит, что просто добавились новые ресурсы для работы с сервисами, нодами и т.д. Но приложению, выводящему список контейнеров, о них знать и не нужно.


                    1. renskiy
                      15.12.2016 18:36

                      Я к тому, что через такие клиенты (которые не знают о новом Swarm) вы увидите только часть контейнеров сервиса, то есть только те, которые работают на конкретной ноде.


  1. BurlakovSG
    15.12.2016 16:21

    Я правильно понимаю то, что NGINX Reverse Proxy позволяет имея один белый IP адрес, который привязан к домену domain.ru, перенаправлять трафик на разные контейнеры в зависимости от вызова субдомена вроде forum.domain.ru в один контейнер, а faq.domain.ru в другой?


    1. Kyborg2011
      15.12.2016 16:29

      Да, если я правильно вас понял, то вы правильно поняли =)


      1. BurlakovSG
        15.12.2016 16:36

        А почему у двух других контейнеров одинаковый хост прописан: VIRTUAL_HOST=yourdomain.com?
        Как NGINX Reverse Proxy понимает в какой контейнер переправлять трафик?


        1. Kyborg2011
          15.12.2016 16:38

          Это только примеры ) Ясное дело, что, если вы запустите оба контейнера из этой статьи (например, с LAMP и с LEMP стеком), то в одном придется прописать один VIRTUAL_HOST, в другом — другой.


          1. BurlakovSG
            15.12.2016 16:47

            Т.е. это настраивается только в контейнерах с LAMP или с LEMP или другим вариантом, но не в контейнере NGINX Reverse Proxy, т.е. NGINX Reverse Proxy вообще трогать не надо?


            1. Kyborg2011
              15.12.2016 16:51

              Именно так. Он просто запускается и все. Главное, чтобы в нем был правильно задан volume (вот этот: -v /full/path/to/ssl-keys:/etc/nginx/certs).

              Далее он автоматически подхватывает все контейнеры, запущенные после него с определенными VIRTUAL_HOST)


              1. BurlakovSG
                15.12.2016 17:00

                Теперь всё понятно. А сертификаты достаточ получить только для основного домена domain.ru или надо для каждого forum.domain.ru и faq.domain.ru?


                1. Kyborg2011
                  15.12.2016 17:05

                  Желательно для каждого. Потому что nginx-proxy будет искать файлы .crt и .key в соответствии с заданным virtual_host.

                  Хотя в теории, можно сгенерировать 1 сертификат сразу под несколько доменов (например, для домена и его поддоменов) — а далее, если файл forum.domain.ru.crt, например, будет отсуствовать, то nginx-proxy вероятнее всего выберет единственный существующий (например, domain.ru.crt). И если окажется, что этот один сертификат подписан сразу на несколько доменов — в том числе на необходимый forum.domain.ru, то ошибки не должно быть…

                  Но все таки, лучше для каждого виртуального хоста генерировать по сертификату )) Тогда просто все будет четко и не будет сомнений в поведении реверс прокси контейнера ) Это стабильный на 100% вариант.


                  1. BurlakovSG
                    15.12.2016 17:11
                    +1

                    Спасибо большое за разъяснения, буду практиковаться на Debian.


        1. Kyborg2011
          15.12.2016 16:39

          Два контейнера с одинаковым VIRTUAL_HOST не имеют абсолютно никакого смысла ))

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

          В общем получилась бы ошибочная ситуация заведомо.


    1. tsabir
      20.12.2016 14:11
      +1

      И кстати, виртуальные хосты на nginx и прочих веб-серверах совсем не обязательно выделять в рамках 1 домена.


      Если средствами DNS привязать yourdomain.com -> 1.2.3.4 и mydomain.com -> 1.2.3.4, то nginx спокойно разрулит запросы на разные домены к разным бэкендам.


      Все будет зависеть от заголовка 'Host', который будет слать ваш браузер на адрес 1.2.3.4


      1. Kyborg2011
        20.12.2016 14:22

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


  1. nonlux
    15.12.2016 20:23
    +1

    1. Зачем такой бАаальшой docker run для gitlab мы же решили использовать docker-compose )
    2. Образ gitlab/gitlab-ce:latest конечно официальный, но по мне удобнее sameersbn/docker-gitlab.
    Вообще у товарища sameersbn на github много интересных образов.

    3.

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

    Это не совсем правда!
    Лучше это объяснить так:
    опция docker run --volume «связывает» (линкует) папку хоста и образа. При использовании этой опции можно хранить данные контейнера хранятся на хосте и поэтому не исчезнут при удалении обновлении и вообще смене образ
    4 Опять про volume:
    во всех настройках данные расшарины абы как. Где-то пути относительные "./api:/src/app", где-то относительные. Когда контейнеров много можно и заплутать, если надо что-то исправить.

    Предлагаю небольшой хак чтобы не все было прозрачно.

    хранить все данные в одном формате:

    /srv/docker/someImage/…

    А еще лучше в домашней папке пользователя

    ~/docker/someImage/…

    5. Все docker-compose в git
    6. Все установки на сервере загонять в ansible (или любой другой инструмент для оркестрации) и тоже все в гит
    7. Как решен вопрос с запуском всего этого после перезагрузки сервера?
    8. На самом деле не понятно какая цель работы? gitlab + LAMP (MEAN)? приватные репозитории + хостинг проекта?
    Тогда бы надо осветить wworkflow код -> gitlab -> ci -> LAMP


  1. MustDie95
    20.12.2016 14:23
    +1

    К сожалению, Docker под CentOS 6/7 по умолчанию использует device mapper как storage driver и это ужас-ужас — сборка больших контейнеров, работа с образами и реестром (registry) отнимает кучу времени и нервов. После перехода на OverlayFS всё начинает прямо-таки летать. При этом желательно использовать более свежее ядро например от ELRepo Project, т.к. в 3.10 от RH у overlayfs всё ещё есть некоторые ограничения.


    1. Kyborg2011
      20.12.2016 14:26

      Благодарю. Не знал раньше ничего о OverlayFS. Так что даете мне одно из направлений для развития в этом )
      Думаю, со временем дойдут руки и до этого…

      В любом случае я давно привык работать с Centos7 (олсо, с RHEL-подобными дистрами, не думаю, что в ближайшее время буду изменять это в своих проектах), так что стоящее замечание.