前端er Go-Frame 的学习笔记:实现 to-do 功能(三),用 docker 封装成镜像,并且同时启动前后端数据库服务

文章目录


前言

目前我手上已经有了两个项目

  • 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

期间遇到了两个问题,第一个是文件放错位置了

第二个是构建到最后报错了

报错内容:

bash 复制代码
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 需要反向代理

我们来进入容器中试一下

bash 复制代码
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:8000prod 走的 /caddy 的代理)

首先说明一下当前情况: 我想测一下前端容器,访问宿主机的后端

Caddyfile 复制代码
: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

bash 复制代码
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 ,所以说明一下平台

bash 复制代码
docker build -t todo-go-frame .

好哎,又报错了

说是要改一下 go.mod 的版本号

然后上面就飘红了

执行一下 go mod tidyemmm 还是不行,tidy 之后就会变成 1.23.0

好的,说是 dockerfile 用的 go1.20,改一下 dockerfilego 版本

中间又遇到个错误

好的,最后终于成功了

这是能打包的 dockerfile

go 复制代码
# 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,但是我觉得不对,在部署的时候我应该能随意的更改端口地址,所以,这个问题暂时保留,起码能跑起来了,🥹


数据库容器

我的想法是,前端,后端,数据库,都容器化,然后组合在一个网络里

数据库容器的话, go-frame 的官方例子中已经有了 https://goframe.org/quick/scaffold-api-sql#%E5%BA%94%E7%94%A8%E6%95%B0%E6%8D%AE%E8%A1%A8

bash 复制代码
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 文件

bash 复制代码
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 的时候跑一下脚本

中途还遇到了些问题

修改了数据库的话要清理卷

bash 复制代码
docker compose down
docker volume ls
docker volume rm <你的卷名,例如 todoList-react-goframe_db_data>
docker compose up --build -d

终于是跑起来了!不过中文好像是乱码!

好,ai 说是环境变量的问题

重启一下,旧的数据应该不行了,不过新的数据是好的!

相关推荐
深红1 小时前
玩转小程序AR-实战篇
前端·微信小程序·webvr
银空飞羽1 小时前
让Trae SOLO全自主学习开发近期爆出的React RCE漏洞靶场并自主利用验证(CVE-2025-55182)
前端·人工智能·安全
钮钴禄·爱因斯晨2 小时前
DevUI 组件生态与 MateChat 智能应用:企业级前端智能化实战
前端
YJlio2 小时前
SDelete 学习笔记(9.18):安全删除、空闲清理与介质回收实战
笔记·学习·安全
不会写DN2 小时前
存储管理在开发中有哪些应用?
前端·后端
清风细雨_林木木2 小时前
Obsidian 笔试环境配置与使用指南
前端
用户47949283569153 小时前
Vite8来啦,告别 esbuild + Rollup,Vite 8 统一用 Rolldown 了
前端·javascript·vite
枫,为落叶3 小时前
VueRouter前端路由
前端