
假如你已经构建了一个 React 应用,但是现在需要部署它。应该怎么做?首先,最好选择一个云提供商,因为它们一般成本低而且部署容易。
大多数云提供商都提供了一种部署静态站点的方法。用 React 构建应用只是 JavaScript、HTML 和 CSS。它们是静态文件,几乎可以在任何 Web 服务器上使用。但实际上,如果你使用了 JSX(JS 中的 HTML)和样式化组件,那么这些可以说只有 JavaScript!
Docker 是用于构建和共享容器化应用的事实标准。你可以使用它打包你的应用程序,并包含多种开源 Web 服务器来为你的应用程序提供服务。另外,你还可以通过配置网络服务器来发送安全标头,这样使你的程序更安全。
前提条件:
- Node 12+
- Docker
- Okta 开发者帐户
创建 React 应用
为了集中精力,我用了一位同事已经构建的程序。首先克隆存储库。
git clone https://github.com/oktadeveloper/okta-react-styled-components-example.git react-docker cd react-docker npm install
这是一个使用样式化组件的 React 应用,并由 OpenID Connect(aka OIDC)保护。你可以在使用样式化组件构建 React 应用 一文中了解其创建方式。
登录你的 Okta 开发者帐户(你已经创建了一个,对吗?)注册此应用并启用 OIDC 身份验证。
- 转到顶部菜单中的 Applications
- 选择 Add Application > Single-Page App ,然后单击 Next
- 在设置屏幕上,为你的应用命名,例如
React Docker
。 - 确保端口设置为
3000
,并且 Login redirect URI 为http://localhost:3000/callback
- 点击 Done
出现的界面将为你提供一个客户端 ID。
将客户端 ID 复制并粘贴到应用程序的 src/App.js
中。 <yourIssuerURI>
的值可以在 Okta 仪表板的 API > Authorization Servers 下找到。例如我的是 https://dev-133320.okta.com/oauth2/default
。
function App() { return ( <Router> <Security issuer='<yourIssuerURI>' clientId='<yourClientId>' redirectUri={window.location.origin + '/callback'} pkce={true}> <SecureRoute path='/' exact={true} component={Calendar}/> <Route path='/callback' component={LoginCallback}/> </Security> </Router> ); }
<>
括号只是占位符,请确保将其删除!
用 npm start
启动你的应用。你将被重定向到 Okta 进行身份验证,然后返你的应用。如果你没有重定向,那是因为你已经登录。请在 private 窗口中重试来查看登录过程。
你会看到一个简单、干净的日历,并选择了今天的日期。
我承认这是一个非常简单的应用,但我们会用它来演示如何用 Docker 进行容器化。
为什么要使用Docker?
你可能会问:“为什么要用 Docker?这不会使事情复杂化吗?”
是的我同意。用 Docker 进行操作比用 Heroku 进行 firebase deploy
或 git push
处理更为复杂。但是如果你真的要使事情复杂化,并用 Kubernetes 去管理你的应用,那么它可以给你更多的控制权。
创建Dockerfile和Nginx配置
在你的根目录中创建一个 Dockerfile
。
FROM node:14.1-alpine AS builder WORKDIR /opt/web COPY package.json package-lock.json ./ RUN npm install ENV PATH="./node_modules/.bin:$PATH" COPY . ./ RUN npm run build FROM nginx:1.17-alpine RUN apk --no-cache add curl RUN curl -L https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst && \ chmod +x envsubst && \ mv envsubst /usr/local/bin COPY ./nginx.config /etc/nginx/nginx.template CMD ["/bin/sh", "-c", "envsubst < /etc/nginx/nginx.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"] COPY --from=builder /opt/web/build /usr/share/nginx/html
这将会构建你的项目并把 Nginx 添加为 Web服务器。它还将安装 envsubst
版本,该版本允许你用环境变量去替换变量,并设置默认值。
在同一目录中创建一个 nginx.config
:
server { listen ${PORT:-80}; server_name _; root /usr/share/nginx/html; index index.html; location / { try_files $$uri /index.html; } }
这个文件把 Nginx 配置为将你的 React 应用作为 SPA(其中所有路由都转到 index.html
)并在 80 端口上运行。在 uri 前面有两个 $$
,以防止 $uri
被替换为空白值。
用 React 应用构建 Docker 镜像
先执行 docker ps
确保你的 Docker 守护进程正在运行。然后运行以下命令来构建你的 Docker 镜像。 命令中的 react-docker
可以是你想要为镜像命名的任何名字。
docker build -t react-docker .
该过程完成后,你将会看到以下消息的内容:
Successfully built 3211a1255527 Successfully tagged react-docker:latest
运行你的 Docker + React 应用
现在,你可以用 docker run
命令通过 Docker 在端口 3000 上运行 React 应用。
docker run -p 3000:80 react-docker
如果你发现这些 docker
命令很难记住,也可以在 package.json
文件中添加几个脚本 。
"docker": "docker build -t react-docker .","react-docker": "docker run -p 3000:80 react-docker"
然后就可以用 npm run docker
和 npm run react-docker
运行了。
很漂亮吧?在短短几分钟内就把你的 React 应用做了 docker 化。
把将你的 React App 部署到 Heroku
你的应用要直到正式投入生产时才会真正的存在,所以让我们把它部署到 Heroku。首先我将向你展示怎样不用 Docker 做到这一点。
首先,你需要 一个 Heroku 帐户。然后,安装 Heroku CLI。
打开终端,登录你的 Heroku 帐户,然后创建一个新应用。
heroku login heroku create
现在,你应该有了一个新的 heroku
Git 远程存储库。可以用 git remote -v
来确认。
在带有安全标头的根目录中创建一个 static.json
文件,并把所有 HTTP 请求重定向到 HTTPS。
{ "headers": { "/**": { "Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' https://*.okta.com;", "Referrer-Policy": "no-referrer, strict-origin-when-cross-origin", "Strict-Transport-Security": "max-age=63072000; includeSubDomains", "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY", "X-XSS-Protection": "1; mode=block", "Feature-Policy": "accelerometer 'none'; camera 'none'; microphone 'none'" } }, "https_only": true, "root": "build/", "routes": { "/**": "index.html" } }
要读取 “static.json”,你必须用 Heroku static buildpack。
把你的更改提交到 Git,添加 Node.js + static buildpack,然后部署 React 应用。
git commit -am "Configure secure headers and static buildpacks"heroku buildpacks:set heroku/nodejs heroku buildpacks:add https://github.com/heroku/heroku-buildpack-static.git git push heroku master
该过程完成后,使用以下方法在浏览器中打开你的应用程序:
heroku open
你将会被重定向到 Okta,可能会看到以下错误:
The 'redirect_uri' parameter must be an absolute URI that is whitelisted in the client app settings.
要解决这个问题,需要修改 Okta 应用,以将你的 Heroku URL 添加为“登录重定向 URI”。例如https://gentle-peak-37809.herokuapp.com/callback
。
现在,你应该可以登录并看到你的应用在 Heroku 上运行了!你可以在 https://securityheaders.com 上验证其安全标头是否正确。
在这个部署示例中,buildpacks 为你完成了所有工作。但是并非每个云提供商都提供 buildpack。这就是需要 Docker 的地方。
把 Docker + React App 部署到 Heroku
当涉及到 Docker 镜像时,Heroku 具有一些出色的功能。如果你的项目有一个 Dockerfile,则可以用 Heroku Container Registry直接部署你的应用。
首先,登录到Container Registry。
heroku container:login
然后,创建一个新的应用。
heroku create
把 Git URL 作为新的 remote 添加到你的应用。
git remote add docker https://git.heroku.com/<your-app-name>.git
然后,把将你的 Docker 镜像 push 到 Heroku 的 Container Registry。
heroku container:push web --remote docker
该过程完成后,release 你的应用程序镜像:
heroku container:release web --remote docker
然后,在浏览器中打开该应用:
heroku open --remote docker
你需要先在 Okta 中添加应用的 URI,然后才能登录。
改善 Docker 中 Nginx 的安全标头
如果在 securityheaders.com 上的 Docker 站点中测试新的 Nginx,你的得分应该是 F。
为了解决这个问题,修改你的 nginx.config
添加安全头。
server { listen ${PORT:-80}; server_name _; root /usr/share/nginx/html; index index.html; location / { try_files $$uri /index.html; } add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' https://*.okta.com;"; add_header Referrer-Policy "no-referrer, strict-origin-when-cross-origin"; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options DENY; add_header X-XSS-Protection "1; mode=block"; add_header Feature-Policy "accelerometer 'none'; camera 'none'; microphone 'none'"; }
更新文件后,运行以下命令:
heroku container:push web --remote docker heroku container:release web --remote docker
现在你应该得到 A!
用 Cloud Native Buildpacks 创建你的 React + Docker 镜像
在本文中,我们学习了把 React 应用部署到 Heroku 的两种方法。首先是利用 buildpack 和 git push
。第二个是使用 Heroku 的 Container Registry 和 heroku container:push
+ heroku push:release
。
Cloud Native Buildpacks 是 Pivotal 和 Heroku 在 2018 年初发起的一项举措。它具有 pack
CLI,可让你用 buildpacks 构建 Docker 映像。
我的好朋友 Joe Kutner是 Heroku 的一名软件架构师,在实现 Cloud Native Buildpacks 中发挥了重要的作用。 Joe 是 JHipster 项目的积极提交者,其作者 The Healthy Programmer 是 Cloud Native Buildpacks 核心团队的创始成员 。他对 Docker 的建议是:“如果不需要,请不要使用 Dockerfile
”。
Joe 对我在弄清楚如何使用 buildpacks 创建 Docker 映像的技术上提供了很大的帮助,所以下面的说明应该归功于他。
首先,请 installpack
。如果你使用的是 Mac 或 Linux,可以使用 Homebrew。如果用的是 Windows,可以安装其可执行文件。
brew tap buildpack/tap brew install pack
在前面的 buildpacks 示例中,我用了 Heroku 的 Node.js 和静态 buildpacks。
Heroku 静态构建包不是 “Cloud Native” 构建包。它使用旧的(原生云)API。这意味着它与开箱即用的 pack
不兼容。
幸运的是,Heroku 确实提供了 cnb-shim,你可以用它来使其工作。在用 cnb-shim
转换后,Joe 为 Heroku 的静态 buildpack 创建了一个 URL (https://cnb-shim.herokuapp.com/v1/heroku-community/static
) 。
在本地构建和运行 Docker 镜像之前,必须先进行一项更改。 从 static.json 中删除 "https_only":true
这一行。
然后用以下命令通过 Node.js 和静态 buildpack(也就是你在 Heroku 上使用的相同 buildpack)构建 Docker 镜像。
pack build react-pack --builder heroku/buildpacks --buildpack \ heroku/nodejs,https://cnb-shim.herokuapp.com/v1/heroku-community/static
提示:如果你想摆脱 --builder
参数,可以用 pack set-default-builder heroku/buildpacks
。
该过程完成后,你应该可以运行它。
docker run --rm -it --init -p 3000:3000 --env PORT=3000 okta
如果你发现这些 pack
命令很难被记住,那么可以把它们添加到 package.json
中。
"pack": "pack build react-pack --builder heroku/buildpacks --buildpack heroku/nodejs,https://cnb-shim.herokuapp.com/v1/heroku-community/static","react-pack": "docker run --rm -it --init -p 3000:3000 --env PORT=3000 react-pack"
然后可以使用 npm run pack
和 npm run react-pack
来运行它们。
把将你的 React + Docker 镜像部署到 Docker Hub
通过把它们部署到 Docker Hub 等注册表中,可以轻松共享 Docker 容器。如果你还没有 Docker Hub 帐户,那就先创建一个。
拥有帐户之后,登录并 push 你的镜像。在下面的示例中,我正在使用 react-docker
,但你也可以使用 react-pack
来部署 buildpacks 版本。
docker login docker image tag react-docker <your-username>/react-docker docker push <your-username>/react-docker
默认情况下,这会将其标记为 latest
。如果要标记和推送特定版本,可以用:
docker image tag react-docker <your-username>/react-docker:1.0 docker push <your-username>/react-docker
然后其他人就可以用以下命令 pull 并运行:
docker run -p 3000:80 <your-username>/react-docker
把 React + Docker 镜像部署到 Heroku
要把现有映像部署到 Heroku,可以用 docker push
。你必须用以下命名约定来标记和推送镜像。
docker tag <image> registry.heroku.com/<app>/<process-type> docker push registry.heroku.com/<app>/<process-type>
要部署 react-pack
镜像,你可以执行以下操作:
docker tag react-pack registry.heroku.com/fierce-eyrie-08414/web docker push registry.heroku.com/fierce-eyrie-08414/web heroku container:release web --remote docker
我尝试了一下,发现没有强制使用 HTTPS。必须将 "https_only":true
添加到 static.json
中,然后重新push。
了解有关 React 和 Docker 的更多信息
在本教程中,我们学习了如何用 Docker 容器化你的 React 应用。你可以用 docker build
手动进行这项操作,也可以用 Heroku 的 Container Registry 通过 Dockerfile 推送和发布项目。在构建容器时,还可以用 pack
命令来利用 Cloud-Native + Heroku 构建包。
如果你用的是 Heroku,它的 buildpack 比 Docker 更容易使用。通过简单的 git push
,你可以在 Heroku 的服务器上部署代码并构建。
可以在 GitHub上 的 oktadeveloper/okta-react-docker-example 上找到本示例的源代码。
原文:https://scotch.io/tutorials/react-docker-with-security-in-10-minutes
作者:Matt Raible
更多web前端开发知识,请查阅 HTML中文网 !!