Nginx 容器化部署实战与 Go Web 项目全栈 Docker 化之路

一、项目构建

1. 修改配置

config.toml 中 host 需要改为 0.0.0.0,否则 Go 服务只监听本地回环(原本默认设置为 127.0.0.1)

2. 本地构建前端

进入到前端文件夹,安装前端所需依赖,然后执行构建操作。

cd vue-frontend
npm install
npm run build

生成 vue-frontend/dist/ 静态文件,将该文件上传到服务器

3. 本地交叉编译 Go 后端

在 GoNexus 项目中一共有两个服务需要启动,一个是 GoNexus 本身的服务,另一个是 MCP 服务,两者都要进行交叉编译

在项目根目录执行以下两条命令:

cd ../
GOOS=linux GOARCH=amd64 go build -o gonexus .
GOOS=linux GOARCH=amd64 go build -o gonexus-mcp ./common/mcp/main.go

得到两个可执行的二进制文件

二、上传到服务器

/opt/gonexus/
├── gonexus # 主服务二进制
├── gonexus-mcp # MCP服务二进制
├── config/
————└ config.toml
└── dist/ # Vue 构建产物(静态文件)

如上所示,在 liunx 服务器上创建对应的文件目录

三、配置 Nginx

部署 Nginx 请先阅读这里。首次部署 Nginx 后,为了操作配置文件,需要将 Nginx 配置文件从 Docker 容器中拷贝到宿主机服务器上才好操作。本项目的 nginx 配置文件已经拷贝到 /data/nginx/conf/ 目录下,在该目录中创建 conf.d 文件,编辑 conf.d 文件下入以下内容

server {
    listen 80;
    server_name 140.143.239.3;

    # 前端静态文件
    root /usr/share/nginx/html;
    index index.html;

    # Vue Router history 模式支持
    location / {
        try_files $uri $uri/ /index.html;
    }

    # API 转发: /api/* -> Go 后端 /api/v1/*
    location /api {
        rewrite ^/api/(.*)$ /api/v1/$1 break;
        proxy_pass http://host.docker.internal:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        # SSE 流式响应需要关闭缓冲
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 300s;
    }
}

四、启动服务

使用 nohup 命令启动服务

在 linux 服务器下进入 /opt/gonexus 目录,先启动 MCP 服务再启动主服务

cd /opt/gonexus
nohup ./gonexus-mcp --mode server > gonexus-mcp.log 2>&1 &
nohup ./gonexus > gonexus.log 2>&1 &

上述代码会将 gonexus 服务启动时的日志输出到 gonexus.log 文件中,而 gonexus-mcp 服务没有显式的指明日志文件,则会自动创建一个 nohup.out 文件并写入(已修改写入 gonexus-mcp.log 文件中)。

五、启动容器

docker run -d \
  --name Nginx \
  -p 443:443 -p 80:80 \
  -v /data/nginx/logs:/var/log/nginx \
  -v /opt/gonexus/dist:/usr/share/nginx/html \
  -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
  -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \
  --add-host host.docker.internal:host-gateway \
  --privileged=true \
  --restart=always \
  nginx

在 /data/nginx/conf/conf.d 文件中前端静态文件路径 root 为 /opt/gonexus/dist,启动 Nginx 镜像挂载的前端页面确定存在 -v /opt/gonexus/dist:/usr/share/nginx/html,确保 Nginx 配置生效。

最后检查服务器是否放行了 TCP 80 端口。采用的腾讯云服务器,腾讯云控制台 -> 安全组,新增入站规则设置端口为 TCP:80。

Docker 中的 Nginx 配置文件复制到了本地,修改本地文件后,将其与容器内的 Nginx 对应的配置文件进行挂载,就可以将本地的配置文件映射到容器内部,覆盖掉容器默认的配置。

命令格式如下:

-v /本地/文件/路径:/容器内/文件/路径

在本项目中挂载了四个配置文件:日志、前端静态页面、两个 Nginx 配置文件

-v /data/nginx/logs:/var/log/nginx \
-v /opt/gonexus/dist:/usr/share/nginx/html \
-v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /data/nginx/conf/conf.d:/etc/nginx/conf.d \

Nginx 的配置文件挂载多采用配置目录的形式(conf.d/)。Nginx 的默认 nginx.conf 文件中通常会包含一行 include /etc/nginx/conf.d/*.conf,这意味着它会自动加载 conf.d 目录下的所有 .conf 文件。

在本地 /data/nginx/conf/ 目录下创建 conf.d 目录,然后在该目录下创建 app.conf 文件,在该文件中写入配置内容。

因为之前在配置 Nginx 的时候已经运行了一个名为 Nginx 的容器,需要先将其停止并删除,才能用新的配置重新启动。执行以下命令:

docker stop Nginx
docker rm Nginx

然后执行启动容器的命令。

在第四步时启动的 Go 后端服务是直接在宿主机服务器上运行的,并不是在 Docker 容器里(后续会改进),所以 Nginx 配置文件中的 proxy_pass 地址需要使用 host.docker.internal

在启动容器时需要给 docker run 命令加上 –add-host 参数,显示告诉容器 host.docker.internal 对应的是宿主机的网关 IP。

--add-host host.docker.internal:host-gateway \

host-gateway 是 Docker 20.10+ 版本支持的特殊 DNS,它会自动解析为宿主机的 IP。

Go 应用必须监听 0.0.0.0:8080,而不是默认的 127.0.0.1:8080,第一步操作已进行修改。因为如果只监听 127.0.0.1,应用就只接受来自宿主机服务器内部的连接,Docker 容器的请求会被拒绝(Docker 容器的请求被视为外部网络)。

启动 Go 应用后,在宿主机服务器上运行 netstat -tlnp | grep 8080 可以查看 gonexus 进程的监听地址,正确返回 0.0.0.0:8080 或 :::8080。

六、重新启动 Go 后端服务

代码修改完成后需要重新构建、上传和部署运行。详细流程如下:

第一步:前端服务构建,进入前端代码目录执行下述命令:

cd vue-frontend
npm install
npm run build

第二步:后端服务构建,在项目主目录下执行下述命令:

GOOS=linux GOARCH=amd64 go build -o gonexus .
GOOS=linux GOARCH=amd64 go build -o gonexus-mcp ./common/mcp/main.go

第三步:上传文件到宿主机服务器

/opt/gonexus/
├── gonexus # 主服务二进制
├── gonexus-mcp # MCP服务二进制
├── config/
————└ config.toml
└── dist/ # Vue 构建产物(静态文件)

参考上述文件目录结构进行对应文件覆盖。

第四步:重新部署 Nginx 服务

执行下述命令先停掉 Nginx 服务然后再删除,也可以直接去 portainer 界面手动操作

docker stop Nginx
docker rm Nginx

执行下述命令重新启动 Nginx 容器

docker run -d \
  --name Nginx \
  -p 443:443 -p 80:80 \
  -v /data/nginx/logs:/var/log/nginx \
  -v /opt/gonexus/dist:/usr/share/nginx/html \
  -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
  -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \
  --add-host host.docker.internal:host-gateway \
  --privileged=true \
  --restart=always \
  nginx

第五步:将宿主机服务器上正在运行的两个后端服务 gonexus 和 gonexus-mcp 停掉,执行以下命令

pkill -f gonexus-mcp
pkill -f gonexus

第六步:重新启动 gonexus 和 gonexus-mcp 两个后端服务

cd /opt/gonexus
nohup ./gonexus-mcp --mode server > gonexus-mcp.log 2>&1 &
nohup ./gonexus > gonexus.log 2>&1 &

运行失败可查看日志,输入 tail gonexus.log -f 实时显示服务后端日志。

参考阅读:https://bugstack.cn/md/devops/2023-04-18-nginx.html

Categories:

Tags:

No responses yet

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注