基于Docker Compose与Nginx构建轻量级私有PaaS平台实战指南
1. 项目概述:一个轻量级、可移植的容器化应用部署平台
最近在折腾个人项目和小型服务部署时,我一直在寻找一种比传统云服务商控制台更灵活、比手动敲Docker命令更体系化的解决方案。直到我遇到了
fscarmen2/Argo-X-Container-PaaS
这个项目,它精准地切中了像我这样,希望拥有一个私有、轻量且功能集中的容器应用管理平台的开发者需求。简单来说,你可以把它理解为一个“开箱即用”的迷你版PaaS(平台即服务),它基于 Docker 和 Docker Compose,并整合了反向代理、SSL证书自动管理、基础监控等核心功能,让你能像在Heroku或Vercel上一样,通过简单的配置和命令,就能在自己的服务器(VPS、家庭服务器甚至树莓派)上部署和管理Web应用。
这个项目的核心价值在于“整合”与“简化”。它没有试图去再造一个Kubernetes那样的巨无霸,而是务实地面向中小规模、以Web服务为主的部署场景。通过预置的、经过验证的最佳实践组合(比如Nginx + Let‘s Encrypt + Docker Compose),它将从代码到可公开访问的HTTPS服务的整个链路标准化、脚本化。对于独立开发者、小团队或是希望将一些自研工具、博客、Nextcloud、Jellyfin媒体库等服务容器化并对外提供安全访问的个人用户而言,这个项目极大地降低了运维门槛和初期搭建成本。你不再需要分别去研究Nginx配置的细节、acme.sh证书续期的cron job怎么写,或者担心不同服务之间的网络互通问题,项目已经为你搭好了一个稳固的舞台。
2. 核心架构与组件选型解析
2.1 为什么是Docker Compose而非K8s?
这是理解该项目设计哲学的第一个关键点。Kubernetes无疑是容器编排的事实标准,但其学习曲线陡峭,资源消耗相对较高,对于管理几个到十几个容器的小型项目来说,属于“杀鸡用牛刀”。Docker Compose则完美契合了中小规模部署的场景:它使用声明式的YAML文件来定义和运行多容器应用,概念简单(服务、网络、卷),一条
docker-compose up -d
命令就能启动整个应用栈,本地开发与生产环境能保持高度一致。
Argo-X-Container-PaaS
选择Docker Compose作为基石,意味着它追求的是极致的轻量、易理解和快速部署。所有服务的依赖关系、环境变量、端口映射、数据持久化位置都在一个或一组清晰的
docker-compose.yml
文件中定义。这种选择使得项目的可移植性极强,你可以在任何安装了Docker和Docker Compose的Linux机器上几乎无差异地复现整个环境,这对于备份、迁移或在不同服务商间切换主机非常友好。
2.2 核心服务栈:Nginx, Let‘s Encrypt与监控
项目预设了一个典型且高效的Web服务网关与安全层组合。
1. Nginx作为反向代理与静态资源服务器 Nginx在这里扮演着入口网关的角色。它监听80和443端口,根据请求的域名(Host),将流量转发到背后对应的Docker容器服务。这种模式的好处显而易见:
-
端口管理简化
:你无需为每个内部服务分配不同的外部端口(如
:8080,:3000),只需都用80/443,通过域名来区分。 - 负载均衡与缓冲 :虽然小型项目可能用不到复杂的负载均衡,但Nginx本身可以作为缓冲层,处理静态文件、进行Gzip压缩,减轻后端应用容器的压力。
- 统一的配置管理 :所有域名的代理规则、SSL、头部信息等都在Nginx的配置中集中管理,结构清晰。
项目通常会采用动态配置的方式,例如将每个应用的代理配置作为独立的
conf
文件放在
nginx/conf.d/
或
nginx/vhost.d/
目录下,由Nginx自动加载。这比写在一个庞大的配置文件里要优雅和易于维护得多。
2. Let‘s Encrypt与Certbot实现自动化HTTPS 在当今互联网,HTTPS已是必需品。项目通过集成Certbot(Let‘s Encrypt的官方客户端),实现了SSL/TLS证书的自动申请和续期。其工作原理通常是利用HTTP-01或DNS-01挑战验证你对域名的控制权,验证通过后,Certbot会自动下载证书并配置Nginx使用它。
关键在于“自动化”。项目通过Docker Compose将Certbot也容器化,并通常设置一个定期执行的计划任务(例如通过
cron
或
docker exec
调用
certbot renew
),在证书到期前自动续期。这彻底解决了手动管理证书过期的问题,实现了“一次配置,永久有效”(在Let‘s Encrypt的政策内)。
3. 基础监控与日志管理 一个健康的系统需要可观测性。项目可能会集成一些轻量级监控组件,例如:
- Portainer :提供Web UI来可视化管理和监控Docker容器、镜像、卷和网络。对于不习惯命令行操作的用户来说,这是非常友好的管理界面。
- cAdvisor + Prometheus + Grafana :更进阶的监控方案。cAdvisor收集容器资源使用情况,Prometheus作为时序数据库存储指标,Grafana则用于制作精美的监控仪表盘。不过,在极简版本中,可能只包含基础的日志聚合。
-
日志驱动
:配置Docker Compose使用
json-file或journald日志驱动,并可能将日志目录挂载到宿主机,方便使用docker logs命令或tail、grep等工具进行查看和排查。
2.3 项目目录结构设计意图
一个清晰的项目结构是维护性的基石。典型的
Argo-X-Container-PaaS
项目目录可能如下:
argo-x-paas/
├── docker-compose.yml # 主编排文件,定义核心服务栈(Nginx, Certbot等)
├── .env # 环境变量文件,存放敏感或可配置参数(如域名、邮箱)
├── nginx/
│ ├── conf.d/ # 动态主机配置目录,每个应用一个.conf文件
│ ├── nginx.conf # Nginx主配置文件
│ └── html/ # 默认静态页面或错误页面
├── certbot/
│ ├── conf/ # Certbot配置目录
│ └── www/ # HTTP-01挑战验证文件目录
├── apps/ # 用户自定义应用目录
│ └── my-web-app/
│ ├── docker-compose.app.yml # 该应用独立的编排文件
│ ├── .env.app # 该应用的环境变量
│ └── data/ # 应用数据持久化目录(可选)
├── scripts/ # 实用脚本目录
│ ├── init-letsencrypt.sh # 初始化SSL证书的脚本
│ └── deploy-app.sh # 部署新应用的脚本
└── README.md # 项目说明文档
这种结构的设计意图是“关注点分离”和“易于扩展”。核心基础设施(Nginx, Certbot)的配置在一个地方,而每个具体的业务应用(
apps/
下的子目录)可以独立管理自己的Docker Compose文件和环境变量。当需要新增一个博客(如WordPress)或一个API服务时,你只需在
apps/
下新建一个目录,按照模板编写自己的
docker-compose.app.yml
,然后通过主编排文件或脚本将其纳入全局网络即可。这种模块化设计避免了所有配置混杂在一起导致的混乱。
3. 从零开始部署与初始化实战
3.1 前置环境准备与检查
在开始之前,你需要准备以下几样东西:
- 一台服务器 :一台具有公网IP的VPS(如DigitalOcean, Linode, Vultr, 或国内的腾讯云、阿里云ECS),操作系统推荐Ubuntu 22.04 LTS或Debian 11/12。1核1GB内存是起步,若部署应用较多,建议2GB以上。
-
一个域名
:你需要拥有一个域名(例如
example.com),并能够管理它的DNS解析。你将使用子域名(如app1.example.com,blog.example.com)来访问不同的服务。 - 基础工具 :确保可以通过SSH连接到服务器。
首先,登录服务器进行基础环境配置:
# 更新系统包列表并升级现有软件
sudo apt update && sudo apt upgrade -y
# 安装必要的工具
sudo apt install -y curl wget git vim
# 安装 Docker 和 Docker Compose Plugin
# 卸载旧版本(如有)
sudo apt remove docker docker-engine docker.io containerd runc
# 设置 Docker 的 apt 仓库
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gosu tee /etc/apt/keyrings/docker.asc > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker 引擎
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 验证安装
sudo docker --version
sudo docker compose version
# (可选)将当前用户加入docker组,避免每次使用docker都要sudo
sudo usermod -aG docker $USER
# 执行此命令后,需要退出SSH重新登录,或者新开一个终端会话才能生效
注意 :将用户加入
docker组会赋予该用户相当于root的权限(因为Docker守护进程以root运行)。在个人服务器上可以接受,但在多用户或生产环境需谨慎评估。你也可以选择一直使用sudo来运行docker命令。
3.2 获取项目代码与初步配置
从GitHub克隆项目仓库(这里以假设的仓库地址为例,实际操作时请替换为
fscarmen2/Argo-X-Container-PaaS
的真实地址或你fork的地址):
# 克隆项目
git clone https://github.com/fscarmen2/Argo-X-Container-PaaS.git
cd Argo-X-Container-PaaS
# 查看项目结构
ls -la
接下来,配置核心环境变量。通常项目会提供一个
.env.example
或直接要求你编辑
.env
文件。
# 复制环境变量示例文件(如果存在)
cp .env.example .env
# 编辑 .env 文件,填入你的配置
vim .env
一个典型的
.env
文件内容可能如下,你需要根据实际情况修改:
# 主域名,用于证书申请和默认配置
DOMAIN=example.com
# 用于Let‘s Encrypt证书申请的联系邮箱
EMAIL=admin@example.com
# 服务器公网IP地址(某些配置可能需要)
SERVER_IP=123.123.123.123
# 时区设置,确保容器内日志时间正确
TZ=Asia/Shanghai
# (可选)基础认证用户名密码,用于保护某些管理界面
BASIC_AUTH_USER=admin
BASIC_AUTH_PASS=your_secure_password_here
3.3 配置DNS解析与初始化Nginx、SSL证书
这是让外部能够访问你服务的关键一步。
-
配置DNS A记录 :登录你的域名注册商或DNS服务商(如Cloudflare)的控制面板。为你计划使用的子域名(例如
app1.example.com,blog.example.com)和主域名(example.com)添加一条A记录,指向你的服务器公网IP。TTL可以设置得短一些(如300秒),方便后续修改快速生效。 -
初始化Nginx与SSL证书 :项目通常会提供一个初始化脚本(如
scripts/init-letsencrypt.sh)。这个脚本会:- 停止可能运行的Nginx容器。
- 以临时模式启动一个Nginx容器,用于通过HTTP-01挑战验证域名所有权。
- 调用Certbot申请第一批SSL证书。
- 配置好正式的Nginx服务,使用刚申请的证书。
在运行脚本前,
务必确保
:
* 你的防火墙(如UFW)已经放行了80和443端口。
* DNS解析已经生效(可以用
ping your-domain.com
或在线工具检查)。
* 服务器上80和443端口没有被其他程序(如Apache)占用。
# 放行防火墙端口(如果使用UFW)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload
# 检查端口占用
sudo netstat -tulpn | grep :80
sudo netstat -tulpn | grep :443
# 赋予脚本执行权限并运行(假设脚本在scripts目录下)
chmod +x scripts/init-letsencrypt.sh
sudo ./scripts/init-letsencrypt.sh
脚本运行过程中,它会提示你输入要申请证书的域名列表。通常你可以输入你的主域名和所有计划使用的子域名,用空格或逗号分隔。脚本执行成功后,你的
certbot/conf/live/
目录下应该会有对应域名的证书文件,并且Nginx应该已经配置好并运行在HTTPS模式下了。
此时,你可以尝试在浏览器中访问
https://your-domain.com
。如果看到的是Nginx默认欢迎页或项目预设的页面,并且地址栏显示安全锁标志,说明基础网关和SSL层已经部署成功。
4. 部署自定义应用实战指南
基础平台搭好后,最激动人心的部分就是部署你自己的应用了。我们以部署一个静态博客(如Hugo生成)和一个动态API服务(如Node.js + Express)为例,演示两种典型场景。
4.1 场景一:部署静态网站(Hugo博客)
静态网站资源(HTML, CSS, JS)只需要一个Web服务器来托管。我们可以使用一个轻量的Nginx容器来服务这些文件。
-
准备应用目录与文件 :
# 在项目根目录的 apps/ 下创建你的博客应用目录 mkdir -p apps/my-hugo-blog cd apps/my-hugo-blog # 假设你已经通过Hugo生成了静态文件在 public/ 目录,将其复制过来 # 这里我们模拟一下,创建一个简单的index.html cat > index.html <<EOF <!DOCTYPE html> <html> <head><title>My Hugo Blog</title></head> <body><h1>Hello from my static blog!</h1></body> </html> EOF -
创建应用专属的Docker Compose文件 : 在
apps/my-hugo-blog/目录下创建docker-compose.app.yml。# apps/my-hugo-blog/docker-compose.app.yml version: '3.8' services: my-hugo-blog: image: nginx:alpine # 使用轻量级的Alpine版本 container_name: my-hugo-blog restart: unless-stopped volumes: - ./:/usr/share/nginx/html:ro # 将当前目录挂载为Nginx的Web根目录,只读 # 如果需要自定义Nginx配置,可以挂载一个配置文件 # - ./default.conf:/etc/nginx/conf.d/default.conf:ro networks: - proxy-network # 连接到主项目定义的网络,使Nginx网关能发现它 # 注意:我们不对外暴露端口,流量通过主Nginx反向代理进来 # expose 仅用于声明容器内部端口,供Docker网络发现 expose: - "80" labels: - "traefik.enable=false" # 如果项目使用Traefik,可能需要此类标签 # 可以添加自定义标签,方便管理 - "com.example.description=My Personal Hugo Blog"关键点解释:
-
volumes:./:/usr/share/nginx/html:ro将宿主机当前目录(即你的静态文件)挂载到容器的Nginx默认网站根目录,ro表示只读,更安全。 -
networks:proxy-network是关键。你需要确保这个网络在主项目的docker-compose.yml中已经定义,或者是一个外部网络。这确保了你的博客容器和主Nginx网关容器在同一个Docker网络中,主Nginx可以通过服务名(my-hugo-blog)来访问它。 -
expose: 声明容器内部监听80端口。这只是一个元数据,不会在宿主机上打开端口。 -
没有
ports映射:这是最佳实践。服务不直接暴露到宿主机,所有流量必须经过反向代理(主Nginx),这更安全,也避免了端口冲突。
-
-
配置主Nginx反向代理规则 : 现在需要告诉主Nginx,当访问
blog.example.com时,将请求转发到刚创建的my-hugo-blog容器。 在主项目的nginx/conf.d/目录下,创建一个新的配置文件,例如blog.example.com.conf。# nginx/conf.d/blog.example.com.conf server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name blog.example.com; # 你的博客子域名 # SSL证书路径,通常由Certbot自动配置,指向统一的目录 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/ssl-params.conf; # 包含SSL优化参数 location / { # 使用Docker Compose中定义的服务名作为上游 # 因为都在同一个Docker网络内,Nginx可以直接解析这个主机名 proxy_pass http://my-hugo-blog:80; # 以下是一些常用的代理头设置,确保后端能获取真实客户端信息 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 支持WebSocket } # 静态文件缓存优化(可选,如果Nginx直接服务静态文件则更有效) location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public, immutable"; proxy_pass http://my-hugo-blog:80; } } # HTTP重定向到HTTPS server { listen 80; listen [::]:80; server_name blog.example.com; return 301 https://$server_name$request_uri; } -
启动应用并重载Nginx :
# 回到你的博客应用目录 cd /path/to/argo-x-paas/apps/my-hugo-blog # 启动博客容器 docker compose -f docker-compose.app.yml up -d # 回到项目根目录,重启主Nginx容器以加载新的配置 cd /path/to/argo-x-paas docker compose restart nginx现在,访问
https://blog.example.com,你应该能看到你的静态博客页面了。
4.2 场景二:部署动态API服务(Node.js + Express)
动态应用需要运行一个应用服务器。我们以Node.js为例。
-
准备应用代码与Dockerfile :
mkdir -p apps/my-node-api cd apps/my-node-api创建最简单的Node.js应用文件:
// app.js const express = require('express'); const app = express(); const port = 3000; app.get('/', (req, res) => { res.json({ message: 'Hello from Node.js API!', timestamp: new Date().toISOString() }); }); app.listen(port, '0.0.0.0', () => { console.log(`API server listening at http://0.0.0.0:${port}`); });// package.json { "name": "my-node-api", "version": "1.0.0", "main": "app.js", "scripts": { "start": "node app.js" }, "dependencies": { "express": "^4.18.2" } }创建
Dockerfile来构建镜像:# Dockerfile FROM node:18-alpine WORKDIR /usr/src/app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD [ "node", "app.js" ] -
创建应用编排文件与环境变量 :
# apps/my-node-api/docker-compose.app.yml version: '3.8' services: api: build: . # 使用当前目录的Dockerfile构建镜像 container_name: my-node-api restart: unless-stopped # 可以挂载本地代码目录用于开发,生产环境通常直接使用构建好的镜像 # volumes: # - ./:/usr/src/app # - /usr/src/app/node_modules # 防止覆盖容器内的node_modules environment: - NODE_ENV=production - PORT=3000 networks: - proxy-network expose: - "3000" # 应用内部监听3000端口 # 健康检查(可选但推荐) healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 40s可以创建一个
.env.app文件来管理环境变量(然后在docker-compose.app.yml中用env_file引入)。 -
配置Nginx代理规则 : 在
nginx/conf.d/下创建api.example.com.conf。server { listen 443 ssl http2; server_name api.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; include /etc/nginx/conf.d/ssl-params.conf; location / { proxy_pass http://my-node-api:3000; proxy_http_version 1.1; 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; # 对于API,可能需要更长的超时时间 proxy_read_timeout 60s; proxy_connect_timeout 60s; proxy_send_timeout 60s; } # 可以添加针对API的限流、日志等配置 access_log /var/log/nginx/api.example.com.access.log; error_log /var/log/nginx/api.example.com.error.log; } server { listen 80; server_name api.example.com; return 301 https://$server_name$request_uri; } -
构建、启动与测试 :
cd apps/my-node-api # 构建Docker镜像 docker compose -f docker-compose.app.yml build # 启动服务 docker compose -f docker-compose.app.yml up -d # 回到根目录,重载Nginx cd /path/to/argo-x-paas docker compose restart nginx # 测试API curl https://api.example.com # 应该返回:{"message":"Hello from Node.js API!","timestamp":"..."}
4.3 数据持久化与备份策略
对于有状态服务(如数据库、文件上传),数据持久化至关重要。Docker Compose中通过
volumes
或
bind mounts
实现。
1. 使用命名卷(Named Volumes) 命名卷由Docker管理,生命周期独立于容器,是更推荐的方式。
# 在docker-compose.app.yml中
services:
database:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data # 使用命名卷
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
volumes:
postgres_data: # 声明一个命名卷
2. 使用绑定挂载(Bind Mounts) 将宿主机特定目录挂载到容器,便于直接从宿主机访问和管理文件。
volumes:
- ./uploads:/app/public/uploads # 挂载相对路径目录
- /opt/app_data:/app/data # 挂载宿主机绝对路径
3. 备份策略
-
定期备份
:使用
cron定时任务执行备份脚本。# 示例备份脚本 backup.sh #!/bin/bash BACKUP_DIR="/backup" DATE=$(date +%Y%m%d_%H%M%S) # 1. 备份数据库(使用docker exec执行pg_dump) docker exec my-postgres-container pg_dump -U postgres mydb > $BACKUP_DIR/mydb_$DATE.sql # 2. 备份重要卷或目录 tar -czf $BACKUP_DIR/app_uploads_$DATE.tar.gz /path/to/argo-x-paas/apps/myapp/uploads/ # 3. (可选)将备份同步到远程存储(如S3, Rclone) - 版本控制 :应用代码和Docker Compose文件本身应纳入Git版本控制。
-
分离数据与配置
:环境变量(密码、密钥)应通过
.env文件或Docker Secrets管理,绝不硬编码在编排文件中。
5. 运维、监控与故障排查实录
5.1 日常运维命令合集
掌握以下Docker Compose命令,足以应对日常管理:
# 项目根目录下,管理核心基础设施
docker compose ps # 查看核心服务状态
docker compose logs -f nginx # 跟踪Nginx日志
docker compose restart nginx # 重启Nginx服务
docker compose up -d # 启动所有核心服务(如果未运行)
docker compose down # 停止并移除所有核心服务容器(谨慎使用,不会删除卷)
# 在具体应用目录下,管理单个应用
docker compose -f docker-compose.app.yml ps
docker compose -f docker-compose.app.yml logs -f
docker compose -f docker-compose.app.yml up -d --build # 重新构建镜像并启动
docker compose -f docker-compose.app.yml down
docker compose -f docker-compose.app.yml exec api sh # 进入名为“api”的容器内部
# 查看所有容器资源使用情况
docker stats
# 查看系统日志,排查启动问题
journalctl -u docker.service -f
5.2 集成轻量级监控:Portainer
Portainer提供了一个Web UI来管理Docker环境,对于可视化监控非常有用。可以将其作为另一个“应用”部署到你的PaaS平台上。
-
创建Portainer应用配置 : 在
apps/下创建portainer目录和其docker-compose.app.yml。version: '3.8' services: portainer: image: portainer/portainer-ce:latest container_name: portainer restart: unless-stopped security_opt: - no-new-privileges:true volumes: - /etc/localtime:/etc/localtime:ro - /var/run/docker.sock:/var/run/docker.sock:ro # 挂载Docker套接字以管理宿主机 - portainer_data:/data # 持久化Portainer数据 networks: - proxy-network expose: - "9000" # 注意:Portainer本身有较强的认证,通常无需在Nginx再加基础认证 volumes: portainer_data: -
配置Nginx代理 : 在
nginx/conf.d/下创建portainer.example.com.conf,将9000端口代理出去。然后重启主Nginx。 -
访问与初始化 : 首次访问
https://portainer.example.com,需要设置管理员密码,并选择连接本地Docker环境。之后,你就能在Web界面中看到所有容器状态、日志、资源使用情况,并能进行启停、进入控制台等操作,极大提升了运维便利性。
5.3 常见问题与排查技巧
在实际操作中,你肯定会遇到各种问题。以下是一些常见坑点及排查思路:
问题1:访问域名显示“502 Bad Gateway”或“Connection refused”。
-
排查思路
:
-
检查应用容器是否运行
:
docker compose -f docker-compose.app.yml ps。确保状态是Up。 -
检查应用日志
:
docker compose -f docker-compose.app.yml logs -f,查看是否有启动错误。 -
检查Nginx配置中的上游地址
:确认
proxy_pass http://[service-name]:[port];中的服务名和端口是否与应用编排文件中定义的完全一致(注意:是Docker Compose中的服务名,不是容器名)。服务名和网络是关键。 -
检查网络
:确保应用容器和Nginx容器在同一个Docker网络中。
docker network ls查看网络列表,docker network inspect [network-name]查看网络中有哪些容器。 -
进入Nginx容器内部测试
:
docker compose exec nginx sh,然后尝试curl http://my-node-api:3000。如果内部能通,外部不通,问题在Nginx配置或DNS解析;如果内部也不通,问题在应用或网络。
-
检查应用容器是否运行
:
问题2:SSL证书申请失败或续期失败。
-
排查思路
:
-
检查域名解析
:确保申请证书的域名A记录已正确指向服务器IP,并且已生效(可使用
dig A your-domain.com检查)。 - 检查80端口是否可访问 :HTTP-01挑战需要外部能通过80端口访问到服务器上的临时文件。确保防火墙开放80端口,且没有其他程序占用。
-
查看Certbot日志
:
docker compose logs certbot。日志通常会明确提示失败原因,如连接超时、验证失败等。 - 注意频率限制 :Let‘s Encrypt有申请频率限制(每周每个域名50次)。失败后不要频繁重试,先根据日志解决问题。
- DNS验证 :如果服务器80端口无法开放,考虑改用DNS-01挑战,这需要在脚本或Certbot配置中设置相应的DNS插件(如Cloudflare API Token)。
-
检查域名解析
:确保申请证书的域名A记录已正确指向服务器IP,并且已生效(可使用
问题3:容器启动失败,提示“端口已被占用”。
- 原因 :多个容器试图映射到宿主机的同一个端口。
-
解决
:牢记“一个宿主机端口只能被一个进程监听”。对于内部服务,
不要使用
ports映射到宿主机 ,仅用expose声明端口,并通过反向代理(Nginx)统一对外。只有像SSH(22)、Docker守护进程(2375/2376)等特殊服务才直接占用宿主机端口。
问题4:磁盘空间不足。
- 原因 :Docker会积累未使用的镜像、停止的容器、悬空卷和构建缓存。
-
清理命令
:
# 删除所有停止的容器 docker container prune -f # 删除所有未被任何容器引用的悬空镜像 docker image prune -f # 删除所有未被使用的卷(谨慎!确保卷内数据已备份) docker volume prune -f # 删除构建缓存 docker builder prune -f # 一键清理所有未使用资源(容器、镜像、网络、卷,构建缓存除外) docker system prune -f
问题5:如何优雅更新应用?
-
无状态应用
(如静态网站、API):
- 更新代码或构建新的Docker镜像。
-
在应用目录下执行:
docker compose -f docker-compose.app.yml up -d --build。Compose会拉取新镜像(或重新构建),创建新容器替换旧容器,实现零停机更新(如果健康检查配置得当)。
-
有状态应用
(如数据库):
- 更新需格外谨慎。务必先 备份数据 。
- 查阅官方镜像的升级指南。对于PostgreSQL、MySQL等,通常有特定的版本升级步骤,不能简单替换镜像。
-
可以考虑使用
docker compose stop然后修改镜像标签再up -d,但前提是数据卷已正确配置且版本兼容。
经过以上步骤,你应该已经能够基于
Argo-X-Container-PaaS
这样的项目模板,搭建起一个属于自己的、功能完备的轻量级容器化应用平台。从基础环境搭建、SSL配置,到部署静态和动态应用,再到日常的运维监控和问题排查,这套组合拳覆盖了个人和小型项目部署的大部分需求。它的魅力在于用相对简单的技术栈(Docker Compose, Nginx, Certbot),实现了接近商业化PaaS的体验,让你能更专注于应用开发本身,而不是底层基础设施的琐碎运维。
更多推荐
所有评论(0)