15

踩坑React + Node.js/Express + Google Cloud Build + Docker前后端分离应用部署

 3 years ago
source link: https://blog.skyju.cc/post/react-express-cloudbuild-docker/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Featured image of post 踩坑React + Node.js/Express + Google Cloud Build + Docker前后端分离应用部署
技术

踩坑React + Node.js/Express + Google Cloud Build + Docker前后端分离应用部署

这段时间完成了一个繁体-简体线上转换的小项目,采用react+express前后端分离开发。顺便学习了一下google cloud build和docker的相关应用。踩了些坑,在这里记录下。

Jul 16, 2021   By  居正

这段时间完成了一个繁体-简体线上转换的小项目,采用react+express前后端分离开发。顺便学习了一下google cloud build和docker的相关应用。踩了些坑,在这里记录下。

GitHub

Demo

前端使用create-react-app开发,采用axios请求后端的接口。

前端请求后端需要制定一个BASE_URL,由于最后是封装进docker镜像中,而一般来讲create-react-app由于使用webpack打包,BASE_URL需要在编译时就指定,不适合docker这种模式。所以这里需要一个能取到运行时环境变量的方法。

我采用的方法是前端加入一个config.json放在public目录下,里面放置BASE_URL的值。前端程序每次启动先请求config得到后端真实地址再进行后续请求。然后在docker容器运行时覆写这个config,就能动态制定BASE_URL。

后来发现一个npm包能做到类似功能:runtime-env-cra

后端唯一需要动态指定的是服务运行的端口,这里用到dotenv这个npm包,这样环境变量可以在docker运行时指定,然后后端程序直接读取process.env.PORT即可。

Docker镜像

前后端代码安装依赖的时候发现会从package-lock.jsonyarn.lock)里读取我本地开发时候用的淘宝源安装,但这样在国外机器上构建镜像的时候就很慢。暂时的解决方法是在Dockerfile中删掉lock文件。

前端Dockerfile

前端镜像用分步构建,先用node:lts-alpine这个镜像编译react app,然后把编译好的文件复制出来,用nginx:stable-alpine作为http server。

记录一点,COPY指令如果前面那个参数是目录,会把目录里面的具体内容复制走,而不是把整个目录复制走。这点跟mv和cp都不一样。

还有一点,如果RUN里面有多个命令用&&之类的符号连接,在最前面加个set -x ; 可以查看如果有报错到底是哪个命令出错了,方便调试。

文件:https://github.com/juzeon/tw-cn/blob/master/frontend/Dockerfile

前面说到的运行时写入config.json的代码放在CMD指令里面。

后端Dockerfile

由于用到opencc库作为繁体-简体转换,而这个库里面核心代码是C写的,安装依赖时遇到node-gyp报错。刚开始还以为是alpine或者python的问题,换了几个镜像问题依旧。最后在构建中加入一行RUN apk add python make gcc g++增加编译环境就解决了。

文件:https://github.com/juzeon/tw-cn/blob/master/backend/Dockerfile

Google Cloud Build

有几个坑:

  1. 如果在步骤中用到环境变量(或者SECRET),需要采用entrypoint: 'bash'格式。
  2. Secret Manager权限设置比较复杂,具体可以看这个文档:https://cloud.google.com/build/docs/interacting-with-dockerhub-images?hl=zh-cn。注意Secret Manager是收费的,$0.06/个/月。
  3. 构建触发器可以选择github上的项目。如果你用自建私有git仓库,需要在自己的服务器上安装谷歌提供的gcloud命令行工具,配置一下钩子。

另可参考文档:https://cloud.google.com/build/docs/configuring-builds/create-basic-configuration?hl=zh-cn

文件:https://github.com/juzeon/tw-cn/blob/master/cloudbuild.yaml

Cloud Build每天免费120分钟,还是很不错的。

docker-compose

docker容器编排,同一个网络中的容器和容器间交互是不需要用ports做端口映射的,只有暴露给宿主机/公网的端口才需要。

这里的配置是前后端分别在容器中运行,另外再运行一个nginx镜像,将前后端组合起来,前端挂在/下,后端挂在/backend下,然后暴露18080端口(映射为nginx容器的80端口)给公网。

在volumes中挂载了一个nginx配置文件,覆写容器中默认的vhost。

文件:https://github.com/juzeon/tw-cn/blob/master/docker-compose.yml

nginx配置文件

其中把后端挂载/backend目录的时候遇到URI方面的问题。查阅以下资料:

Nginx reverse proxy + URL rewrite

Nginx代理proxy pass配置去除前缀

一文理清 nginx 中的 location 配置(系列一)

可以写成下面几种形式之一:

location ^~ /backend {
  rewrite ^/backend/(.*)$ /$1 break;
  proxy_pass   http://backend:9999;
}
location ^~ /backend {
  rewrite ^/backend(.*)$ $1 break;
  proxy_pass   http://backend:9999;
}
location ^~ /backend/ {
  proxy_pass   http://backend:9999/;
}

上面配置中的^~都是可以去掉的,加上是为了保证优先级。

具体是什么原理,可以参考上面的链接的资料。

本来自己nginx都是乱配,通过这次把location、proxy相关的东西理解的更深刻了一点。

文件:https://github.com/juzeon/tw-cn/blob/master/nginx.conf

这次进行一次全栈开发+部署,还是有学到很多运维相关的知识。

Licensed under CC BY-NC-SA 4.0


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK