Разработка под Docker. Локальное окружение. Часть 1

Возможно, одна из самых основных причин почему мне нравится докер это то, что он позволяет избавиться от необходимости установки на компьютер различных сервисов. К их числу можно отнести и сам веб-сервер Apache или Nginx, базы данных и прочие компоненты инфраструктуры приложения. Вся инфраструктура прописана в конфигурационном файле docker-compose.yml и запускается одной командой вместе с вашим приложением. Все что нужно разработчику работающему с докером, это по сути сам докер и любимая среда разработки и ВСЕ!

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

Итак, докер следует рассматривать, как некоторую систему виртуализации и контейнеризации.
Одно из базовых понятий докера — это образ. Образ можно сравнить с файлом (может быть даже с исполняемым файлом программы), в котором содержится некоторая информация. Докер может выполнить запуск образа. Запущенный образ называется контейнером. Может быть запущено несколько контейнеров одного и того же образа.

Так что же содержится в образе?

Может быть образ операционной системы. К примеру, образ ubuntu. Может быть образ с базой данных, веб-сервером и php и практически с чем угодно. Для начала этих знаний нам будет достаточно.

Предполагается, что у читателя уже установлен сам docker и утилита docker-compose.

Начнем развертывание нашего окружения от простого к более сложному.

Урок №1. Установка Nginx


Попробуем для начала установить один лишь Nginx. Создадим docker-compose.yml следующего содержания:

version: '3.0'

services:

  nginx:
    image: nginx
    ports:
      - 80:80

Далее выполняем команду docker-compose up -d в ответ должно появиться примерно следующее:

Creating network "lesson1_default" with the default driver
Creating lesson1_nginx_1 ... done

Вводим в адресной строке браузера http://localhost/ и нашему взору должно открыться приветствие «Welcome to nginx!». Если все так, вы на верном пути.

Что тут вообще происходит?

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

Разберем представленный файл:

  • version — В начале объявляется версия compose-файла. Вместо 3.0, можно было бы указать и 2.0. Меньше уже не поддерживается. От версии зависят опции в compose-файле, которые доступны для использования.
  • services — объявление сервисов
  • nginx — имя нашего сервиса, задается произвольно по своему усмотрению. В данном примере совпадает с названием образа.
  • image: nginx — имя используемого образа.
  • ports — директива объявляет «проброс» портов. 8080:80 — данная запись означает, что открытому порту 80 контейнера будет соответствовать порт 8080 на хостовой машине, на который запущен докер. В примере из файла, 80 порт в контейнере связан с 80 портом на вашем компьютере.

Более детально разберем объявление образа, директива image: nginx.

Главным хранилищем всех образов является Docker Hub там представлено множество различных готовых образов (Можно собирать и свои собственные, но об этом позже). Объявленный образ nginx является одним из них.

Что касается «проброса» портов. Если вы указываете соответствие 80:80, как и в указанном примере, то nginx будет доступен по адресу localhost:80 или просто localhost. Если же 80 порт уже занят, то можно указать 8080:80. Тогда сайт будет доступен по адресу localhost:8080. И соответственно, если вы вовсе забыли указать данную директиву ports, то порт будет доступен только внутри контейнера и nginx через браузер уже будет недоступен.

Контейнер запущен. А как собственно с ним работать?

Установка Веб-сервера предполагает, что мы хотим с его помощью получать и просматривать html-страницы сайта. Появляется вопрос. Каким образом можно передать в контейнер какие-либо html-файлы? В этом нам помогут volumes

volumes


Приведем наш docker-compose.yml к следующему виду:

version: '3.0'

services:

  nginx:
    image: nginx
    ports:
      - 80:80
    volumes:
      - ./html:/usr/share/nginx/html

Из нового тут появилась директива volumes, которая говорит, что происходит монтирование локальной папки ./html в контейнер по адресу /usr/share/nginx/html.

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

Чтобы все заработало, создадим папку html на одном уровне с файлом docker-compose.yml и добавим в нее файл index.html с произвольным текстом. Например, Hello from Docker!

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

Recreating lesson1_nginx_1 ... done

Проверяем в браузере получившийся результат. И видим: Hello from Docker! Все получилось.

Важно заметить, что монтированная папка доступна для изменений в реальном времени. Т.е. если мы изменим текст в файле index.html или добавим новый файл в папку, то все эти изменения сразу же будут доступны внутри контейнера. Эта важная функция и позволяет вести разработку через докер. Мы изменения вносим на своем компьютере в примонтированные файлы, папки и они сразу же отображаются и в контейнере докера.

Часть 2 — Nginx+PHP+MySql+phpMyAdmin
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 82

    +8
    Наверное первая статья на хабре с подробностями по docker!
      –9

      Шёл 2019 год. PHP разработчикам рассказали про Docker… Продолжение следует )

        +1
        согласен, что технологию сложно назвать новой, да и все что я могу рассказать для знатоков ни в коей мере Америки не откроет, но по своему опыту вижу довольно много разработчиков-староверов, которые даже из подобных статей что-то могут почерпнуть для себя нового)
          +2
          Нуу, они продолжат так же запихивать все в один контейнер. Ничего не изменится.
            +1
            Да хрен бы с ним с одним контейнером, это уже прорыв. Знаю человека который до сих пор работает исключительно на Open Server, и уверен что vagrant и docker это какая-то ненужная фигня.
              +1

              да, может это и нужно когда работаешь над каким-то сложным продуктом, да еще и не с последней версией php, но как-то все слишком неудобно и долго, что с докер, что вагрант, я пару лет назад пытался все проекты перевести на докер и в один момент поймал себя на том, что на докер я трачу больше времени чем на разработку) Куда удобней в шторме написать php -S localhost:8000, или artisan serve и просто работать)
              Может я тупой, может не понимаю истины, но когда все проекты на php 7.2, куда проще пользоваться обычным терминалом и сделать просто composer install и не вспоминать как подключиться к контейнеру и выполнить там команду)

                0
                Видимо у вас какие-то очень мелкие проекты, ведь помимо раздачи самого php (с чем, в принципе, вполне справится и php -S) часто надо держать mysql, mongo, memcached, иногда ещё websocket-сервер на ноде. Да при этом проектов несколько, и им надо разное окружение, разную версию PHP. И вот тут уже хочешь не хочешь, а надо нормальное решение.

                По поводу
                на докер я трачу больше времени чем на разработку
                — у меня на докер в день уходит ну секунд 6, чтобы не соврать. Утром его запускаю с одной кнопки (точнее не сам докер, а все нужные контейнеры), вечером выключаю. Если не гасить контейнеры — то вообще будет уходить 0 секунд. Что с ним нужно делать чтобы времени уходило больше чем на разработку?)
                  0
                  часто надо держать mysql, mongo, memcached, иногда ещё websocket-сервер на ноде.

                  mysql есть, остальное — нет) есть .env и адаптеры которые решают где хранить кеш, или key-value данные, например локально кеш хранится в файлах, а на проде в redis, web sockets есть на php, которые работают не хуже ноды, да и nodejs и npm установлены одной коммандой и используется)
                  По поводу того на что тратил время — настройка, вот читаешь мануал, на ноутбуке должен быть только докер, остальное в конейнерах, надо тебе поставить композер? И Пошло гугление как это сделать и как это потом использовать через docker exec что-бы не писать километровые команды, а если надо ng serve сделать? Опять гугления пошли) ну и так далее, я согласен, что проблемы из-за неопытности, но пока мне проще без докера чем с ним — я наверное не поборю лень и не выучу его)

                    0
                    Два слова
                    docker multi-stage

                    Первый этап это image с композер в котором ставится все необходимое
                    Второй это сам php
                    Контейнеры это не ВМ как обычно все ее представляют, а готовое окружение которое не нужно потом через docker exec менять.
                    –2
                    А что делать мне?
                    У меня тоже один мелкий проект. Для своей полной работы требует что-то под 120Гб RAM и поднимает порядка 80+ контейнеров

                    Доктор, мне поможет докер?
                    +1
                    Поначалу когда начинаешь с ним разбираться, да, бывают сложности. Но это именно от опускания каких-то моментов и недостатка опыта. Как и в любом деле со временем рука набивается. Лично мне кажется, что докер может стать в перспективе неотъемлемой частью программирования. Развертывание окружение это тоже самое что и минимальные познания в веб-серверах и прочей инфраструктуре.
                      0

                      Есть сложности, которые решаются только разного уровня костылями. Банально, сделать composer install в билд-тайме с закрытыми репозиториями, чтобы ключи в образ не попали. Multi stage билды не сразу были. Запуск процесса типа того же php-fpm от пользователя, соответствующего локальному, чтобы права и в контейнере, и на хосте были минимальные, но работали. Несколько способов обеспечить правильное и удобное заполнение статики и динамики на образах nginx и php, желательно без дублирования, каждый со своими плюсами и минусами. Да совсем банально: запустить две ветки проекта под разными доменными именами, не лазая в /etc/hosts

                        0

                        Кстати, какими именно костылями вы делали, чтобы ключи в образ не попали? Ведь сокет ssh-agent напрямую не прокидывается с MacOS и Linux-контейнер.

                          0

                          Прокидывал ssh-agent (что такое MacOS? :), передавал через ARG как сами ключи, так и ссылки на внешние самописные сервисы, недоступные снаружи, предоставляющие ключ с очень ограниченным сроком действия, много чего пробовал и всегда это был компромис за счёт безопасности — закрывали одни векторы атаки, создавая новые, которые волевым решением были признаны как маловероятные.

                            0
                            Вот тут волевым усилием нашелся еще вариант:

                            1. Не шарить volume с хостом, а просто давать ему висеть «в воздухе» (docker-compose исправно данные на нем сохраняет, не стирает). Когда volume не берется с хост-машины, то и тормозов файловых операций между MacOS и Linux нет. Это «volumes: blah: external: false» в docker-compose.yml.
                            2. Для редактирования файлов внутри контейнера есть вот такое расширение: code.visualstudio.com/docs/remote/containers (оно реально создает иллюзию локального редактирования; кстати, вся разработка в фейсбуке ведется похожим образом, через IDE и «толстый» серверный модуль-агент для него).
                            3. Вот с ключами git проблема (никак ее не решить, если ключ защищен паролем), но зато данное расширение для vscode магически прокидывает токен от credential.helper, так что если клонировать git-репозиторий по https (а не по ssh), то логин-пароль приходится вводить всего один раз (а не для каждой git-операции). И в терминале vscode работают git-команды без пароля. Я сам всю жизнь хожу в git по ssh-ключам, но, похоже, https-способ и правда более современный.

                            Костыльно все это, конечно. А что делать.
                              0

                              Ну вот вроде завезли пару фич https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information Ещё не тестил даже локально под линуксом

                                0
                                Так не поможет же, если ключ с паролем. Между MacOS host и Linux guest domain socket не пробросить, а сокет нужен для ssh-agent'а.
                                  0

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

                0
                Но ведь можно было бы в такую статью хотя бы добавить как установить docker-compose и указать откуда в названии сети и контейнера взялся lesson1, и как работает service: в котором ничего не прописано — что именно происходит по умолчанию.
              +2
              Пока что скорее про docker-compose, чем про Docker, но ничего плохого в этом не вижу ибо инструмент крайне полезный!
                +1
                Жаль, что не все поняли.
                +1

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


                volumes:
                  code:
                    driver: local
                    driver_opts:
                      type: 'none'
                      o: 'bind'
                      device: $PWD
                
                services:
                  myservice:
                    container_name: mycontainer
                    build:
                      context: .
                      dockerfile: docker/go/Dockerfile
                    volumes:
                      - ./docker/go/path:/data/path  # обычный
                      - code:/go/src/myproject  # именованный

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


                $ docker volume ls
                DRIVER              VOLUME NAME
                local               b4a3ceda689f820e5ef1add990e1853b032fe9048e1ed7668a9cf160de9cff3d
                local               myservice_code

                Тут первая строка — обычный volume, а вторая строка — именованный volume. По названию можно легко понять, к какому проекту он относится.

                  0
                  Представленный вариант это по сути и есть монтирование текущей папки. А при простом монтирование по моему именной volume не создается (может конечно путаю). И я особо никогда не задавался большой целью удаления лишних вольюмов. В конце концов есть команда docker volume prune, которая подчищает неиспользуемые вольюмы.
                    +1

                    Попробуйте как-нибудь, очень удобно.
                    А насчет docker volume prune, он не удаляет, например, последние версии остановленных контейнеров (и это, конечно же, хорошо). Но если надо удалить и их, и вместе с волюмом, то удобнее, когда он именованный. Контейнер, кстати, тоже удобно именовать как написал выше. Тогда потом удобно, например, смотреть логи этого контейнера не разыскивая его по закодированным именам.

                  0
                  А подскажите, как использовать Docker, когда у тебя несколько проектов параллельно? Экосистема Docker предполагает изоляцию отдельных сервисов в отдельные контейнеры.
                  Теперь представим, у нас есть один проект на PHP, для его работы крутятся 3 конейтенера: nginx + php-fpm + mysql server. Из контейнера nginx проброшен 80 порт на хост машину (в конфигах nginx прописан доступ по your-domain.loc).
                  И вот появляется необходимость развернуть еще один проект параллельно. Как быть в этом случае?
                  1) Добавлять в существующие контейнеры настройки для второго проекта — протеворечить принципам изоляции сервисов, ну и, соотвественно, в случае падения одного из проектов (ошибка nginx или типа того) все проекты, которые были завязаны на этих контейнерах тоже упадут.
                  2) Создать +3 контйенра для второго пректа, но так, как 80 порт уже занят первым проектом, то нам необходимо будет из браузера стучаться через кастомный порт, что весьма неудобно. Та же самая проблема касается и всех остальных сервисов. С хост машины в MySQL уже придется ломиться по кастомному порту.
                  3) Находил еще вариант с добавлением доп. контейнера nginx, который будет выступать в качестве прокси сервера, принимащего все запросы, выявлять имя домена и направлять запросы в соотвествующие контейнеры. Но этот вариант тоже не самый удобный, и не решает проблем с остальными сервисами (php-fpm и mysql тоже придется вешать на другие порты).

                  Вот и сижу и думаю, как этот вопрос решается с Docker, наверняка многие должны были сталкиваться с ним.
                    +1
                    С 80м портом это довольно известная и типовая проблема. Для ее решения можно использовать реверс-прокси. К примеру, у меня довольно популярен вот этот hub.docker.com/r/jwilder/nginx-proxy. Отдельно запускается данный прокси только у него прокидывается 80 порт и к нему коннектятся отдельные фронты уже без проброса 80го порта.
                    Касаемо Mysql, исключительно для нужд приложения проброс портов на хостовую машину вообще не нужен. Я порой пробрасываю кастомные порты, чтобы соединятся с контейнером через PHPSTORM (может быть кто-то из местных подскажет функцию у шторма, чтобы без проброса коннектиться к базе в докере.) Или если использовать например phpmyadmin настроенную через прокси, то можно обойтись и без проброса.
                      0

                      Ну да, nginx-proxy — это и есть мой вариант №3. Он мне не понравился наличием отдельного контейнера, но, возможно, я тогда погорячился и на самом деле это не так страшно.


                      может быть кто-то из местных подскажет функцию у шторма, чтобы без проброса коннектиться к базе в докере

                      Тоже активно использую Phpstrom, на сколько мне известно, на текущий момент функции прямого подключения БД в Docker нет. Вот только недавно подвезли возможность запускать composer через Docker из шторма, не думаю, что есть вариант коннекта для БД.

                        0
                        Можно же подключится со шторма к бд через ssh тунель? Или я не правильно понял проблему?
                          0

                          Можно через SSH тунель, но экосистема Docker не рекомендует использование SSH внутри контейнеров (хоть и не запрещено).

                            0
                            Хм, понял. А если тогда порт наружу от бд пробросить?
                              0

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

                              0
                              Можно прокинуть socket на хост систему, как вариант?
                                0
                                Что-то не видел функции у шторма соединяться с сокетом…
                                  0
                                  Я честно не разработчик и шторм использовать не приходилось, но если указывать localhost — клиенты mysql обычно цепляются к сокету. Если у IDE нет каких-либо особенностей — должно сработать кмк.
                            0

                            Ну, можно же юникс-сокет пробросить, не? Как volume? И к нему подключаться уже.

                            0
                            может быть кто-то из местных подскажет функцию у шторма, чтобы без проброса коннектиться к базе в докере

                            Можно, как немного костыльный вариант, после создания контейнера выполнить
                            docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' idOrName
                            и подключаться уже по этому адресу.
                              0
                              Минус в том, что при перезапуске этот адрес можем меняться, а так да, вариант
                              0

                              На хостингах могут добавлять выделенные IP для отдельных доменов, на локальной машине возможно такое изобразить?

                                0

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

                              0

                              Просто-же, начали работать со вторым проектом — закрыли первый. Или умеете программировать асинхронно? :)

                                0

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


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

                                  0
                                  Vagrant достаточно всего пару строк добавить в конфиг, дабы поднять новый хост.
                                  Ну, вагрант решает эту проблему пока у нас оба проекта на одной версии php. В ином случае нам надо две вагрант-машины, и вот они не поделят порт 80 точно так же само как докер.
                                    +1

                                    Используя, например, homestead (бокс от Laravel), можно в конфиге и версию php тоже прописывать. Внутри бокса крутится nginx + несколько версий php-fpm, в зависимости от конфига homestead создает нужный локейшн для nginx с подключением нужной версии php-fpm сокета.

                                      0
                                      Фигасе, не знал что homestead такое умеет. Тогда согласен, vagrant в этом плане удобнее.
                                    0

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

                                      0

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

                                        0

                                        Я имел в виду проекты, с которых нужно что-то переносить.

                                +1

                                Подскажите, а как в 2019 году на практике обстоят дела с производительностью файлового доступа к подмонтированной таким образом папке? Хост-система MacOS (вероятно, это важно!), в контейнере Linux.


                                Я слышал, что раньше люди мучались с дев-окружением в Докере, потому что доступ к примонтированным файлам был ну ооочень медленным (например, запускать какой-нибудь build, лопатящий много файлов, внутри контейнера было весьма неприятно). А как сейчас?

                                  +1
                                  с mac к сожалению возможности не имел работать, хотя коллеги работают с докером в маке и вроде как не жалуются. В виндовсе действительно проблема со скоростью есть. Симфони могла свой кеш грузить секунды по три, в то время как в линуксе скорость не вызывает нареканий. По сравнению с виндовс симфони там работает в десятки раз быстрее. (миллисекунды против секунд)
                                    +1
                                    Не заметил разницы в скорости работы.
                                      0
                                      Если небольшое количество файлов, то не заметно, а к примеру magenta 2 с пару десятком тысяч файлов будет работать ооооочень медленно, отработка запроса пару минут. Но docker sync эту проблему решает.
                                        0
                                        Она сама по себе работает очень медленно, насколько мне известно. Особенно, если отключить кеширование.
                                          0

                                          Нет, под Docker Mac OS + docker sync работает так же быстро как и под Linux. Без sync работать невозможно под Mac OS.

                                      0
                                      Такая проблема точно сувществовала около года назад, изза этого пришлось отказатся от докера на локальном дев окружении. Но вроде как говорят что уже пофиксили это, сам подтвердить к сожалению не могу, ещё не проверял
                                        +2

                                        Все так же хреново.
                                        Не используйте мак для разработки.


                                        Но если без мазохизма никак, то docker sync и dinghy

                                          +1
                                          Понятно.

                                          1. Docker sync создает новый свой искусственный контейнер, в котором крутится линукс, и монтирует в него нашу папку с MacOS под именем dir1.
                                          2. Дальше он уже эту папку dir1 там, в этом контейнере, unison-синкает с другой папкой в том же (!) контейнере, dir2. Фактически, копирует пофайлово в обе стороны.
                                          3. И, наконец, мы монтируем папку dir2 из искусственного контейнера в наш настоящий контейнер (с webpack-ами, php и т.д.). Т.к. это докер-монтирование «из линукса в линукс», то файловый доступ происходит мгновенно.

                                          И все это с 2016-го где-то года. Какой ужас. Неудивительно, что Соломон ушел. :)

                                          (Unison написан на Окамле в стиле «плюс-минус разница в третьей цифре версии Окамла между клиентом и сервером — смерть», а также почти что не поддерживается уже. Впрочем, для п. 1 это не важно, т.к. искусственный контейнер уже заранее подготовлен.)
                                          0
                                          проверил только что — разница очень небольшая, <10%.

                                          docker -v
                                          Docker version 18.09.1, build 4c52b90
                                          MacOs 10.13.6
                                            0

                                            Какое количество файлов в volume?

                                              0
                                              1 :-) (то есть сотня, но копировал я один большой файл)
                                              уже увидел, что жаловались на медленную работу при большом кол-ве файлов.
                                          +1

                                          Пропустил момент, откуда появился идентификатор lesson1 и куда класть docker-compose.yml, чтобы docker-compose up его нашел

                                            0

                                            Ничего сложного. docker-compose.yml класть в то место, где ты его будешь запускать. Он ищет в той папке, где ты вызвал команду docker-compose up -d. Идентификатор lesson1 появился из названия папки в которой запускается проект. То есть автор запускал проект в папке lesson1.

                                              0
                                              Я подозреваю, что предполагалось добавить эту информацию в статью.
                                              +1
                                              Еще есть параметр -f. С его помощью можно подцепить несколько yml конфигов. Это позволяет раскидать настройки между несколькими файлами. В одном фале базовые сервисы (MySQL, Redis, их базовая настройка и др), во втором файле запуск контейнеров вашего приложения, а в третьем например override портов. Выглядеть это будет примерно так

                                              docker-compose -f docker-compose.yml -f docker-compose.app.yml -f docker-compose.override.yml up -d
                                              +1
                                              Не хочу негативить но:
                                              1. Почему так коротко? Это больше на новость похоже
                                              2. Подобных статей навалом, чем Ваша статья отличается от остальных? Например, этой habr.com/ru/post/346086

                                              У меня в закладках эта habr.com/ru/company/flant/blog/336654
                                              А когда просят рассказать как работает, даю эту habr.com/ru/company/ruvds/blog/438796
                                                0
                                                Чем больше — тем лучше!
                                                  0
                                                  Проба пера, продолжение следует)
                                                  0
                                                  Господа, а что в июле 2019 принято делать в таком случае:

                                                  • Есть production-образ с каким-нибудь php и веб-приложением внутри. Исходники приложения принадлежат www-data:www-data.
                                                  • Есть локальная машина для разработки с docker-compose. В docker-compose стягивается этот production-образ и в docker-compose.override.yml исходники монтируется снаружи, но принадлежат они vasya:vasya.

                                                  Вот такие советы иначе как костылями язык не поворачивается назвать toster.ru/q/542064
                                                    +2
                                                    По идее если вы монтируете исходники снаружи, то вы должны полностью перекрывать то что внутри и принадлежало www-data, потом выполнять сборку своих исходников в виде. composer install или чего-то подобного. И тогда никаких проблем с правами быть не должно.
                                                    А по хорошему, вообще кажется не совсем верный подход монтировать образ с прода.
                                                    Должно быть локальное окружение для нужд разработчиков и отдельно сборка из исходников образа для прода.
                                                      –1

                                                      А мне кажется неверным подход использовать разные образы. Опять увеличиваем вероятность "локально у меня всё работает". В крайнем случае дев-образ наследуем от прода, но очень аккуратно.

                                                        0
                                                        На проде используется «монолитный» собранный образ без проброса кода, на деве пробрасывать код необходимо, в этом вся суть разработки. И в том и другом образах основа одинаковая, один и тот же php, одни и те же расширения. Образ для прода в идеале должен собираться автоматически через CI, точно также автоматически должен и деплой происходить. После сборки в идеале должны запускаться различные тесты, юнит-тестирование как минимум. Потом бы в идеале чтобы образ выгружался сначала на тестовый сервер, там дополнительно проверялась логика работы кода и только затем уже аналогичный образ устанавливается на прод.
                                                          0

                                                          Вот расширения типа xdebug на проде лишними будут точно. Как бы не хотелось иметь одинаковые, дев-образ наследуем от прода. Можно просто в одном докерфайле мультистейдж использовать.

                                                        +1
                                                        Всё так, вместо prod-образа может быть какой-нибудь dev-образ, но сорцы точно так же будут в контейнере лежать в папке с gid/uid отличным от хоста. Я встречал разные варианты вплоть до использования шаблонов в www.conf, nginx.conf и где там ещё может использоваться юзер. При этом отдельно стоит отметить это чудо:

                                                        /bin/sh -c "envsubst < /tmp/www.conf.tpl > /tmp/www.conf"

                                                        Проблема достаточно распространённая и каждый решает на свой лад:
                                                        stackoverflow.com/questions/23544282/what-is-the-best-way-to-manage-permissions-for-docker-shared-volumes
                                                        www.inanzzz.com/index.php/post/q1rj/running-docker-container-with-a-non-root-user-and-fixing-shared-volume-permissions-with-dockerfile
                                                        denibertovic.com/posts/handling-permissions-with-docker-volumes
                                                        github.com/moby/moby/issues/2259
                                                        medium.com/@nielssj/docker-volumes-and-file-system-permissions-772c1aee23ca

                                                        Что касается composer install, то это отдельная головная боль. Для установки зависимостей приходится запускать отдельный контейнер из-под root, в который пробрасывается приватный ключ.

                                                        #!/usr/bin/env bash
                                                        source .env
                                                        IMAGE=composer
                                                        docker run --rm --interactive --tty \
                                                            --volume $PWD/app:/usr/src/app \
                                                            --workdir /usr/src/app \
                                                            --env COMPOSER_ALLOW_SUPERUSER=1 \
                                                            --entrypoint '/bin/bash' \
                                                            ${IMAGE} \
                                                             -c "mkdir -p /root/.ssh && chmod 0700 /root/.ssh && \
                                                            cp /usr/src/app/deploy_key /root/.ssh/id_rsa && chmod 600 /root/.ssh/id_rsa && \
                                                            composer $@ &&
                                                            chown -R www-data:www-data vendor composer.json composer.lock"

                                                        Можно было бы пробросить SSH_AUTH_SOCK, но есть ещё Windows/Mac.
                                                          0
                                                          В последнее время использую следующий подход. В контейнер с композером копируется два файла composer.json composer.lock при необходимости можно добавлять приватный ключ в контейнер и запускается инстал, без проверки зависимостей. Затем в основной образ бекенда копируется все то что собрал композер. Копирование выполняется с использованием параметра chown: COPY [--chown=:]. И далее в основном образе выполняется композер дамп и пост-скрипты. Если изменений в composer.json composer.lock не было, то при сборке используется кеш, что значительно ускоряет процесс.
                                                            0

                                                            Приватный ключ в уже поднятый контейнер копируется или в его образ?

                                                              0
                                                              в dockerfile на этапе сборки
                                                                0

                                                                Безопасней чем в целевой образ копировать, но как по мне не сильно безопасней, если речь не идёт о публичных образах.

                                                        0
                                                        можно сделать chown директории, на которую mapping volume.
                                                          0
                                                          Можно, но здесь тоже есть подводные камни: если chown засунуть, к примеру, в entrypoint, то контейнер с крупным приложением на Symfony может стартовать этак минут 5

                                                          github.com/docker/for-linux/issues/388
                                                        0
                                                        Не, такими темпами, в час по чайной ложке, народ как раз к завершению поддержки всея докера и научится им пользоваться… Вы бы лучше во вводной статье показали зачем это надо (можно не просто поставить сервисы на комп, но поставить сервисы единообразно — уж если у вас есть докер, то одни и те же образы заработают и под виндой и под макосью и под линуксом; что удалить их потом можно одной командой; что можно запустить 3 разных версии сайта в разных папках и просто на разных портах они будут висеть; что удобно переносить между компами разработчиков один и тот же метод запуска, который 1в1 будет и на проде так же работать; что удобно экономить диск, если надо запустить 15 «виртуалок», отличающихся чуть чуть в паре конфигов. Ну и ссылки на хорошие статьи по теме сразу выдайте… куда полезнее, чем переписывать сейчас тут учебник черепашьими темпами.
                                                          0
                                                          Я постараюсь разогнаться) А за мысли спасибо, но как-то они воспринимались само-собой разумеющимися.
                                                            0

                                                            В разных папках это мелочи. Вот из одной папки запустить разные ветки на одном порту с разными доменами очень удобно

                                                            0
                                                            Мои комплименты автору. Все хотел разобраться с Docker'ом, но не находил статьи под свой уровень

                                                            Only users with full accounts can post comments. Log in, please.