文章目录
访问路径ip+端口:端口可以了,但是小程序中不支持该格式,还需要配置nginx代理通过域名访问
1. Go 代码示例(main.go
)
这个示例是一个简单的 Gin Web 服务,监听 8085
端口:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "pong"})
})
r.Run(":8085") // 监听 8085 端口
}
2. Dockerfile
多段构建
使用 Alpine + Go 进行多阶段构建,以减少最终镜像大小:
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY . .
RUN go mod init api/upd-unionid && go mod tidy # 依赖管理
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o upd-unionid updappunionidbyopenid.go # 编译 Go 二进制文件
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/upd-unionid .
# 监听 8085 端口
EXPOSE 8085
# 运行服务
CMD ["./upd-unionid"]
3.构建 Docker 镜像
通过dockerfile构建镜像,然后上传远程仓库,方便使用
## build 使用 Dockerfile 构建镜像(替换 yourusername)
docker build -t yourusername/myapp:latest .
## 打tag,做标记,用于后续推送远程仓库必备步骤
docker tag myapp:v0.1 firehmx/myapp:v0.1
## 登录 Docker Hub(如果是私有仓库,替换仓库地址),本地运行docker账户,直接docker login 可快捷登录
docker login -u username -p password
## 推送镜像到 Docker Hub
docker push yourusername/myapp:latest
docker logout
4. docker-compose.yml
直接拉取镜像
修改 docker-compose.yml
,从远程镜像启动服务:
version: "3.8"
services:
app:
image: upd-unionid:v0.2 # 本地/远程构建的镜像
ports:
- "8085:8085"
restart: always
networks:
- mynetwork
networks:
mynetwork:
driver: bridge
5. 运行容器
# 1. 拉取最新镜像(可选)
docker pull yourusername/myapp:latest
# 2. 启动容器
docker-compose up -d
# 3.关闭服务
docker-compose down
6. 测试 API
到这里,一个go应用的接口,通过ip+端口形式可以在容器环境中运行完成。
curl http://localhost:8085/ping
返回:
{"message":"pong"}
7、配置域名访问
- 具体讲解下apache中配置反向代理,将域名请求代理到ip+端口,这期间走了些弯路。配置单独项目来转发该业务,但是无法正常访问,后来通过在泛域名所在服务中进行配置转发解决。
- 通过问答形式来还原下场景
问: 在A服务器nginx环境下配置项目请求具体域名(wechatapi.xxx.com)转发ip+端口出错,因为该域名在B服务器有Apache环境的泛域名项目(*.xxx.com),没有请求我在A服务器中配置的具体域名,请求了B服务器中泛域名的配置的项目。
答:
7.1、先排查域名所在的ip是哪个。发现确实A服务器配置的项目,访问到了B服务器的项目。
1.验证某一个域名解析的ip地址: dig 域名 +short
场景需求
- 泛域名
*.example.com
解析到默认服务器1.1.1.1
。 - 特定子域名
sub.example.com
解析到另一台服务器2.2.2.2
。
排查泛域名:
- dig random.example.com +short # 应返回 1.1.1.1
具体子域名:
- dig sub.example.com +short # 应返回 2.2.2.2
7.2、直接将我需要的二级域名重新解析到对应服务器中,正常配置也行,不过稍微麻烦,毕竟解析DNS是在老板账户控制。
- 这里是由于A服务器的nginx环境下,有一些域名a.xxx.com和b.xxx.com是可以配置走通,且指定下A服务器所在域名,我就通过复制修改该配置,想将容器化的项目改为新域名,但是由于项目长久,我记不大清了,后来验证,应该是这两域名配置过DNS解析导致的,我新增的服务区没有配置过DNS解析,导致无法请求到具体项目(容器化项目,我改为ip+8086端口是可以访问到)
- 我也验证了C服务器Apache环境下的api.xxx.com,通过dig验证,也是指定C服务器的ip,这些都属于上边提到的泛域名所属域名,只不过均不在一个服务器中,这个C服务器的域名应该也是配置了DNS解析的。
后来我确定应该是DNS解析问题,全貌应该是:泛域名解析到了B服务器中,A服务器又有a.xxx.com和b.xxx.com项目都正常运行,C服务器的api.xxx.com也运行很久了,并且ABC三台服务器都是同一个域名下,子域名的解析会覆盖泛域名的解析,也就是子域名优先级更高,这就解释通了。
这就联系到最经典的面试题:浏览器输入网址到最终页面展示的过程( DNS解析 → 网络连接 → 请求处理 → 数据渲染 ),这里温习下DNS解析过程:
DNS解析:将域名转换为IP地址
- 浏览器缓存:检查浏览器是否缓存过该域名的IP。
- 系统缓存:查询操作系统(如Windows的hosts文件或DNS缓存)。
- 路由器缓存:向本地路由器查询缓存记录。
- ISP的DNS服务器:向互联网服务提供商(ISP)的DNS服务器发起请求。
- 递归查询:
- 若ISP无缓存,依次查询根域名服务器(
.
)→ 顶级域名服务器(.com
)→ 权威域名服务器(example.com
),最终获取IP。
- 若ISP无缓存,依次查询根域名服务器(
- 结果:获得服务器的IP地址。
DNS寻址示例
以查询 www.example.com
为例:
- 浏览器检查缓存 → 未命中。
- 操作系统检查缓存 → 未命中。
- 路由器检查缓存 → 未命中。
- 请求发送到ISP的DNS服务器 → 未命中。
- ISP的DNS服务器发起递归查询:
- 查询根域名服务器,获得
.com
顶级域名服务器地址。 - 查询
.com
顶级域名服务器,获得example.com
权威域名服务器地址。 - 查询
example.com
权威域名服务器,获得www.example.com
的IP地址(如93.184.216.34
)。
- 查询根域名服务器,获得
- ISP的DNS服务器将结果返回给客户端,客户端缓存结果。
DNS记录类型
A记录:将域名映射到IPv4地址。
AAAA记录:将域名映射到IPv6地址。
CNAME记录:将域名指向另一个域名(别名)。
MX记录:指定邮件服务器地址。
NS记录:指定域名服务器。
总结:由于再进行DNS解析,还需要找老板配置,并且还有单独配置项目,毕竟没有项目,这个逻辑就是想配置转发到ip+端口接口,这个就较为繁琐,不是最优方案,接着继续有最优方案。
7.3、在B服务器的项目中配置代理转发是最优方案,且指定具体的路由
在泛域名所在项目的apache的ssl.conf中配置转发ip+端口的可用服务(nginx转发也一样,参考:[每周一更]-(第88期):Nginx 之 proxy_pass使用详解 - 胡梦旭博客,技术博客,个人博客模板, php博客系统,go语言,Python语言),结果:是可以行
# xxx.com泛域名 + 增加了ip+端口的转发 - 完整请求配置 - xxx替换你自己的域名
<VirtualHost *:443>
DocumentRoot "/var/www/html/gkmobile/public"
ServerName xxx.com:443
ServerAlias *.xxx.com:443
Header set Access-Control-Allow-Origin "http://ip"
Header set Access-Control-Allow-Origin "https://域名"
ErrorLog "logs/xxx.com-error_log"
CustomLog "logs/xxx.com-access_log" common
LogLevel warn
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM
SSLHonorCipherOrder on
SSLCertificateFile /etc/httpd/conf/xxx-ssl/xxx.com.cer
SSLCertificateKeyFile /etc/httpd/conf/xxx-ssl/xxx.com.key
SSLCertificateChainFile /etc/httpd/conf/xxx-ssl/fullchain.cer
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/var/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog logs/ssl_request_log \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
SSLProxyEngine on
ProxyPass /api/small https://api.xxx.com/version1/small/
ProxyPassReverse /api/small https://api.xxx.com/version1/small/
# ADD 核心配置:仅在特定子域名+路径时触发转发
ProxyRequests Off
ProxyPreserveHost On
# ADD 条件判断:仅当请求域名为 wechatapi.xxx.com 且路径为 /update_unionid 时转发
RewriteEngine On
RewriteCond %{HTTP_HOST} ^wechatapi\.xxx\.com$ [NC]
RewriteRule ^/update_unionid(.*)$ http://IP:端口/update_unionid$1 [P,L]
</VirtualHost>
详细逻辑:
- 泛域名
*.xxx.com
已经配置了一个虚拟主机(例如处理静态网站)。 - 新增需求:当访问
wechatapi.xxx.com/update_unionid
时,自动转发到另一台服务器的IP:Port/update_unionid
,而其他子域名(如blog.xxx.com
)或路径仍由当前项目处理。
直接访问 wechatapi.xxx.com/update_unionid 请求正常了,到此整个逻辑就完整了。
8.错误记录
5.1、问:ERROR: failed to solve: golang:1.23-alpine: failed to resolve source metadata for docker.io/library/golang:1.23-alp
ine: failed to authorize: failed to fetch oauth token: Post “https://auth.docker.io/token”: dial tcp 31.13.69.245:4
43: connectex: A connection attempt failed because the connected party did not properly respond after a period of t
ime, or established connection failed because connected host has failed to respond.
该问题集中在服务器中拉去镜像超时连接失败。
答:
Linux系统
步骤 1:修改 Docker Daemon 配置 执行:
vim /etc/docker/daemon.json
添加以下内容:
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com",
"https://dockerproxy.com"
]
}
步骤 2:重启 Docker
systemctl daemon-reload
systemctl restart docker
报错拉取不到镜像就直接拉去: golang:1.23-alpine
Windows
步骤 1:打开 Docker Desktop 设置
- 确保 Docker Desktop 已经启动
- 点击任务栏 Docker 图标 → 进入 “Settings”(设置)
- 在左侧导航栏中,找到 “Docker Engine”
步骤 2:修改 daemon.json 配置
在 “Docker Engine” 选项卡里,你会看到一个 JSON 配置文件,找到 "registry-mirrors"
,修改或添加如下内容:
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com",
"https://docker.mirrors.ustc.edu.cn",
"https://registry.docker-cn.com",
"https://dockerproxy.com"
]
}
注意:如果
"registry-mirrors"
字段不存在,直接添加进去。
步骤 3:应用配置并重启 Docker
点击 “Apply & Restart”(应用并重启),等待 Docker Desktop 重启完成。
2、问:本地docker部署运行正常,但是linux报错:Using default tag: latest
Error response from daemon: Get “https://registry-1.docker.io/v2/”: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
答:
windows返回如下证明本地API接通:
{
"code": -1,
"msg": "fail",
"data": {
"error": "微信 API 错误: invalid code, rid: 67d7db58-4d4f29d9-5c73463c"
}
}
阿里云工程师提供的代理镜像就可以(配置一些其他加速地址):
操作步骤
vim /etc/docker/daemon.json,将如下配置添加进去
service restart docker
{
"registry-mirrors": [
"https://docker.registry.cyou",
"https://docker-cf.registry.cyou",
"https://dockercf.jsdelivr.fyi",
"https://docker.jsdelivr.fyi",
"https://dockertest.jsdelivr.fyi",
"https://mirror.aliyuncs.com",
"https://dockerproxy.com",
"https://mirror.baidubce.com",
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://docker.mirrors.sjtug.sjtu.edu.cn",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.iscas.ac.cn",
"https://docker.rainbond.cc"]
}
这里说明下:提供了其他registry-mirrors,寻求了各大AI工具,均不行,且测试本地流程都可以,就是ECS不行(采用阿里云给的就可以)
如本地可拉取, 可docker save导出为tar.gz文件,然后上传到自己的机器,使用docker load -i XXX.tar.gz解压出来使用。
如果是正式环境业务,可评估将镜像上传到自建仓库管理,通过自建仓库拉取,避免依赖外部仓库通信,影响后续业务稳定性。、
容器镜像个人版免费管理可参考:https://help.aliyun.com/zh/acr/user-guide/use-a-container-registry-personal-edition-instance-to-push-and-pull-images