Я обычно всегда обходился без докера и думал, что докер нужен только для больших проектов в больших компаниях. Но однажды я увидел как работает докер в паре с гитлабом у моего товарища и понял, что мне все таки стоит его изучить. Однако, как обычно это бывает, одной подходящей статьи я не нашел — они были либо слишком сложные, либо не полные, либо подразумевали, что вы все знаете само собой. Мне пришлось долго искать различные источники, соединять все это вместе и в итоге у меня получилось сделать простенький проект и CI/CD для него.
Всю работу можно разделить на три части: на локальной машине, на гитлабе и на сервере.
Итак, для реализации проекта нам понадобится аккаунт gitlab и удаленный сервер с виртуализацией KVM или XEN.
Часть 1. Локальная машина
На локальной машине необходимо установить docker.
Для установки на Linux среде необходимо выполнить следующие команды.
Удалить старые контейнеры:
sudo apt-get remove docker docker-engine docker.io containerd runc
Обновить apt:
sudo apt-get update
Установить следующие пакеты, чтобы можно было скачать docker из репозитория по https:
sudo apt-get install
apt-transport-https
ca-certificates
curl
gnupg-agent
software-properties-common
Добавить официальный GPG ключ докера:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Убедится в верности отпечатка:
sudo apt-key fingerprint 0EBFCD88
Ответ:
pub rsa4096 2017-02-22 [SCEA]
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
uid [ unknown] Docker Release (CE deb) <docker@docker.com>
sub rsa4096 2017-02-22 [S]
Скачать стабильную версию:
sudo add-apt-repository
"deb [arch=amd64] https://download.docker.com/linux/ubuntu
$(lsb_release -cs)
stable"
Еще раз обновить apt:
sudo apt-get update
Установить последнюю версию движка докера:
sudo apt-get install docker-ce docker-ce-cli containerd.io
Проверить работу докера:
sudo docker run hello-world
Если все верно — начнется скачивание образа Hello World.
Полная инструкция в официальной документации докер.
Также нам необходимо установить docker-compose. Официальная инструкция находится здесь.
Для его установки выполняем команды в терминале.
Скачивание из репозитория:
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Добавление права исполнения:
sudo chmod +x /usr/local/bin/docker-compose
Проверка версии:
sudo docker-compose --version
Докер мы установили, теперь необходимо собрать образ. Для этого я воспользовался статьей с сайта digitalocean: www.digitalocean.com/community/tutorials/how-to-set-up-laravel-nginx-and-mysql-with-docker-compose-ru. Здесь будет перепечатка этой статьи.
Загрузка Laravel и установка зависимостей
На первом шаге мы загрузим последнюю версию Laravel и установим зависимости проекта, включая Composer, диспетчер пакетов PHP на уровне приложения. Мы установим эти зависимости с помощью Docker, чтобы не выполнять глобальную установку Composer.
Перейдите в домашний каталог и клонируйте последнюю версию Laravel в каталог с именем laravel-app:
cd ~
git clone https://github.com/laravel/laravel.git laravel-app
Перейдите в каталог laravel-app:
cd ~/laravel-app
Затем смонтируйте образ composer из Docker в каталоги, которые нужны для вашего проекта Laravel, чтобы избежать издержек глобальной установки Composer:
docker run --rm -v $(pwd):/app composer install
Флаги -v и --rm команды docker run создают виртуальный контейнер, который привязывается к текущему каталогу вплоть до его удаления. Содержимое вашего каталога ~/laravel-app будет скопировано в контейнер, а содержимое создаваемой Composer внутри контейнера папки vendor будет скопировано в текущий каталог.
В заключение установите в каталоге проекта такой уровень разрешений, чтобы ее владельцем был пользователь без привилегий root:
sudo chown -R $USER:$USER ~/laravel-app
Это будет важно, когда вы будете записывать Dockerfile для образа вашего приложения, поскольку позволит работать с кодом приложения и запускать процессы в контейнере, не имея привилегий root.
Теперь вы разместили код приложения и можете переходить к определению служб с помощью Docker Compose.
Создание файла Docker Compose
Построение приложений с помощью Docker Compose упрощает процесс настройки и контроля версий в вашей инфраструктуре. Чтобы настроить наше приложение Laravel, мы создадим файл docker-compose с определением служб веб-сервера, базы данных и приложения.
Откройте файл:
nano ~/laravel-app/docker-compose.yml
В файле docker-compose определяются три службы: app, webserver и db. Добавьте в файл следующий код, при этом замените пароль root для MYSQL_ROOT_PASSWORD, определяемый как переменная среды службы db, надежный паролем по своему выбору:
~/laravel-app/docker-compose.yml
version: '3'
services:
#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: digitalocean.com/php
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
networks:
- app-network
#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
networks:
- app-network
#MySQL Service
db:
image: mysql:5.7.22
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: your_mysql_root_password
SERVICE_TAGS: dev
SERVICE_NAME: mysql
networks:
- app-network
#Docker Networks
networks:
app-network:
driver: bridge
Сюда включены следующие службы:
- app: это определение службы содержит приложение Laravel и запускает персонализированный образ Docker, digitalocean.com/php. Также оно устанавливает для параметра working_dir в контейнере значение /var/www.
- webserver: это определение службы берет образ nginx:alpine из Docker и открывает порты 80 и 443.
- db: это определение службы извлекает образ mysql:5.7.22 из Docker и определяет новые переменные среды, в том числе базу данных laravel для вашего приложения и пароль пользователя root для базы данных. Вы можете использовать любое имя базы данных, которое захотите, также вам следует заменить your_mysql_root_password собственным надежным паролем. Это определение службы также сопоставляет порт хоста 3306 и порт контейнера 3306.
Каждое свойство container_name определяет имя контейнера, соответствующее имени службы. Если вы не определите это свойство, Docker будет присваивать каждому контейнеру имена, состоящие из имени исторической личности и случайного слова, разделенных символом подчеркивания.
Для упрощения взаимодействия между контейнерами, службы подключаются к соединительной сети с именем app-network. Соединительная сеть использует программный мост, позволяющий подключенным к этой сети контейнерам взаимодействовать друг с другом. Драйвер моста автоматически устанавливает правила хоста, чтобы контейнеры в разных соединительных сетях не могли напрямую взаимодействовать друг с другом. Это повышает уровень безопасности приложений, поскольку друг с другом могут взаимодействовать только связанные службы. Также это означает, что вы сможете задавать разные сети и службы, подключающиеся к связанным функциям: например, клиентские службы приложения могут использовать сеть frontend, а серверные — сеть backend.
Теперь посмотрим, как добавлять тома и привязывать смонтированные образы к определениям служб для постоянного сохранения данных приложения.
Постоянное сохранение данных
В Docker имеются мощные и удобные средства для постоянного сохранения данных. В нашем приложении мы будем использовать тома и монтируемые образы для постоянного сохранения файлов базы данных, приложения и конфигурации. Тома обеспечивают гибкость резервного копирования и сохранение по прекращении жизненного цикла контейнера, а привязываемые монтируемые образы упрощают изменение кода во время разработки с немедленным отражением изменений файлов или каталогов хоста в контейнерах. Мы используем оба варианта.
Определите в файле docker-compose том с именем dbdata в определении службы db для постоянного сохранения базы данных MySQL:
~/laravel-app/docker-compose.yml
...
#MySQL Service
db:
...
volumes:
- dbdata:/var/lib/mysql
networks:
- app-network
...
Том с именем dbdata используется для постоянного сохранения содержимого папки /var/lib/mysql внутри контейнера. Это позволяет останавливать и перезапускать службу db без потери данных.
Добавьте в конце файла определение тома dbdata:
~/laravel-app/docker-compose.yml
...
#Volumes
volumes:
dbdata:
driver: local
С этим определением вы сможете использовать этот том для разных служб.
Затем добавьте привязку монтируемого образа к службе db для файлов конфигурации MySQL:
~/laravel-app/docker-compose.yml
...
#MySQL Service
db:
...
volumes:
- dbdata:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/my.cnf
...
Этот монтируемый образ привязывает файл ~/laravel-app/mysql/my.cnf к каталогу /etc/mysql/my.cnf в контейнере.
Затем добавьте монтируемые образы в службу веб-сервера. Их будет два: один для кода приложения, а другой — для определения конфигурации Nginx
~/laravel-app/docker-compose.yml
#Nginx Service
webserver:
...
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network
Первый монтируемый образ привязывает код приложения в каталоге ~/laravel-app к каталогу /var/www внутри контейнера. Файл конфигурации, добавляемые в ~/laravel-app/nginx/conf.d/, также монтируется в /etc/nginx/conf.d/ в контейнере, что позволяет добавлять и изменять содержимое каталога конфигурации по мере необходимости.
В заключение добавьте следующие привязки монтируемых образов в службу app для кода приложения и файлов конфигурации:
~/laravel-app/docker-compose.yml
#PHP Service
app:
...
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
Служба app привязывает монтируемый образ папки ~/laravel-app, который содержит код приложения, к папке /var/www. Это ускорит процесс разработки, поскольку любые изменения в локальном каталоге приложения будут немедленно отражаться в контейнере. Также вы привязываете файл конфигурации PHP ~/laravel-app/php/local.ini к файлу /usr/local/etc/php/conf.d/local.ini в контейнере. Позже вы создадите локальный файл конфигурации PHP.
Теперь ваш файл docker-compose будет выглядеть следующим образом:
~/laravel-app/docker-compose.yml
version: '3'
services:
#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: digitalocean.com/php
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network
#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network
#MySQL Service
db:
image: mysql:5.7.22
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: your_mysql_root_password
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- dbdata:/var/lib/mysql/
- ./mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network
#Docker Networks
networks:
app-network:
driver: bridge
#Volumes
volumes:
dbdata:
driver: local
Создание файла Dockerfile
Docker позволяет задавать среду внутри отдельных контейнеров с помощью файла Dockerfile. Файл Dockerfile позволяет создавать персонализированные образы. которые можно использовать для установки требуемого программного обеспечения приложения и изменения настроек в соответствии с требованиями. Вы можете передавать созданные образы в Docker Hub или любой частный реестр.
Файл Dockerfile будет располагаться в каталоге ~/laravel-app. Создайте файл:
nano ~/laravel-app/Dockerfile
Этот файл Dockerfile будет задавать базовый образ и необходимые команды и инструкции для построения образа приложения Laravel. Добавьте в файл следующий код:
~/laravel-app/php/Dockerfile
FROM php:7.2-fpm
# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/
# Set working directory
WORKDIR /var/www
# Install dependencies
RUN apt-get update && apt-get install -y
build-essential
mysql-client
libpng-dev
libjpeg62-turbo-dev
libfreetype6-dev
locales
zip
jpegoptim optipng pngquant gifsicle
vim
unzip
git
curl
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd
# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# Copy existing application directory contents
COPY . /var/www
# Copy existing application directory permissions
COPY --chown=www:www . /var/www
# Change current user to www
USER www
# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
Сначала Dockerfile создает образ поверх образа php:7.2-fpm Docker. Это образ на базе с установленным экземпляром PHP FastCGI PHP-FPM. Также этот файл устанавливает требуемые пакеты для Laravel: mcrypt, pdo_mysql, mbstring и imagick с composer.
Директива RUN задает команды для обновления, установки и настройки параметров внутри контейнера, включая выделенного пользователя и группу с именем www. Инструкция WORKDIR задает каталог /var/www как рабочий каталог приложения.
Создание отдельного пользователя и группы с ограниченными правами доступа снижает уязвимость при запуске контейнеров Docker, которые по умолчанию запускаются с привилегиями root. Вместо запуска этого контейнера с привилегиями root мы создали пользователя www с правами чтения и записи для папки /var/www с помощью команды COPY с флагом --chown для копирования разрешений папки приложения.
Команда EXPOSE открывает порт 9000 в контейнере для сервера php-fpm. CMD указывает команду, которая должна запускаться после создания контейнера. Здесь CMD указывает команду php-fpm, которая запускает сервер.
Когда закончите вносить изменения, сохраните файл и закройте редактор.
Теперь вы можете перейти к определению конфигурации PHP.
Настройка PHP
Вы определили инфраструктуру в файле docker-compose, и теперь можете настроить службу PHP для работы в качестве процессора PHP для входящих запросов Nginx.
Для настройки PHP вы создадите файл local.ini в папке php. Это файл, который вы привязали к файлу /usr/local/etc/php/conf.d/local.ini в контейнере выше. Создание этого файла позволит вам игнорировать файл по умолчанию php.ini, который PHP считывает при запуске.
Создайте каталог php:
mkdir ~/laravel-app/php
Затем откройте файл local.ini:
nano ~/laravel-app/php/local.ini
Чтобы продемонстрировать настройку PHP, мы добавим следующий код для установки ограничений размера выгруженных файлов:
~/laravel-app/php/local.ini
upload_max_filesize=40M
post_max_size=40M
Директивы upload_max_filesize и post_max_size задают максимальный разрешенный размер выгружаемых файлов и показывают, как задавать конфигурации php.ini из файла local.ini. Вы можете вставить любой параметр конфигурации PHP, который хотите игнорировать в файле local.ini.
Настройка Nginx
При настройке службы PHP вы можете изменять службу Nginx для использования PHP-FPM как сервера FastCGI для обслуживания динамического контента. Сервер FastCGI основан на двоичном протоколе для взаимодействия интерактивных программ с веб-сервером. Дополнительную информацию можно найти в статье «Понимание и реализация прокси FastCGI в Nginx».
Для настройки Nginx вы создадите файл app.conf с конфигурацией служб в папке ~/laravel-app/nginx/conf.d/.
Вначале создайте каталог nginx/conf.d/:
mkdir -p ~/laravel-app/nginx/conf.d
Затем создайте файл конфигурации app.conf:
nano ~/laravel-app/nginx/conf.d/app.conf
Добавьте в файл следующий код, чтобы задать конфигурацию Nginx:
~/laravel-app/nginx/conf.d/app.conf
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
Серверный блок задает конфигурацию веб-сервера Nginx с помощью следующих директив:
- listen: эта директива определяет порт, который сервер прослушивает для получения входящих запросов.
- error_log и access_log: эти директивы определяют файлы для записи журналов.
- root: эта директива задает путь к корневой папке, формируя полный путь для любого запрошенного файла в локальной файловой системе.
В блоке расположения php директива fastcgi_pass указывает, что служба app прослушивает сокет TCP на порту 9000. С ней сервер PHP-FPM выполняет прослушивание через сеть, а не через сокет Unix. Хотя сокет Unix дает небольшое преимущество в скорости по сравнению с сокетом TCP, у него нет сетевого протокола и он пропускает сетевой стек. В случаях расположения хостов в одной системе использование сокета Unix может иметь смысл, но если службы работают на разных хостах, сокет TCP дает преимущество, позволяя подключаться к распределенным службам. Поскольку наши контейнеры app и webserver работают на разных хостах, в нашей конфигурации эффективнее использовать сокет TCP.
Когда закончите вносить изменения, сохраните файл и закройте редактор.
Благодаря привязке, созданной ранее, любые изменения в папке nginx/conf.d/ прямо отражаются в контейнере webserver.
Теперь посмотрим на параметры MySQL.
Настройка MySQL
После настройки PHP и Nginx вы можете активировать MySQL как базу данных для вашего приложения.
Для настройки MySQL нужно создать файл my.cnf в папке mysql. Это файл, который вы привязали к файлу /etc/mysql/my.cnf внутри контейнера на этапе конфигурирования базы данных. Привязка монтируемого образа позволяет игнорировать любые параметры my.cnf, если и когда это требуется.
Чтобы продемонстрировать, как это работает, мы добавим в файл my.cnf настройки, которые включают журнал общих запросов и задают файл журнала.
Создайте каталог mysql:
mkdir ~/laravel-app/mysql
Создайте файл my.cnf:
nano ~/laravel-app/mysql/my.cnf
Добавьте в файл следующий код, чтобы активировать журнал запросов и задать местоположение файла журнала:
~/laravel-app/mysql/my.cnf
[mysqld]
general_log = 1
general_log_file = /var/lib/mysql/general.log
Файл my.cnf поддерживает журналы, задавая для параметра general_log значение 1, разрешающее общие журналы. Параметр general_log_file указывает, где будут храниться журналы.
Запуск контейнеров и изменение параметров среды
Вы определили все службы в файле docker-compose и создали файлы конфигурации для этих служб. Теперь вы можете запускать контейнеры. В заключение мы создадим копию файла .env.example, которую Laravel включает по умолчанию, и назовем ее .env, поскольку Laravel использует такой файл для определения среды:
cp .env.example .env
После запуска контейнеров мы настроим в этом файле конкретные параметры установки.
Теперь все ваши службы определены в файле docker-compose, и вам просто нужно запустить одну команду для запуска всех контейнеров, создания томов и настройки и подключения сетей:
docker-compose up -d
При первом запуске docker-compose up будут загружены все необходимые образы Docker, что может занять некоторое время. После загрузки образов и их сохранения на локальном компьютере Compose создаст ваши контейнеры. Флаг -d преобразует процесс в демона, с которым контейнеры остаются запущенными в фоновом режиме.
После завершения процесса используйте следующую команду для вывода списка всех запущенных контейнеров:
docker ps
Вы увидите следующие результаты с данными о контейнерах app, webserver и db:
Output
CONTAINER ID NAMES IMAGE STATUS PORTS
c31b7b3251e0 db mysql:5.7.22 Up 2 seconds 0.0.0.0:3306->3306/tcp
ed5a69704580 app digitalocean.com/php Up 2 seconds 9000/tcp
5ce4ee31d7c0 webserver nginx:alpine Up 2 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp
В этих результатах CONTAINER ID — это уникальный идентификатор каждого контейнера, а NAMES перечисляет имена служб для каждого контейнера. Вы можете использовать для доступа к контейнерам оба эти идентификатора. IMAGE определяет имя образа каждого контейнера, а STATUS предоставляет информацию о состоянии контейнера: запущен, перезапускается или остановлен.
Теперь вы можете изменить файл .env в контейнере app, чтобы добавить определенные параметры вашей системы.
Откройте файл с помощью docker-compose exec, позволяющего запускать определенные команды в контейнерах. В этом случае вы открываете файл для редактирования:
docker-compose exec app nano .env
Найдите блок, задающий DB_CONNECTION и обновите его для отражения особенностей настройки вашей системы. Вы измените следующие поля:
- DB_HOST будет вашим контейнером базы данных db.
- DB_DATABASE будет базой данных laravel.
- DB_USERNAME будет именем пользователя для вашей базы данных. В этом случае мы будем использовать laraveluser.
- DB_PASSWORD будет защищенным паролем для этой учетной записи пользователя.
/var/www/.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=your_laravel_db_password
Так же необходимо поправить эти же переменные в файле .env.example, так как он будет использован позже при разворачивании на сервере.
Затем настройте ключ приложения для Laravel с помощью команды php artisan key:generate. Эта команда сгенерирует ключ и скопирует его в файл .env, что обеспечит защиту сеансов пользователя и шифрованных данных:
docker-compose exec app php artisan key:generate
Теперь у вас есть все необходимые настройки среды для запуска приложения. Чтобы кэшировать эти настройки в файле, ускоряющем загрузку приложения, запустите команду:
docker-compose exec app php artisan config:cache
Настройки конфигурации будут загружены в файл /var/www/bootstrap/cache/config.php в контейнере.
В заключение откройте в браузере сайт localhost. Откроется главная страница приложения Laravel.
Создание пользователя MySQL
При установке MySQL по умолчанию создается только административная учетная запись root с неограниченными привилегиями доступа к серверу баз данных. Обычно при работе с базой данных лучше избегать использования административной учетной записи root. Вместо этого мы создадим специального пользователя базы данных для базы данных Laravel нашего приложения.
Чтобы создать нового пользователя, запустите интерактивную оболочку bash в контейнере db с помощью команды docker-compose exec:
docker-compose exec db bash
Выполните внутри контейнера вход в административную учетную запись MySQL root:
mysql -u root -p
Вам будет предложено ввести пароль, заданный для учетной записи MySQL root при установке в файл docker-compose.
Для начала проверьте наличие базы данных laravel, определенной в файле docker-compose.
Запустите команду show databases для проверки существующих баз данных:
show databases;
В результатах вы должны увидеть базу данных laravel:
Output
+--------------------+
| Database |
+--------------------+
| information_schema |
| laravel |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Затем создайте учетную запись пользователя, которой будет разрешен доступ к этой базе данных.
Мы используем имя пользователя laraveluser, но вы можете заменить его любым предпочитаемым именем. Просто убедитесь, что имя пользователя и пароль соответствуют заданным в файле .env на предыдущем шаге:
GRANT ALL ON laravel.* TO 'laraveluser'@'%' IDENTIFIED BY 'your_laravel_db_password';
Обновите привилегии, чтобы уведомить сервер MySQL об изменениях:
FLUSH PRIVILEGES;
Закройте MySQL:
EXIT;
Выйдите из контейнера:
exit
Теперь можно сделать миграцию, чтобы проверить работу базы данных:
docker-compose exec app php artisan migrate
Результаты подтверждения миграции выглядят следующим образом:
Output
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table
Часть 2. Gitlab
В гитлабе необходимо создать новый проект.
Теперь нам нужно сохранить проект в репозитории гитлаба. Для этого вызываем из папки проекта на локальной машине следующие команды:
git init
git remote add origin git@gitlab.com:<аккаунт>/<проект> или
git remote add origin https://gitlab.com/<аккаунт>/<проект> если не хочется возится с SSH
git add .
git commit -m "Initial commit"
git push -u origin master
Проект должен оказаться в Project Overview -> Details
Чтобы было удобно сразу получать готовую среду мы сохраняем докер-образ среды в регистре гитлаба.
Для этого необходимо сделать:
docker login registry.gitlab.com
И закинуть образ на гитлаб:
docker build -t registry.gitlab.com/<аккаунт>/<проект> .
docker push registry.gitlab.com/<аккаунт>/<проект>
Образ будет находится в Packages->Container Registry
Чтобы закончить с гитлабом сразу получим ключ от gitlab-runner. Для этого необходимо зайти в Setting->CI/CD->Runner. Ключ находится на 3 шаге в разделе Ручная настройка (Set up a specific Runner manually).
Часть 3. Настройка на сервере
sudo apt-get update
sudo apt-get install php7.3-mbstring
Далее нам необходимо установить gitlab-runner. Runner это сервис, который будет принимать вебхук от гитлаба при получении новой версии и разворачивать все на нашем сервере.
Для установки gitlab-runner нужно выполнить:
curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
После скачивания задать разрешение на исполнение:
sudo chmod +x /usr/local/bin/gitlab-runner
Далее создаем пользователя gitlab-runner и запускаем сервис gitlab runner:
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start
Регистрируем runner. Для этого нам понадобится токен из части 2 этой статьи:
sudo gitlab-runner register
В ответ у вас спросят адрес вашего гитлаба.
Указываем gitlab.com:
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
https://gitlab.com
Далее необходимо ввести токен. Вводим токен из части 2.
Please enter the gitlab-ci token for this runner
xxx
Далее указываем описание и теги через запятую. Потом нам предлагают выбрать экзекутор. Здесь необходимо выбрать shell:
Please enter the executor:
shell
Как я понял экзекутор это среда, в которой выполняется код из файла .gitlab-ci.yml. На выбор есть bash, ssh, docker, parallels, virtualbox и kubernets. В документации рекомендуют если вы не знаете чем воспользоваться — пользоваться bash. Это универсальный вариант, который выполняется в командной строке на вашем сервере.
Потом нам необходимо добавить пользователя gitlab-runner в группу пользователей docker.
sudo usermod -aG docker gitlab-runner
Чтобы не возникало ошибок доступа, добавляем в sudoers
sudo nano /etc/sudoers
строку
gitlab-runner ALL=(ALL) NOPASSWD: ALL
Теперь мы можем создать файл .gitlab-ci.yml. Он необходим для выполнения так называемых Pipeline: последовательности команд для разворачивания проекта.
Для этого необходимо зайти в репозиторий проекта на гитлабе и нажать Создать новый файл. Гитлаб сам предложит шаблоны файлов, среди них необходимо выбрать .gitlab-ci.yml. После создания файла в гитлабе есть возможность выбрать шаблон содержимого файла. Я выбрал laravel и немного переделал под себя:
# This file is a template, and might need editing before it works on your project.
# Official framework image. Look for the different tagged releases at:
# https://hub.docker.com/r/library/php
#Базовый образ. В нашем случае образ, который был загружен в регистр во второй части
image: registry.gitlab.com/<аккаунт>/<образ>:latest
# Pick zero or more services to be used on all builds.
# Only needed when using a docker container to run your tests in.
# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
services:
- mysql:latest
#Переменные для доступа к БД
variables:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: ***********
# This folder is cached between builds
# Папки, которые будут кэшироваться при билде
# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
paths:
- vendor/
- node_modules/
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
# Здесь будут выполнены подготовительные команды
before_script:
# Обновлены все пакеты
- sudo apt-get update -yqq
# Подготовлен для установки nodejs
- sudo apt-get install gnupg -yqq
# Обновлен Node до версии 12
- curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
# Установлены зависимости
- sudo apt-get install git nodejs libcurl4-gnutls-dev libicu-dev libmcrypt-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libpq-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev -yqq
# Установлен composer
- curl -sS https://getcomposer.org/installer | php
- php composer.phar install
- composer install
# Установлены зависимости Node
- npm install
# Copy over testing configuration.
# Don't forget to set the database config in .env.testing correctly
- DB_HOST=mysql
- DB_DATABASE=laravel
- DB_USERNAME=root
- DB_PASSWORD=*********
# Меняем .env.example в файл конфигурации .env
- cp .env.example .env
# Делаем npm build
- npm run dev
# Очищаем кэш и генерируем ключ для laravel
- php artisan key:generate
- php artisan config:cache
- php artisan route:clear
- php artisan config:clear
- php artisan cache:clear
# Делаем миграции.
- docker-compose exec app php artisan migrate
# Делаем сиды БД
#- docker-compose exec app php artisan db:seed
#тестирование
test:
script:
# запускаем тесты
- php vendor/bin/phpunit --coverage-text --colors=never
# тесты npm
- npm test
# деплой на сервере
deploying:
stage: deploy
script:
- echo "Deployed"
- docker-compose stop
- docker-compose up -d
После успешного выполнения пайплайна (CI/CD->Pipelines) по ip адресу вашего сервера вы должны увидеть вашу страницу laravel.
Для настройки CI/CD я использовал инструкцию от Sean Bradley:
и medium.com/@sean_bradley/auto-devops-with-gitlab-ci-and-docker-compose-f931233f080f
Автор: Ильшат Латыпов