在 AWS Lightsail 上部署 React 应用程序:测试、Docker、Docker Compose、Nginx 和 Github Actions
那么,您已经编写了 React 应用程序并准备部署它了吗?
尽管已经有像 Netlify、Vercel 这样的现有解决方案来帮助您轻松快速地部署应用程序,但对于开发人员来说,了解如何在私有服务器上部署应用程序总是有益的。
今天,我们将学习如何在 AWS Lightsail 上部署 React App。此方法也适用于其他 VPS 提供商。
目录
- 设置
- 准备 React 应用程序以进行部署
- 环境变量
- 测试
- Docker 配置
- Github Actions(测试中)
- 准备服务器
- Github 操作(部署)
1 - 设置
对于这个项目,我们将使用一个已经配置好的 React 应用程序。它是为这篇关于FullStack React 和 React 身份验证的文章而制作的项目:React REST、TypeScript、Axios、Redux 和 React Router。
您可以直接在这里克隆该 repo 。
完成后,请确保安装依赖项。
cd django-react-auth-app
yarn install
2 - 准备部署应用程序
在这里,我们将配置应用程序以使用环境变量,同时也配置Docker。
环境变量
保护 API 密钥、密码和密钥等敏感代码免遭窥探至关重要。
最好的方法是什么?使用环境变量。以下是如何在我们的应用程序中执行此操作。
创建两个文件:
.env
包含所有环境变量的文件- 以及一个
env.example
包含与 相同内容的文件.env
。
实际上,该.env
文件会被 git 忽略。这里的文件代表一个框架,我们可以用它在另一台机器上env.example
创建我们的文件。.env
它是可见的,因此请确保不包含敏感信息。
# ./.env
REACT_APP_API_URL=YOUR_BACKEND_HOST
现在,让我们复制内容并将其粘贴进去.env.example
,但一定要删除这些值。
./env.example
REACT_APP_API_URL=
测试
在应用程序中进行测试是确保 React 服务器可维护性和可靠性的首要保证。
我们将进行测试,以确保在正式部署之前一切顺利。
为了在这里编写测试,我们将使用 React 测试库。
我们主要会测试组件输入的值Login
。
// src/pages/Login.test.tsx
import React from "react";
import '@testing-library/jest-dom'
import {fireEvent, render, screen} from "@testing-library/react";
import Login from "./Login";
import store from '../store'
import {Provider} from "react-redux";
const renderLogin = () => {
render(
<Provider store={store}>
<Login/>
</Provider>
)
}
test('Login Test', () => {
renderLogin();
expect(screen.getByTestId('Login')).toBeInTheDocument();
const emailInput = screen.getByTestId('email-input');
expect(emailInput).toBeInTheDocument();
fireEvent.change(emailInput, {target: {value: 'username@gmail.com'}})
expect(emailInput).toHaveValue('username@gmail.com');
const passwordInput = screen.getByTestId('password-input');
expect(passwordInput).toBeInTheDocument();
fireEvent.change(passwordInput, {target: {value: '12345678'}})
expect(passwordInput).toHaveValue('12345678');
})
现在运行测试。
yarn test
现在让我们转到Docker配置。
Docker化我们的应用程序
Docker是一个用于在容器内开发、交付和运行应用程序的开放平台。
为什么要使用 Docker?因为
它可以帮助您将应用程序与基础架构分离,并有助于更快地交付代码。
如果这是您第一次使用 Docker,我强烈建议您阅读快速教程并阅读一些相关文档。
以下是一些对我有帮助的优秀资源:
Dockerfile
代表Dockerfile
一个文本文档,其中包含可以在命令行上调用以创建图像的所有命令。
在项目根目录下添加一个Dockerfile.dev
。它代表开发环境。
# Dockerfile.dev
FROM node:14-alpine
WORKDIR /app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
在这里,我们从基于 Alpine 的 JavaScript Docker 镜像开始。它是一个专为安全性和资源效率而设计的轻量级 Linux 发行版。
另外,让我们添加一个.dockerignore
文件。
node_modules
npm-debug.log
Dockerfile.dev
Dockerfile.prod
.dockerignore
yarn-error.log
Docker Compose
Docker Compose是一款很棒的工具(<3)。你可以使用它来定义和运行多容器 Docker 应用程序。
我们需要什么?嗯,只需要一个包含我们应用程序服务所有配置的 YAML 文件。
然后,使用docker-compose
命令,我们可以创建并启动所有这些服务。
这里,该docker-compose.dev.yml
文件将包含构成我们应用程序的三个服务:nginx 和 web。
该文件将用于开发。
正如你所猜测的:
version: "3"
services:
nginx:
container_name: core_web
restart: on-failure
image: nginx:stable
volumes:
- ./nginx/nginx.dev.conf:/etc/nginx/conf.d/default.conf
ports:
- "80:80"
depends_on:
- web
web:
container_name: react_app
restart: on-failure
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./src:/app/src
ports:
- "3000:3000"
command: >
sh -c "yarn start"
env_file:
- .env
nginx
:NGINX是用于 Web 服务、反向代理、缓存、负载平衡、媒体流等的开源软件。web
:我们将运行并提供 React 应用程序的端点。
下一步,让我们创建 NGINX 配置文件来代理到后端应用程序的请求。
在根目录中,创建一个nginx
目录并创建一个nginx.dev.conf
文件。
upstream webapp {
server react_app:3000;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://webapp;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Docker 构建
设置已完成。让我们构建容器并测试一切是否在本地正常运行。
docker-compose -f docker-compose.dev.yml up -d --build
完成后,点击localhost/
查看你的应用程序是否正常运行。
你应该会看到类似的页面。
太棒了!我们的 React 应用程序已成功在容器内运行。
让我们转到 Github Actions,以便在每次分支上有推送时运行测试main
。
Github Actions(测试)
GitHub 操作是 Github 最棒的功能之一。它可以帮助您构建、测试或部署应用程序等等。
在这里,我们将创建一个名为的 YAML 文件main.yml
来运行一些 React 测试。
在根项目中,创建一个名为 的目录.github
。在该目录内,创建另一个名为 的目录workflows
并创建main.yml
文件。
name: React Testing and Deploying
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
name: Tests
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Installing dependencies
run: yarn install
- name: Running Test
run: yarn test
基本上,我们在这里所做的是为GitHub 操作工作流设置规则、安装依赖项并运行测试。
- 确保仅当主分支上有 push 或 pull_request 时才会触发此工作流程
- 选择
ubuntu-latest
操作系统并精确指定此工作流程将在其上运行的 Python 版本。 - 之后,我们安装 javascript 依赖项并运行测试。
如果您将代码推送到存储库中,则当您转到存储库页面时会看到类似的内容。
片刻之后,黄色将变为绿色,表示检查已成功完成。
设置AWS服务器
我将在这里使用Lightsail 服务器。请注意,这些配置适用于任何 VPS 提供商。
如果您想设置 Lightsail 实例,请参阅 AWS文档。
就我个人而言,我的 VPS 在 Ubuntu 20.04.3 LTS 上运行。
此外,您还需要在机器上安装Docker和docker-compose 。
之后,如果您想将您的服务器链接到域名,请确保将其添加到您的 DNS 配置面板。
完成后,我们就可以开始部署过程了。
Docker 构建脚本
为了实现这里的自动化,我们将编写一个 bash 脚本来从 repo 中提取更改,并构建 docker 镜像并运行容器。
在再次拉出并重建容器之前,我们还将检查是否有任何即将发生的变化。
#!/usr/bin/env bash
TARGET='main'
cd ~/app || exit
ACTION='\033[1;90m'
NOCOLOR='\033[0m'
# Checking if we are on the main branch
echo -e ${ACTION}Checking Git repo
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" != ${TARGET} ]
then
exit 0
fi
# Checking if the repository is up to date.
git fetch
HEADHASH=$(git rev-parse HEAD)
UPSTREAMHASH=$(git rev-parse ${TARGET}@{upstream})
if [ "$HEADHASH" == "$UPSTREAMHASH" ]
then
echo -e "${FINISHED}"Current branch is up to date with origin/${TARGET}."${NOCOLOR}"
exit 0
fi
# If that's not the case, we pull the latest changes and we build a new image
git pull origin main;
# Docker
docker-compose -f docker-compose.prod.yml up -d --build
exit 0;
好!使用 SSH 登录你的服务器。我们将创建一些新目录:一个用于代码仓库,另一个用于脚本。
mkdir app .scripts
cd .scripts
vim docker-deploy.sh
只需粘贴先前脚本的内容并根据需要进行修改即可。
cd ~/app
git clone <your_repository> .
别忘了添加点.
。使用它,它将简单地克隆当前目录中存储库的内容。
太棒了!现在我们需要编写docker-compose.prod.yml
将在此服务器上运行的文件。
顺便说一下,我们将添加 SSL 证书,因此我们需要创建另一个nginx.conf
文件。
这是docker-compose.prod.yml
文件。
version: "3.7"
services:
nginx:
container_name: core_web
restart: on-failure
image: jonasal/nginx-certbot:latest
env_file:
- .env.nginx
volumes:
- nginx_secrets:/etc/letsencrypt
- ./nginx/user_conf.d:/etc/nginx/user_conf.d
ports:
- "80:80"
- "443:443"
depends_on:
- web
web:
container_name: react_app
restart: on-failure
build:
context: .
dockerfile: Dockerfile.prod
volumes:
- ./src:/app/src
ports:
- "5000:5000"
command: >
sh -c "yarn build && serve -s build"
env_file:
- .env
volumes:
nginx_secrets:
如果您注意到,我们已经更改了nginx
服务。现在,我们正在使用docker-nginx-certbot
镜像。它将使用Let's Encrypt免费 CA(证书颁发机构)及其客户端自动创建和更新 SSL 证书certbot
。
我们的 React 服务器正在运行构建应用。使用yarn build
,它将创建一个针对生产环境优化的应用,供我们服务。
最后,我们将添加Dockerfile.prod
文件
FROM node:14-alpine AS builder
WORKDIR /app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install --frozen-lockfile
COPY . .
user_conf.d
在目录内创建一个新目录nginx
并创建一个新文件nginx.conf
。
upstream webapp {
server react_app:5000;
}
server {
listen 443 default_server reuseport;
listen [::]:443 ssl default_server reuseport;
server_name dockerawsreact.koladev.xyz;
server_tokens off;
client_max_body_size 20M;
ssl_certificate /etc/letsencrypt/live/dockerawsreact.koladev.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dockerawsreact.koladev.xyz/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/dockerawsreact.koladev.xyz/chain.pem;
ssl_dhparam /etc/letsencrypt/dhparams/dhparam.pem;
location / {
proxy_pass http://webapp;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
确保dockerawsreact.koladev.xyz
用您自己的域名替换...
没问题!我会解释我做了什么。
server {
listen 443 default_server reuseport;
listen [::]:443 ssl default_server reuseport;
server_name dockerawsreact.koladev.xyz;
server_tokens off;
client_max_body_size 20M;
和往常一样,我们监听 HTTPS 端口443
。我们 添加了一个,即域名。我们将 设置为 off,这样错误页面上就不会显示服务器版本。 最后,我们将请求大小设置为最大值 20MB。这意味着大于 20MB 的请求将导致HTTP 413(请求实体过大)错误。server_name
server_tokens
现在,我们来在 Github Action 中编写部署作业。
...
deploy:
name: Deploying
needs: [test]
runs-on: ubuntu-20.04
steps:
- name: SSH & Deploy
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_AWS_SERVER_IP }}
username: ${{ secrets.SSH_SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
script: |
cd ~/.scripts
./docker-deploy.sh
请注意这里 Github Secrets 的用法。它允许在你的仓库中存储敏感信息。查看此文档了解更多信息。
我们还在这里使用了一个 GitHub 操作,该操作需要主机名、用户名、密钥和密码。您也可以将此操作与密码一起使用,但需要进行一些配置。您
可以查看此操作的文档以了解更多详细信息。
另外,请注意这一needs: [build]
行。它可以帮助我们确保在部署新版本的应用程序之前,先前的作业已经成功。
完成后,通过 ssh 登录您的服务器并创建一个 .env 文件。
cd app/
vim .env # or nano or whatever
最后,创建一个.env.nginx
文件。它将包含创建 SSL 证书所需的配置。
# Required
CERTBOT_EMAIL=
# Optional (Defaults)
STAGING=1
DHPARAM_SIZE=2048
RSA_KEY_SIZE=2048
ELLIPTIC_CURVE=secp256r1
USE_ECDSA=0
RENEWAL_INTERVAL=8d
添加您的电子邮件地址。请注意,此处设置为 1。我们将首先使用Let's EncryptSTAGING
暂存环境测试配置!请务必在 100% 确定配置正确之前不要设置 staging=0。
这是因为颁发证书的重试次数有限,您不想等到它们重置(每周一次)。
声明您的项目所需的环境变量。
我们快完成了。:)
推送到存储库并等待操作成功完成。
好了,配置完成了。
如果您的浏览器显示类似这样的错误,则说明配置正常!我们现在可以颁发可用于生产的证书了。
在您的服务器上,停止所有容器。
docker-compose down -v
编辑您的.env.nginx
文件并设置STAGING=0
。
然后,重新启动容器。
sudo docker-compose up -d --build
我们完成了。:)
结论
在本文中,我们学习了如何使用 Github Actions 在 AWS Lightsail 服务器上部署 Docker 化的 React 应用程序。请注意,您可以在任何 VPS 上使用这些步骤。
每篇文章都可以变得更好,所以欢迎在评论区提出您的建议或问题。😉
在此处查看本教程的代码。
文章来源:https://dev.to/koladev/deploy-a-react-app-on-aws-lightsail-testing-docker-docker-compose-nginx-github-actions-4lb5