Как использовать docker на этапе разработки жизненного цикла devops? - PullRequest
7 голосов
/ 09 марта 2020

У меня есть пара вопросов, связанных с использованием Docker на этапе разработки.

devops

Я собираюсь предложить три различных сценария ios того, как я думаю, Docker можно использовать в среде разработки. Давайте представим, что мы создаем REST API в Java и Spring Boot. Для этого мне понадобится база данных MySQL.

  1. Первый сценарий - иметь docker -компонент для разработки с контейнером MySQL и производственным docker - составьте с MySQL и приложением Java (jar) в другом контейнере. Для разработки я запускаю docker -compose-dev.yml, чтобы запустить только базу данных. Приложение запускается и отлаживается с помощью среды IDE, например IntelliJ Idea. Любые изменения, внесенные в код, IDE распознает и перезапустит приложение, применив эти изменения.

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

  3. Третий Сценарий состоит из смеси двух предыдущих. Два docker -композит. Компонент docker для разработки содержит оба контейнера, но с механизмами, позволяющими перезагружать приложение в реальном времени, отображать тома и использовать, например, Spring Dev Tools. Таким образом, контейнеры запускаются, и в случае каких-либо изменений в файлах контейнер приложения обнаруживает изменение и будет перезапущен. Для производства docker -композиция будет создаваться просто с обоими контейнерами, но без функциональной возможности оперативной перезагрузки. По моему мнению, это был бы идеальный сценарий, но я думаю, что он очень зависит от используемых технологий, поскольку не все допускают перезагрузку в реальном времени.

Вопросы заключаются в следующем.

  • Какой из этих сценариев ios является наиболее типичным при использовании Docker для фазы?

  • Хорошо ли поднят сценарий 1? То есть докеризуйте только внешние службы, такие как базы данных, очереди и т. Д. c. и выполнить разработку и отладку приложения с помощью IDE, не используя для этого Docker.

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

Заранее спасибо за ваше время.

ПРИМЕЧАНИЕ : Возможно, вопрос мнение, но было бы неплохо узнать, как разработчики обычно решают эти проблемы.

Ответы [ 4 ]

2 голосов
/ 12 марта 2020

Я использую нечто подобное вашему третьему сценарию для моего веб-разработчика, но оно основано на Node. Итак, у меня есть 3 docker -композитные файлы (на самом деле 4, один базовый и , имеющий все общее для других ) для сред разработки, промежуточных и производственных сред.

промежуточных docker - compose config аналогичен производственному config, за исключением SSL, портов и других вещей, которые могут не позволять использовать его локально.

У меня есть отдельный контейнер для каждой службы (например, БД, очередь), а для dev я также иметь дополнительные dev DB и контейнеры очереди в основном для запуска авто-тестов. В среде разработчика все источники монтируются в контейнеры, что позволяет использовать IDE / редактор по выбору за пределами контейнера и видеть изменения внутри.

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

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

Production docker -compose config используется только во время развертывания, поскольку он включает SSL, надлежащие порты и имеет некоторые дополнительные производственный материал.

Обновление сведений о перезапуске внутреннего приложения с помощью Supervisor:

Вот как я использую его в своих проектах:

Часть моего Dockerfile с установкой Supervisor:

FROM node:10.15.2-stretch-slim

RUN apt-get update && apt-get install -y \
  # Supervisor
    supervisor \
    ...

...

# Configs for services/workers managed by supervisor
COPY some/path/worker-configs/*.conf /etc/supervisor/conf.d/

Это пример одной из конфигураций Supervisor для работника:

[program:myWorkerName]
command=/usr/local/bin/node /app/workers/my-worker.js
user=root
numprocs=1
stopsignal=INT
autostart=true
autorestart=true
startretries=10

В этом примере в вашем случае command должно запускать ваше приложение Java.

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

# Used to run all workers
su-start:
    @docker exec -t MY-WORKERS-CONTAINER-NAME supervisorctl start all

# Used to stop all workers
su-stop:
    @docker exec -t MY-WORKERS-CONTAINER-NAME supervisorctl stop all

# Used to restart all workers
su-restart:
    @docker exec -t MY-WORKERS-CONTAINER-NAME supervisorctl restart all

# Used to check status of all workers
su-status:
    @docker exec -t MY-WORKERS-CONTAINER-NAME supervisorctl status

Как я уже говорил выше, эти команды Supervisor необходимо запускать вручную, но я думаю, что можно реализовать может быть, другой рабочий на основе Node или какой-то наблюдатель вне контейнера с работниками, которые будут обнаруживать изменения файловой системы для каталога sources и автоматически запускать эти команды. Я думаю, что можно реализовать что-то подобное, используя Java, а также , например или this .

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

2 голосов
/ 12 марта 2020

Отказ от ответственности: это мое собственное мнение по этому вопросу, заданное г-ном Марсом. Несмотря на то, что я приложил все усилия, чтобы подкрепить свой ответ фактическими источниками, он в основном основан на моем собственном опыте и немного здравого смысла

Какой из этих сценариев ios является наиболее типичным при использовании Docker для разработки?

Я видел все 3 сценария ios в нескольких проектах, каждый из которых имеет свои преимущества и недостатки. Однако я думаю, что сценарий 3 с Docker Compose, допускающим динамическую перезагрузку кода c, является наиболее выгодным с точки зрения гибкости и согласованности:

  • Dev и Prod Docker Compose являются близкими совпадениями, это означает, что среда разработки максимально приближена к среде Prod
  • Вам не нужно постоянно перестраивать образ при разработке, но это легко сделать, когда вам нужно
  • Многие технологии поддерживают такой сценарий как Spring Dev Tools, как вы упомянули, но также Python Flask, et c.
  • Вы можете легко использовать Docker Compose расширяет механизм обмена конфигурациями (также возможно в сценарии 2)

Хорошо ли поднят сценарий 1? То есть докеризуйте только внешние службы, такие как базы данных, очереди и т. Д. c. и выполнить разработку и отладку приложения с помощью IDE, не используя для этого Docker.

Сценарий 1 довольно распространен, но среда IDE, вероятно, будет отличаться от среды * 1069. * контейнер (и было бы трудно поддерживать соответствие версии для каждой библиотеки, зависимостей и т. д. c. из среды IDE в среду Docker). Также, вероятно, потребуется go через промежуточный шаг между Dev и Production, чтобы на самом деле протестировать образ Docker, созданный после того, как Dev работает до перехода в Production.

По моему собственному опыту, делать это замечательно, когда вы не хотите слишком много работать с Docker, когда фактически делаете dev и / или язык или технология, которую вы используете, не адаптированы для динамической перезагрузки c, как описано в сценарии 3. Но в итоге это только добавляет дрейф между ваши среды и больше сложностей между Dev и Prod методом развертывания.

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

Помимо описанного вами сценария ios, у вас есть способы прилично (даже радикально) сократить время сборки изображения, используя Docker сборка кеша и проектирование вашего Dockerfile . Например, приложение Python обычно копирует код как последний (или почти последний) шаг сборки, чтобы избежать аннулирования кэша, а для приложения Java можно было бы разбить код, чтобы избежать компиляции всего приложение каждый раз, когда немного изменений кода - это будет зависеть от вашей реальной настройки.


Я лично использую сценарий 3, приблизительно соответствующий рабочему процессу, например:

  • a docker-compose.yml файл, соответствующий моей производственной среде
  • a docker-compose.dev.yml который переопределяет некоторые аспекты моего основного Docker Compose-файла, такие как код вызова с моего компьютера, добавляя в команды dev speci c flags, et c. - это будет выполнено, например,
    docker-compose -f docker-compose.yml -f docker-compose.dev.yml 
    
    , но также будет возможно иметь docker-compose.override.yml как Docker Compose использует по умолчанию для переопределения
  • , в некоторых ситуациях я бы использовать другие переопределения для определенных c ситуаций, таких как docker-compose.ci.yml в моем CI, но обычно основного Docker Compose-файла достаточно для описания моей среды Prod (и если это не так, docker-compose.prod.yml добивается цели)
1 голос
/ 20 марта 2020

Я видел их все в разных сценах ios. Есть некоторые ошибки, которых следует избегать:

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

  2. Разрешения для файлов с томами хоста могут быть сложными в зависимости от вашей версии docker. Некоторые из более новых установок Docker Desktop автоматически обрабатывают сопоставления uid, но если вы разрабатываете непосредственно на Linux, вам необходимо убедиться, что контейнеры работают с тем же uid, что и пользователь вашего хоста.

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

Просмотр каждого из параметров Вот моя оценка каждого из них:

  1. Контейнерирование только БД: Это хорошо работает, когда разработчики уже имеют среду разработки для выбранного языка, и нет никакого риска внешних зависимостей, напр., разработчик, обновляющий свою JDK-инсталляцию до более новой версии, чем образ, созданный с помощью. Он следует идее сначала контейнирования зависимостей, а также дает разработчикам знакомую интеграцию IDE со своими приложениями.

  2. Перестройка образа для каждого изменения: Это имеет тенденцию к быть наименее идеальным для рабочего процесса разработчика, но самым быстрым для реализации, когда вы не знакомы с инструментарием. Я дам 4-й вариант, который я считаю улучшением.

  3. Все в контейнере, объемных монтировках и динамической перезагрузке: Это самое сложное реализовать и требует самого языка для поддержки таких вещей, как живая перезагрузка. Тем не менее, когда они это делают, это почти незаметно для разработчиков и позволяет быстро освоить новый проект без необходимости устанавливать какие-либо другие инструменты для начала работы.

  4. Перестройте приложение в контейнере с монтируемыми томами: Это промежуточная точка между 2 и 3. Если у вас нет оперативной перезагрузки, вам, вероятно, потребуется перекомпилировать или перезапустить интерпретатор, чтобы увидеть какие-либо изменения. Вместо того, чтобы перестраивать образ, я помещаю шаг перекомпиляции в точку входа образа разработки. Я буду монтировать код в контейнер и запускать полный JDK вместо JRE (или любого другого необходимого компилятора). Я использую именованные тома для любых кэшей зависимостей, поэтому их не нужно загружать при каждом перезапуске. Тогда способ увидеть изменения состоит в том, чтобы перезапустить один контейнер. Шаги идентичны скомпилированному двоичному файлу вне контейнера, остановите старый сервис, перекомпилируйте и перезапустите сервис, но теперь это происходит внутри контейнера, который должен иметь те же инструменты, которые использовались при создании рабочего образа.

Для варианта 4 я склонен использовать многоэтапную сборку, имеющую этапы сборки, разработки и выпуска. Стадия сборки извлекает код и компилирует его, стадия разработки - это тот же базовый образ, что и для сборки, но с точкой входа, которая выполняет компиляцию / запуск, а стадия выпуска копирует результат стадии сборки в минимальное время выполнения. Затем разработчики получают составной файл для разработки, который создает образ разработки и запускает его с монтируемыми томами и открытыми портами отладки.

0 голосов
/ 20 марта 2020

Прежде всего, docker -compose предназначен только для этапа разработки и тестирования, а не для производства. Пример:

С минимальным и базовым составом c docker все ваши контейнеры будут работать на одном компьютере? Для целей разработки это нормально, но в производстве все приложения на одном компьютере - это риск

Мы примем

  • 01 java api
  • 01 mysql база данных
  • 01 веб-приложение, которому необходим API
  • все область этих приложений уже находится в производстве

Быстрый ответ

Если вам нужно исправить или добавить новую функцию в java api, я советую вам использовать ide, например eclipse или IntelliJ Идея. Почему?

  • Поскольку java требует компиляции.
  • Компиляция внутри контейнера docker займет больше времени из-за зависимостей maven
  • IDE имеет автозаполнение кода
  • et c

На этом этапе разработки Docker помогает вам воспользоваться одной из самых мощных функций: «Переносить производственные контейнеры на локальный хост». Да, в этом случае docker -compose.yml - лучший вариант, потому что с одним файлом вы можете запустить все, что вам нужно: mysql база данных и веб-приложение, но не ваш java API. Откройте ваш java API с вашим любимым ide.

В любом случае, если вы хотите использовать docker для "разработки", вам просто нужен Dockerfile и выполните сборку docker ... когда вам нужно запустите ваш исходный код на локальном хосте

Basi c Жизненный цикл Devops с docker

  • Developer pu sh Изменения исходного кода с использованием git
  • Ваша платформа непрерывной интеграции (C .I) обнаружит это изменение и выполнит
    • docker build ... (На этом этапе запускается модульное тестирование)
    • docker pu sh к вашему личному концентратору. Контейнер загружается на этом этапе и будет использоваться для развертывания на других серверах.
    • docker запуск или развертывание контейнера в следующей среде: тестирование
  • Human testers, Селен или другая автоматизация начинают свою работу
  • Если ошибок не обнаружено, ваш C .I выполняет окончательное развертывание загруженного контейнера в вашей производственной среде. docker сборка не требуется, просто разверните или docker запустите.

Некоторые советы

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

Java и Nodejs - это стабильные языки, и ваши остальные API или веб-приложения не нуждаются в сумасшедших настройках. Просто компиляция maven и java -jar ... или npm установка и npm запуск.

Для журналов вы можете использовать https://www.graylog.org/, google stasckdriver или другое управление журналом.

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

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

...