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

news2025/3/24 22:54:03

在这里插入图片描述

文章目录

      • **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 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地址
  1. 浏览器缓存:检查浏览器是否缓存过该域名的IP。
  2. 系统缓存:查询操作系统(如Windows的hosts文件或DNS缓存)。
  3. 路由器缓存:向本地路由器查询缓存记录。
  4. ISP的DNS服务器:向互联网服务提供商(ISP)的DNS服务器发起请求。
  5. 递归查询
    • 若ISP无缓存,依次查询根域名服务器(.)→ 顶级域名服务器(.com)→ 权威域名服务器(example.com),最终获取IP。
  • 结果:获得服务器的IP地址。
DNS寻址示例

以查询 www.example.com 为例:

  1. 浏览器检查缓存 → 未命中。
  2. 操作系统检查缓存 → 未命中。
  3. 路由器检查缓存 → 未命中。
  4. 请求发送到ISP的DNS服务器 → 未命中。
  5. ISP的DNS服务器发起递归查询:
    • 查询根域名服务器,获得 .com 顶级域名服务器地址。
    • 查询 .com 顶级域名服务器,获得 example.com 权威域名服务器地址。
    • 查询 example.com 权威域名服务器,获得 www.example.com 的IP地址(如 93.184.216.34)。
  6. 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 设置

  1. 确保 Docker Desktop 已经启动
  2. 点击任务栏 Docker 图标 → 进入 “Settings”(设置)
  3. 在左侧导航栏中,找到 “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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2319861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringCache小记

Spring Cache 小记 官方文档&#xff1a;https://springdoc.cn/spring-cache-tutorial/ 基础知识 常用注解 EnableCaching&#xff1a;开启缓存功能&#xff0c;一般放在启动类上。 Cacheable&#xff1a;表示该方法支持缓存。当调用被注解的方法时&#xff0c;如果对应的键已…

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&#xff0c;修改localhost为靶机ip&#…

第十五次CCF-CSP认证(含C++源码)

第十五次CCF-CSP认证 小明上学满分思路 数据中心满分思路 小明放学满分题解 小明上学 题目链接 满分思路 其实题目看着长&#xff0c;但是做起来是非常好写的&#xff0c;其实主要原因在于&#xff0c;他的红绿灯的变化规律是一定的&#xff0c;而且小明路上的每次红绿灯情况…

Java-servlet(七)详细讲解Servlet注解

Java-servlet&#xff08;七&#xff09;详细讲解Servlet注解 前言一、注解的基本概念二、Override 注解2.1 作用与优势2.2 示例代码 三、Target 注解3.1 定义与用途3.2 示例代码 四、WebServlet 注解4.1 作用4.2 示例代码 五、反射与注解5.1 反射的概念5.2 注解与反射的结合使…

SQLark 实战 | 如何通过对象名和 DDL 快速搜索数据库对象

在数据库运维管理、应用开发和问题定位时&#xff0c;常常需要搜索相关的数据库对象。本文将为你介绍如何使用 SQLark 的搜索功能&#xff0c;实现对数据库对象的快速查找与定位。 &#x1f449; 前往 SQLark 官网&#xff1a;www.sqlark.com 下载全功能免费版。 通过对象名称搜…

C/S模型-TCP

下图是基于TCP协议的客户端/服务器程序的一般流程&#xff1a; TCP协议通讯流程 服务器调用socket()、bind()、listen()完成初始化后&#xff0c;调用accept()阻塞等待&#xff0c;处于监听端口的状态&#xff0c;客户端调用socket()初始化后&#xff0c;调用connect()发出SY…

51c自动驾驶~合集24

我自己的原文哦~ https://blog.51cto.com/whaosoft/11926510 #DriveArena 上海AI Lab又放大招&#xff1a;首个高保真闭环生成仿真平台 仓库链接&#xff1a;https://github.com/PJLab-ADG/DriveArena 项目链接&#xff1a;https://pjlab-adg.github.io/DriveArena/ D…

19.哈希表的实现

1.哈希的概念 哈希(hash)⼜称散列&#xff0c;是⼀种组织数据的⽅式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进⾏快速查找。 1.2.直接定址法…

【PCB工艺】晶体管的发展历史

晶体管被认为是20世纪最伟大的发明之一&#xff0c;因为没有晶体管就不会有现代电脑、手机或平板​​&#xff0c;你也无法阅读到这里的内容&#xff0c;因为不存在网络。 ——本文纯粹出于对过往奋斗在这个领域中科学家的缅怀。科学家有太多宝贵的思想和经验值得我们认真总结和…

通向AGI的未来之路!首篇2D/视频/3D/4D统一生成框架全景综述(港科大中山等)

文章链接&#xff1a; https://arxiv.org/pdf/2503.04641 摘要 理解并复现现实世界是人工通用智能&#xff08;AGI&#xff09;研究中的一个关键挑战。为实现这一目标&#xff0c;许多现有方法&#xff08;例如世界模型&#xff09;旨在捕捉支配物理世界的基本原理&#xff0…

【亚马逊云科技】大模型选型实战(挑选和测评对比最适合业务的大模型)

文章目录 前言1、实验内容2、手册内容 一、环境准备二、Prompt 实战与模型配置2.1 基于 Amazon Bedrock 对比测试不同模型的逻辑推理效果2.2 基于 Amazon Bedrock 对比测试不同模型知识问答能力2.3 Prompt 实战结果分析 三、基于 Amazon Bedrock Evaluations 进行模型评测与自动…

调用feapder作为子程序时setting.py文件不起作用

feaper 官方文档地址&#xff1a; 简介及安装 - feapder官方文档|feapder-document 问题&#xff1a; 在最近的开发中需要调用feapder作为主程序调用的子程序时发现自动入库时无法入库&#xff0c;通过查看日志信息发现连接数据库时被拒绝连接了&#xff0c;但是我的setting.p…

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试

【从零开始学习计算机科学】软件测试(九)Web系统测试 与 数据库测试 Web系统测试Web系统基本组成Web系统的服务器端应用特点Web系统测试的分类Web应用系统测试的实施功能测试链接测试表单测试性能测试连接速度测试负载测试压力测试可用性测试导航测试图形测试内容测试表格测试…

G-Star 校园开发者计划·黑科大|开源第一课之 Git 入门

万事开源先修 Git。Git 是当下主流的分布式版本控制工具&#xff0c;在软件开发、文档管理等方面用处极大。它能自动记录文件改动&#xff0c;简化合并流程&#xff0c;还特别适合多人协作开发。学会 Git&#xff0c;就相当于掌握了一把通往开源世界的钥匙&#xff0c;以后参与…

5.0 VisionPro调用USB相机的方法与步骤说明(一)

本文介绍如何在C#中调用visionPro以处理USB相机采集到的图片。示例如下: 主要思路如下: 1. 使用AForge来打开以及采集usb相机照片。 usb相机处于一直运行状态。每隔100ms采集一次照片。且触发一次事件。 public void Start() { this.videoSourcePlayer.Stop(); …

微信小程序计算属性与监听器:miniprogram-computed

小程序框架没有提供计算属性相关的 api &#xff0c;但是官方为开发者提供了拓展工具库 miniprogram-computed。 该工具库提供了两个功能&#xff1a; 计算属性 computed监听器 watch 一、安装 miniprogram-computed 在项目的根目录下&#xff0c;使用如下命令&#xff0c;…

强大的AI网站推荐(第二集)—— V0.dev

网站&#xff1a;V0.dev 号称&#xff1a;前端开发神器&#xff0c;专为开发人员和设计师设计&#xff0c;能够使用 AI 生成 React 代码 博主评价&#xff1a;生成的UI效果太强大了&#xff0c;适合需要快速创建UI原型的设计师和开发者 推荐指数&#xff1a;&#x1f31f;&…

整理和总结微信小程序的高频知识点

前言 近期萌生了一些想法&#xff0c;感觉可以做一个小程序作为产出。 但小程序做得比较少&#xff0c;因此边做边复习。整理和总结了一些高频知识点和大家一起分享。 一、模板和组件 1.1模板&#xff08;Template&#xff09; 优势 简单灵活&#xff1a;模板定义和使用都较…

vue中js简单创建一个事件中心/中间件/eventBus

vue中js简单创建一个事件中心/中间件/eventBus 目录结构如下&#xff1a; eventBus.js class eventBus {constructor() {this.events {};}// 监听事件on(event, callback) {if (!this.events[event]) {this.events[event] [];}this.events[event].push(callback);}// 发射…

# [RPA] 使用八爪鱼进行高效网页数据采集

在许多行业中&#xff0c;数据是核心资产。然而&#xff0c;虽然许多网站的文本内容可以免费访问&#xff0c;但手动一条一条采集&#xff0c;不仅耗时耗力&#xff0c;还容易出错。这种情况下&#xff0c;使用自动化工具来提高采集效率就显得尤为重要。本文将介绍 八爪鱼 这一…