使用docker部署react项目到服务器
前言
看此文章前需要您具备 docker,linux,makefile ,nginx 的基础知识
镜像准备
编写 Makefile
# 这个名称在拉取镜像的时候有用哦
imagePath = [你的harbor地址]/[镜像名]:[镜像版本号]
push-webapp:
yarn build
docker build -t ${imagePath} .
docker push ${imagePath}
编写 Dockerfile
# nginx的版本可以自行选择
FROM nginx:1.19-alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./dist/ /opt/www/
ENTRYPOINT nginx -g "daemon off;"
EXPOSE 80
编写 nignx.conf
主要是在 nginx.conf 文件的 server 块中修改或添加以下代理就可以了
# 指定静态文件夹的根目录
root /opt/www;
# api_url 为后端容器的ip地址,api_port为容器开启的服务端口
location ~ /api/ {
proxy_pass http://[api_url]:[api_port];
proxy_set_header real_ip $remote_addr;
}
# 因为是单页应用,所以需要总是返回index.html文件
location / {
try_files $uri /index.html;
}
在服务器端运行镜像
拉取镜像
# 上面打的镜像变量名imagePath
docker pull [imagePath]
以守护态形式运行镜像
# 这里的-p是映射主机80端口到容器的80端口,dockerfile中的EXPOSE是容器暴露的端口
docker run --name [容器名] -d -p 80:80 [imagePath的镜像id]
遇到的问题以及解决方法
nignx 无法访问上游服务器
- 一开始我配置的
proxy_pass http://[api_url]:[api_port]
中的api_url
是 127.0.0.1,导致打开页面报网关错误的问题,大佬一看就肯定知道啥原因了。 - 经过排查,docker 容器的网络是通过 linux 的 namespace 进行隔离的,默认的桥接情况下,每个容器都有自己的一块独立的网卡,学过 linux 的肯定知道 127.0.0.1 是 lo 回环网卡的地址,所以是访问不到后端服务的(QAQ,我这里的错误就是误认为后端服务和前端服务同用宿主机的网卡了,hahahah~)。
-
解决方案:
- 使用宿主机的 ip + 后端服务的端口(相当于外部访问宿主机的后端服务,转了一圈~)
- 如果是同一网桥 docker0 中,可以将请求地址改成后端服务在网段中的地址(具体地址可以进容器查看,也可以通过
docker network inspect bridge
,bridge 是网桥的名称,可以通过docker netword ls
查看所有的网桥)
nginx 部署单页应用遇到白屏问题
可以查看 nginx 部署 react 项目
docker 一共有四种网络模式:
host 模式
- 设置命令:
--net=host
- 详细说明: 容器不会获得一个独立的 network namespace,而是与宿主机共用一个 network namespace,容器不会虚拟出自己的网卡、配置自己的 ip 等,而是使用宿主机的 ip 和端口。
应用场景:当网络不应与 Docker 主机隔离,但又希望容器的其他方面隔离时,主机网络是最佳选择。
container 模式
- 设置命令:
--net=container
- 详细说明:指定新创建的容器和已经存在的一个容器共享一个 network namespace,而不是和宿主机共享,新创建的容器不会创建自己的网卡、配置自己的 ip,而是和指定的容器共享 ip、端口等。两个容器除网络方面相同外,其他的如文件系统、进程列表等还是隔离的。
none 模式
- 设置命令:
--net=none
- 详细说明:容器拥有自己的 network namespace,但是并未对容器进行任何网络配置,需要手工为容器添加网卡、配置 ip 等。可以使用 pipework 工具为容器指定 ip 等信息
应用场景:第三方网络插件使您可以将 docker 与专用网络集成。
bridge 模式
- 设置命令:
--net=bridge
- 详细说明:bridge 模式是容器默认的网络模式,该模式会为每个容器分配独立的 network namespace,设置 ip、路由等信息,默认会将容器连接到一个虚拟网桥交换机 docker0 上,容器之间组成一个局域网,可以相互访问。
应用场景:当您需要多个容器在同一 docker 主机上进行通信时,最好使用用户定义的网桥网络。用户定义的网桥网络的容器会自动将所有端口彼此公开,而不会向外界公开任何端口。默认网桥网络上运行相同的应用程序堆栈,则需要使用-p 或–publish 标志分别打开 Web 端口和数据库端口。这意味着 docker 主机需要通过其他方式阻止对数据库端口的访问。