做者:Matt Raible翻译:疯狂的技术宅html
原文:https://scotch.io/tutorials/r...前端
未经容许严禁转载node
假如你已经构建了一个 React 应用,可是如今须要部署它。应该怎么作?首先,最好选择一个云提供商,由于它们通常成本低并且部署容易。react
大多数云提供商都提供了一种部署静态站点的方法。用 React 构建应用只是 JavaScript、HTML 和 CSS。它们是静态文件,几乎能够在任何 Web 服务器上使用。但实际上,若是你使用了 JSX(JS 中的 HTML)和样式化组件,那么这些能够说只有 JavaScript!nginx
Docker 是用于构建和共享容器化应用的事实标准。你可使用它打包你的应用程序,并包含多种开源 Web 服务器来为你的应用程序提供服务。另外,你还能够经过配置网络服务器来发送安全标头,这样使你的程序更安全。git
前提条件:程序员
为了集中精力,我用了一位同事已经构建的程序。首先克隆存储库。github
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 应用 一文中了解其建立方式。web
登陆你的 Okta 开发者账户(你已经建立了一个,对吗?)注册此应用并启用 OIDC 身份验证。面试
React Docker
。3000
,而且 Login redirect URI 为 http://localhost:3000/callback
出现的界面将为你提供一个客户端 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 进行操做比用 Heroku 进行 firebase deploy
或 git push
处理更为复杂。可是若是你真的要使事情复杂化,并用 Kubernetes 去管理你的应用,那么它能够给你更多的控制权。 😛
在你的根目录中建立一个 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
被替换为空白值。
先执行 docker ps
确保你的 Docker 守护进程正在运行。而后运行如下命令来构建你的 Docker 镜像。 命令中的 react-docker
能够是你想要为镜像命名的任何名字。
docker build -t react-docker .
该过程完成后,你将会看到如下消息的内容:
Successfully built 3211a1255527 Successfully tagged react-docker:latest
如今,你能够用 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 化。 🎉
你的应用要直到正式投入生产时才会真正的存在,因此让咱们把它部署到 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 镜像时,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,而后才能登陆。
若是在 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!
在本文中,咱们学习了把 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
来运行它们。
经过把它们部署到 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
要把现有映像部署到 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。
在本教程中,咱们学习了如何用 Docker 容器化你的 React 应用。你能够用 docker build
手动进行这项操做,也能够用 Heroku 的 Container Registry 经过 Dockerfile 推送和发布项目。在构建容器时,还能够用 pack
命令来利用 Cloud-Native + Heroku 构建包。
若是你用的是 Heroku,它的 buildpack 比 Docker 更容易使用。经过简单的 git push
,你能够在 Heroku 的服务器上部署代码并构建。
能够在 GitHub上 的 oktadeveloper/okta-react-docker-example 上找到本示例的源代码。