РАЙТ ДЖОЙНt

Тестовое задание на php-devOps разработчика. Решение по шагам

ЗАКАЗ

Стек: php, mySql, docker, ubuntu, openssh сервер. Сборка dockerfile, нормализация базы данных, небольшой php-скрипт и отчет

Опубликовано:2025-04-10
Тэги:Базы данныхphpdocker

1. Анализ постановки

Задание мне было выдано в виде ms-word документа и при беглом просмотре показалось довольно обычным, 100% что оно не может нести коммерчекую выгоду тому кто его выдал и не очень большое по объему. Попробуем вникнуть в детали, что именно требуется.

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

В моем случае обратная связь по вопросам поддреживалась через hr, которая обычно отвечала в течении дня. В данном задании было непонятно что следует понимать под суммой, а что под количеством книг (строка 17), так же непонятно было что такое mc чтоб включить его в образ (строка 8).

На уточняющие вопросы я получил следующие ответы:

  1. сумму книг выводить не надо, только к-во
  2. внутри категории не может быть другой категории
  3. mc - это midnight commander

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

2. Сборка образа в docker-контейнере

Мне не часто приходилось выполнять сборки на Ubuntu, в пояснениях было указано что за основу можно взять образ mrxder/docker-apache-php7.2-mysql-phpmyadmin. Так и сделаем.

Клонируем репозиторий. Пока Dockerfile оставим без изменений, просто проверим как все работает. Попробуем собрать образ в docker, выполним следующие команды из каталога с Dockerfile. (bookshop-test-1 - имя image, bookshop-c-test-1 - имя контейнера)

  • docker build . -t bookshop-test-1
  • docker run -d -p 8080:80 -p 3306:3306 --name bookshop-c-test-1 bookshop-test-1

По идее, после этих действий мы должны увидеть страницу входа в phpMyAdmin по адресу localhost:8080/phpmyadmin, но что-то пошло не так, попробуем разобраться.

Обратим внимание что контейнер не запущен. Посмотрим логи, они ведут к файлу rc.local, посмотрим что в нем написано: этот файл стартует mysql и apache2.

Пока закомментим эти строки в Dockerfile и проверим что выйдет. Снова соберем имадже и запустим контейнер. В этот раз он остался запущенным, но phpmyadmin по прежнему недоступно. Попробуем запустить mysql и apache2 вручную.

  • /etc/init.d/mysql start
  • /etc/init.d/apache2 start

При ручном запуске серверов страница localhost:8080/phpmyadmin открывается браузером, можно зайти в phpmyadmin с теми логин и пароль что даны в описании к репозиторию. Пока оставим решение проблемы с автостартом серверов на потом. Продолжим выполнение задания...но помним что пока сервер после остановки контейнера придется запускать вручную. Для п.2.1 и 2.2 web все равно пока не потребуется.

2.1 Устанавливаем midnight commander

Чисто для теста я сначала устанавливал его в запущенном контейнере из командной строки, проверил, а после добавил ту же команду в Dockerfile, снова собрал image и запустил контейнер.

  • apt-get install mc -y

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

2.2 Устанавливаем openssh - сервер

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

  • RUN useradd -ms /bin/bash newuser

Снова пересобираем имадже, проверяем, незабыв добавить 2222-й порт в команду при запуске контейнера.

  • docker build . -t bookshop-test-1
  • docker run -d -p 8080:80 -p 3306:3306 -p 2222:22 --name bookshop-c-test-1 bookshop-test-1

Пытаемся подключиться с помощью putty с логин admin и пароль trust. Збс, работает!

Вспоминаем что в задании написано, хост должен быть доступен по адресу bookshop.loc Так как я использую linux docker engine на windows, настроим хост

Для этого откроем файл

  • C:\Windows\System32\drivers\etc\hosts

Добавим в него строчку

  • 127.0.0.1 bookshop.loc

Запустим контейнер, указав при этом название хоста, проверим доступность по ssh. Получилось!

  • docker run -d -p 8080:80 -p 3306:3306 -p 2222:22 -h bookshop.loc --name bookshop-c-test-1 bookshop-test-1

2.3 Настраиваем virtual host apache

В репозитории уже была заготовка, 000-default.conf для конфигурации apache и виртуальных хостов, ей я и воспользуюсь. Это ясно, что виртуальных хостов может быть несколько. Поправим 000-default.conf, поменяем настройку DocumentRoot на /var/www/html/bookshop.loc и добавим в него настройку

  • ServerName bookshop.loc

А в Dockerfile закоментим строчку и убрав лишние знаки, это нам уже не нужно.

  • echo "ServerName localhost" >> /etc/apache2/apache2.conf

Скопируем папку проекта, дописав команду в Dockerfile, без нее при старте apache выдаст ошибку.

  • COPY /src /var/www/html/bookshop.loc

Снова собираем сборку и запускаем контейнер, из контейнера в ручном режиме запускаем mysql и apache, проверяем доступность в браузере по адресу http://bookshop.loc:8080/phpmyadmin/ Отлично, все работает, значит осталась последняя часть задания.

3. php скрипты и нормализация базы данных

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

3-1. Таблицы и связи в базе данных

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

  1. books - таблица с книгами, связь с таблицей категории (много к одному)
  2. authors - таблица с авторами
  3. categories - таблица с категориями
  4. bookstoauthors - таблица, связанная с книгами (много к одному) и с авторами (много к одному)

Сейчас очень часто на собесах спрашивают про внешние ключи, используем их для автоматического удаления строк из таблицы bookstoauthors при удалении строки из authors или books, а также для установки поля books.bookCategory_id в NULL при удалении записи из таблицы categories, для этого создадим таблицы ENGINE=InnoDB

3-2. php-скрипты

С точки зрения php-кода проект довольно простой, в нем не будет наследования, интерфесов и прочих штук. Однако оформим весь код классами, для разнообразия сделаем публичные и приватные методы, некоторые методы сделаем статическими.

По итогу у нас будут следующие скриты:

  • Классы
    1. Db.php (класс) extends PDO - для подключения и БД, чтоб не дублировать код в скрипте установки и в отчете
    2. BookShopInstall.php (класс) - создание БД, таблиц и заполнения тестовыми данными
    3. Report.php (класс) - отчет, один метод реализует логику, а второй представление
  • Файлы, буквально 3-5 строчек, в них влючаются классы и вызываются их методы
    1. install.php - для загрузки тестовых данных
    2. index.php - для отчета
  • js-файлы
    1. googleapis.js - это jQuery
    2. report.js - это для разворачивания списка

Собираем имадже, запускаем контейнер

  • docker build . -t bookshop-test
  • docker run -d -p 8080:80 -p 3306:3306 -p 2222:22 -h bookshop.loc --name bookshop-c-test bookshop-test

Вручную в контейнере запускаем mysql и apache

  • /etc/init.d/mysql start
  • /etc/init.d/apache2 start

Проверяем http://bookshop.loc:8080/install.php и отчет http://bookshop.loc:8080

Похоже, на этом задание выполнено

4. Дополнительные шаги

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

4.1 Подключаем второй репозиторий к проекту

Я создал на своем аккаунте голый репозиторий https://github.com/rightJoint/test-bookshop в который буду отправлять изменения. Может мне придется публиковать эту статью, но давать в ней ссылку на архив как-то не очень, куда лучше ссылку на репозиторий. Подключим репозиторий и сделаем push.

  • git remote add test-bookshop https://github.com/rightJoint/test-bookshop
  • git push test-bookshop bookshop

Кроме ноута у меня есть ещё micro-pc, подключенный к по hdmi к телеку. На нем и проверим.

4.2 Рефакторинг Dockerfile

Можно удалить лишние команды из Dokerfile и лишние файлы из проекта, которые для него сейчас уже не нужны.

4.3 Решить проблему с автозапуском

Конечно меня напрягает запускать сервера вручную. Пока я не нашел способа сделать это, гугл выводил меня на следующие ресурсы по этому запросуforums.docker.com и stackoverflow.com,но предложенные там решения мне не помогли.

Комментарии

1
пред.1след.
Right Joint

На этот раз интуиция подвела меня, hr просто перестала выходить на связь. Ох как я устал уже от этого (((

2025-04-10 20:30:22
Вход по логин и парольok-кнопкаvk-кнопка - Зарегистрируйтесь чтобы писать комменты
Написать новый коммент