Всем привет, хочу рассказать о своей утилите dcw (Docker Compose Workspace) для удобного управления тестовыми окружениями на базе docker-compose.

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

У меня есть такая проблема как переключение между проектами, которое может происходить довольно часто, даже по несколько раз в день. Раньше было как без докера? На машине разработчика устанавливался весь необходимый софт, базы данных Postgres, Redis, какие-то вспомогательные сервисы, такие как Keycloak, Apache PHP, Java... Возможно каждый сервис или язык разработки представлен ещё и несколькими разными версиями. В общем такой зоопарк операционка долго не могла нормально переносить и по итогу, что-то с чем-то конфликтовало, что-то всё-равно где-то ломалось и приходилось переустанавливать всё заново и с этим бороться. В общем это был ад.

Как же хорошо что сейчас есть docker и мы можем все необходимые сервисы, языки и прочее запускать в нём. Можно для описания тестового dev окружения использовать docker-compose, это ещё упрощает жизнь в плане запуска и останова.

Более того, например, VSCode поддерживает Dev Containers и может за нас проделывать всю работу по запуску и останову dev окружения. Но к сожалению, это не полностью спасает, так как есть ещё другие IDE, в которых такой поддержки нет.

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

Много ручной работы, переключений между проектами много. Немного пострадав, я написал себе простенькие bash скрипты, которые запоминали текущий docker-compose.yml, потом останавливали его и запускали новый. Скрипты лежали в ~/bin и выглядели примерно так: switch_to_some_project, switch_to_another_project ...

И вот настало время и я решил сделать это по человечески, так появилась утилита dcw (https://github.com/navrocky/dcw).

Она написана на C++, скомпилирована в статику с рантаймом uClibc, работает без пересборки на всех возможных Линуксах (x86, x86_64), также работает в docker from scratch (правда не знаю зачем, но работает). Устанавливается простым копированием бинарника в /usr/local/bin или в ~/bin. Кому интересно как собирать такие статические бинарники можете заглянуть в докер файл Dockerfile.uclibc.

Позволяет добавлять docker-compose.yml файлы в свою локальную БД, присваивать alias и потом по этому alias быстро переключаться между ними. Имеется в наличии автодополнение для bash, поэтому не обязательно полностью вводить команды и алиасы, достаточно пощёлкать табом.

Работа с утилитой
Работа с утилитой

Хотелось бы добавить её в популярные дистрибутивы, но там как-то всё сложно с этим, я пока эту затею не реализовал. Если кто-то в комментариях напишет как можно добавить свой пакет, например, в Ubuntu я был бы очень признателен.

Очень надеюсь, что эта утилита кому-нибудь будет полезна. Спасибо за внимание.

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


  1. MadridianFox
    23.04.2024 21:02
    +1

    Похоже на ELC


    1. navrocky Автор
      23.04.2024 21:02
      +1

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


    1. navrocky Автор
      23.04.2024 21:02
      +1

      Сейчас ещё раз глянул на описание. Да, я кстати думал наворотить функционал, чтобы поддерживался не только докер. Наверное должно было бы получиться совсем что-то похожее на ELC. Но я сдержался и решил сделать что-то простое под конкретную задачку с docker-compose.


  1. Alekseyl
    23.04.2024 21:02
    +4

    Проблема актуальная, да. Я её иногда решаю примерно так:

    docker stop $(docker ps -q) && docker compose up -d

    Это остановит все ранее запущенные контейнеры и поднимет те, что описаны в docker-compose.yaml в текущей папке.

    В случае с Windows и PowerShell, правда, приходится вместо && использовать ;, но в данном случае это не критично.

    Длинно, да, но так как аргументы тут менять не нужно — достаточно просто нажать Ctrl+R в терминале.


    1. opusmode
      23.04.2024 21:02
      +9

      Ну, как бы, такое...

      Вообще говоря, уже давно мжно давать сервисам имена

      Буквально берём compose.yml и пишем

      name: app

      потом делаем docker compose up -d и docker compose ls и видим name. Собственно в name будет входить всё связанное с проектом. Далее корректнее погасить через docker compose -p app down. И не говрите, что у вас сотни миллиардов запущенных проектов и вы замучаетесь переключать - это проблема на вашей стороне.

      Плюс докер умеет в профили. Т.е. каждому сервису можно повесить профиль и запускать (А так же гасить) только нужные профили приложения.

      Вообще, самая актуальная проблема с докером в том, что он уже лет 10 как перешёл из разряда хайпа, в разряд обычного инструмента, а люди так и не научились работать с ним и до сих пор лепять какую-то непонятную дичь. ОСобенно это любят делать как раз разработчики, которые делаю докер ради докер, даже там, где он нафиг не нужен.


      1. mayorovp
        23.04.2024 21:02
        +1

        Не надо давать имена, и уж точно не такие фиксированные.

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


        1. opusmode
          23.04.2024 21:02

          1. Что значит "не надо давать имена"? Кому не надо, тот пусть не даёт. Функция есть. Мне надо - я даю.

          2. Что значит "такие фиксированные"? Я привёл пример. Вы знаете, что такое пример? Это абстракция. Я не буду придумывать за вас имена.

          3. Это не фича docker compose. Это фича docker. Compose Это удобная обёртка, чтобы не пилить конструкции страшного содержимого. И имена вам вообще никак не мешают развернуть несколько независимых проектов рядом.

            Более того, расскажу вам очень крутую фишку. Когда-то, 10+ лет назад, когда я ещё был зелёным джуном в джава разработке и не ушёл в инфраструктуру, была там такая штука, как полиморфизм и такая опция, как Override. Я, конечно, извиняюсь, наверное мои знания остались в глубокой древности и современные разработчики не используют такие отсталые инструменты, но в моём мышлении описанная конструкция это всё ещё схема, а итоговая реализация может быть допилена. Так вот, вы не поверите, но описанное в compose.yml это дефолтное значение переменной и его можно переопределить через туже опцию -p или через длинный ключ --project-name. Так что даже если у вас что-то, внезапно, не запустится, а такое иногда бывает, когда Network занят чем-то, то можно просто пересобрать.

          4. Расскажу вам ещё пару хинтов. В докере есть понятие образа, т.е. шаблона изделия и контейнера, т.е. конечной реализации. Как я уже сказал, compose это просто удобный способ делать что-то. Правда бывают ситуации, при которых там описан не image а dockerfile, т.е. образ надо предварительно сбилдить. Потому вызнать надо будет, по хорошему, docker compose --build up -d.
            А иногда надо сделать docker compose up -d --force-recreate.
            А ещё надо помнить, что погашеный контейнер всё равно существует и может тянуть за собой пачку всякого. Так что иногда неплохо сделать что-то врде docker system prune. Ну, знаете, место освобождает, удаляя кешированые слои, вольюмы с нетворками лишние убирает, а самое офигенное - не трогает текущие контейнеры.


      1. zorn-v100500
        23.04.2024 21:02

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

        Вот да. По заголовку зашел сказать что то такое, но уже сказали )

        Вообще сам всегда запускаю `up` без `-d` чтобы висело где то в консоле `vscode` и по CTRL+C потушить можно было. Ну и не представляю зачем нужно держать кучу запущенных проектов разом. Хотя и делаю всякие финтифлюшки типа
        ports: ["${DOCKER_HTTP_BIND:-8000}:80"]

        Чтобы в `.env` можно было указать другой проброшеный на машину порт.


        1. opusmode
          23.04.2024 21:02

          Можно демонизировать, можно не демонизировать, это вопрос вкуса и потребности.

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

          Люди до сих пор не поняли, что такое контейнеризация и как её использовать. Да и что такое cloud native тоже не поняли. И что такое stateless приложение это тоже вызывает ступор и панику.

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


          1. zorn-v100500
            23.04.2024 21:02
            +1

            Очень часто докер вообще нафиг не нужен, в частности разработчику.

            Тут не соглашусь. Я всегда от всяких очередей и редиса сторонился именно потому что не было докера.

            Я за подход "запустил одну команду и разрабатывай", а не "установи X Y Z, ах точно еще про A B и C забыли" на свой комп.

            `./bin/dev-start` и погнал )

            #!/bin/bash

            set -e

            cd `dirname $0`/..

            . bin/.init

            ./bin/db-init

            . .env

            export ACT_UID=${SUDO_UID:-${UID}}

            docker compose -f docker-compose.yaml -f docker-compose.dev.yaml up


      1. navrocky Автор
        23.04.2024 21:02

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

        1. Если вы погасили проект по имени, то поднять его по имени уже не получится, надо идти в папку с docker-compose и там писать docker-compose up -d

        2. Чтобы быстро переключиться нужно значительно больше писать в консоли:
          docker compose ls
          docker compose -p app down
          docker-compose up -f where/is/my/project/docker-compose.yml -d

          вместо:
          dcw up my_project

        Так что я считаю, что кому-то это будет наверняка полезно. Мне вот удобно.


  1. navrocky Автор
    23.04.2024 21:02

    У меня ещё есть идея сделать гуёвое приложение, чтобы висело в трее и было видно какое пространство запущено, ну и в выпадающей менюшке была возможность переключить. Жалко что статический бинарь уже не получится.


    1. MadridianFox
      23.04.2024 21:02

      Есть вариант попроще - вывести текущий воркспейс в bash prompt.

      Ну или сделать интерфейс управления в виде веб-приложения, которое показывает какое окружение запущено, позволяет запустит/остановить, и может даже показывает адреса компонентов, получая их из docker inspect (container name + container ip + exposed port) или же из лейблов контейнеров если они заданы