这一篇主要记录从接口开发、多阶段镜像构建,到接口验证和容器维护的完整过程
操作步骤:
- 准备业务代码与运行环境
- 编写Dockerfile与.dockerignore
- docker build构建自定义docker镜像
- docker run运行服务
- 服务状态监控与维护
1. 准备业务代码与运行环境
| 接口 | 请求方式 | 功能 |
|---|---|---|
/health | GET | 返回服务健康状态 |
/predict | POST | 接收文本,返回固定分类结果 |
package main
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
func health(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
}
func predict(c *gin.Context) {
var request struct {
Text string `json:"text"`
}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求体必须是 JSON,例如 {\"text\":\"这是一条测试\"}"})
return
}
if strings.TrimSpace(request.Text) == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "text 不能为空"})
return
}
// 第一版使用固定结果,后续替换为真实模型推理。
c.JSON(http.StatusOK, gin.H{"result": "positive"})
}
func main() {
// Creates a gin router with default middleware:
// logger and recovery (crash-free) middleware
router := gin.Default()
router.GET("/health", health)
router.POST("/predict", predict)
// By default it serves on :8080 unless a
// PORT environment variable was defined.
// router.Run()
router.Run(":8000") // for a hard coded port
}
检查docker是否能够正常运行容器
docker run --rm hello-world
2. Dockerfile 与 .dockerignore
# 第一阶段:编译程序
FROM golang:1.26-alpine AS builder
WORKDIR /app
# 先复制依赖清单,让依赖下载可以复用构建缓存
COPY go.mod go.sum ./
RUN go mod download
# 复制项目源码
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
-trimpath \
-o /app/server \
.
# 第二阶段:运行程序
FROM alpine:3.22
COPY --from=builder /app/server /server
EXPOSE 8000
ENTRYPOINT ["/server"]
解析:
FROM确认镜像构建的基底环境,AS作为镜像构建的阶段名称
使用WORKDIR确认打包环境中的工作目录
通过COPY […SOURCE FILES] [DESTINATION DIR]将本机文件复制到镜像构建的环境中
RUN即在镜像环境中执行一些CMD命令
COPY –from=[STAGENAME] 可以从指定阶段取出文件复制给当前阶段
这样最终镜像包含 Alpine 及编译好的服务,无需把 Go 编译器和整份源码一起带入运行环境
docker在构建环境中会启动一个虚拟机,阶段有各自独立的文件系统状态,可以通过 FROM 继承已有状态,也可以通过 COPY –from 复制文件。如果写成 FROM builder AS another,新阶段就会以 builder 的结果为起点,继承当时的文件系统内容,但后续修改仍然独立。
# Git 信息
.git
.gitignore
# 编辑器配置
.vscode
.idea
# 本地构建产物
bin/
dist/
tmp/
*.exe
*.test
coverage.out
# 日志
logs/
*.log
# 本地环境变量与私钥
.env
.env.*
*.pem
*.key
# 前端依赖
node_modules/
# 文档
README*
docs/
与.gitignore类似,需要排除到构建环节中的文件主要有下面几种
- 环境变量,密钥
- 构建产物
- 包依赖
- IDE个性化配置,git
- 开发文档
- 运行时数据(本地跑的数据)
3. docker build 镜像构建
# 日常构建
docker build -t myapp:dev .
# Dockerfile 放在 docker 目录中
docker build -f docker/Dockerfile -t myapp:dev .
# 查看详细日志,排查构建失败
docker build --progress=plain -t myapp:dev .
# 指定 Linux x86-64 目标平台
docker build --platform linux/amd64 -t myapp:dev .
解析:
-t可以为镜像标注多个Tag,例如myapp:dev,tag为dev。myworker:v1,tag为v1
常用的可选参数如下
| 参数 | 作用 | 示例 |
|---|---|---|
-t / --tag | 设置镜像名称和标签 | -t myapp:v1 |
-f / --file | 指定 Dockerfile 路径 | -f docker/Dockerfile |
--build-arg | 传入构建时参数,配合 ARG | --build-arg APP_VERSION=v1 |
--target | 指定哪个阶段作为构建结果 | --target builder |
--no-cache | 不复用构建步骤的缓存 | --no-cache |
--pull | 尝试拉取基础镜像的更新版本 | --pull |
--platform | 指定目标系统和 CPU 架构 | --platform linux/amd64 |
--progress=plain | 用普通文本显示详细构建日志 | --progress=plain |
--help | 查看本机版本支持的参数 | docker build --help |
4. docker run 容器运行
docker run -d --name ai-practice -p 8000:8000 ai-service:v1
-d表示容器作为后台运行,不占用当前shell的进程
–name xxx,为容器指定name,后续操作使用name即可
-p 8000:8000,将电脑的8000端口映射到容器的8000端口
有时候会出现-rm,表示运行容器后,如果被结束则自动销毁该容器。
一般不加该参数,停止容器后,容器变为stop状态依旧保留运行的数据。
当容器被销毁时,内部的数据也会被销毁
5. 容器维护
docker ps # 查看运行的容器
docker ps -a # 查看所有容器
docker logs xxx # 查看xxx容器的日志(非实时)
docker logs --tail 20 ai-practice # 查看xxx容器的日志(最新20条)
docker logs -t xxx # 查看xxx容器的日志(包含timestamp)
docker logs -f xxx # 查看xxx容器的日志(实时)
docker stop xxx
docker start xxx
评论(0)
暂无评论