Работаете с docker-compose? И как только это включает более одного репозитория или более одной службы, все становится грязным. Клетка вносит некий порядок в этот хаос и здорово помогает в таких установках.

Чтобы понять Cage, вы должны понять рабочий процесс, для которого он создан, и то, что люди из faraday.io считают правильным рабочим процессом:

  • Один репозиторий для инфраструктуры мультисервисного стека. Например, десять файлов docker-compose.yml для служб, развернутых вместе.
  • После этого вы сможете загрузить с помощью одной команды cage pull все десять образов Docker, созданных на сервере CI, из репозитория образов на локальный компьютер.
  • После этого вы сможете проверить исходный код одной из десяти служб, изменить его, перестроить только одну, протестировать как отдельную службу, так и интеграцию с другими и зафиксировать изменения для запуска. снова через сервер CI.

И это все. Кроме того, в Cage есть общие файлы для размещения переменных среды и перезаписей для разных сред развертывания.

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

Минимальная примерная установка

Давайте представим простую установку, один сервис в одном контейнере с базой данных Postgres. Мы определяем все в одном репозитории, включая:

  • исходный код для нашего единственного сервиса и
  • код инфраструктуры, то есть docker-compose.yml.

Это код для минимального примера. Cage — это в основном способ структурирования вашего кода. Вот самая простая возможная структура:

.
├── Makefile          # with "make dep" to downlaod cage
├── README.md
├── cage              # in .gitignore
├── pods
│   ├── common.env    # empty file
│   ├── db.yml        # docker-compose.yml for a Postgres
│   ├── service.yml   # docker-compose.yml for our service
│   └── targets
│       └── development # one deployment target for cage.
└── src
    └── Dockerfile    # source code: a plain httpd-alpine image

Для второго примера мы добавим больше. На данный момент нас устраивает:

  • Инструмент cage, который вы можете получить, изменив Makefile в соответствии с вашей операционной системой (по умолчанию используется моя: OSX), и запустите make dep.
  • Папка под названием «pods», содержащая различные индивидуально развернутые сервисы.
  • pods/db.yml — это файл docker-compose.yml для Postgres.
  • pods/service.yml — это файл docker-compose.yml для нашего фиктивного сервиса.
  • src/Dockerfile — это исходный файл для нашего фиктивного сервиса.
  • targets/development/common.env и pods/common.env — это пустые файлы для создания хотя бы одной целевой среды.

Давай повеселимся

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

$ ./cage build 
...
db uses an image, skipping
Building dummy_service
Step 1/1 ...
...
Successfully tagged test/image:latest

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

$ ./cage up
Starting exampleminimal_db_1 .... done
...
Starting exampleminimal_dummy_service_1 ... done

Мы также могли бы просто поднять одну службу с помощью $ ./cage up service_1 на тот случай, если мы изменили ее код и хотели проверить, работает ли эта.

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

Теперь давайте попробуем выполнить настоящую работу.

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

$ ./cage source ls 
src        .../src
$ ./cage source mount src
Now run cage up for these changes to take effect.

и смонтируйте их второй командой. Это источник для service_1.

Теперь перейдите в Dockerfile и измените версию.

FROM httpd:2-alpine # change i.e. to httpd:2

Отлично, давайте посмотрим, как изменения вступят в силу

$ ./cage build
...
Building dummy_service
Step 1/1: FROM httpd:2
...
$ ./cage up
exampleminimal_db_1 is up-to-date
...
Recreating example_minimal_dummy_service_1 ... done

Итак, как видите, изменение исходного кода вызвало новую сборку, а база данных осталась на месте. Вы можете остановить все с помощью $ ./cage stop и перейти ко второму примеру.

Давайте повеселимся

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

Именно это я включил в облегченную версию во втором примере. Дерево файлов для второго примера выглядит так.

.
├── Makefile                      # run make dep to get cage into this folder
├── cage                          # is in .gitignore
├── pods                          # now contains two services.
│   ├── common.env                # empty
│   ├── service_1.yml             # This contains two containers in one "service", a db and another container
│   ├── service_2.yml             # Contains an external container, gruntworks shellcheck
│   └── targets                   # Contains two environments to play around with
│       ├── development
│       └── production
├── src                           # not there in your example, as this is the mounted src code...
│   └── bash-commons
│       ├── CODEOWNERS
│       ├── Dockerfile.bats
│       ├── Dockerfile.shellcheck
│       ├── LICENSE
│       ├── NOTICE
│       ├── README.md
│       ├── docker-compose.yml
│       ├── modules
│       └── test
└── src_service1                  # again an httpd:2-alpine image...
    └── Dockerfile

Мы снова начнем с создания изображений. За исключением того, что на этот раз мы добавили немного сложности. В частности, service_2 – это внешний образ. Я выбираю образ shellcheck от gruntworks. Нажимаем кнопку сборки.

$ ./cage build
...
Building dummy_service
Step 1/1: FROM httpd:2
...
Building shellcheck
Step 1/8: ...
...

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

$ ./cage up
Recreating example2_db_1 ... done
Recreating example2_dummy_service_1 ... done
Recreating example2_shellcheck_1 ... done

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

$ ./cage source ls 
bash-commons ...
src_service1 ...
$ ./cage source mount bash-commons
$ ls src
bash-commons
...# change the image version to something else...
$ ./cage build
...

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

А как насчет целей? Я включил простой пример, на который мы можем посмотреть. По умолчанию наш стек был поднят в среде «разработки». Если мы запустим его в «производственной» среде, все, что мы поместим в эту папку, переопределит части старых файлов, включая либо переменные, либо конфигурации docker-compose. Я просто решил переопределить версию Postgres следующим образом в targets/production/service_1.yml:

version: "2"
services:
  db:
    image: "postgres:9.4"

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

$ ./cage --target production up
Pulling db (postgres:9.4)
...

...
$ ./cage stop

И это все! Мне кажется, это огромное улучшение рабочего процесса. Если вы все же решите погрузиться в cage, взгляните на две дополнительные вещи, которые

  • метаданные
  • одноразовые задачи, которые можно запускать как тесты в «тестовой» среде.

Ресурсы

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

Наслаждаться!