外观
Go应用Linux服务器部署完整指南
本文详细介绍如何将Go应用从本地开发环境部署到Linux服务器,包括交叉编译、自动化部署脚本、Systemd服务管理、Nginx反向代理配置以及安全最佳实践。
前置要求
本地环境
Go 1.21 或更高版本
go version # 需要 Go 1.21+SSH 客户端
- macOS/Linux: 系统自带
- Windows: 使用 Git Bash 或 WSL
服务器 SSH 访问权限
- SSH 密钥文件(推荐)
- 或用户名密码
服务器环境
Linux 系统
- Ubuntu/Debian(推荐)
- CentOS/RHEL
- 其他主流 Linux 发行版
Systemd
- 现代 Linux 系统默认已安装
- 用于服务管理
Nginx(可选但推荐)
- 用于反向代理
- 提供 HTTPS 支持
部署方法
方法一:使用自动化部署脚本(推荐)
deploy.sh 脚本内容:
#!/bin/bash
# Go 应用部署脚本
# 使用方法:
# ./deploy.sh [服务器IP] [用户名] [部署路径] [SSH密钥文件]
# 或设置环境变量: export SSH_KEY=/path/to/key.pem
# 然后: ./deploy.sh [服务器IP] [用户名] [部署路径]
#
# 选项:
# - 设置环境变量 SKIP_CONFIG=1 可以跳过配置文件的部署(只更新二进制文件)
# 例如: SKIP_CONFIG=1 ./deploy.sh 192.168.1.100 root /opt/blog-api
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 配置参数
SERVER_IP=${1:-"your-server-ip"}
SERVER_USER=${2:-"root"}
DEPLOY_PATH=${3:-"/opt/blog-api"}
SSH_KEY=${4:-${SSH_KEY:-""}} # 支持参数或环境变量
SKIP_CONFIG=${SKIP_CONFIG:-"0"} # 是否跳过配置文件部署(0=部署,1=跳过)
APP_NAME="blog-api"
BINARY_NAME="blog-api"
# 构建 SSH 选项
SSH_OPTS=""
SCP_OPTS=""
if [ -n "$SSH_KEY" ]; then
if [ ! -f "$SSH_KEY" ]; then
echo -e "${RED}错误: SSH 密钥文件不存在: $SSH_KEY${NC}"
exit 1
fi
SSH_OPTS="-i $SSH_KEY"
SCP_OPTS="-i $SSH_KEY"
echo -e "${GREEN}使用 SSH 密钥文件: $SSH_KEY${NC}"
fi
echo -e "${GREEN}开始部署 Go 应用到 Linux 服务器...${NC}"
# 1. 编译 Linux 版本
echo -e "${YELLOW}步骤 1: 编译 Linux 版本...${NC}"
GOOS=linux GOARCH=amd64 go build -o ${BINARY_NAME} -ldflags="-s -w" main.go
if [ $? -ne 0 ]; then
echo -e "${RED}编译失败!${NC}"
exit 1
fi
echo -e "${GREEN}编译成功!${NC}"
# 2. 创建部署目录结构
echo -e "${YELLOW}步骤 2: 创建部署目录...${NC}"
ssh ${SSH_OPTS} ${SERVER_USER}@${SERVER_IP} "mkdir -p ${DEPLOY_PATH}/logs" || {
echo -e "${RED}SSH 连接失败!请检查:${NC}"
echo -e " 1. 服务器 IP 和用户名是否正确"
echo -e " 2. SSH 密钥文件路径是否正确(如果使用)"
echo -e " 3. 网络连接是否正常"
exit 1
}
# 3. 传输文件到服务器
echo -e "${YELLOW}步骤 3: 传输文件到服务器...${NC}"
scp ${SCP_OPTS} ${BINARY_NAME} ${SERVER_USER}@${SERVER_IP}:${DEPLOY_PATH}/ || {
echo -e "${RED}文件传输失败!${NC}"
exit 1
}
# 根据 SKIP_CONFIG 决定是否传输配置文件
if [ "$SKIP_CONFIG" = "1" ]; then
echo -e "${YELLOW}跳过配置文件传输(SKIP_CONFIG=1)${NC}"
else
scp ${SCP_OPTS} blog-api.service ${SERVER_USER}@${SERVER_IP}:/tmp/ 2>/dev/null || echo "跳过 systemd 服务文件传输"
scp ${SCP_OPTS} nginx-blog-api.conf ${SERVER_USER}@${SERVER_IP}:/tmp/ 2>/dev/null || echo "跳过 Nginx 配置文件传输"
fi
# 4. 设置执行权限
echo -e "${YELLOW}步骤 4: 设置执行权限...${NC}"
ssh ${SSH_OPTS} ${SERVER_USER}@${SERVER_IP} "chmod +x ${DEPLOY_PATH}/${BINARY_NAME}"
# 5. 安装 systemd 服务(如果存在且未跳过配置)
if [ "$SKIP_CONFIG" != "1" ] && [ -f "blog-api.service" ]; then
echo -e "${YELLOW}步骤 5: 安装 systemd 服务...${NC}"
ssh ${SSH_OPTS} ${SERVER_USER}@${SERVER_IP} "sudo cp /tmp/blog-api.service /etc/systemd/system/ && sudo systemctl daemon-reload"
echo -e "${GREEN}服务已安装,使用以下命令管理:${NC}"
echo -e " 启动: ${GREEN}sudo systemctl start blog-api${NC}"
echo -e " 停止: ${GREEN}sudo systemctl stop blog-api${NC}"
echo -e " 重启: ${GREEN}sudo systemctl restart blog-api${NC}"
echo -e " 状态: ${GREEN}sudo systemctl status blog-api${NC}"
echo -e " 开机自启: ${GREEN}sudo systemctl enable blog-api${NC}"
elif [ "$SKIP_CONFIG" = "1" ]; then
echo -e "${YELLOW}步骤 5: 跳过 systemd 服务配置(SKIP_CONFIG=1)${NC}"
fi
# 6. 配置 Nginx(如果配置文件存在且未跳过配置)
if [ "$SKIP_CONFIG" != "1" ] && [ -f "nginx-blog-api.conf" ]; then
echo -e "${YELLOW}步骤 6: 配置 Nginx 反向代理...${NC}"
echo -e "${YELLOW}注意: 请先修改 nginx-blog-api.conf 中的 server_name 为你的域名或 IP${NC}"
ssh ${SSH_OPTS} ${SERVER_USER}@${SERVER_IP} "
if [ -f /tmp/nginx-blog-api.conf ]; then
# 检测系统类型(CentOS 或 Ubuntu/Debian)
if [ -d /etc/nginx/conf.d ]; then
# CentOS/RHEL 系统
echo '检测到 CentOS/RHEL 系统,使用 /etc/nginx/conf.d/'
sudo cp /tmp/nginx-blog-api.conf /etc/nginx/conf.d/blog-api.conf
echo 'Nginx 配置文件已安装到 /etc/nginx/conf.d/blog-api.conf'
else
# Ubuntu/Debian 系统
echo '检测到 Ubuntu/Debian 系统,使用 sites-available/sites-enabled'
# 禁用默认站点(避免配置冲突)
if [ -L /etc/nginx/sites-enabled/default ]; then
echo '禁用默认站点以避免配置冲突...'
sudo rm -f /etc/nginx/sites-enabled/default
fi
# 安装 blog-api 配置
sudo cp /tmp/nginx-blog-api.conf /etc/nginx/sites-available/blog-api
if [ ! -L /etc/nginx/sites-enabled/blog-api ]; then
sudo ln -s /etc/nginx/sites-available/blog-api /etc/nginx/sites-enabled/
fi
echo 'Nginx 配置文件已安装到 /etc/nginx/sites-available/blog-api'
echo '默认站点已禁用(如果存在)'
fi
echo '请修改 server_name 后执行: sudo nginx -t && sudo systemctl reload nginx'
fi
" || echo "跳过 Nginx 配置(可能需要手动配置)"
elif [ "$SKIP_CONFIG" = "1" ]; then
echo -e "${YELLOW}步骤 6: 跳过 Nginx 配置(SKIP_CONFIG=1)${NC}"
fi
# 7. 清理本地编译文件
echo -e "${YELLOW}步骤 7: 清理本地文件...${NC}"
rm -f ${BINARY_NAME}
echo -e "${GREEN}部署完成!${NC}"
if [ "$SKIP_CONFIG" = "1" ]; then
echo -e "${YELLOW}注意: 已跳过配置文件部署,仅更新了二进制文件${NC}"
echo -e "${YELLOW}后续步骤:${NC}"
echo -e " 1. 重启 API 服务: ${GREEN}sudo systemctl restart blog-api${NC}"
echo -e " 2. 检查服务状态: ${GREEN}sudo systemctl status blog-api${NC}"
else
echo -e "${YELLOW}后续步骤:${NC}"
echo -e " 1. 启动 API 服务: ${GREEN}sudo systemctl start blog-api${NC}"
echo -e " 2. 设置开机自启: ${GREEN}sudo systemctl enable blog-api${NC}"
if [ -f "nginx-blog-api.conf" ]; then
echo -e " 3. 配置 Nginx:"
echo -e " - 编辑配置文件: ${GREEN}sudo nano /etc/nginx/sites-available/blog-api${NC}"
echo -e " - 修改 server_name 为你的域名或 IP"
echo -e " - 测试配置: ${GREEN}sudo nginx -t${NC}"
echo -e " - 重载 Nginx: ${GREEN}sudo systemctl reload nginx${NC}"
echo -e " 4. 访问 API: ${GREEN}http://your-domain.com/api/bing${NC}"
else
echo -e " 3. 访问 API: ${GREEN}http://your-server-ip:57514/api/bing${NC}"
fi
fi自动化部署脚本可以一键完成编译、传输、配置等所有步骤。
1. 修改部署脚本配置
编辑 deploy.sh,修改以下变量:
SERVER_IP="your-server-ip" # 服务器 IP 地址
SERVER_USER="root" # SSH 用户名
DEPLOY_PATH="/opt/blog-api" # 部署路径2. 执行部署脚本
不使用 SSH 密钥(使用密码或已配置 SSH 密钥):
chmod +x deploy.sh
./deploy.sh [服务器IP] [用户名] [部署路径]
# 示例
./deploy.sh 192.168.1.100 root /opt/blog-api使用 SSH 密钥文件(.pem 文件):
chmod +x deploy.sh
./deploy.sh [服务器IP] [用户名] [部署路径] [SSH密钥文件路径]
# 示例
./deploy.sh 192.168.1.100 ubuntu /opt/blog-api ~/.ssh/my-server.pem或使用环境变量:
export SSH_KEY=~/.ssh/my-server.pem
./deploy.sh 192.168.1.100 ubuntu /opt/blog-api注意: 如果使用 SSH 密钥文件,请确保密钥文件权限正确:
chmod 400 ~/.ssh/my-server.pem # 设置密钥文件权限跳过配置文件部署(仅更新 Go 程序):
如果只需要更新 Go 二进制文件,不想重新部署配置文件(blog-api.service 和 nginx-blog-api.conf),可以使用 SKIP_CONFIG 环境变量:
# 只更新二进制文件,不更新配置文件
SKIP_CONFIG=1 ./deploy.sh 192.168.1.100 root /opt/blog-api
# 或使用环境变量
export SKIP_CONFIG=1
./deploy.sh 192.168.1.100 root /opt/blog-api💡 使用场景:
- 首次部署:使用默认方式(不设置
SKIP_CONFIG),会部署所有文件- 仅更新 Go 程序:使用
SKIP_CONFIG=1,只更新二进制文件,保留服务器上的配置文件- 需要更新配置文件:使用默认方式,或手动更新服务器上的配置文件
⚠️ 注意事项:
- 使用
SKIP_CONFIG=1时,部署脚本不会传输和更新blog-api.service和nginx-blog-api.conf- 这样可以避免覆盖服务器上手动修改的配置文件
- 如果配置文件有变化,需要手动更新或使用默认方式重新部署
3. 启动服务
部署完成后,SSH 登录服务器执行:
# 启动服务
sudo systemctl start blog-api
# 设置开机自启
sudo systemctl enable blog-api
# 查看状态
sudo systemctl status blog-api部署脚本功能
部署脚本会自动完成以下操作:
- ✅ 交叉编译 - 在本地编译 Linux amd64 版本
- ✅ 创建目录 - 在服务器上创建部署目录和日志目录
- ✅ 传输文件 - 将编译好的二进制文件传输到服务器
- ✅ 设置权限 - 设置二进制文件执行权限
- ✅ 安装服务 - 自动安装 Systemd 服务文件
- ✅ 配置 Nginx - 自动配置 Nginx 反向代理(如果配置文件存在)
方法二:手动部署
如果需要更多控制或了解部署细节,可以手动执行每个步骤。
1. 交叉编译 Linux 版本
在本地(macOS/Windows)交叉编译 Linux 版本:
# 进入项目目录
cd blog-api
# 编译 Linux amd64 版本
GOOS=linux GOARCH=amd64 go build -o blog-api -ldflags="-s -w" main.go
# 参数说明:
# - GOOS=linux: 目标操作系统
# - GOARCH=amd64: 目标架构
# - -ldflags="-s -w": 减小二进制文件大小(去除符号表和调试信息)其他架构编译示例:
# ARM64 (适用于树莓派、云服务器等)
GOOS=linux GOARCH=arm64 go build -o blog-api -ldflags="-s -w" main.go
# 32位系统
GOOS=linux GOARCH=386 go build -o blog-api -ldflags="-s -w" main.go2. 传输到服务器
不使用 SSH 密钥:
# 使用 SCP 传输
scp blog-api user@server-ip:/opt/blog-api/
# 或使用 SFTP
sftp user@server-ip
put blog-api /opt/blog-api/使用 SSH 密钥文件:
# 使用 SCP 传输(带密钥文件)
scp -i ~/.ssh/my-server.pem blog-api user@server-ip:/opt/blog-api/
# 或使用 SFTP
sftp -i ~/.ssh/my-server.pem user@server-ip
put blog-api /opt/blog-api/3. 在服务器上设置权限
# SSH 登录服务器
ssh user@server-ip
# 创建目录并设置权限
sudo mkdir -p /opt/blog-api/logs
sudo chmod +x /opt/blog-api/blog-api
sudo chown -R www-data:www-data /opt/blog-api # Ubuntu/Debian
# 或
sudo chown -R nginx:nginx /opt/blog-api # CentOS/RHEL4. 配置 Systemd 服务
复制服务文件:
# 从项目目录复制服务文件
sudo cp blog-api.service /etc/systemd/system/服务文件内容:
[Unit]
Description=Blog API Service
After=network.target
[Service]
Type=simple
# 注意: CentOS 使用 nginx 用户,Ubuntu/Debian 使用 www-data 用户
User=nginx
Group=nginx
# ⚠️ 重要: 请根据实际部署路径修改以下两个路径
WorkingDirectory=/opt/blog-api # 修改为你的实际部署目录
ExecStart=/opt/blog-api/blog-api # 修改为你的实际二进制文件路径
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=blog-api
# 环境变量(如果需要)
# Environment="GIN_MODE=release"
# Environment="PORT=57514"
# 安全设置
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target⚠️ 重要提示:
WorkingDirectory: 必须设置为你的 Go 应用实际部署的目录路径(例如:/opt/blog-api、/var/www/blog-api等)ExecStart: 必须设置为你的 Go 二进制文件的完整路径(例如:/opt/blog-api/blog-api、/var/www/blog-api/blog-api等)- 这两个路径必须与实际部署路径一致,否则服务无法启动
安装并启动服务:
# 重新加载 systemd
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start blog-api
# 设置开机自启
sudo systemctl enable blog-api
# 查看服务状态
sudo systemctl status blog-api
# 查看日志
sudo journalctl -u blog-api -fSystemd 服务管理
为什么使用 Systemd?
Systemd 是现代 Linux 系统的服务管理器,使用 Systemd 管理 Go 应用有以下优势:
- ✅ 自动重启 - 应用崩溃后自动重启
- ✅ 开机自启 - 服务器重启后自动启动应用
- ✅ 后台运行 - 不需要保持终端连接
- ✅ 统一管理 - 使用标准命令管理服务
- ✅ 日志管理 - 统一的日志查看和管理
- ✅ 资源控制 - 可以限制 CPU、内存使用
- ✅ 安全隔离 - 可以指定运行用户和权限
服务管理命令
# 启动服务
sudo systemctl start blog-api
# 停止服务
sudo systemctl stop blog-api
# 重启服务
sudo systemctl restart blog-api
# 查看状态
sudo systemctl status blog-api
# 查看日志
sudo journalctl -u blog-api -n 50 # 查看最近 50 条日志
sudo journalctl -u blog-api -f # 实时查看日志
# 禁用开机自启
sudo systemctl disable blog-apiSystemd 服务文件详解
[Unit] 部分 - 定义服务的基本信息和依赖关系
Description: 服务的描述信息After=network.target: 确保在网络服务启动后再启动本服务
[Service] 部分 - 定义服务的运行方式
Type=simple: 服务类型,simple 表示主进程就是服务本身User=nginx: 以 nginx 用户运行(非 root,更安全)Group=nginx: 以 nginx 组运行WorkingDirectory=/opt/blog-api: ⚠️ 必须修改为你的实际部署目录路径(例如:/opt/blog-api、/var/www/blog-api等)ExecStart=/opt/blog-api/blog-api: ⚠️ 必须修改为你的实际二进制文件完整路径(例如:/opt/blog-api/blog-api、/var/www/blog-api/blog-api等)Restart=always: 总是自动重启(崩溃、退出都会重启)RestartSec=5: 重启前等待 5 秒StandardOutput=journal: 标准输出写入 systemd journalStandardError=journal: 错误输出写入 systemd journalNoNewPrivileges=true: 禁止提升权限PrivateTmp=true: 使用私有临时目录
⚠️ 重要:
WorkingDirectory和ExecStart必须根据你的实际部署路径进行修改,否则服务将无法正常启动!
[Install] 部分 - 定义服务的安装方式
WantedBy=multi-user.target: 在系统进入多用户模式时启动
Nginx 反向代理配置
使用 Nginx 反向代理可以让外网通过 80/443 端口访问 API,无需在 URL 中添加端口号,同时提供更好的安全性和性能。
为什么使用 Nginx 反向代理?
- 统一入口 - 通过标准 HTTP/HTTPS 端口访问
- SSL/TLS 支持 - 方便配置 HTTPS
- 负载均衡 - 可以配置多个后端实例
- 安全增强 - 隐藏后端服务端口
- 性能优化 - Gzip 压缩、缓存等
方法一:使用部署脚本自动配置(推荐)
部署脚本会自动传输 nginx-blog-api.conf 配置文件到服务器,你只需要:
修改配置文件中的域名
在部署前或部署后,编辑
nginx-blog-api.conf,修改server_name:server_name your-domain.com; # 改为你的域名或 IP完成配置
# SSH 登录服务器 ssh user@server-ip # 编辑配置文件(修改 server_name) # Ubuntu/Debian: sudo nano /etc/nginx/sites-available/blog-api # CentOS/RHEL: sudo nano /etc/nginx/conf.d/blog-api.conf # 测试配置 sudo nginx -t # 重载 Nginx sudo systemctl reload nginx
方法二:手动配置
安装 Nginx(如果未安装)
# Ubuntu/Debian sudo apt update sudo apt install nginx -y # CentOS/RHEL sudo yum install nginx -y # 或 sudo dnf install nginx -y复制配置文件
# Ubuntu/Debian: 复制到 sites-available sudo cp nginx-blog-api.conf /etc/nginx/sites-available/blog-api # CentOS/RHEL: 直接复制到 conf.d sudo cp nginx-blog-api.conf /etc/nginx/conf.d/blog-api.conf # 或手动创建配置文件 # Ubuntu/Debian: sudo nano /etc/nginx/sites-available/blog-api # CentOS/RHEL: sudo nano /etc/nginx/conf.d/blog-api.conf编辑配置文件
修改
server_name为你的域名或 IP:server_name your-domain.com; # 或 your-server-ip启用配置
# Ubuntu/Debian: 创建软链接启用配置 sudo ln -s /etc/nginx/sites-available/blog-api /etc/nginx/sites-enabled/ # CentOS/RHEL: 配置文件已在 conf.d 目录,无需额外操作 # conf.d 目录下的配置文件会自动被加载 # 测试配置 sudo nginx -t # 如果测试通过,重载 Nginx sudo systemctl reload nginx # 检查 Nginx 状态 sudo systemctl status nginx
Nginx 配置文件说明
server {
listen 80 default_server; # default_server 确保此配置优先处理请求
server_name your-domain.com; # 修改为你的域名或 IP 地址
# API 反向代理
location /api/ {
proxy_pass http://127.0.0.1:57514;
# 代理请求头
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/javascript application/json application/xml;
# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}访问方式
配置完成后,可以通过以下方式访问:
- HTTP:
http://your-domain.com/api/bing - 或 IP:
http://your-server-ip/api/bing
不再需要添加端口号 :57514!
配置 HTTPS(可选但推荐)
安装 Certbot
# Ubuntu/Debian sudo apt install certbot python3-certbot-nginx -y # CentOS/RHEL sudo yum install certbot python3-certbot-nginx -y获取 SSL 证书
sudo certbot --nginx -d your-domain.com自动配置
Certbot 会自动:
- 获取 Let's Encrypt 证书
- 修改 Nginx 配置启用 HTTPS
- 设置 HTTP 到 HTTPS 的重定向
- 配置自动续期
安全最佳实践
1. 使用非 Root 用户运行服务
为什么不应该使用 root?
- ❌ 权限过大 - root 可以删除任何文件,包括系统文件
- ❌ 安全风险 - 如果服务被攻击,影响范围是整个系统
- ❌ 违反最小权限原则 - Go API 服务不需要 root 权限
正确的做法:
[Service]
User=nginx # CentOS
# 或
User=www-data # Ubuntu/Debian
Group=nginx
NoNewPrivileges=true
PrivateTmp=true设置文件权限:
# 设置目录所有者
sudo chown -R nginx:nginx /opt/blog-api
# 设置执行权限
sudo chmod +x /opt/blog-api/blog-api
# 设置目录权限
sudo chmod 755 /opt/blog-api2. 防火墙配置
使用 Nginx 反向代理(推荐)
如果使用 Nginx 反向代理,不需要开放应用端口,只需要开放 80 和 443 端口:
# Ubuntu/Debian (ufw)
sudo ufw allow 'Nginx Full' # 允许 HTTP (80) 和 HTTPS (443)
# 或分别开放
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload注意:API 服务运行在 127.0.0.1:57514(本地),不需要对外开放。
不使用 Nginx(不推荐生产环境)
如果直接访问 API,需要开放应用端口:
# Ubuntu/Debian (ufw)
sudo ufw allow 57514/tcp
# CentOS/RHEL (firewalld)
sudo firewall-cmd --permanent --add-port=57514/tcp
sudo firewall-cmd --reload3. 环境变量配置
如果需要配置环境变量,可以修改 blog-api.service 文件:
[Service]
Environment="GIN_MODE=release"
Environment="PORT=57514"
Environment="LOG_LEVEL=info"修改后重新加载:
sudo systemctl daemon-reload
sudo systemctl restart blog-api故障排查
1. 服务无法启动
# 查看详细错误信息
sudo journalctl -u blog-api -n 100
# 检查端口是否被占用
sudo netstat -tlnp | grep 57514
# 或
sudo ss -tlnp | grep 57514
# 检查服务文件语法
sudo systemd-analyze verify blog-api.service2. 权限问题
如果遇到 status=217/USER 错误,说明指定的用户不存在或权限不足:
# 检查用户是否存在
id nginx # CentOS
id www-data # Ubuntu/Debian
# 如果用户不存在,创建用户
sudo useradd -r -s /bin/false nginx # CentOS
# Ubuntu/Debian 通常已存在 www-data 用户
# 确保文件所有者正确
sudo chown -R nginx:nginx /opt/blog-api3. 端口冲突
如果端口 57514 被占用,可以:
- 修改
main.go中的端口号 - 或使用环境变量动态配置端口
- 或使用
netstat查找占用端口的进程并停止
4. Nginx 配置冲突
如果访问域名时显示的是其他站点,可能是配置冲突:
# Ubuntu/Debian:
# 1. 禁用默认站点
sudo rm -f /etc/nginx/sites-enabled/default
# 2. 确保 blog-api 配置已启用
sudo ln -sf /etc/nginx/sites-available/blog-api /etc/nginx/sites-enabled/blog-api
# 3. 检查配置中的 default_server(应该存在)
grep "listen 80" /etc/nginx/sites-available/blog-api
# CentOS/RHEL:
# 1. 禁用默认站点(如果存在)
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak
# 2. 检查 blog-api 配置文件
grep "listen 80" /etc/nginx/conf.d/blog-api.conf
# 3. 测试并重载(两种系统通用)
sudo nginx -t && sudo systemctl reload nginx5. 查看实时日志
# 实时查看服务日志
sudo journalctl -u blog-api -f
# 查看最近 100 行日志
sudo journalctl -u blog-api -n 100
# 查看今天的日志
sudo journalctl -u blog-api --since today
# 查看 Nginx 日志
sudo tail -f /var/log/nginx/blog-api-access.log
sudo tail -f /var/log/nginx/blog-api-error.log性能优化建议
1. 使用 Release 模式
设置环境变量 GIN_MODE=release 以提升性能:
[Service]
Environment="GIN_MODE=release"2. 资源限制
可以在 blog-api.service 中添加资源限制:
[Service]
# 限制内存使用为 512MB
MemoryLimit=512M
# 限制 CPU 使用为 50%
CPUQuota=50%
# 限制文件描述符数量
LimitNOFILE=655363. 编译优化
使用编译参数减小二进制文件大小:
# 去除符号表和调试信息
go build -ldflags="-s -w" main.go
# 进一步压缩(需要安装 UPX)
upx --best blog-api4. 监控
- 使用 Prometheus + Grafana 监控应用性能
- 或使用简单的健康检查端点
- 配置日志轮转避免日志文件过大
更新部署
当需要更新应用时:
# 方法一:使用部署脚本(推荐)
# 完整更新(包括配置文件)
./deploy.sh server-ip user /opt/blog-api
# 仅更新 Go 程序(推荐用于日常更新)
SKIP_CONFIG=1 ./deploy.sh server-ip user /opt/blog-api💡 更新建议:
- 日常更新 Go 程序:使用
SKIP_CONFIG=1,只更新二进制文件,避免覆盖配置文件- 首次部署或配置文件有变化:使用默认方式,会更新所有文件
方法二:手动更新
# 1. 重新编译
GOOS=linux GOARCH=amd64 go build -o blog-api -ldflags="-s -w" main.go
# 2. 传输新版本
scp blog-api user@server-ip:/opt/blog-api/
# 3. 重启服务
ssh user@server-ip "sudo systemctl restart blog-api"零停机更新(高级):
对于生产环境,可以考虑:
- 使用多个实例 + 负载均衡
- 蓝绿部署
- 滚动更新
常见问题
Q: 编译后的文件很大怎么办?
A: 使用 -ldflags="-s -w" 可以减小文件大小,或使用 UPX 压缩工具。
Q: 如何查看应用是否正常运行?
A: 使用 curl http://localhost:57514/api/bing 测试,或查看 systemd 状态 sudo systemctl status blog-api。
Q: 如何配置多个实例?
A: 可以创建多个服务文件(如 blog-api-1.service、blog-api-2.service),使用不同的端口和部署路径,然后在 Nginx 中配置负载均衡。
Q: 服务启动后立即退出怎么办?
A: 检查日志 sudo journalctl -u blog-api -n 100,常见原因包括:端口被占用、权限不足、配置文件错误等。
Q: 如何查看服务占用的资源?
A: 使用 sudo systemctl status blog-api 查看,或使用 sudo systemd-cgtop 查看所有服务的资源使用情况。
总结
本文介绍了将 Go 应用部署到 Linux 服务器的完整流程:
- ✅ 交叉编译 - 在本地编译 Linux 版本
- ✅ 自动化部署 - 使用部署脚本一键部署
- ✅ 服务管理 - 使用 Systemd 管理服务
- ✅ 反向代理 - 使用 Nginx 提供统一入口
- ✅ 安全配置 - 使用非 root 用户、防火墙等
- ✅ 故障排查 - 常见问题解决方案
通过遵循这些最佳实践,可以确保 Go 应用在 Linux 服务器上稳定、安全地运行。
参考资源
贡献者
更新日志
2025/11/23 20:35
查看所有更新日志
444a2-docs(blog): 更新Go应用部署指南中的Nginx配置说明于a9239-docs(config): 启用Markdown折叠功能并新增Go应用部署指南于
版权所有
版权归属:ntzw
许可证:CC0 1.0 通用 (CC0)
