Среда разработки PHP на базе Docker

    Решение, которое позволит создать на локальном компьютере универсальную среду разработки на PHP за 30 — 40 минут.

    Почему Docker?

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

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

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

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

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

    Требования

    • Git.

    • Docker engine 19.x и выше.

    Возможности и особенности среды разработки 

    • Несколько версий PHP — 7.3 и 7.1 с набором наиболее востребованных расширений.

    • Возможность использовать для web-проектов разные версии PHP.

    • Готовый к работе монитор процессов Supervisor.

    • Предварительно сконфигурированный веб-сервер Nginx.

    • Базы данных: MySQL 5.7MySQL 8PostgreSQL (latest), MongoDB 4.2Redis (latest).

    • Настройка основных параметров окружения через файл .env.

    • Возможность модификации сервисов через docker-compose.yml.

    • Последняя версия docker-compose.yml.

    • Все docker-контейнеры базируются на официальных образах.

    • Структурированный Dockerfile для создания образов PHP.

    • Каталоги большинства docker-контейнеров, в которых хранятся пользовательские данные и параметры конфигурации смонтированы на локальную машину.

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

    Репозиторий проекта

    https://github.com/drandin/docker-php-workspace

    Структура проекта 

    Рассмотрим структуру проекта.

    ├── .env-example
    ├── .gitignore
    ├── .ssh
    ├── README.md
    ├── docker-compose.yml
    ├── mongo
    ├── mysql-5.7
    ├── mysql-8
    ├── nginx
    ├── php-ini
    ├── php-workers
    ├── php-workspace
    ├── postgres
    ├── projects
    └── redis

    Примечание

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

    .gitkeep — является заполнением каталога, это фиктивный файл, на который не следует обращать внимание.

    .env-example 

    Пример файла с основными настройками среды разработки.

    # Временная зона
    WORKSPACE_TIMEZONE='Europe/Moscow'
    
    # XDEBUG
    DOCKER_PHP_ENABLE_XDEBUG='on'
    
    # Настройки Nginx
    # Порт, который следует использовать
    # для соединения с локального компьютера
    NGINX_PORT=80
    
    # Настройки Redis
    # Порт, который следует использовать
    # для соединения с локального компьютера
    REDIS_PORT=6379
    # Настройки Postgres
    POSTGRES_DB=test
    POSTGRES_USER=pg_user
    POSTGRES_PASSWORD=secret
    POSTGRES_PORT=54322
    
    # Настройки общие для MySQL 8.x и MySQL 5.7.x
    MYSQL_ROOT_PASSWORD=secret
    MYSQL_DATABASE=test
    
    # Настройки MySQL 8.x
    # Порт, который следует использовать
    # для соединения с локального компьютера
    MYSQL_8_PORT=4308
    
    # Настройки MySQL 5.7.x
    # Порт, который следует использовать
    # для соединения с локального компьютера
    MYSQL_5_7_PORT=4307
    
    # Настройки MongoDB
    # Порт, который следует использовать
    # для соединения с локального компьютера
    MONGO_PORT=27017
    
    # Настройки PHP 7.3
    # Внешний порт, доступен с локального компьютера
    PHP_7_3_PORT=9003
    
    # Настройки PHP 7.1
    # Внешний порт, доступен с локального компьютера
    PHP_7_1_PORT=9001

    .gitignore

    Каталоги и файлы, в которых хранятся пользовательские данные, код ваших проектов и ssh-ключи внесены в. gitignore.

    .ssh 

    Этот каталог предназначен для хранения ssh-ключей.

    readme.md 

    Документация.

    docker-compose.yml 

    Документ в формате YML, в котором определены правила создания и запуска многоконтейнерных приложений Docker. В этом файле описана структура среды разработки и некоторые параметры необходимые для корректной работы web-приложений.

    mongo 

    Каталог базы данных MongoDB.

    ├── configdb
    │   └── mongo.conf
    ├── db
    └── dump

    mongo.conf — Файл конфигурации MongoDB. В этот файл можно добавлять параметры, которые при перезапуске MongoDB будут применены.

    db — эта папка предназначена для хранения пользовательских данных MongoDB.

    dump — каталог для хранения дампов.

    mysql-5.7 

    Каталог базы данных MySQL 5.7.

    ├── conf.d
    │   └── config-file.cnf
    ├── data
    ├── dump
    └── logs

    config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 5.7 будут применены.

    data — эта папка предназначена для хранения пользовательских данных MySQL 5.7.

    dump — каталог для хранения дампов.

    logs — каталог для хранения логов.

    mysql-8 

    Каталог базы данных MySQL 8.

    ├── conf.d
    │   └── config-file.cnf
    ├── data
    ├── dump
    └── logs

    config-file.cnf — файл конфигурации. В этот файл можно добавлять параметры, которые при перезапуске MySQL 8 будут применены.

    data — эта папка предназначена для хранения пользовательских данных MySQL 8.

    dump — каталог для хранения дампов.

    logs — каталог для хранения логов.

    nginx 

    Эта папка предназначена для хранения файлов конфигурации Nginx и логов.

    ├── conf.d
    │   ├── default.conf
    │   └── vhost.conf
    └── logs

    default.conf — файл конфигурации, который будет применён ко всем виртуальным хостам.

    vhost.conf — здесь хранятся настройки виртуальных хостов web-проектов.

    Рассмотрим vhost.conf подробнее:

    server {
        listen 80;
        index index.php index.html;
        server_name project-1.localhost;
        error_log /var/log/nginx/project-1.error.log;
        access_log /var/log/nginx/project-1.access.log combined if=$loggable;
        root /var/www/project-1.ru;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php-7.3:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_script_name;
        }
    }
    
    server {
        listen 80;
        index index.php index.html;
        server_name project-2.localhost;
        error_log /var/log/nginx/project-2.error.log;
        access_log /var/log/nginx/project-2.access.log combined if=$loggable;
        root /var/www/project-2.ru;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass php-7.1:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_script_name;
        }
    }

    В файле конфигурации описаны настройки для двух web-проектов — project-1.localhost и project-2.localhost.

    Здесь следует обратить внимание на то, как производится перенаправление запросов к нужному docker-контейнеру.

    Например, для проекта project-1.localhost указано:

    fastcgi_pass php-7.3:9000;

    php-7.3 — название docker-контейнера, а 9000 — порт внутренней сети. Контейнеры между собой связаны через внутреннюю сеть, которая определена в файле docker-compose.yml.

    php-ini 

    В этом каталоге находятся файлы конфигурации PHP.

    ├── 7.1
    │   └── php.ini
    └── 7.3
        └── php.ini

    Для каждой версии PHP — свой файл конфигурации.

    php-workers 

    Место для хранения файлов конфигурации Supervisor.

    ├── 7.1
    │   └── supervisor.d
    │       
    └── 7.3
        └── supervisor.d

    Для каждой версии PHP — могут быть добавлены свои файлы с настройками.

    php-workspace 

    Здесь хранится файл, в котором описаны действия, выполняемые при создании образов docker-контейнеров PHP.

    └── Dockerfile

    Dockerfile — это текстовый документ, содержащий все команды, которые следует выполнить для сборки образов PHP.

    postgres

    Каталог для системы управления базами данных PostgreSQL.

    ├── .gitkeep
    ├── data
    └── dump

    data — эта папка предназначена для хранения пользовательских данных PostgreSQL.

    dump — каталог для хранения дампов.

    projects 

    Каталог предназначен для хранения web-проектов.

    Вы можете создать в это каталоге папки, и поместить в них ваши web-проекты.

    Например:

    project-1.ru
    project-2.ru 
    ...

    Содержимое каталога projects доступно из контейнеров php-7.1 и php-7.3.

    Если зайти в контейнер php-7.1 или php-7.3, то в каталоге /var/www будут доступны проекты, которые расположены в projects на локальной машине.

    redis 

    Каталог key-value хранилища Redis.

    ├── conf
    └── data

    conf — папка для хранения специфических параметров конфигурации.

    data — если настройки конфигурации предполагают сохранения данных на диске, то Redis будет использовать именно этот каталог.

    Программы в docker-контейнерах PHP 

    Полный перечень приложений, которые установлены в контейнерах php-7.xможно посмотреть в php-workspace/Dockerfile.

    Здесь перечислим лишь некоторые, наиболее важные:

    • bash

    • htop

    • curl

    • Git

    • Сomposer

    • make

    • wget

    • NodeJS

    • Supervisor

    • npm

    Начало работы 

    1. Выполните клонирование данного репозитория в любое место на вашем компьютере.

    git clone https://github.com/drandin/docker-php-workspa

    Перейдите в директорию, в которую вы клонировали репозиторий. Все дальнейшие команды следует выполнять именно в этой директории.

    2. Скопируйте файл .env-example в .env

    cp .env-example .env

    Если это необходимо, то внесите изменения в файл .env. Измените настройки среды разработки в соответствии с вашими требованиями.

    3. Выполните клонирование web-проектов в каталог projects.

    Для примера, далее мы будем исходить из предположения, что у вас есть 2 проекта:

    project-1.ru
    project-2.ru

    project-1.ru — будет работать на версии PHP 7.3, а project-2.ru — на PHP 7.1.

    4. Отредактируйте настройки виртуальных хостов Nginx.

    Файл конфигурации виртуальных хостов находится в каталоге ./nginx/conf.d/.

    5. Настройте хосты (доменные имена) web-проектов на локальной машине.

    Необходимо добавить названия хостов web-проектов в файл hosts на вашем компьютере.

    В файле hosts следует описать связь доменных имён ваших web-проектов в среде разработки на локальном компьютере и IP docker-контейнера Nginx.

    На Mac и Linux этот файл расположен в /etc/hosts. На Windows он находится в C:\Windows\System32\drivers\etc\hosts.

    Строки, которые вы добавляете в этот файл, будут выглядеть так:

    127.0.0.1   project-1.localhost
    127.0.0.1   project-2.localhost

    В данном случае, мы исходим из того, что Nginx, запущенный в docker-контейнере, доступен по адресу 127.0.0.1 и web-сервер слушает порт 80.

    Не рекомендуем использовать имя хоста с .dev на конце в среде разработки. Лучшей практикой является применение других названий — .localhost или .test.

    6[опционально, если это необходимо] Настройте маршрутизацию внутри контейнеров web-проектов.

    Web-проекты должны иметь возможность отправлять http-запросы друг другу и использовать для этого название хостов.

    Из одного запущенного docker-контейнера php-7.1 web-приложение № X должно иметь возможность отправить запрос к другому web-приложению № Y, которое работает внутри docker-контейнера php-7.3. При этом адресом запроса может быть название хоста, которое указано в файле /etc/hosts локального компьютера.

    Чтобы это стало возможным нужно внутри контейнеров так же внести соответствующие записи в файл /etc/hosts.

    Самый простой способ решить данную задачу — добавить секцию extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.

    Пример:

    ...  
      php-7.1:  
      ...
        extra_hosts:
          - 'project-1.localhost:IP_HOST_MACHINE'
          - 'project-2.localhost:IP_HOST_MACHINE'
      ...

    IP_HOST_machine — IP адрес, по которому из docker-контейнера доступен ваш локальный компьютер.

    Если вы разворачиваете среду разработки на Mac, то внутри docker-контейнера вам доступен хост docker.for.mac.localhost.

    Узнать IP адрес вашего Mac можно при помощи команды, который нужно выполнить на локальной машине:

    docker run -it alpine ping docker.for.mac.localhost

    В результате вы получите, что-то подобное:

    PING docker.for.mac.localhost (192.168.65.2): 56 data bytes
    64 bytes from 192.168.65.2: seq=0 ttl=37 time=0.286 ms
    64 bytes from 192.168.65.2: seq=1 ttl=37 time=0.504 ms
    64 bytes from 192.168.65.2: seq=2 ttl=37 time=0.801 ms

    После того, как вам станет известен IP-адрес, укажите его в секции extra_hostsв описание сервисов php-7.1 и php-7.3 в docker-compose.yml.

    ...  
      php-7.1:  
      ...
        extra_hosts:
          - 'project-1.localhost:192.168.65.2'
          - 'project-2.localhost:192.168.65.2'
      ...

    8. Настройте параметры соединения с системами хранения данных.

    Хосты и порты сервисов

    Для того, чтобы настроить соединения с базами данных из docker-контейнеров php-7.1 и php-7.3 следует использовать следующие названия хостов и порты:

    Сервис

    Название хоста

    Порт

    MySQL 5.7

    mysql-5.7

    3308

    MySQL 8

    mysql-8

    3308

    PostgreSQL

    postgres

    5432

    MongoDB

    mongo

    27017

    Redis

    redis

    6379

    Именно эти параметры следует использовать для конфигурации web-проектов.

    Для соединения с базами данных с локальной машины:

    • Хост для всех баз данных — 127.0.0.1.

    • Порты — значения указанные в .env.

    7. Создайте контейнеры и запустите их.

    Выполните команду:

    docker-compose build && docker-compose up -d

    Создание контейнеров займёт некоторое время. Обычно от 10 до 30 минут. Дождитесь окончания процесса. Ваш компьютер не должен потерять доступ в интернет.

    Если вы всё сделали правильно, то контейнеры будут созданы и запущены. 

    Откройте Docker Dashboard и убедитесь в этом:

    8. Создайте SSH-ключи.

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

    Создать SSH-ключи можно при помощи следующей команды:

    ssh-keygen -f ./.ssh/id_rsa -t rsa -b 2048 -C "your-name@example.com"

    Вместо your-name@example.com укажите свой Email.

    В папку .ssh/ будут сохранены 2 файла — публичный и приватный ключ.

    9. Проверьте созданные docker-контейнеры.

    Выполните команду:

    docker ps

    Если создание контейнеров прошло успешно, то вы увидите примерно такой результат:

    CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                               NAMES
    8d348959c475        docker-php-workspace_php-7.1   "docker-php-entrypoi…"   6 minuts ago        Up 54 seconds       0.0.0.0:9001->9000/tcp              php-7.1
    a93399727ff6        docker-php-workspace_php-7.3   "docker-php-entrypoi…"   6 minuts ago        Up 53 seconds       0.0.0.0:9003->9000/tcp              php-7.3
    5cd80ac95388        nginx:stable-alpine            "/docker-entrypoint.…"   6 minuts ago        Up 51 seconds       0.0.0.0:80->80/tcp                  nginx
    70182bc9e44c        mysql:5.7                      "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       33060/tcp, 0.0.0.0:4307->3306/tcp   mysql-5.7
    46f2766ec0b9        mysql:8.0.21                   "docker-entrypoint.s…"   6 minuts ago        Up 53 seconds       33060/tcp, 0.0.0.0:4308->3306/tcp   mysql-8
    a59e7f4b3c61        mongo:4.2                      "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       0.0.0.0:27017->27017/tcp            mongo
    eae8d62ac66e        postgres:alpine                "docker-entrypoint.s…"   6 minuts ago        Up 53 seconds       0.0.0.0:54322->5432/tcp             postgres
    bba24e86778a        redis:latest                   "docker-entrypoint.s…"   6 minuts ago        Up 54 seconds       0.0.0.0:6379->6379/tcp              redis
    

    10. Установка зависимостей для web-приложений.

    Если для работы web-приложений необходимо установить зависимости, например через менеджер пакетов Composer или NPM, то сейчас самое время сделать это.

    В контейнерах php-7.1 и php-7.3 уже установлен и Composer и NPM.

    Войдите в контейнер php-7.1:

    docker exec -it php-7.1 bash

    или php-7.3:

    docker exec -it php-7.3 bash

    Перейдите в рабочий каталог необходимого web-проекта и выполните требуемые действия.

    Например, установите зависимости через Composer при помощи команды:

    composer install

    Вопросы и ответы 

    Несколько важных вопросов и ответов.

    Как зайти в работающий docker-контейнер? 

    Выполните команду:

    docker exec -it container_name bash

    container_name — имя контейнера.

    Как останавливать и удалить контейнеры и другие ресурсы среды разработки, которые были созданы? 

    docker-compose down

    Как получить список всех контейнеров? 

    docker ps -a

    Как получить подробную информацию о docker-контейнере? 

    docker inspect containername

    containername — имя контейнера.

    Как получить полный список расширений PHP, которые установлены в контейнере php-7.3? 

    Если контейнер php-7.3 запущен, то выполните команду:

    docker exec -it php-7.3 php -m

    Как удалить все контейнеры? 

    Удаление всех контейнеров:

    docker rm -v $(docker ps -aq)

    Удаление всех активных контейнеров:

    docker rm -v $(docker ps -q)

    Удаление всех неактивных контейнеров:

    docker rm -v $(docker ps -aq -f status=exited)

    Развёртывание дампов MySQL, PostgreSQL и MongoDB

    Если для работы web-проектов требуются перенести данные в хранилища, то следуйте описанным ниже инструкциям.

    Как развернуть дамп PostgreSQL? 

    Выполните следующую команду на локальной машине:

    docker exec -i postgres psql --username user_name database_name < /path/to/dump/pgsql-backup.sql

    Или зайдите в контейнер postgres и выполните:

    psql --username user_name database_name < /path/to/dump/pgsql-backup.sql

    user_name — имя пользователя. Значение postgres_USER (см. файл .env).

    database_name — название базы данных. Значение postgres_DB (см. файл .env).

    Как развернуть дамп MySQL? 

    Существует два варианта.

    Вариант 1

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

    В файле mysql/conf.d/config-file.cnf отключите лог медленных запросов slow_query_log=0 или установите большое значение long_query_time, например 1000.

    Если дамп сжат утилитой gzip, сначала следует распаковать архив:

    gunzip databases-dump.sql.gz

    Затем можно развернуть дамп, выполнив на локальном компьютере команду:

    docker exec -i mysql mysql --user=root --password=secret --force < databases-dump.sql

    Указывать пароль в командной строке — плохая практика, не делайте так в производственной среде.

    MySQL выдаст справедливое предупреждение:

    mysql: [Warning] Using a password on the command line interface can be insecure

    Ключ --force говорит MySQL, что ошибки следует проигнорировать и продолжить развёртывание дампа. Этот ключ иногда может пригодится, но лучше его без необходимости не применять.

    Вариант 2

    Воспользоваться утилитой Percona XtraBackup.

    Percona XtraBackup — это утилита для горячего резервного копирования баз данных MySQL.

    О том, как работать с XtraBackup можно узнать по ссылке: https://medium.com/@drandin/создание-резервной-копии-mysql-при-помощи-утилиты-xtrabackup-26bd3f843075

    Как развернуть дамп MongoDB? 

    • Скопируйте фалы дампа в каталог mongo/dump.

    • Войдите в контейнер mongo:

    docker exec -it mongo sh

    Выполните следующую команду, чтобы развернуть дамп базы database_name:

    mongorestore -d database_name /dump/databases/database_nam

    Git-репозиторий проекта: https://github.com/drandin/docker-php-workspace

    Средняя зарплата в IT

    111 111 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 6 788 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 38

      +1
      Отличный инструмент. Минимализм и функциональность.
      Из похожего — давно использую devilbox.readthedocs.io/en/latest
        0

        А зачем Вам нужен Supervisor в докер контейнере?

          0
          Например, для работы с queues в Laravel.
            0
            Можно же просто запускать докер-контейнер с командой очереди?
              +7

              Использования Supervisor да и в целом других дополнительных процессов внутри основного приложения это не "docker-way". К примеру для обработки очередей я бы предложил такую схему в Вашем случае:


              1. Создать дополнительный entrypoint entrypoint-queue.sh


                #!/usr/bin/env bash
                
                trap "echo 'Shutting down'; kill \$!; exit" SIGINT SIGTERM
                
                echo "Start the queue..."
                php /var/www/project/artisan queue:work 

              2. В docker-compose.yml создать сервис обработки очередей на основе главного сервиса:


                # main application example
                &app-service app: &app-service-template
                 image: some-image
                 hostname: *app-service
                 volumes:
                   - ..:..
                 restart: always
                
                # queue service
                &queue-service queue:
                 <<: *app-service-template
                 entrypoint: /scripts/entrypoint_queue.sh
                 hostname: *queue-service
                 restart: always
                 ports: []


              Готово. Супервайзер не нужен.
              Похожим способом решается задача планирования (аля cron)

                0
                В документации докера есть даже пример по запуску супервизора: docs.docker.com/config/containers/multi-service_container
                Какие тут могут быть подводные камни?
                Просто если представить ситуацию, что есть условно 5 очередей, на каждую хочется 3 воркера запустить, это тогда нужно 15 контейнеров поднять?
                  +1
                  в приведенном скрипте, если появляется временно-постоянная проблема (например отвалился какой-нибудь сервис или очередь), то один из процессов будет постоянно умирать, а с ним — и весь супервизор (читай все остальные процессы в нем принудительно перезапускаются). Либо надо придумывать какие-то свои политики для перезапуска, либо следить за проблемами вручную.

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

                  Просто если представить ситуацию, что есть условно 5 очередей, на каждую хочется 3 воркера запустить, это тогда нужно 15 контейнеров поднять?


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

                    не очень понял, почему весь супервизор умирать будет, умирать будет только косячный процесс
                      0
                      while sleep 60; do
                        ps aux |grep my_first_process |grep -q -v grep
                        PROCESS_1_STATUS=$?
                        ps aux |grep my_second_process |grep -q -v grep
                        PROCESS_2_STATUS=$?
                        # If the greps above find anything, they exit with 0 status
                        # If they are not both 0, then something is wrong
                        if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
                          echo "One of the processes has already exited."
                          exit 1
                        fi
                      done


                      Вот этот кусок проверяет каждую минуту, какой процесс умер и прибивает весь супервизор. Если он не будет так делать, то какой-то процесс умрет и вы не сможете его перезапустить без перезапуска всего супервизора все равно
                        0
                        можно и без этого всего, просто запустить супервизор же
                        Use a process manager like supervisord. This is a moderately heavy-weight approach that requires you to package supervisord and its configuration in your image (or base your image on one that includes supervisord), along with the different applications it manages. Then you start supervisord, which manages your processes for you. Here is an example Dockerfile using this approach, that assumes the pre-written supervisord.conf, my_first_process, and my_second_process files all exist in the same directory as your Dockerfile.

                        FROM ubuntu:latest
                        RUN apt-get update && apt-get install -y supervisor
                        RUN mkdir -p /var/log/supervisor
                        COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
                        COPY my_first_process my_first_process
                        COPY my_second_process my_second_process
                        CMD ["/usr/bin/supervisord"]
                          +1
                          в докере, полагаю, можно запустить все что угодно, вопрос зачем.

                          суть в том что нормальный оркестратор докеров — он сам по себе по сути супервизор — следит за процессами и поддерживает их жизненый цикл. зачем вставлять супервизор в супервизор? какие бонусы он дает, кроме «так привычней»? плюсов без него я могу сразу кучу назвать:
                          * возможность индивидуально масштабировать каждый процесс без необходимости трогать все остальные
                          * возможность задавать индивидуальные ограничения по ресурсам на каждый процесс
                          * самое на мой взгляд главное — возможность размазывать вашу нагрузку по разным нодам

                          По этой же ссылке дословно написано следующее:

                          It’s ok to have multiple processes, but to get the most benefit out of Docker, avoid one container being responsible for multiple aspects of your overall application
                  0
                  А можете пример для CRON привести?
                    0
                    entrypoint_scheduler.sh
                    #!/usr/bin/env bash
                    
                    trap "echo 'Shutting down'; kill \$!; exit" SIGINT SIGTERM
                    
                    SCHEDULE_COMMAND="${@:-echo 'scheduler ticked'}";
                    FIRST_START_DELAY="${FIRST_START_DELAY:-2}";
                    SCHEDULE_PERIOD="${SCHEDULE_PERIOD:-60}";
                    
                    STDOUT="${STDOUT:-/proc/1/fd/1}";
                    STDERR="${STDERR:-/proc/1/fd/2}";
                    
                    echo "[ Info ] Command to execute: \"$SCHEDULE_COMMAND\". Delay between executions: $SCHEDULE_PERIOD";
                    echo '[ Info ] Press [CTRL+C] to stop';
                    
                    sleep "$FIRST_START_DELAY";
                    
                    while :; do
                      # Stop freeze on large delay
                      for (( i=1; i<=$SCHEDULE_PERIOD; i+=1)); do
                        sleep 1;
                      done;
                    
                      # Execute command
                      ${SCHEDULE_COMMAND} > ${STDOUT} 2> ${STDERR};
                    done;

                    docker-compose.yml
                    &scheduler-service scheduler:
                      <<: *app-service-template
                      entrypoint: /scripts/entrypoint_scheduler.sh
                      command: /path/to/app/artisan schedule:run
                      hostname: *scheduler-service
                      ports: []
                    
              +2

              Отличная работа! Перед создаем не смотрели в Laradock (самый удобный, на мой взляд, способ работы с php в Docker. Для разработки)? Какие преимущества вашего контейнера?

                0
                Laradock — интересный проект, разработчики, которые его поддерживают достойны уважения. Я внимательно его изучал. Но Laradock содержит в себе намного больше сервисов, чем может потребоваться. Там есть почти всё. И из-за этого он становиться чем-то похожим на Homestead, 90% того что там есть, скорее всего не пригодится. Моя цель заключалась в том, чтобы создать лёгкую среду, которую можно быстро модифицировать.
                  +1
                  Ларадок содержит возможность развернуть множество сервисов. Их вовсе не обязательно все разворачивать. Скачиваются и запускаются только нужные контейнеры. При необходимости расширяется своими контейнерами в лёт. Например, я недавно настраивал окружение в докер контейнерах для разработчиков — склонировал ларадок, прокинул внутрь нужные конфиги, добавил два контейнера которых не было в комплекте, и в результате у меня есть репозиторий с sh скриптом, который по одной команде разворачивает: nginx, mariadb, php, redis, clickhouse, couchbase, клонирует кодовую базу, прокидывает альясы в hosts, поднимает контейнеры, накатывает миграции и дамп базы. На всё минут 15 — запустить скрипт, пойти попить кофе, вернуться, и можно работать.

                  Ларадок очень хорошо использовать именно в качестве базы для своей сборки. Если вам мозолят глаза лишние папки\разделы в docker-compose — можно их выпилить. По опыту(раньше у меня был самописный комплект контейнеров) скажу, что там из коробки предусмотрено многое, и чтобы потом не допиливать напильником своё решение, лучше взять готовое.

                  З.Ы. Хотя документация у ларадока так себе.
                    0

                    +1
                    Читал статью и не мог понять почему не Ларадок
                    Автор не разобрался с Ларадоком и сделал свой аналог.

                +5

                Как по мне докер все же лучше для каждого проекта свой, а не одна свалка для всех проектов

                  0

                  Не сравнивали скорость mysql в докере и на голом железе? Я не могу понять или собрано для докера с какими то параметрами или что, но все докеровские образы просадку в бд дают около 30-40%, и это не сеть и не разрешение имен. Когда у приложения свои обработки тяжелые то можно не заметить, а когда пхп код очень быстрый то слабым звеном бд становится.

                    0

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


                    P.S. Не раз были проблемы с MySQL при запуске разных контейнеров с разными версиями Docker.

                    0
                    Если я правильно помню, то Docker по умолчанию пробрасывает порты на все доступные сетевые интерфейсы. Таким образом:

                    nginx:
                    image: nginx:stable-alpine
                    container_name: nginx
                    ports:
                    - "${NGINX_PORT}:80"


                    выставит в локалку 80 порт (и ваше веб-приложение) на общий доступ, и в случае использования Linux в качестве хоста, радостно пропишет все в iptables так, чтобы порт действительно открылся в локалку, даже если у вас стоит что-то в духе «deny all incoming from all». Для меня это в свое время стало весьма неприятным открытием.
                      0
                      с докером есть много сюрпризов — он сложнее и разнообразней чем хочет казаться: )

                      для проблемы описанной вами есть решение для docker-compose.yml:
                      services:
                      your_service:
                      ports:
                      - ${NETWORK_INTERFACE:-127.0.0.1}:${YOUR_SERVICE_PORT:-8000}:80

                      .env может содержать
                      NETWORK_INTERFACE=0.0.0.0
                      или
                      NETWORK_INTERFACE=127.0.0.1
                        0
                        Класс, спасибо — не знал про такое. Не могу найти это в документации (искал вот тут и вокруг)… не подскажете, начиная с какой версии Docker Compose доступны такие рюшечки?
                          0
                          судя по документации в docker-compose v1 уже было
                          docs.docker.com/compose/compose-file/compose-file-v1/#ports
                            0
                            Чьорт, надо же. Полезно, но не меняет того факта, что большинство забивает на привязку к IP и выставляет порты наружу (сам этим болел когда-то по незнанию). Есть также вариант вписать «ip»: «127.0.0.1» в /etc/docker/daemon.json, и тогда все контейнеры будут по дефолту только на локалхосте — КМК так надёжнее.
                              0
                              у меня была задача делать докер композ чтоб разработчики могли стартовать работу на проекте с нулевой ручной настройкой. внешний доступ к сервисам был даже удобен для совместной работы, но корпоративный сканер безопасности постоянно шлёт дурацкие запросы так что пришлось по умолчанию доступ ограничивать.
                      0

                      Делал в свое время видео на эту тему — https://youtu.be/QHXiQI7APcE
                      Без очередей, кронов и прочего. Просто чтобы начать писать. Обе базы: mysql и psql

                        0

                        Шикарно!
                        Добавьте ClickHouse.

                          0
                          Интересный проект)

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

                          Возможно вам будет интересно — github.com/rhamdeew/docker-compose-php
                            0
                            Если рабочая машина windows, получиться поднять?
                              0
                              Если pro или выше, то докер там работает относительо хорошо через hyper-v (есть еще экспериментальные с wsl2, но не пробовал). Если хомяк, то привет виртуалбокс и гемор с шаренными папками (оч. тормозные по умолчанию)
                                0
                                wsl2 пользуюсь с момента появления, полёт отличный. Стартует мгновенно, к работе никаких нареканий. Субъективно всё быстрее стало.
                                  0
                                  + в сторону WSL2, экспериментальным он был пока из Insider Preview не вылез (у меня вешал хост по 3 и более раз на дню).

                                  Но с выходом Win10 v2004 уже почти пол года полет нормальный.
                              0

                              У меня вопрос по этим двум командам:
                              docker exec -i postgres psql --username user_name database_name < /path/to/dump/pgsql-backup.sql
                              Или зайдите в контейнер postgres и выполните:


                              psql --username user_name database_name < /path/to/dump/pgsql-backup.sql


                              1. В первом случае чтобы задуть дамп в базу указываем путь к дампу на хост-машине, да?(кстати как это технически происходит, через пайп?)
                              2. А как во втором случае изнутри контейнера виден тот же самый путь? Пробрасывать внутрь папку с дампом не нужно?
                                0
                                В первом случае да, путь на хост машине.
                                Во втором — путь внутри контейнера.
                                0
                                Могу также посоветовать удобный сервис phpdocker.io — конструктор контейнеров
                                  0
                                  А под Windows можно всё это развернуть?
                                    0
                                    могу посоветовать еще один проект оркестратора docker warden.dev

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

                                    Самое читаемое