做者: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 上找到本示例的源代碼。