Ручной деплой NestJS и Angular приложений на выделенном сервер через "Docker Compose" и "PM2"
Покупаем выделенный сервер и настраиваем SSH доступ к нему с локального компьютера.
Добавляем https://github.com/SteveLTN/https-portal в "Docker compose" для автоматической генерации и продления сертификатов.
1. Находим бесплатный или покупаем выделенный сервер
Шаги по этому пункту не буду расписывать, я уже расписывал ранее в разделе "Buy VPS" другого поста - Deploy nestjs project to VPS with dokku.
В рамках текущих постов я купил на том же сайте самый дешевый выделенный сервер.
Операционная система: Ubuntu 22.04 x64
Доступ в мир: 100 MB/sec (shared)
RAM: 2GB
CPU: 2 vCPU
Количество IPv4 адресов: 1
При покупке выделенного сервера мне также дали домен третьего уровня: vps1724252356.tech0.ru, в будущем этот проект переедет на домен https://fullstack.nestjs-mod.com.
2. Настройка подключение к выделенному серверу по SSH
После покупки необходимо установить пароль если он не был установлен, разные сайты имеют свои интерфейсы для этого, в моем случаи установка пароля находится на странице https://ztv.su/clientarea.php?action=productdetails&id=33376#tabChangepw.
Копируем наш локальный публичный SSH на удаленный сервер, при запуске появится запрос на ввод пароля, необходимо ввести свой пароль и нажать "Enter".
Если SSH-ключа на компьютере не было, то его нужно создать с помощью команды ssh-keygen
Команды
ssh-copy-id root@194.226.49.162
Вывод консоли
$ ssh-copy-id root@194.226.49.162
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_rsa.pub"
The authenticity of host '194.226.49.162 (194.226.49.162)' can't be established.
ECDSA key fingerprint is SHA256:SOME_SYMBOLS.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@194.226.49.162's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@194.226.49.162'"
and check to make sure that only the key(s) you wanted were added.
3. Подключение к удаленному серверу
Команды
ssh root@194.226.49.162
Вывод консоли
$ ssh root@194.226.49.162
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-91-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Wed Aug 21 18:42:37 MSK 2024
System load: 0.02734375 Processes: 103
Usage of /: 9.4% of 24.05GB Users logged in: 0
Memory usage: 10% IPv4 address for eth0: 194.226.49.162
Swap usage: 0%
* Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
just raised the bar for easy, resilient and secure K8s cluster deployment.
https://ubuntu.com/engage/secure-kubernetes-at-the-edge
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Wed Aug 21 18:41:46 2024 from X.X.X.X
root@vps1724252356:~#
4. Установка всех необходимых пакетов на выделенный сервер
Команды
sudo snap install curl
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo groupadd docker
sudo usermod -aG docker $USER
sudo apt install git -y
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" --no-use
nvm install v20
nvm use v20
npm install --global yarn
sudo apt install default-jre -y
sudo apt install -y unzip
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
sudo reboot
Вывод консоли
root@vps1724252356:~# sudo snap install curl
curl 8.1.2 from Wouter van Bommel (woutervb) installed
root@vps1724252356:~# curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
sudo groupadd docker
sudo usermod -aG docker $USER
# Executing docker install script, commit: 0d6f72e671ba87f7aa4c6991646a1a5b9f9dae84
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ca-certificates curl >/dev/null
+ sh -c install -m 0755 -d /etc/apt/keyrings
+ sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" -o /etc/apt/keyrings/docker.asc
+ sh -c chmod a+r /etc/apt/keyrings/docker.asc
+ sh -c echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu jammy stable" > /etc/apt/sources.list.d/docker.list
+ sh -c apt-get update -qq >/dev/null
+ sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-ce-rootless-extras docker-buildx-plugin >/dev/null
+ sh -c docker version
Client: Docker Engine - Community
Version: 27.1.2
API version: 1.46
Go version: go1.21.13
Git commit: d01f264
Built: Mon Aug 12 11:50:12 2024
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 27.1.2
API version: 1.46 (minimum version 1.24)
Go version: go1.21.13
Git commit: f9522e5
Built: Mon Aug 12 11:50:12 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.7.20
GitCommit: 8fc6bcff51318944179630522a095cc9dbf9f353
runc:
Version: 1.1.13
GitCommit: v1.1.13-0-g58aa920
docker-init:
Version: 0.19.0
GitCommit: de40ad0
================================================================================
To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:
dockerd-rootless-setuptool.sh install
Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/
WARNING: Access to the remote API on a privileged Docker daemon is equivalent
to root access on the host. Refer to the 'Docker daemon attack surface'
documentation for details: https://docs.docker.com/go/attack-surface/
================================================================================
groupadd: group 'docker' already exists
root@vps1724252356:~# sudo apt install git -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Suggested packages:
git-daemon-run | git-daemon-sysvinit git-doc git-email git-gui gitk gitweb git-cvs git-mediawiki git-svn
The following packages will be upgraded:
git
1 upgraded, 0 newly installed, 0 to remove and 137 not upgraded.
Need to get 3165 kB of archives.
After this operation, 16.4 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 git amd64 1:2.34.1-1ubuntu1.11 [3165 kB]
Fetched 3165 kB in 1s (2408 kB/s)
(Reading database ... 94596 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.34.1-1ubuntu1.11_amd64.deb ...
Unpacking git (1:2.34.1-1ubuntu1.11) over (1:2.34.1-1ubuntu1.10) ...
Setting up git (1:2.34.1-1ubuntu1.11) ...
Scanning processes...
Scanning linux images...
Running kernel seems to be up-to-date.
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@vps1724252356:~# curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" --no-use
nvm install v20
nvm use v20
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 15037 100 15037 0 0 36871 0 --:--:-- --:--:-- --:--:-- 36945
=> Downloading nvm from git to '/root/.nvm'
=> Cloning into '/root/.nvm'...
remote: Enumerating objects: 376, done.
remote: Counting objects: 100% (376/376), done.
remote: Compressing objects: 100% (320/320), done.
remote: Total 376 (delta 46), reused 176 (delta 29), pack-reused 0 (from 0)
Receiving objects: 100% (376/376), 372.57 KiB | 2.13 MiB/s, done.
Resolving deltas: 100% (46/46), done.
* (HEAD detached at FETCH_HEAD)
master
=> Compressing and cleaning up git repository
=> Appending nvm source string to /root/.bashrc
=> Appending bash_completion source string to /root/.bashrc
=> Close and reopen your terminal to start using nvm or run the following to use it now:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
Downloading and installing node v20.16.0...
Downloading https://nodejs.org/dist/v20.16.0/node-v20.16.0-linux-x64.tar.xz...
################################################################################################################################################################ 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v20.16.0 (npm v10.8.1)
Creating default alias: default -> v20 (-> v20.16.0)
Now using node v20.16.0 (npm v10.8.1)
root@vps1724252356:~# npm install --global yarn
added 1 package in 2s
npm notice
npm notice New patch version of npm available! 10.8.1 -> 10.8.2
npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.8.2
npm notice To update run: npm install -g npm@10.8.2
npm notice
root@vps1724252356:~# sudo apt install -y unzip
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Suggested packages:
zip
The following NEW packages will be installed:
unzip
0 upgraded, 1 newly installed, 0 to remove and 137 not upgraded.
Need to get 175 kB of archives.
After this operation, 386 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 unzip amd64 6.0-26ubuntu3.2 [175 kB]
Fetched 175 kB in 0s (485 kB/s)
Selecting previously unselected package unzip.
(Reading database ... 96234 files and directories currently installed.)
Preparing to unpack .../unzip_6.0-26ubuntu3.2_amd64.deb ...
Unpacking unzip (6.0-26ubuntu3.2) ...
Setting up unzip (6.0-26ubuntu3.2) ...
Processing triggers for man-db (2.10.2-1) ...
Scanning processes...
Scanning linux images...
Running kernel seems to be up-to-date.
No services need to be restarted.
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@vps1724252356:~# sudo reboot
Connection to 194.226.49.162 closed by remote host.
Connection to 194.226.49.162 closed.
5. Генерация SSH-ключа на выделенном сервере
Это нужно для того чтобы мы могли скачать репозиторий на выделенный сервер
Команды
ssh-keygen
Вывод консоли
root@vps1724252356:~# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:SOME_RANDOM_SYMBOLS root@vps1724252356
The key's randomart image is:
+---[RSA 3072]----+
| .o*oo. |
+----[SHA256]-----+
6. Привязка публичного ключа выдленного сервера к GitHub
Необходимо запустить команды cat /root/.ssh/id_rsa.pub
и ответ вставить в настройки проекта, у меня они тут: https://github.com/nestjs-mod/nestjs-mod-fullstack/settings/keys/new
Команды
root@vps1724252356:~# cat /root/.ssh/id_rsa.pub
Вывод консоли
# cat /root/.ssh/id_rsa.pub
ssh-rsa AAAARANDOM_SYMBOLS= root@vps1724252356
7. Клонируем проект
Команды
git clone git@github.com:nestjs-mod/nestjs-mod-fullstack.git
cd nestjs-mod-fullstack
Вывод консоли
root@vps1724252356:~# git clone git@github.com:nestjs-mod/nestjs-mod-fullstack.git
Cloning into 'nestjs-mod-fullstack'...
The authenticity of host 'github.com (140.82.121.3)' can't be established.
ED25519 key fingerprint is SHA256:+SOME_RANDOM_SYMBOLS.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 426, done.
remote: Counting objects: 100% (426/426), done.
remote: Compressing objects: 100% (294/294), done.
remote: Total 426 (delta 190), reused 340 (delta 106), pack-reused 0 (from 0)
Receiving objects: 100% (426/426), 536.69 KiB | 1.56 MiB/s, done.
Resolving deltas: 100% (190/190), done.
root@vps1724252356:~# cd nestjs-mod-fullstack
root@vps1724252356:~/nestjs-mod-fullstack#
8. Устанавливаем зависимости и прогоняем запуск и тестирование двух режимов: PM2-продакшен и "Docker Compose"
E2E-тесты запускаем указывая внешний глобальный ИП адрес приложений.
Команды
npm i
npx playwright install
npx playwright install-deps
npm run test
cp example.env .env
npm run pm2-full:prod:start
export BASE_URL=http://194.226.49.162:3000 && npm run test:e2e
npm run pm2-full:prod:stop
npm run docker-compose-full:prod:start
export BASE_URL=http://194.226.49.162:8080 && npm run test:e2e
npm run docker-compose-full:prod:stop
E2E-тестирование в режиме "Docker Compose" упало с ошибкой, в следующих шагах будем их исправлять на локальном компьютере и затем через коммит в репозиторий проекта, донесем их на выделенный сервер.