在macOS下搭建《苍穹外卖》开发环境
首先感谢黑马程序员在B站上以免费的方式发布了“苍穹外卖”(2023版)这个企业级Java后端项目,让我有机会端到端地手撸一个近乎真实的项目。
这套课程时有一套基于Windows环境的starter project,讲员一开始花了很大精力讲解开发环境的搭建。毋庸置疑,开发环境的搭建是学习一门技术最难的一大步了。毕竟在什么都不懂的情况下,把各种软件、系统、数据和运行平台配搭起来,总会有些it doesn't work on my computer问题。特别是讲员是用Windows系统,而我是macOS系统,这必然意味着我需要特别注意在搭建开发环境时系统的差异。
我的macOS系统版本是Sonoma,M1 Pro的芯片。肯定会遇到许多坑机,最后我还是动手搭建了开发环境,一动手才发现很多问题。Windows和macOS真是两个不兼容的系统。
导入并运行项目的starter project,需要三步:
- 用sky.sql文件,创建MySQL数据库并导入数据;
- 用IntelliJ IDEA导入sky-take-out这个maven项目;
- 用提供的Windows版本的nginx-1.20.2目录,跑起nginx服务;
讲员是在他的Windows电脑上运行MySQL和nginx服务,而我的是macOS,并不能用他教的方式直接做。
关于第一步,我让MySQL跑在了Docker上,这样我本地就不用安装MySQL软件了,其实我并不喜欢在本地安装一个MySQL版本,因为要是我想灵敏地换一个MySQL版本会很麻烦,当然也有不想污染mac OS系统的私心。毕竟装一个软件容易,卸载一个软件困难。
用Docker运行mysql容器,需要命令:
docker run -p 3306:3306 -v /path/to/host/directory:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=password mysql
容器运行后,我通过DataGrip连接到了MySQL容器,并运行sky.sql创建数据库、表和初始数据。
关于第二步,其实是最简单的,用IntelliJ IDEA可以直接导入maven项目。
第三步是最难的,因为我无法直接使用课程配套的nginx-1.20.2目录,而且nginx的Docker容器里的nginx相关目录结构和Windows版本有些不一样。
我仔细分析了这个nginx-1.20.2目录,里面有一个html/sky目录,这里面是前端为生产环境打包后的项目压缩文件。我需要把它让入nginx容器的相应位置,可是发现nginx Docker容器里的目录结构是这样的:
$ find / -name nginx ... /etc/nginx ... /usr/share/nginx ...
/usr/share/nginx下虽有个html目录,但是似乎应该把sky目录放入/etc/nginx/html下。此外,我还需要用nginx-1.20.2/conf/nginx.conf覆盖掉Docker中的nginx.conf文件。
覆盖之后,在容器的任意目录下运行:
$ service nginx reload Reloading nginx: nginx.
表示nginx服务已经重新加载了更新后的nginx.conf文件。
此外,还可以用如下命令检查nginx.conf是否有语法错误:
$ nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
我在nginx容器中发现修改nginx.conf特别麻烦,因为nginx镜像文件居然精简到连nano, vi都没有安装,所以我在宿主机上修改完nginx.conf后,再用docker cp拷贝到容器中。
% docker cp nginx.conf romantic_stonebraker:/etc/nginx/
Successfully copied 5.12kB to romantic_stonebraker:/etc/nginx/
做完这些步骤后,我发现前端网站已经能够跑起来了。运行效果图如下:

然而,按下“登录”按钮,nginx返回了502 Bad Gateway。nginx的日志对应的错误行是:
2024/01/04 04:07:50 [error] 84#84: *102 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.65.1, server: localhost,
request: "POST /api/employee/login HTTP/1.1", upstream: "http://127.0.0.1:8080/admin/employee/login", host: "localhost", referrer: "http://localhost/" 192.168.65.1 - - [04/Jan/2024:04:07:50 +0000] "POST /api/employee/login HTTP/1.1" 502 494 "http://localhost/" "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
根据日志猜测,nginx是找不到upstream server。可是我的后端程序确实是在http:localhost:8080上跑的好好的。我花了很多时间去troubleshoot这个问题。nginx配置的问题确实比较难调试,我在网上搜到了一篇文章 - https://shaohualee.com/article/955,里面写到:
docker 配置nginx的一些坑 2019-03-29 03:12:26 catherine 在docker中用nginx,要是你的工程部署在外面,就要注意,127.0.0.1是容器里的ip,你要用你的宿主机的ip。不然会报错...
原因出在我在nginx容器的nginx.conf用localhost去指向宿主机(我的macOS),但这其实指向容器的本地,而不是宿主机。
正确的做法是在nginx.conf中用宿主机IP指向宿主机的localhost。这里使用host.docker.internal可指代宿主机IP。
upstream webservers{
server <填入宿主机IP>:8080;
# 如下配置是错误的
#server localhost:8080;
}
server {
listen 80;
server_name localhost;
location / {
root html/sky;
index index.html index.htm;
}
# 反向代理,处理管理端发送的请求
location /api/ {
proxy_pass http://webservers/admin/;
}
...
}
最后,成功登入Dashboard页:


浙公网安备 33010602011771号