go聊天室接入mysql的项目部署流程:
聊天室项目 Docker 部署笔记
一、Dockerfile 设计要点
1️⃣ 服务端 Dockerfile(server)
- 使用 多阶段构建 :
- 构建阶段:
golang:1.22.2-alpine- 设置
WORKDIR /app COPY go.mod go.sum ./→ 下载依赖 (go mod download)COPY . .→ 复制源码RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server ./server→ 构建静态二进制
- 设置
- 最终镜像阶段:
alpine:latestWORKDIR /root/COPY --from=builder /app/server .chmod +x ./server确保可执行mkdir -p ./logsEXPOSE 8888CMD ["./server"]
- 构建阶段:
bash
# 使用官方Golang镜像作为构建环境
FROM golang:1.22.2-alpine AS server-builder
# 设置工作目录
WORKDIR /app
# 设置GOPROXY
ENV GOPROXY=https://goproxy.cn,direct
# 复制go模块文件
COPY go.mod go.sum ./
# 下载依赖
RUN go mod download
# 复制源代码
COPY . .
# 构建服务端应用
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server ./server
# 最终镜像
FROM alpine:latest AS server
WORKDIR /root/
# 从构建阶段复制二进制文件
COPY --from=server-builder /app/server .
# 确保二进制文件有执行权限
RUN chmod +x ./server
# 创建日志目录
RUN mkdir -p ./logs
# 暴露端口
EXPOSE 8888
# 运行服务
CMD ["./server"]
2️⃣ 客户端 Dockerfile(client)
- 与 server 类似,构建阶段生成二进制
client - 终镜像阶段同样保证可执行权限,并创建日志目录
- 注意:client 是交互式程序,所以
stdin_open: true和tty: true在 compose 中配置
bash
# 使用官方Golang镜像作为构建环境
FROM golang:1.22.2-alpine AS client-builder
# 设置工作目录
WORKDIR /app
ENV GOPROXY=https://goproxy.cn,direct
# 复制go模块文件
COPY go.mod go.sum ./
# 下载依赖
RUN go mod download
# 复制源代码
COPY . .
# 构建客户端应用
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o client ./client/client.go
# 最终镜像
FROM alpine:latest AS client
WORKDIR /root/
# 从构建阶段复制二进制文件
COPY --from=client-builder /app/client .
# 确保二进制文件有执行权限
RUN chmod +x ./client
# 创建日志目录
RUN mkdir -p ./logs
# 运行客户端
CMD ["./client"]
二、.dockerignore 使用
-
避免无关文件被 COPY 进镜像,提高构建速度
-
常见内容:
.git node_modules logs *.md
三、Docker Compose 配置要点
1️⃣ 服务定义
-
server、client、mysql(可选)分开定义
-
depends_on确保启动顺序,但不保证服务端口就绪 -
environment 配置容器所需变量,例如:
yamlenvironment: SERVER_HOST: server SERVER_PORT: 8888 -
client 设置交互模式:
yamlstdin_open: true tty: true
2️⃣ 网络管理
- 默认情况下,Compose 自动创建
<项目名>_default网络 - 手动创建网络 (
chatroom-net) 并不影响 Compose 默认行为,除非在 compose 文件中指定external networks - 容器 DNS 名称解析依赖于网络,同一 network 下服务名可以互相访问
docker-compose文件:
yaml
# version: '3.8'
services:
# 数据库服务(如果需要)
# mysql:
# image: mysql:8.0
# container_name: chatroom-mysql
# environment:
# MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
# MYSQL_DATABASE: ${DB_NAME}
# MYSQL_USER: ${DB_USER}
# MYSQL_PASSWORD: ${DB_PASSWORD}
# ports:
# - "3306:3306"
# volumes:
# - mysql_data:/var/lib/mysql
# logging:
# driver: "json-file"
# options:
# max-size: "10m" # 单个日志文件最大10MB
# max-file: "3" # 保留3个日志文件
# restart: unless-stopped
# 聊天室服务端
server:
build:
context: .
dockerfile: Dockerfile
target: server #新加一个target标签
container_name: chatroom-server
ports:
- "8888:8888"
# depends_on:
# - mysql
environment:
- DB_HOST=mysql8.0 # mysql容器名
- DB_PORT=3306
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
- DB_NAME=${DB_NAME}
networks:
- chatroom-net # 需要将mysql加入到该网络中
logging:
driver: "json-file"
options:
max-size: "10m" # 单个日志文件最大10MB
max-file: "5" # 保留5个日志文件
restart: unless-stopped
# 聊天室客户端(示例,实际使用时可能需要交互式运行)
client:
build:
context: .
dockerfile: Dockerfile.client
target: client #新加一个targer标签
container_name: chatroom-client
depends_on:
- server
environment:
- SERVER_HOST=server
- SERVER_PORT=8888
stdin_open: true
tty: true
logging:
driver: "json-file"
options:
max-size: "5m" # 单个日志文件最大5MB
max-file: "2" # 保留2个日志文件
# 注意:客户端通常需要交互式运行,所以这主要用于测试目的
networks:
chatroom-net:
external: true
# 告诉所有容器,你已经建立一个网络了,不用在创建网络了
# networks:
# default:
# external:
# name: chatroom-net
# volumes:
# mysql_data:
四、常见问题及解决方法
| 问题 | 原因 | 解决方案 |
|---|---|---|
| client 容器启动立即退出 | Go 程序连接 127.0.0.1:8888 → 连接不到 server |
将 client 代码改为 conn, err := net.Dial("tcp", "server:8888") 或使用环境变量读取 host/port |
client 报 server misbehaving |
client 不在 server 同一网络,DNS 无法解析 | 删除旧 client 容器,使用 docker compose up -d client 或 docker network connect |
Docker Compose 自动生成 chatroomplus_default |
Compose 默认网络机制 | 可以通过 networks: default: external: name: chatroom-net 指定使用自定义网络 |
| 修改 client/server 代码后旧镜像未更新 | 镜像是静态文件,不会自动刷新 | 重新 build client 镜像:docker compose build client --no-cache |
五、调试技巧
-
查看容器日志:
bashdocker logs -f chatroom-client docker logs -f chatroom-server -
进入容器调试:
bashdocker exec -it chatroom-client /bin/sh # 或者 attach docker attach chatroom-client -
检查网络和 DNS:
bashdocker network inspect chatroomplus_default ping server # 在容器内测试 DNS 是否解析 -
容器交互式启动:
- client 是 CLI,需要
stdin_open: true+tty: true
- client 是 CLI,需要
六、最佳实践总结
- 多阶段构建:减少镜像体积,仅拷贝编译好的二进制
- 环境变量配置:程序不要写死 IP,容器间通信使用服务名 + 环境变量
- 网络管理:同一 Compose 网络内 DNS 名称可互相访问
- 容器重建策略:修改代码后,只 rebuild 需要更新的服务,旧服务可以保留
- 日志和调试:保证容器日志可查,调试方便
七、本篇注意点:
1.docker镜像源的更换需要重启docker才能使用
bash
# 重启docker
sudo systemctl restart docker
# 清理旧缓存
docker system prune -f # 清理无用镜像/缓存
2.客户端进入方式
bash
# 依据# 运行客户端
# CMD ["./client"]
# 所以启动方式是:
.client
注意:当 dockerfile和dockerfile-client写在同级目录中时,需要注意不能使用相同的构建名,否则同时搭建镜像时,构建名字相同后后者顶替前者,导致构建文件无法找到
对于客户端容器启动失败原因:
client没有 和server在同一个网络中,需要让两个容器 在同一个网络中。
删除原来容器,重新创建。(不用)
bash
docker rm chatroom-client
docker compose up -d client
对于某个容器启动失败,修改该容器网络,使通信的容器在同一个网络内,然后可以单独启动该容器,不用每次都启动使用docker compose up -d
手动把现有的client容器加入网络。
bash
# 连接到 chatroomplus_default 网络
docker network connect chatroomplus_default chatroom-client
# 重启 client
docker restart chatroom-client
八、构建并运行
如果go文件有变动,需要重新构建,使用代码
docker compose build --no-cache来确保使用最新的代码和依赖。
注意构建完毕后需要手动把原来的镜像删除。
输入docker compose up -d直接运行即可。
运行完后,可以通过docker compose logs 服务名 [-f]来查看运行状态和日志输出
注意:进入mysql容器时,输入docker exec -it netchat-mysql /bin/bash,最后的路径是/bin/bash
进入客户端容器是,输入docker exec -it chatroom-client /bin/sh,最后的路径是/bin/sh(Alpine Linux 默认使用 sh)