Главная » Хабрахабр » [Из песочницы] Docker для Symfony 4 — от локалки до production

[Из песочницы] Docker для Symfony 4 — от локалки до production

Предистория

Одним прекрасным днём мне понадобилось развернуть среду разработки для своего проекта. Vagrant уже порядком поднадоел и хотелось иметь единую среду разработки для всех участников проекта которая была бы идентичной production серверу. Соответственно наслушавшись информации про хипстерский docker, я решил начать с ним разбираться. Далее я постараюсь максимально подробно описать все шаги начиная от установки докера на локалке вплоть до разворачивания продуктива на KVM.

Исходный стек технологий:

— Docker
— Symfony 4
— nginx
— php-fpm
— postgresql
— elasticsearch
— rabbitmq
— jenkins

Железо:

04
— продакшн сервер на хостинге KVM — ноутбук под ОС Ubuntu 16.

Почему кроме технологического стека я перечислил ещё и стек железа?

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

Проще всего работать с докером именно на linux системах. Первый и наверно самый важный аспект при начале работы с докером — это операционная система вашего ноутбука. Если вы работаете на Windows или Mac то у вас 100 % будут некоторые сложности, но эти сложности не будут являться критическими и при желании «нагуглить» как это исправляется не составит никаких проблем.

Зачем нужен Hosting именно с типом виртуализации KVM? Второй вопрос — это хостинг. Причина в том, что виртуализация VPS разительно отличается от KVM и установить сам docker на VPS у вас попросту не выйдет, так как VPS распределяет ресурсы сервера динамически.

Далее рассказ пойдёт опираясь именно на эти две составляющие.
Подитог: для самого быстрого старта на докере резоннее всего выбирать Ubuntu в качестве локальной операционки и KVM хостинг (либо собственный сервер).

Docker-compose для локалки

Установка

Для начала необходимо установить локально сам докер. Инструкцию по установке можно посмотреть на официальном сайте ссылка на официальную документацию для ubuntu (необходимо установить docker и docker-compose), либо запустив команду в консоли:

curl -sSl https://get.docker.com/ | sh

Эта команда установит и docker и docker-compose. После этого проверить версию докера можно командой:

docker --version

Я все это дело запускаю на докере версии 18.06.0-ce.

Установка закончена!

Осознание

Чтобы с чем-то работать более менее успешно — необходимо иметь представление как оно работает. Если вы ранее работали только с Vagrant или чем-либо похожим, то будет крайне непривычно и непонятно поначалу, но это лишь поначалу.

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

Каждый контейнер можно представить как будто бы это крохотный Vagrant на котором установлен всего 1 инструмент, например nginx или php. Мое видение контейнера «на пальцах» представляется так: каждый контейнер — это крохотный изолированный мирок. Это не значит, что каждый из контейнеров — это отдельная виртуальная машина, совсем нет. Изначально контейнеры изолированы вообще от всего вокруг, но путём не хитрых манипуляций можно настроить все так, чтобы они общались между собой и работали совместно. Но так проще для первоначального понимания, как мне кажется.

В конечном итоге это выглядит примерно так: Vagrant просто откусывает у вашего компьютера часть ресурсов, создает виртуальную машину, устанавливает на нее операционную систему, устанавливает библиотеки, устанавливает все то, что вы прописали в скрипте после vagrant up.

→ Посмотреть схемку

Он не создает виртуальных машин. Docker в свою очередь работает кардинально иначе. При этом Docker не блокирует под себя ресурсы вашей системы, а просто использует их по мере необходимости. Docker создает контейнеры (можете воспринимать пока что их как микро-виртуалки) со своей операционной системой Alpine и 1-3 библиотеками, которые необходимы для работы приложения, например php или nginx. В конечном итоге, если проиллюстрировать, то это выглядеть будет примерно так:

→ Посмотреть схемку

Подавляющая часть образов представляет из себя расширение другого образа, например Ubuntu xenial или Alpine или Debian, на которые сверху накатываются дополнительные драйверы и другие компоненты. Каждый из контейнеров имеет образ из которого он создаётся.

Мой образ расширяет официальный образ php:7. Мой первый образ был для php-fpm. 6. 2-fpm-alpine3. Таким образом можно создать образ, который нужен именно вам. То есть по сути он берет официальный образ и доставляет на него нужные мне компоненты, например, pdo_pgsql, imagick, zip и прочее. Если есть желание можете пользоваться тут.

До начала работы с докером я про Alpine в принципе и не слышал, так как Vagrant у меня всегда работал под Ubuntu xenial. С созданием образов все довольно просто на мой взгляд, если они сделаны на базе xenial например, но доставляют немного геморроя, если они сделаны на базе Alpine. Поэтому поначалу работать с ней крайне не удобно, так как нет например того же apt-get install (к которому так привыкаешь), а есть только apk add и не вполне вменяемый набор пакетов. Alpine представляет из себя пустую Linux операционную систему, в которой по сути вообще нет ничего (крайний минимум). На что же это вообще влияет? Большой плюс Alpine заключается в его весе, например, если Xenial весит (абстрактно) 500мешков, то Alpine (абстрактно) порядка 78мешков. Допустим, у вас 5 разных контейнеров и все на базе xenial суммарный их вес будет более 2,5 гигов, а alpine — порядка 500 мешков всего лишь. А влияет это на скорость сборки и на конечный вес всех образов, которые будут храниться у вас на сервере в конечном итоге. (Полезная ссылка для установки пакетов в Alpine — Пакеты Alpine). Поэтому в идеале надо стремиться к тому, чтобы контейнеры были как можно более худые.

Docker-compose от лица пользователя выглядит просто файл yaml с настройками. На docker hub везде пишут как запускать контейнер используя команду docker run, и при этом почему-то не пишут как его можно запустить через docker-compose, а ведь именно через docker-compose он и будет запускаться большую часть времени, так как мало кому охота вручную запускать все контейнеры, сетки, порты открывать и прочее. Моя сборка для локального окружения выглядит следующим образом: Он включает в себя описание каждого из сервисов, которые необходимо запустить.

version: '3.1' services: php-fpm: image: otezvikentiy/php7.2-fpm:0.0.11 ports: - '9000:9000' volumes: - ../:/app working_dir: /app container_name: 'php-fpm' nginx: image: nginx:1.15.0 container_name: 'nginx' working_dir: /app ports: - '7777:80' volumes: - ../:/app - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf postgres: image: postgres:9.6 ports: - '5432:5432' container_name: 'postgresql' working_dir: /app restart: always environment: POSTGRES_DB: 'db_name' POSTGRES_USER: 'db_user' POSTGRES_PASSWORD: 'db_pass' volumes: - ./data/dump:/app/dump - ./data/postgresql:/var/lib/postgresql/data rabbitmq: image: rabbitmq:3.7.5-management working_dir: /app hostname: rabbit-mq container_name: 'rabbit-mq' ports: - '15672:15672' - '5672:5672' environment: RABBITMQ_DEFAULT_USER: user RABBITMQ_DEFAULT_PASS: password RABBITMQ_DEFAULT_VHOST: my_vhost elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.3.0 container_name: 'elastic-search' environment: - discovery.type=single-node - "discovery.zen.ping.unicast.hosts=elasticsearch" - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ports: - 9200:9200 - 9300:9300 working_dir: /app volumes: - ../:/app - ./data/elasticsearch:/usr/share/elasticsearch/data volumes: elasticsearch: postgresql:

docker-compose.yaml для SF4 представляет из себя определенный набор сервисов: nginx, php-fpm, postgresql, rabbitmq (если он вам нужен), elasticsearch (если он вам нужен). Для локального окружения этого хватит. Чтобы все это заработало — есть минимальный набор настроек, без которых ничего работать не будет. Чаще всего это image, volumes, ports, environment, working_dir и container_name. Все для запуска того или иного образа описано в его документации на hub.docker.com. Там не всегда есть описание для docker-compose, но это не значит, что оно с ним не работает. Просто необходимо перенести все входящие данные из команды docker run в docker-compose и все заработает.

Когда видишь ЭТО впервые — это вызывает смешанные чувства и эмоции, но не все так страшно. Например, есть образ для RabbitMQ тут. Обычно тэги — представляют собой разные образы, разных версий приложения с различными расширяемыми образами. В Этом образе указаны тэги. 7. Например, тэг 3. 7. 7-alpine означает, что этот образ более тонкий, нежели чем, например, 3. Ну и так же в тэгах указываются чаще всего версии самого приложения. 7, так как он сделан на базе Alpine. Я обычно выбираю наиболее свежую версию и стабильную версию самого приложения и образ alpine.

После того как вы изучили и выбрали тэг — далее зачастую вы видите что-то подобного рода:

docker run -d --hostname my-rabbit --name some-rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password rabbitmq:3-management

И первая мысль — WTF? Как перебросить это в docker-compose?

По факту, в этой строке указываются все те же параметры, что и в yaml файле, только сокращенные. Все довольно не сложно. Соответственно, чтобы качественно использовать незнакомый образ, надо просто «загуглить» сокращения docker run команды и применять полные наименования в yaml файле. Например, -e — это environment, в который передаются различные параметры, могут быть так же записи типа -p — это порты, которые в yaml называются ports.

Теперь вернемся в docker-compose.yml, который я привел в виде образца выше.

2 сделанный как расширение для официального образа php7. В данном примере используется мой образ для php7. Остальные образы для локалки у меня используются полностью оригинальные и официальные. 2-fpm-alpine, но если вам не требуется такого количества дополнительных библиотек — то вы можете собрать своё расширение для официального образа и использовать его.

Например (rabbitmq:3. image — указываем какой образ скачать. 7-management-alpine). 7.

документацию образа). ports — указываем порты, которые будет использовать контейнер (см. Соответственно, если вы хотите использовать порт 80, то здесь необходимо указать 80:80 и ваш сайт будет доступен на localhost. Пример порт nginx это 80 по дефолту. Это необходимо бывает для того, чтобы несколько проектов можно было разворачивать на одном и том же хосте. Либо можно указать 7777:80, и тогда ваш сайт будет по url localhost:7777.

Например ваш проект лежит в директории ~/projects/my-sf4-app, а контейнер php настроен на работу с директорией /app (то же самое, что в варианте /var/www/my-sf4-app). volumes — здесь указываются расшаренные директории. Соответственно в volumes мы прописываем ~/projects/my-sf4-app:/app (см. Соответственно было бы удобно, чтобы контейнер имел доступ к проекту. этот пример в docker-compose.yml выше (у меня это указано относительным путем ../:/app)).

Так же эти директории удобно использовать для того, чтобы сохранять данные приложений. Таким образом для контейнера будет расшарена папка и он сможет выполнять в ней различные действия типа php bin/console doctrine:migrations:migrate. Например postgresql можно указать директорию для хранения данных БД и тогда при пересоздании контейнера не нужно будет накатывать дамп или фикстуры.

В данном случае /app (или по аналогии с вагрантом /var/www/my-sf4-app). working_dir — указывается рабочая директория контейнера.

Например для rabbitmq передаются имя пользователя и пароль, для postgresql передаётся имя базы, имя пользователя, пароль. environment — сюда передаются все переменные для контейнера.

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

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

Теперь, чтобы все это запустить необходимо провести команду docker-compose up -d в директории, где расположен файл docker-compose.

Как и где все это хранить для локалки?

Для локалки я использую папку docker в корне проекта.

В ней находится папка data в которой я храню всю информацию postgresql и elasticsearch, чтобы при пересоздании проекта не приходилось накатывать фикстуры с нуля. Так же есть папочка nginx в которой я храню конфиг для локального nginx контейнера. Эти папки я синхронизирую в docker-compose.yml с соответствующими файлами и папками в контейнерах. Так же на мой взгляд очень удобно писать bash скрипты для работы с докером. Например, start.sh скрипт запускает контейнеры, потом проводит composer install, чистит кэш и проводит миграции. Для коллег по проекту это так же удобно, им не приходится что-либо делать, они просто запускают скрипт и все работает.

Пример скрипта start.sh


#!/usr/bin/env bash
green=$(tput setf 2)
toend=$(tput hpa $(tput cols))$(tput cub 6) echo -n 'Как к вам обращаться?: '
read name
echo "Привет тебе $name! Мы начинаем старт докера для проекта tutmesto.ru"
echo -n "$name, ты хочешь использовать дамп для БД? (y/n): "
read use_dump
echo 'Сейчас мы запустим сборку докера!'
docker-compose up -d || exit
echo -en '\n'
echo -n "Докер успешно собрался! $${toend}[OK]"
echo -en '\n'
echo 'Теперь нам необходимо собрать композер.'
./composer-install.sh
echo -en '\n'
echo -n "Композер успешно собрался ${green}${toend}[OK]"
echo -en '\n'
echo 'Сейчас надо будет заснуть на 40 секунд, чтобы успела развернуться postgres-ка'
sleep 5
echo 'Осталось еще 35 секунд...'
sleep 5
echo 'Осталось еще 30 секунд...'
sleep 5
echo 'Осталось еще 25 секунд...'
sleep 5
echo 'Осталось еще 20 секунд...'
sleep 5
echo 'Осталось еще 15 секунд...'
sleep 5
echo 'Осталось еще 10 секунд...'
sleep 5
echo 'Осталось еще 5 секунд...'
sleep 5
echo 'Сон завершился. По идее postgres-ка уже поднялась и сейчас мы будем закачивать дамп!' case "$use_dump" in y|Y) ./dump.sh echo -en '\n' echo -n "Дамп успешно закачался! ${green}${toend}[OK]" echo -en '\n' ;; *) echo "$name, хорошо, обойдемся без дампа! =)" ;;
esac
echo 'Теперь нам надо провести миграции!'
./migrations-migrate.sh
echo -en '\n'
echo -n "Миграции успешно проведены! ${green}${toend}[OK]"
echo -en '\n'
echo 'Теперь почистим кэш!'
./php-fpm-command.sh rm -rf var/cache/*
./php-fpm-command.sh chmod 777 var/ -R
./cache-clear.sh
echo -en '\n'
echo -n "Кэш успешно очищен! ${green}${toend}[OK]"
echo -en '\n'
echo 'Теперь скопируем настройки для локалки!'
./env.sh
echo -en '\n'
echo -n "Настройки для локалки скопированы! ${green}${toend}[OK]"
echo -en '\n'
echo "Теперь, $name, ты можешь пользоваться локалкой! Открой в браузере localhost:7777 и наслаждайся!"
echo -en '\n'
echo "------------------------------------------------------------------------------"
echo -en '\n'
echo "ОСНОВНЫЕ КОМАНДЫ КОТОРЫЕ МОЖНО ИСПОЛЬЗОВАТЬ:"
echo "./cache-clear.sh |Очистка кэша symfony 4"
echo "./composer.sh [command(ex. install)] |Обращение к композеру"
echo "./composer-install.sh |Запуск composer install"
echo "./connect-to-php-fpm.sh |Подключение к консоли php"
echo "./console.sh [command(ex. cache:clear)] |Запуск команды php bin/console"
echo "./destroy.sh |Жесткое сворачивание локалки. Убивает все кроме образов."
echo "./dump.sh |Закачать дамп, который находится в корне (dump.sql)"
echo "./env.sh |Скопировать настройки для локалки"
echo "./migrations-migrate.sh |Провести миграции"
echo "./php-fpm-command.sh [command(ex. php -m)] |Выполнить команду в php-fpm контейнере"
echo "./start.sh |Запуск локалки (этот скрипт)"
echo "./stop.sh |Gracefull shutdown локалки"
echo -en '\n'
echo "ДЛЯ УДОБНОГО ПОЛЬЗОВАНИЯ В ДАМПЕ БЫЛИ СОЗДАНЫ СЛЕДУЮЩИЕ ПОЛЬЗОВАТЕЛИ:"
echo "client@c.cc | QWEasd123"
echo "admin@a.aa | QWEasd123"
echo "moderator@m.mm | QWEasd123"
echo -en '\n'
echo "------------------------------------------------------------------------------"
echo -en '\n'
echo -en '\n'
echo 'OtezVikentiy brain corporation!'
echo -en '\n'
echo -en '\n'

Пример скрипта php-fpm-command.sh


#!/usr/bin/env bash cd "`dirname \"$0\"`" && \ docker-compose exec -T "php-fpm" sh -c "cd /app && $*"

Пример скрипта connect-to-php-fpm.sh


#!/usr/bin/env bash
docker exec -i -t --privileged php-fpm bash

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

Продуктив

Подготовка

Допустим, вы уже что-то написали на локалке и хотите выложить это на production сервер или на тестовый сервер. У вас есть хостинг на KVM виртуализации или свой сервер в соседней комнате с кондиционером.

Docker можно установить точно так же, как и на локалку, отличий никаких. Чтобы развернуть продуктив или бету — на сервере должна быть операционная система (в идеале linux) и установленный docker.

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

Если прям на пальцах, то эта система отличается лишь другими командами и тем, что docker swarm представляет из себя распределитель нагрузок для кластера (опять же немного абстрактно, но так будет проще для понимания). Docker для продуктива использует docker swarm и docker stack.

S.: советую потренироваться настраивать docker swarm на Vagrant (как бы ни парадоксально это звучало). P. Простой рецепт для тренировки — поднимаете пустой Vagrant с той же операционной системой, что и в продуктиве и настраиваете его для начала.

Чтобы настроить docker swarm — необходимо просто выполнить несколько команд:


docker swarm init --advertise-addr 192.168.***.** (ip-адрес вашего сервера)
mkdir /app (в случае если ваш докер настроен на работу с директорией app)
chown docker /app (ну или раздать права на директорию)
docker stack deploy -c docker-compose.yml my-first-sf4-docker-app

Рассмотрим теперь все это немного подробнее.

docker swarm init --advertise-addr — оно запускает непосредственно сам docker swarm и шарит ссылку, чтобы вы могли бы подцепить к этому «рою» еще какой-то другой сервер, чтобы они работали в кластере.
mkdir /app && chown .. — необходимо создать заранее все необходимые директории для работы докера, чтобы во время сборки он не жаловался бы на отсутствие директорий.
docker stack deploy -c docker-compose.yml my-first-sf4-docker-app — эта команда запускает сборку самого вашего приложения, аналог docker-compose up -d только для docker swarm.

Чтобы началась какая-либо сборка, вам необходим все тот же docker-compose.yaml, но уже немного измененный именно под продуктив/бету.

version: '3.1' services: php-fpm: image: otezvikentiy/php7.2-fpm:0.0.11 ports: - '9000:9000' networks: - my-test-network depends_on: - postgres - rabbitmq volumes: - /app:/app working_dir: /app deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] nginx: image: nginx:1.15.0 networks: - my-test-network working_dir: /app ports: - '80:80' depends_on: - php-fpm volumes: - /app:/app - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] postgres: image: postgres:9.6 ports: - '5432:5432' working_dir: /app networks: - my-test-network secrets: - postgres_db - postgres_user - postgres_pass environment: POSTGRES_DB_FILE: /run/secrets/postgres_db POSTGRES_USER_FILE: /run/secrets/postgres_user POSTGRES_PASSWORD_FILE: /run/secrets/postgres_pass volumes: - ./data/dump:/app/dump - ./data/postgresql:/var/lib/postgresql/data deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] rabbitmq: image: rabbitmq:3.7.5-management networks: - my-test-network working_dir: /app hostname: my-test-sf4-app-rabbit-mq volumes: - /app:/app ports: - '5672:5672' - '15672:15672' secrets: - rabbitmq_default_user - rabbitmq_default_pass - rabbitmq_default_vhost environment: RABBITMQ_DEFAULT_USER_FILE: /run/secrets/rabbitmq_default_user RABBITMQ_DEFAULT_PASS_FILE: /run/secrets/rabbitmq_default_pass RABBITMQ_DEFAULT_VHOST_FILE: /run/secrets/rabbitmq_default_vhost deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.3.0 networks: - my-test-network depends_on: - postgres environment: - discovery.type=single-node - discovery.zen.ping.unicast.hosts=elasticsearch - bootstrap.memory_lock=true - ES_JAVA_OPTS=-Xms512m -Xmx512m ports: - 9200:9200 - 9300:9300 working_dir: /app volumes: - /app:/app - ./data/elasticsearch:/usr/share/elasticsearch/data deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] jenkins: image: otezvikentiy/jenkins:0.0.2 networks: - my-test-network ports: - '8080:8080' - '50000:50000' volumes: - /app:/app - ./data/jenkins:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock - /usr/bin/docker:/usr/bin/docker deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager] volumes: elasticsearch: postgresql: jenkins: networks: my-test-network: secrets: rabbitmq_default_user: file: ./secrets/rabbitmq_default_user rabbitmq_default_pass: file: ./secrets/rabbitmq_default_pass rabbitmq_default_vhost: file: ./secrets/rabbitmq_default_vhost postgres_db: file: ./secrets/postgres_db postgres_user: file: ./secrets/postgres_user postgres_pass: file: ./secrets/postgres_pass

Как вы можете видеть — файл с настройками для продуктива немного отличается от файла для локалки. В нем добавились secrets, deploy и networks.

Ключи создаются довольно просто. secrets — файлы для хранения ключей. После этого в docker-compose.yml вы указываете раздел secrets и в него передаете весь список файлов с ключами. Вы создаете файл с названием ключа — внутрь пишете значение. На локалке — это делается автоматически, но на продуктиве — это необходимо немного сделать вручную. Подробнее.
networks — это созадется некая внутренняя сетка, через которую общаются между собой контейнеры. Подробнее.
deploy — это основное отличие локалки от продуктива/беты. Плюс ко всему, можно указывать дополнительные настройки кроме дефолтных.

deploy: replicas: 1 restart_policy: condition: on-failure placement: constraints: [node.role == manager]

Минимальный набор бойца:

Например, у вас есть два сервера и вы их соединили через docker swarm. replicas — указываете количество реплик, которое необходимо запускать (по сути это используется в случае, если у вас кластер и вы используете распределитель нагрузок от докера). Таким образом, нагрузка на сервера будет разделяться напополам.
restart_policy — политика автоматического «переподнятия» контейнера в случае, если он по какой-то причине упал.
placement — расположение инстанса контейнера. Указывая здесь цифру 2, например, 1 инстанс у вас будет создан на 1 сервере, а второй на втором сервере. Например бывает случаи, когда вы хотите, чтобы все инстансы контейнера крутились именно на 1 из 5 серверов, а не распределялись между ними.

Хочу почитать документацию!

Теперь давайте попробуем запустить это дело. Итак, мы немного подразобрались с тем, что отличает docker-compose.yaml для локалки от версии для продуктива/беты.

Допустим, вы тренируетесь на Vagrant'е и в корне сервера у вас лежит уже настроенный файл для продуктива docker-compose.yml


sudo apt-get update
sudo apt-get -y upgrade sudo apt-get install -y language-pack-en-base export LC_ALL=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8 curl -sSl https://get.docker.com/ | sh
sudo usermod -aG docker ubuntu sudo apt-get install git sudo docker swarm init --advertise-addr 192.168.128.77 sudo mkdir /app
sudo chmod 777 /app -R docker stack deploy -c /docker-compose.yml my-app git clone git@bitbucket.org:JohnDoe/my-app.git /app docker stack ps my-app
docker stack ls
docker stack services my-app

P.S.: не пинайте за sudo и 777, естественно на продуктиве так делать не стоит. Это лишь для скорости обучения.

Итак, нас более всего интересуют строки связанные с докером.
Сначала мы инициализируем «рой» (docker swarm).
Потом создаем директории, необходимые для работы.
Скачиваем репу с нашим кодом на SF4 в директорию /app.
После этого идут три команды: ps, ls и services.

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

Чтобы увидеть причину падения необходимо выполнить docker container ps -a — и там будет отображаться контейнер, который постоянно падает. Допустим, у нас поднялись контейнеры, но какой-то из них постоянно падает с ошибкой и в docker stack ps my-app вы видите кучу перезапусков. 1.*какой-либо лютый hash*. Их будет много инстансов одного и того же контейнера, например my-app_php-fpm.

1.*какой-либо лютый hash* и просматриваем логи. Соответственно, теперь, зная имя контейнера — выполняем docker logs my-app_php-fpm. Чтобы грохнуть все контейнеры можно сделать так: Исправляем ошибку и перезапускаем ВСЁ.

docker stack rm my-app

После этого у вас будет чистый swarm без каких-либо контейнеров. Исправляете ошибку — и снова docker stack deploy -c docker-compose.yml my-app.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Китайская панель биомаркеров старения

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

Как работает stack trace на ARM

Добрый день! Несколько дней назад столкнулся с небольшой проблемой в нашем проекте — в обработчике прерывания gdb неправильно выводил stack trace для Cortex-M. Поэтому в очередной раз полез выяснять, а какими способами можно получать stack trace для ARM? Какие флаги ...