БайтМеханик
Блог программиста. Полетел бы я на самолете, автопилот которого написал сам?

Простой деплой на сервер для Laravel с помощью bash-скриптов

Время на чтение: 15 мин. Категория: Laravel

Пока я делал этот блог, мне нужно как-то автоматизировать деплой на удаленный сервер, чтобы каждый раз не делать это руками. Сам блог собран на Laravel. Делать полноценный деплой через CI/CD слишком накладно, поэтому я написал два простых скрипта, которые позволяют автоматизировать заливку на сервер и выполнение рутинных операций (запуск миграций, сборка CSS / JS и тому подобное).

Выкладываю скрипты тут. Подробно объяснять я не буду. Предполагается, что вы знакомы с Linux-ом, поникаете, что такое bash-скрипт, как работает Laravel, пробросили ключи через SSH и тому подобное.

Скрипт, который скачивает Laravel-проект с удаленного сервера и раскладывает всё куда надо. Вместо IP используется 111.111.111.111, вместо локального каталога проекта каталог project, вместо каталога проекта на удаленному сервере - project_root.

База данных - PostgreSQL. Однако, изменения для MySQL нужны небольшие, предлагаю сделать их вам самостоятельно при необходимости.

Скачивание с сервера через bash-скрипт:

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

С самим проектом предполагается работать через GIT, разумеется. То есть мы не редактируем исходник на сервере и работаем по git-flow.

#!/bin/bash

echo "1. dumping storage"
cd /project/
rm storage.tar.gz
ssh root@111.111.111.111 "cd /project_root/public_html/; rm storage.tar.gz; tar -czf storage.tar.gz storage/"

echo "2. downloading storage"
scp root@111.111.111.111:/project_root/public_html/storage.tar.gz /project/

echo "3. extracting storage"
tar -xzf storage.tar.gz
sudo chmod 777 storage/ -R

echo "4. dumping & gzip database"
ssh root@111.111.111.111 "cd project_root; rm dbdump; sudo -u postgres pg_dump database | gzip > dbdump.gz"

echo "5. downloading & ungzip database"
cd /project/
rm dbdump.gz
scp root@111.111.111.111:/project_root/dbdump.gz /project/
rm dbdump
gunzip dbdump.gz

echo "6. installing database"
sudo -u postgres psql -c 'DROP DATABASE bm;'
sudo -u postgres psql -c 'CREATE DATABASE bm;'
sudo -u postgres psql --set ON_ERROR_STOP=on database < dbdump

echo "7. cleaning up"
rm dbdump.gz
rm dbdump
rm storage.tar.gz

echo "8. finish"

Заливка на сервер через bash-скрипт:

Здесь чуть посложнее. Во-первых, скрипт надо вытащить "вверх", чтобы он лежал рядом с каталогом проекта. Во-вторых, заливается вообще всё. Поэтому если вы не скачали storage на предыдущем этапе, вы удалите все картинки.

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

#!/bin/bash

read -p "Did you downloaded storage with download.sh? [Y/n] " -n 1 -r
echo # move to a new line
if [[ $REPLY =~ ^[Y]$ ]]
then
    echo "1. creating site archive"
    rm site.tar.gz -f
    tar -czf site.tar.gz project/

    echo "2. coping archive to server"
    scp site.tar.gz root@111.111.111.111:/project_root/

    echo "3. extracting on server & run migrations"
    ssh root@111.111.111.111 "cd /project_root/; rm public_html/ -rf; tar -xzf site.tar.gz; mv project/ public_html/;"

    echo "4. composer install"
    ssh root@111.111.111.111 "cd /project_root/public_html/; COMPOSER_ALLOW_SUPERUSER=1 composer install"

    echo "5. npm install & build"
    ssh root@111.111.111.111 "cd /project_root/public_html/; npm install; npm run build"

    echo "6. migrating"
    ssh root@111.111.111.111 "cd /project_root/public_html/; php artisan migrate"

    echo "7. finished"
fi

Важно заметить, что проект на сервере лежит внутри каталога public_html. Nginx смотрит именно туда. Поэтому на всякий случай прикладываю пример конфига nginx для этого Laravel-проекта, чтобы было полное понимание:

server {
  listen 80;
	root /project_root/public_html/public;
	index index.php;
	server_name domain.com;

	location / {
		try_files $uri $uri/ /index.php$is_args$args;
	}

	location ~ \.php$ {
		include fastcgi_params;
		fastcgi_intercept_errors on;
		fastcgi_pass unix:/run/php/php8.3-fpm.sock;
		fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
		fastcgi_read_timeout 30;
	}
}

Еще обращаю внимание, что .env едет на сервер вместе со всем кодом, поэтому все пароли на сервере (например, для базы данных) совпадают с локальными. Я же обещал простой деплой, а не умный, да?