# Laravel + Docker + Ansible (thin repo) Воспроизводимая инфраструктура: локально — Docker Compose; на сервере Debian 11 — Ansible (Docker, TLS, GitLab Runner); CI/CD — GitLab с self-hosted runner. ## Структура репозитория | Путь | Назначение | |------|------------| | Корень | Исходный код Laravel | | `docker/` | Образ PHP-FPM, Nginx, файл `app.env` (не секреты в примере) | | `docker-compose.yml`, `docker-compose.prod.yml` | Сервисы приложения | | `ansible/` | Плейбуки, роли, переменные | | `.gitlab-ci.yml` | Pipeline деплоя при пуше в основную ветку | Секреты для Ansible храните в `ansible/group_vars/laravel/vault.yml` (рекомендуется `ansible-vault`). Пример без шифрования — `vault.yml.example`. Конфигурация приложения в Docker задаётся **файлами** (`docker/app.env`), а не переменными окружения хоста. Для GitLab CI целевой сервер и путь к проекту задаются **переменными в интерфейсе GitLab** (см. ниже) — это не конфигурация приложения. --- ## Часть 1. Локальный запуск ### Требования - Docker и Docker Compose v2 ### Подготовка 1. Скопируйте пример конфигурации: ```bash cp docker/app.env.example docker/app.env ``` 2. При необходимости отредактируйте `docker/app.env` (URL, пароли MySQL для локальной разработки). ### Запуск ```bash docker compose up -d --build ``` - Приложение: `http://localhost:8080` (порт меняется через `HTTP_PORT` в `docker-compose.yml`, по умолчанию `8080`). - phpMyAdmin: `http://localhost:8080/pma/` — вход пользователем БД `db` и паролем из `docker/app.env` (`MYSQL_PASSWORD`). Первый запуск PHP-контейнера выполнит `composer install` (зависимости в именованном томе `laravel_vendor`), сгенерирует `APP_KEY` при необходимости и применит миграции. Код монтируется с хоста — правки PHP/Blade видны без пересборки образа. ### Полезные команды ```bash docker compose logs -f php docker compose exec php php artisan migrate:status ``` --- ## Часть 2. GitLab CI/CD ### Self-hosted Runner Runner ставится Ansible-ролью `gitlab_runner` (Docker executor, тег `docker`, доступ к `docker.sock`). Регистрация использует токен из **Ansible Vault** (`vault_gitlab_runner_token`). ### Pipeline Файл `.gitlab-ci.yml`: при пуше в **основную ветку** (`CI_DEFAULT_BRANCH`) job `deploy_production` подключается по SSH к серверу и выполняет `git fetch` / `git reset --hard` и `docker compose ... up -d --build`. ### Переменные в GitLab (Settings → CI/CD → Variables) | Переменная | Маскировать | Описание | |------------|-------------|----------| | `CI_DEPLOY_SSH_PRIVATE_KEY` | да | Приватный ключ для пользователя деплоя на сервере | | `DEPLOY_HOST` | нет | Хост или IP сервера | | `DEPLOY_USER` | нет | Обычно `deploy` | | `DEPLOY_PATH` | нет | Каталог клона репозитория на сервере (как в Ansible `project_path`) | На сервере в `authorized_keys` пользователя деплоя должен быть **публичный** ключ, соответствующий этому приватному ключу. Удобно добавить его в Ansible в `deploy_authorized_keys` в `ansible/group_vars/laravel/main.yml`. ### Доступ Git на сервере Для приватного репозитория на сервере нужен доступ к GitLab (Deploy Key или `vault_git_repo_url` с токеном при первом клоне). После клона можно переключить `origin` на SSH и использовать deploy key. --- ## Часть 3. Ansible (Debian 11) ### Подготовка 1. Установите Ansible на управляющей машине (например `pip install ansible` или пакет дистрибутива). 2. Скопируйте инвентарь и vault: ```bash cd ansible cp inventory/hosts.ini.example inventory/hosts.ini cp group_vars/laravel/vault.yml.example group_vars/laravel/vault.yml ``` 3. В `inventory/hosts.ini` укажите `ansible_host` и пользователя SSH (часто `root` для первого захода). 4. В `group_vars/laravel/main.yml` задайте: - `project_domain` — домен для Let's Encrypt и `APP_URL`; - `letsencrypt_email` — почта для ACME; - `git_repo_url_public` — URL публичного репозитория **или** оставьте пустым и задайте приватный URL в vault; - `deploy_authorized_keys` — список SSH-публичных ключей для пользователя `deploy`. 5. Заполните `group_vars/laravel/vault.yml` (минимум токен регистрации Runner и пароли БД, см. комментарии в `vault.yml.example`). Рекомендуется шифрование: ```bash ansible-vault encrypt group_vars/laravel/vault.yml ``` 6. Сгенерируйте `vault_app_key` (например после локального `php artisan key:generate --show`). ### Запуск плейбука Из каталога `ansible`: ```bash ansible-playbook -i inventory/hosts.ini playbooks/site.yml --ask-vault-pass ``` Если vault не шифруется: ```bash ansible-playbook -i inventory/hosts.ini playbooks/site.yml ``` ### Пропуск получения сертификата (нет DNS / тест) ```bash ansible-playbook -i inventory/hosts.ini playbooks/site.yml --ask-vault-pass --skip-tags letsencrypt ``` Тег `letsencrypt` назначен задаче `certbot` в роли `nginx_letsencrypt`. ### Что делает плейбук 1. **common** — пользователь `deploy`, каталог проекта, `authorized_keys`. 2. **docker** — пакеты `docker.io` и `docker-compose-plugin`, группа `docker`. 3. **security** — UFW: 22, 80, 443. 4. **laravel_docker** — клон репозитория, шаблон `docker/app.env`, `docker compose up` (с `docker-compose.prod.yml`: Nginx приложения только на `127.0.0.1:8080`). 5. **nginx_letsencrypt** — системный Nginx как reverse proxy на `127.0.0.1:8080`, Certbot (Let's Encrypt), попытка включить `certbot.timer` (при отсутствии — обычно остаётся cron из пакета). 6. **gitlab_runner** — установка и однократная регистрация runner с тегом `docker`. После успешного выполнения приложение доступно по **HTTPS** на `project_domain`, phpMyAdmin — по `https://<домен>/pma/`. --- ## Переменные: краткая таблица | Где | Что задать | |-----|------------| | `docker/app.env` (локально, из примера) | Параметры Laravel и MySQL для Compose | | `ansible/group_vars/laravel/main.yml` | Домен, email LE, URL репозитория, ключи SSH | | `ansible/group_vars/laravel/vault.yml` | Токен Runner, пароли MySQL, `APP_KEY`, опционально URL приватного Git | | GitLab CI Variables | SSH-ключ, `DEPLOY_HOST`, `DEPLOY_USER`, `DEPLOY_PATH` | --- ## Технические детали - **Очереди:** по умолчанию `QUEUE_CONNECTION=redis`, воркер — сервис `queue` в Compose. - **Миграции:** выполняются entrypoint-скриптом PHP-контейнера при старте. - **Тонкий репозиторий:** `vendor` не в Git — в Docker том `laravel_vendor` и установка через Composer внутри контейнера.