前言
目前我手上已经有了两个项目
go-frame的React写的前端
现在来学一下企业级的部署,让 AI 大师给我指条明路
什么是 k8s
Kubernetes(k8s)= 一个用于自动运行、扩缩容、自动恢复你的应用的系统。
简单说:你把镜像给它,它帮你稳定运行(并且几乎不会挂)。
前端项目封装成镜像
给前端项目写一个 Dockerfile
我可能要写两个文件,第一个是 Dockerfile
# === 构建阶段 ===
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install --production=false
COPY . .
RUN npm run build
# === 运行阶段:使用 Caddy 作为静态服务器 ===
FROM caddy:2-alpine
# 将构建产物复制到 Caddy 默认站点目录
COPY --from=build /app/dist /usr/share/caddy
# 复制 Caddyfile(如果你需要自定义路由)
COPY Caddyfile /etc/caddy/Caddyfile
期间遇到了两个问题,第一个是文件放错位置了
第二个是构建到最后报错了
报错内容:
cannot replace to directory ... node_modules/@ant-design/icons with file意思是:容器里
node_modules是文件夹 你宿主机的node_modules中某些内容可能是软链接或文件 COPY 全目录的时候冲突了。 💥 根本原因:你把整个项目(包括本地 node_modules) COPY 进入容器!
这个 .dockerignore的作用如下
我是m1 芯片,16G 内存,大概要打 1 分半的镜像。
构建好的 docker 镜像,我准备测一下
然后在浏览器里看一下
ok 啊,果然失败了,容我检查一下哪里出了问题!
首先,本地构建,预览,没有问题
那非常有可能的是我的代理问题了
问了一下,说是 caddy 需要反向代理
我们来进入容器中试一下
docker ps
docker exec -it 容器名 sh
wget -qO- http://localhost/api/v1/todo
wget -qO- http://host.docker.internal:8000/api/v1/todo
# 强制无缓存刷新
docker build --no-cache -t todo-front-test .
docker run -d -p 2345:80 --name todo-front-test todo-react-app
很好,这个问题折磨了我一阵子,我试了各种各样版本的 caddyfile,只有用 handle 语法的成功了。
我只改了两个地方
一个是 env 文件,改成了如下图所示,这个文件是硬编码的,所以不能写成这个。
问题:那如果改这里的话,dev 环境就不能调试了 所以,我来写
.env.development和.env.production两个,看看能不能解决环境问题 (我自己验证了一下,是可行的,dev 走的localhost:8000,prod走的/,caddy的代理)
首先说明一下当前情况: 我想测一下前端容器,访问宿主机的后端
:80 {
# 静态文件根目录
root * /usr/share/caddy
# 1. 优先处理 API 请求(使用 handle 强制隔离和执行)
# 只要路径匹配 /api/*,就执行反向代理,并停止处理。
handle /api/* {
reverse_proxy http://host.docker.internal:8000
}
# 2. 处理所有其他请求 (前端路由和静态文件)
handle {
# 静态文件服务
file_server
# SPA 路由回退:如果文件不存在,返回 index.html
try_files {path} /index.html
}
}
后端封装 docker
go-frame 似乎自带了封装 docker 的命令,我们看一下官方的例子 https://goframe.org/docs/cli/docker#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B
gf docker main.go -p -tn loads/gf-demos:test
然后这是后端打包的速度, 还行 40 多秒
好吧,感觉看错地方了,应该是这里 https://goframe.org/docs/deploy/container#1-%E7%BC%96%E8%AF%91%E7%A8%8B%E5%BA%8F
写好 dockerfile 文件之后,编译,我的是m1 ,所以说明一下平台
docker build -t todo-go-frame .
好哎,又报错了
说是要改一下
go.mod 的版本号
然后上面就飘红了
执行一下 go mod tidy,emmm 还是不行,tidy 之后就会变成 1.23.0
好的,说是 dockerfile 用的 go 是 1.20,改一下 dockerfile 的 go 版本
中间又遇到个错误
好的,最后终于成功了
这是能打包的 dockerfile
# Stage 1: Builder
FROM golang:1.23-alpine AS builder
WORKDIR /app/main
# Copy go.mod and go.sum
COPY go.mod go.sum ./
RUN go mod download
# Copy the rest
COPY . .
# Build
RUN go mod tidy
RUN CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o main .
# Stage 2: Production
FROM alpine:3.18
LABEL maintainer="john@goframe.org"
ENV WORKDIR /app/main
RUN mkdir -p $WORKDIR
# Copy binary
COPY --from=builder /app/main/main $WORKDIR/main
RUN chmod +x $WORKDIR/main
# Copy resources
COPY resource $WORKDIR/resource
WORKDIR $WORKDIR
CMD ["./main"]
跑了一下容器,但是感觉端口并没有对应上呢
我发现容器里估计缺了 config
➜ docker run --rm -it todo-go-frame sh
ls -R
ok,我自己重新加了个文件夹
好,现在问题卡在如何把容器中的后端接口固定住,目前是随机分配的。我打算用框架的目录
docker build -t goframe-app:latest -f manifest/docker/Dockerfile .
好啊,容器里终于定下来了
然后我宿主机中映射的 8080,打开看一下!不错子!终于连上了
这里我固定写死了
8000,但是我觉得不对,在部署的时候我应该能随意的更改端口地址,所以,这个问题暂时保留,起码能跑起来了,🥹
数据库容器
我的想法是,前端,后端,数据库,都容器化,然后组合在一个网络里
docker run -d --name mysql \
-p 3306:3306 \
-e MYSQL_DATABASE=test \
-e MYSQL_ROOT_PASSWORD=12345678 \
loads/mysql:5.7
启动了容器 mysql
在宿主机上连接一下容器 mysql
可以看到用的是容器的,因为我本地的是 mysql 9
docker-compose.yml
我现在要把前端,后端,数据库的容器放到一个网络里
现在在项目根目录下创建 docker-compose.yml 文件
docker compose up --build -d
数据库容器从 postgre 换成 mysql 之后,因为有写数据卷(持久化),所以要清理一下。
docker compose down
docker volume ls
部署的时候遇到的问题记录
后端接口报错
返回数据了,但是拒接链接
好的,是我 docker-componse.yaml 中没写数据库的名称和密码
docker compose down
docker volume ls
docker volume rm <你的卷名,例如 todoList-react-goframe_db_data>
docker compose up --build -d
这个文件也不能硬编码,但是我在想如果是开发的话该怎么办,这里是不是还要改
改了上面的信息之后,报错就变了
"message": "SELECT `id`,`title`,`done`,`created_at`,`updated_at` FROM `todo`: Error 1146 (42S02): Table 'todo_db.todo' doesn't exist",
终于不是被拒绝了,
init sql
我现在后端创建一个 sql 文件,
然后在 docker compose 的时候跑一下脚本
中途还遇到了些问题
修改了数据库的话要清理卷
docker compose down
docker volume ls
docker volume rm <你的卷名,例如 todoList-react-goframe_db_data>
docker compose up --build -d
终于是跑起来了!不过中文好像是乱码!
好,ai 说是环境变量的问题
重启一下,旧的数据应该不行了,不过新的数据是好的!
接下来可能要用 k8s ,或者,在开发一下,体验真实的开发+部署流程
因为有些地方并不合理,比方说我在部署的时候写死了后端的接口,一些部署的环境变量也是硬编码,这不好,不过,先把整个流程跑通吧!