[每周一更]-(第137期):Go + Gin 实战:Docker Compose + Apache 反向代理全流程

文章目录
- **1. Go 代码示例(`main.go`)**
- **2. `Dockerfile` 多段构建**
- 3.构建 Docker 镜像
- **4. `docker-compose.yml` 直接拉取镜像**
- **5. 运行容器**
- **6. 测试 API**
- 7、配置域名访问
- **DNS解析:将域名转换为IP地址**
- **DNS寻址示例**
- 8.错误记录
访问路径ip+端口:端口可以了,但是小程序中不支持该格式,还需要配置nginx代理通过域名访问
1. Go 代码示例(main.go)
这个示例是一个简单的 Gin Web 服务,监听 8085 端口:
package mainimport ("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:latestdocker logout
4. docker-compose.yml 直接拉取镜像
修改 docker-compose.yml,从远程镜像启动服务:
version: "3.8"
services:app:image: upd-unionid:v0.2 # 本地/远程构建的镜像ports:- "8085:8085"restart: alwaysnetworks:- mynetworknetworks: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:443ServerAlias *.xxx.com:443Header 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" commonLogLevel warnSSLEngine onSSLProtocol all -SSLv2 -SSLv3SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUMSSLHonorCipherOrder onSSLCertificateFile /etc/httpd/conf/xxx-ssl/xxx.com.cerSSLCertificateKeyFile /etc/httpd/conf/xxx-ssl/xxx.com.keySSLCertificateChainFile /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.0CustomLog logs/ssl_request_log \"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"SSLProxyEngine onProxyPass /api/small https://api.xxx.com/version1/small/ProxyPassReverse /api/small https://api.xxx.com/version1/small/# ADD 核心配置:仅在特定子域名+路径时触发转发ProxyRequests OffProxyPreserveHost On# ADD 条件判断:仅当请求域名为 wechatapi.xxx.com 且路径为 /update_unionid 时转发RewriteEngine OnRewriteCond %{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
相关文章:
[每周一更]-(第137期):Go + Gin 实战:Docker Compose + Apache 反向代理全流程
文章目录 **1. Go 代码示例(main.go)****2. Dockerfile 多段构建**3.构建 Docker 镜像**4. docker-compose.yml 直接拉取镜像****5. 运行容器****6. 测试 API**7、配置域名访问**DNS解析:将域名转换为IP地址****DNS寻址示例** 8.错误记录 访问…...
HTTPS 加密过程详解
HTTPS 详解及其加密过程流程框架 HTTPS(Hypertext Transfer Protocol Secure)是一种基于 HTTP 协议的安全通信协议,通过 SSL/TLS 协议对传输数据进行加密和身份验证,解决了 HTTP 明文传输的安全隐患。以下是其核心原理和加密流程的…...
SpringCache小记
Spring Cache 小记 官方文档:https://springdoc.cn/spring-cache-tutorial/ 基础知识 常用注解 EnableCaching:开启缓存功能,一般放在启动类上。 Cacheable:表示该方法支持缓存。当调用被注解的方法时,如果对应的键已…...
Web-Machine-N7靶机通关攻略
获取靶机ip arp-scan -l 端口扫描 nmap xxxx 访问80端口发现没用 扫描目录 gobuster dir -u http:/192.168.117.160 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium,txt -x php,html,txt ,zip 打开exploit.html 点击F12,修改localhost为靶机ip&#…...
笔记本运行边缘计算
笔记本电脑可以用来运行PCDN(Peer-to-Peer Content Delivery Network)服务。实际上,如果你有闲置的笔记本电脑,并且它具备一定的硬件条件和网络环境,那么它可以成为一个不错的PCDN节点。 运行PCDN的基本要求 硬件需求…...
self Attention为何除以根号dk?(全新角度)
全网最独特解析:self Attention为何除根号dk? 一、假设条件:查询向量和键向量服从正态分布 假设查询向量 q i q_i qi和键向量 k j k_j kj的每个分量均为独立同分布的随机变量,且服从标准正态分布,即:…...
第十五次CCF-CSP认证(含C++源码)
第十五次CCF-CSP认证 小明上学满分思路 数据中心满分思路 小明放学满分题解 小明上学 题目链接 满分思路 其实题目看着长,但是做起来是非常好写的,其实主要原因在于,他的红绿灯的变化规律是一定的,而且小明路上的每次红绿灯情况…...
基于Azure Delta Lake与Databricks的医疗数据变更管理
设计Azure云架构方案实现Azure Delta Lake和Azure Databricks,在医疗场景下记录所有数据变更,满足合规性要求(如 GDPR),并具备回滚能力,能快速恢复误删数据(如 RESTORE TABLE table VERSION AS …...
简述Mybatis的插件运行原理,以及如何编写一个插件?
MyBatis 插件运行原理 MyBatis 插件的核心原理基于 Java 的动态代理和责任链模式。下面详细阐述其工作机制: 动态代理 MyBatis 允许你在四大核心对象(Executor、StatementHandler、ParameterHandler 和 ResultSetHandler)的方法执行前后进…...
Java-servlet(七)详细讲解Servlet注解
Java-servlet(七)详细讲解Servlet注解 前言一、注解的基本概念二、Override 注解2.1 作用与优势2.2 示例代码 三、Target 注解3.1 定义与用途3.2 示例代码 四、WebServlet 注解4.1 作用4.2 示例代码 五、反射与注解5.1 反射的概念5.2 注解与反射的结合使…...
SQLark 实战 | 如何通过对象名和 DDL 快速搜索数据库对象
在数据库运维管理、应用开发和问题定位时,常常需要搜索相关的数据库对象。本文将为你介绍如何使用 SQLark 的搜索功能,实现对数据库对象的快速查找与定位。 👉 前往 SQLark 官网:www.sqlark.com 下载全功能免费版。 通过对象名称搜…...
C/S模型-TCP
下图是基于TCP协议的客户端/服务器程序的一般流程: TCP协议通讯流程 服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SY…...
51c自动驾驶~合集24
我自己的原文哦~ https://blog.51cto.com/whaosoft/11926510 #DriveArena 上海AI Lab又放大招:首个高保真闭环生成仿真平台 仓库链接:https://github.com/PJLab-ADG/DriveArena 项目链接:https://pjlab-adg.github.io/DriveArena/ D…...
19.哈希表的实现
1.哈希的概念 哈希(hash)⼜称散列,是⼀种组织数据的⽅式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系,查找时通过这个哈希函数计算出Key存储的位置,进⾏快速查找。 1.2.直接定址法…...
【PCB工艺】晶体管的发展历史
晶体管被认为是20世纪最伟大的发明之一,因为没有晶体管就不会有现代电脑、手机或平板,你也无法阅读到这里的内容,因为不存在网络。 ——本文纯粹出于对过往奋斗在这个领域中科学家的缅怀。科学家有太多宝贵的思想和经验值得我们认真总结和…...
通向AGI的未来之路!首篇2D/视频/3D/4D统一生成框架全景综述(港科大中山等)
文章链接: https://arxiv.org/pdf/2503.04641 摘要 理解并复现现实世界是人工通用智能(AGI)研究中的一个关键挑战。为实现这一目标,许多现有方法(例如世界模型)旨在捕捉支配物理世界的基本原理࿰…...
C# BindingFlags 使用详解
总目录 前言 在 C# 编程的世界里,反射(Reflection)是一个强大且灵活的特性,它允许我们在运行时动态地获取和操作类型的信息。而 BindingFlags 枚举类型,作为反射中的核心概念之一,为我们提供了精确控制类型…...
【亚马逊云科技】大模型选型实战(挑选和测评对比最适合业务的大模型)
文章目录 前言1、实验内容2、手册内容 一、环境准备二、Prompt 实战与模型配置2.1 基于 Amazon Bedrock 对比测试不同模型的逻辑推理效果2.2 基于 Amazon Bedrock 对比测试不同模型知识问答能力2.3 Prompt 实战结果分析 三、基于 Amazon Bedrock Evaluations 进行模型评测与自动…...
调用feapder作为子程序时setting.py文件不起作用
feaper 官方文档地址: 简介及安装 - feapder官方文档|feapder-document 问题: 在最近的开发中需要调用feapder作为主程序调用的子程序时发现自动入库时无法入库,通过查看日志信息发现连接数据库时被拒绝连接了,但是我的setting.p…...
神经网络量化3-全连接层实现量化
本节,我们模拟下全连接层实现量化,原理上为了方便计算,全连接矩阵采用动态量化的方法,而输入由于不断在变化,我们采用静态量化的方法,直接给出代码: import torch import numpy as np import m…...
【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试
【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试 Web系统测试Web系统基本组成Web系统的服务器端应用特点Web系统测试的分类Web应用系统测试的实施功能测试链接测试表单测试性能测试连接速度测试负载测试压力测试可用性测试导航测试图形测试内容测试表格测试…...
G-Star 校园开发者计划·黑科大|开源第一课之 Git 入门
万事开源先修 Git。Git 是当下主流的分布式版本控制工具,在软件开发、文档管理等方面用处极大。它能自动记录文件改动,简化合并流程,还特别适合多人协作开发。学会 Git,就相当于掌握了一把通往开源世界的钥匙,以后参与…...
笔记:代码随想录算法训练营day58:101.孤岛的总面积、102.沉没孤岛、103.水流问题、104.建造最大岛屿
学习资料:代码随想录 文中含大模型生成内容 101. 孤岛的总面积 卡码网:101. 孤岛的总面积 所以找周边都是水的陆地的方法就是找边缘的陆地然后删除它连同它的连通的陆地 深搜 #include <iostream> #include <vector> using namespac…...
5.0 VisionPro调用USB相机的方法与步骤说明(一)
本文介绍如何在C#中调用visionPro以处理USB相机采集到的图片。示例如下: 主要思路如下: 1. 使用AForge来打开以及采集usb相机照片。 usb相机处于一直运行状态。每隔100ms采集一次照片。且触发一次事件。 public void Start() { this.videoSourcePlayer.Stop(); …...
微信小程序计算属性与监听器:miniprogram-computed
小程序框架没有提供计算属性相关的 api ,但是官方为开发者提供了拓展工具库 miniprogram-computed。 该工具库提供了两个功能: 计算属性 computed监听器 watch 一、安装 miniprogram-computed 在项目的根目录下,使用如下命令,…...
强大的AI网站推荐(第二集)—— V0.dev
网站:V0.dev 号称:前端开发神器,专为开发人员和设计师设计,能够使用 AI 生成 React 代码 博主评价:生成的UI效果太强大了,适合需要快速创建UI原型的设计师和开发者 推荐指数:🌟&…...
整理和总结微信小程序的高频知识点
前言 近期萌生了一些想法,感觉可以做一个小程序作为产出。 但小程序做得比较少,因此边做边复习。整理和总结了一些高频知识点和大家一起分享。 一、模板和组件 1.1模板(Template) 优势 简单灵活:模板定义和使用都较…...
vue中js简单创建一个事件中心/中间件/eventBus
vue中js简单创建一个事件中心/中间件/eventBus 目录结构如下: eventBus.js class eventBus {constructor() {this.events {};}// 监听事件on(event, callback) {if (!this.events[event]) {this.events[event] [];}this.events[event].push(callback);}// 发射…...
01. Linux嵌入式系统学习笔记(一)
一. linux基础操作指令 1. 新建文件和目录 (1) 新建文件 touch 命令:用于创建空文件。 touch filename.txt 如果文件已存在,touch 会更新文件的访问时间和修改时间。 (2) 新建目录 mkdir 命令:用于创建目录。 mkdir directoryname 使…...
【从零开始学习计算机科学】软件测试(十)嵌入式系统测试、游戏开发与测试过程、移动应用软件测试 与 云应用软件测试
【从零开始学习计算机科学】软件测试(十)嵌入式系统测试、游戏开发与测试过程、移动应用软件测试 与 云应用软件测试 嵌入式系统测试测试策略及测试流程嵌入式软件测试问题及测试方法嵌入式软件的测试流程游戏开发与测试过程游戏开发与通用软件的开发过程区别游戏测试主要内容…...
