Docker容器化部署完全指南:从零到生产环境
先把全貌看清楚
Docker容器化技术已成为现代应用部署的标准选择。本指南基于真实生产环境经验,详细讲解从Docker基础到生产级部署的完整流程,包含多个实战案例和最佳实践。
本指南基于以下实际项目经验:
- 1000y游戏论坛(Laravel 11 + PHP 8.4)三服务器Docker化部署
- WordPress网站容器化改造
- OpenClaw AI网关微服务架构
- 千年MMORPG游戏服务器容器编排
学习目标:
- 掌握Docker核心概念和架构
- 学会编写生产级Dockerfile
- 理解Docker Compose多容器编排
- 掌握生产环境部署和优化
- 了解安全最佳实践
—
第一部分:Docker核心概念
1.1 什么是容器?
容器 vs 虚拟机:
虚拟机架构:
应用 → 操作系统 → Hypervisor → 硬件
(每个VM需要完整OS,启动慢,占用资源多)容器架构:
应用 → Docker引擎 → 操作系统 → 硬件
(共享OS内核,启动快,资源占用少)
关键优势:
- 启动速度:容器秒级启动,VM分钟级
- 资源利用率:容器共享内核,内存占用仅为VM的1/10
- 环境一致性:开发、测试、生产环境完全一致
- 快速扩展:秒级水平扩展
1.2 Docker核心组件
#### 1.2.1 Docker引擎(Docker Engine)
Docker Engine = Docker Daemon + REST API + Docker CLI
验证安装:
# 查看Docker版本和系统信息
docker --version
docker info查看系统详细信息
docker system info
#### 1.2.2 镜像(Image)
镜像是一个只读的模板,包含运行应用所需的所有内容:
- 代码
- 运行时
- 库
- 环境变量
- 配置文件
镜像分层结构:
应用层(可写)
↓
依赖层(只读)
↓
基础镜像层(只读)
↓
内核层(共享)
#### 1.2.3 容器(Container)
容器是镜像的运行实例:
# 镜像 → 容器
docker run nginx:latest # 创建并启动容器查看运行中的容器
docker ps查看所有容器(包括停止的)
docker ps -a
#### 1.2.4 仓库(Registry)
存储和分发镜像的服务:
- Docker Hub:官方公共仓库(hub.docker.com)
- 私有仓库:Harbor、GitLab Registry、AWS ECR
- 阿里云容器镜像服务:国内加速
—
第二部分:Docker安装和配置
2.1 系统要求
生产环境推荐配置:
CPU: 4核心以上
内存: 8GB以上(建议16GB)
磁盘: 100GB以上SSD
系统: CentOS 8+ / Ubuntu 20.04+ / Debian 11+
内核: 4.0以上
真实案例:
我们的生产环境配置(1000y游戏论坛):
服务器1: 2C8G(主库1)
服务器2: 2C4G(主库2)
服务器3: 2C8G(主库3)
总容器数: 15个
平均容器内存占用: 512MB
2.2 安装Docker
#### 2.2.1 Ubuntu/Debian系统
官方推荐方式(使用脚本):
# 1. 更新包索引
sudo apt-get update2. 安装依赖
sudo apt-get install -y
ca-certificates
curl
gnupg
lsb-release3. 添加Docker官方GPG密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg4. 设置仓库
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null5. 安装Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin6. 验证安装
sudo docker run hello-world
#### 2.2.2 CentOS/RHEL系统
生产环境安装(我们主库1的配置):
# 1. 卸载旧版本
sudo yum remove docker
docker-client
docker-client-latest
docker-common
docker-latest
docker-latest-logrotate
docker-logrotate
docker-engine2. 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm23. 添加Docker仓库
sudo yum-config-manager
--add-repo
https://download.docker.com/linux/centos/docker-ce.repo4. 安装Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin5. 启动Docker
sudo systemctl start docker
sudo systemctl enable docker6. 验证
sudo docker --version
输出:Docker version 24.0.7, build afdd53b
2.3 配置Docker守护进程
生产环境配置文件(/etc/docker/daemon.json):
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
},
"storage-driver": "overlay2",
"data-root": "/data/docker",
"live-restore": true,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
},
"max-concurrent-downloads": 10,
"max-concurrent-uploads": 10,
"metrics-addr": "127.0.0.1:9323",
"experimental": false
}
配置说明:
registry-mirrors:国内镜像加速(提高拉取速度)log-opts:日志轮转(防止磁盘占满)storage-driver:存储驱动(overlay2性能最好)data-root:数据目录(使用独立磁盘)live-restore:容器守护进程重启时不停止容器metrics-addr:启用Prometheus监控
重启Docker使配置生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
—
第三部分:Dockerfile编写最佳实践
3.1 Dockerfile基础语法
基本结构:
# 1. 基础镜像
FROM php:8.4-apache2. 维护者信息
LABEL maintainer="your-email@your-domain.com"3. 工作目录
WORKDIR /var/www/html4. 安装依赖
RUN apt-get update && apt-get install -y
git
unzip
libpng-dev
&& rm -rf /var/lib/apt/lists/5. 安装PHP扩展
RUN docker-php-ext-install mysqli pdo pdo_mysql gd6. 复制应用代码
COPY . /var/www/html7. 设置权限
RUN chown -R www-data:www-data /var/www/html8. 暴露端口
EXPOSE 809. 启动命令
CMD ["apache2-foreground"]
3.2 生产级Dockerfile示例
#### 3.2.1 Laravel应用(1000y论坛实际配置)
优化后的Dockerfile:
# 阶段1:构建阶段
FROM composer:2.6 as builderWORKDIR /app
复制依赖文件
COPY composer.json composer.lock ./安装依赖(仅生产环境)
RUN composer install
--no-dev
--no-scripts
--no-autoloader
--prefer-dist
--optimize-autoloader复制应用代码
COPY . .生成自动加载文件
RUN composer dump-autoload --optimize --classmap-authoritative阶段2:运行阶段
FROM php:8.4-apache AS production安装系统依赖
RUN apt-get update && apt-get install -y
libpng-dev
libonig-dev
libxml2-dev
libzip-dev
zip
unzip
git
curl
&& rm -rf /var/lib/apt/lists/安装PHP扩展
RUN docker-php-ext-install
pdo_mysql
mbstring
exif
pcntl
bcmath
gd
zip
opcache配置PHP
COPY docker/php/php.ini /usr/local/etc/php/conf.d/custom.ini
COPY docker/php/opcache.ini /usr/local/etc/php/conf.d/opcache.ini配置Apache
RUN a2enmod rewrite
COPY docker/apache/vhost.conf /etc/apache2/sites-available/000-default.conf从构建阶段复制应用
COPY --from=builder /app /var/www/html设置权限
RUN chown -R www-data:www-data /var/www/html
&& chmod -R 755 /var/www/html/storage工作目录
WORKDIR /var/www/html暴露端口
EXPOSE 8080健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD curl -f http://localhost:8080/ || exit 1启动Apache
CMD ["apache2-foreground"]
PHP配置文件(docker/php/php.ini):
memory_limit=256M
post_max_size=50M
upload_max_filesize=50M
max_execution_time=300
date.timezone=Asia/ShanghaiOPcache配置
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
Apache虚拟主机配置(docker/apache/vhost.conf):
<VirtualHost :8080>
ServerName localhost
DocumentRoot /var/www/html/public
AllowOverride All
Require all granted
# 启用压缩
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript
# 缓存静态资源
ExpiresActive On
ExpiresByType image/gif "access plus 30 days"
ExpiresByType image/jpeg "access plus 30 days"
ExpiresByType image/png "access plus 30 days"
ExpiresByType text/css "access plus 7 days"
ExpiresByType application/javascript "access plus 7 days"
# 日志配置
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#### 3.2.2 WordPress应用
优化的WordPress Dockerfile:
FROM php:8.4-apache安装依赖
RUN apt-get update && apt-get install -y
default-mysql-client
libpng-dev
libjpeg-dev
libfreetype6-dev
locales
zip
unzip
git
curl
&& rm -rf /var/lib/apt/lists/配置GD库
RUN docker-php-ext-configure gd
--with-freetype
--with-jpeg安装PHP扩展
RUN docker-php-ext-install
pdo_mysql
exif
gd
zip
opcache安装WP-CLI
COPY --from=ghcr.io/wp-cli/wp-cli:latest /usr/local/bin/wp /usr/local/bin/wp配置PHP
COPY docker/php/php.ini /usr/local/etc/php/conf.d/custom.ini配置Apache
RUN a2enmod rewrite expires headers下载WordPress
RUN curl -o /tmp/wordpress.tar.gz -fSL https://wordpress.org/latest.tar.gz
&& tar -xzf /tmp/wordpress.tar.gz -C /var/www/
&& rm /tmp/wordpress.tar.gz
&& chown -R www-data:www-data /var/www/wordpressWORKDIR /var/www/wordpress
暴露端口
EXPOSE 80健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3
CMD curl -f http://localhost/ || exit 1CMD ["apache2-foreground"]
3.3 Dockerfile优化技巧
#### 3.3.1 减小镜像体积
优化前后对比:
未优化镜像: 1.2GB
优化后镜像: 350MB
减少: 71%
具体方法:
# 差异
FROM php:8.4-apache # 800MB
FROM php:8.4-alpine # 150MB注意:Alpine需要额外安装依赖
RUN apk add --no-cache $PHPIZE_DEPS
&& docker-php-ext-install mysqli pdo pdo_mysql
# 构建阶段(包含编译工具)
FROM node:18 AS builder
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run build运行阶段(仅包含运行时)
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package.json ./
RUN npm install --production
CMD ["node", "server.js"]
# 在同一RUN命令中清理
RUN apt-get update && apt-get install -y
git
&& rm -rf /var/lib/apt/lists/ # 立即清理或者使用.no-cache(Alpine)
RUN apk add --no-cache git
#### 3.3.2 利用Docker构建缓存
最佳实践:
# ❌ 错误:每次都重新安装依赖
COPY . /app
RUN npm install✅ 正确:只在依赖变化时重新安装
COPY package.json ./
RUN npm install
COPY . .
缓存失效策略:
# 1. 变化最少的层放前面
FROM php:8.4-apache2. 依赖层(变化少)
COPY composer.json composer.lock ./
RUN composer install --no-dev3. 代码层(变化多)
COPY . .4. 配置层(变化最少)
COPY docker/php/php.ini /usr/local/etc/php/conf.d/
#### 3.3.3 安全最佳实践
安全扫描:
# 使用Trivy扫描漏洞
trivy image my-php-app:latest输出示例:
2023-10-15T10:00:00Z INFO Vulnerability scanning...
2023-10-15T10:00:05Z INFO Total: 150 (HIGH: 5, MEDIUM: 20)
安全加固措施:
FROM php:8.4-apache创建专用用户
RUN groupadd -r appuser && useradd -r -g appuser appuser切换用户
USER appuser指定工作目录
WORKDIR /home/appuser/app
# 只读文件系统
RUN chown -R appuser:appuser /var/www/html
USER appuser临时目录
RUN mkdir -p /tmp && chmod 1777 /tmp
# 使用特定版本标签,不使用latest
FROM php:8.4.3-apache # ✅ 好
FROM php:8.4-apache # ⚠️ 可接受
FROM php:latest # ❌ 差
—
第四部分:Docker Compose多容器编排
4.1 Docker Compose基础
核心概念:
- Service(服务):一个容器实例
- Network(网络):容器间通信
- Volume(卷):数据持久化
4.2 生产环境配置示例
#### 4.2.1 Laravel完整栈(Web + DB + Redis)
docker-compose.yml(1000y论坛实际配置):
version: '3.8'services:
# Laravel应用
app:
build:
context: .
dockerfile: Dockerfile
target: production
container_name: 1000y-app
restart: unless-stopped
working_dir: /var/www/html
volumes:
- ./storage:/var/www/html/storage:cached
- ./bootstrap/cache:/var/www/html/bootstrap/cache:cached
environment:
- APP_NAME=1000y
- APP_ENV=production
- APP_DEBUG=false
- APP_URL=https://1000y.chencunli.com
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=1000y
- DB_USERNAME=1000y
- DB_PASSWORD=${DB_PASSWORD}
- REDIS_HOST=redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
- CACHE_DRIVER=redis
- SESSION_DRIVER=redis
networks:
- app-network
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
deploy:
resources:
limits:
cpus: '1.5'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# Nginx反向代理
nginx:
image: nginx:1.25-alpine
container_name: 1000y-nginx
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
- ./storage/app/public:/var/www/html/storage/app/public:ro
networks:
- app-network
depends_on:
- app
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
interval: 30s
timeout: 3s
retries: 3
# MySQL数据库
db:
image: mysql:8.0
container_name: 1000y-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: 1000y
MYSQL_USER: 1000y
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.25'
memory: 256M
# Redis缓存
redis:
image: redis:7-alpine
container_name: 1000y-redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
networks:
- app-network
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 10s
timeout: 3s
retries: 5
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.1'
memory: 128M
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
db-data:
driver: local
redis-data:
driver: local
环境变量文件(.env):
# 数据库密码(生产环境使用强密码)
DB_ROOT_PASSWORD=RootPass2026StrongSecure789XYZ
DB_PASSWORD=1000y_db_password_2026Redis密码
REDIS_PASSWORD=qTeXaxBQ4MMDNnX9qbOh9F0l
#### 4.2.2 WordPress完整栈
docker-compose.yml:
version: '3.8'services:
# WordPress应用
wordpress:
image: wordpress:6.4-php8.4-apache
container_name: wordpress-app
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: chencunli
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_TABLE_PREFIX: wp_
WORDPRESS_DEBUG: false
volumes:
- wordpress-data:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
networks:
- wp-network
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 3s
retries: 3
# MySQL数据库
db:
image: mysql:8.0
container_name: wordpress-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: chencunli
MYSQL_USER: wp_user
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db-data:/var/lib/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
networks:
- wp-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
# phpMyAdmin
phpmyadmin:
image: phpmyadmin:latest
container_name: wordpress-phpmyadmin
restart: unless-stopped
ports:
- "8081:80"
environment:
PMA_HOST: db
PMA_PORT: 3306
UPLOAD_LIMIT: 100M
networks:
- wp-network
depends_on:
- db
networks:
wp-network:
driver: bridge
volumes:
wordpress-data:
driver: local
db-data:
driver: local
4.3 Docker Compose常用命令
启动和管理:
# 启动所有服务(后台运行)
docker-compose up -d查看运行状态
docker-compose ps查看日志
docker-compose logs -f查看特定服务日志
docker-compose logs -f app重启服务
docker-compose restart停止所有服务
docker-compose stop停止并删除容器
docker-compose down停止并删除容器、网络、卷
docker-compose down -v
扩缩容:
# 扩展app服务到3个实例
docker-compose up -d --scale app=3查看扩展后的容器
docker-compose ps
更新服务:
# 重新构建镜像
docker-compose build --no-cache重新创建容器
docker-compose up -d --force-recreate
—
第五部分:生产环境部署和优化
5.1 资源限制和监控
#### 5.1.1 设置资源限制
docker-compose.yml配置:
services:
app:
deploy:
resources:
limits:
cpus: '1.5' # 最多使用1.5个CPU核心
memory: 2G # 最多使用2GB内存
reservations:
cpus: '0.5' # 保证0.5个CPU核心
memory: 512M # 保证512MB内存
验证资源配置:
# 查看容器资源使用
docker stats查看特定容器
docker stats 1000y-app输出示例:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
1000y-app 15.50% 512MiB / 2GiB 25.00% 10kB / 5kB 0B / 0B
#### 5.1.2 性能监控
使用cAdvisor监控:
version: '3.8'services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
ports:
- "8082:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
networks:
- monitor
networks:
monitor:
driver: bridge
访问监控面板:
http://your-server:8082
Prometheus + Grafana监控:
version: '3.8'services:
# Prometheus
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
networks:
- monitor
# Grafana
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: admin
volumes:
- grafana-data:/var/lib/grafana
networks:
- monitor
networks:
monitor:
driver: bridge
volumes:
prometheus-data:
grafana-data:
5.2 日志管理
#### 5.2.1 配置日志驱动
daemon.json配置:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3",
"compress": "true"
}
}
docker-compose.yml配置:
services:
app:
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "3"
compress: "true"
#### 5.2.2 日志收集(ELK Stack)
使用Filebeat收集日志:
version: '3.8'services:
app:
image: my-app:latest
logging:
driver: "json-file"
options:
max-size: "100m"
filebeat:
image: docker.elastic.co/beats/filebeat:8.11.0
container_name: filebeat
restart: unless-stopped
user: root
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
command: filebeat -e -strict.perms=false
networks:
- elk
5.3 备份和恢复
#### 5.3.1 数据卷备份
备份脚本(backup.sh):
#!/bin/bash配置
BACKUP_DIR="/data/backups"
DATE=$(date +%Y%m%d_%H%M%S)
COMPOSE_FILE="/path/to/docker-compose.yml"创建备份目录
mkdir -p $BACKUP_DIR备份数据卷
docker-compose -f $COMPOSE_FILE exec -T db
mysqldump -u root -p${DB_ROOT_PASSWORD}
--all-databases
--single-transaction
--quick
--lock-tables=false > $BACKUP_DIR/db_$DATE.sql备份应用数据
docker run --rm
-v wordpress-data:/data
-v $BACKUP_DIR:/backup
alpine tar czf /backup/wordpress_$DATE.tar.gz -C /data .删除7天前的备份
find $BACKUP_DIR -name ".sql" -mtime +7 -delete
find $BACKUP_DIR -name ".tar.gz" -mtime +7 -deleteecho "Backup completed: $DATE"
恢复脚本(restore.sh):
#!/bin/bashBACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ]; then
echo "Usage: $0 "
exit 1
fi
恢复数据库
docker-compose exec -T db
mysql -u root -p${DB_ROOT_PASSWORD} < $BACKUP_FILEecho "Database restored from $BACKUP_FILE"
#### 5.3.2 容器快照
导出容器:
# 导出容器为镜像
docker commit 1000y-app 1000y-app:backup-20261015保存为tar文件
docker save 1000y-app:backup-20261015 -o 1000y-app-backup.tar
导入容器:
# 从tar文件加载
docker load -i 1000y-app-backup.tar运行容器
docker run -d --name 1000y-app-restored 1000y-app:backup-20261015
5.4 自动化部署
#### 5.4.1 CI/CD集成
GitHub Actions配置(.github/workflows/docker.yml):
name: Docker Build and Deployon:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: yourusername/1000y-app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /server/docker/1000y-site
docker-compose pull
docker-compose up -d --force-recreate
#### 5.4.2 零停机部署
滚动更新脚本(rolling-update.sh):
#!/bin/bashAPP_NAME="1000y-app"
NEW_IMAGE="1000y-app:v2.0"
OLD_CONTAINERS=$(docker ps -q -f name=$APP_NAME)
拉取新镜像
docker pull $NEW_IMAGE逐个替换容器
for container in $OLD_CONTAINERS; do
echo "Updating container: $container" # 启动新容器
NEW_CONTAINER=$(docker run -d
--name "${APP_NAME}-$(date +%s)"
$NEW_IMAGE)
# 等待新容器健康
sleep 10
# 停止旧容器
docker stop $container
docker rm $container
echo "Container updated: $container -> $NEW_CONTAINER"
done
echo "Rolling update completed"
—
第六部分:安全最佳实践
6.1 镜像安全
#### 6.1.1 使用私有镜像仓库
Harbor安装:
# 下载Harbor离线安装包
wget https://github.com/goharbor/harbor/releases/download/v2.9.0/harbor-offline-installer-v2.9.0.tgz解压
tar xvf harbor-offline-installer-v2.9.0.tgz
cd harbor配置harbor.yml
cp harbor.yml.tmpl harbor.yml
vim harbor.yml安装
./install.sh
推送镜像到Harbor:
# 登录Harbor
docker login your-domain.com标记镜像
docker tag 1000y-app:latest your-domain.com/project/1000y-app:latest推送镜像
docker push your-domain.com/project/1000y-app:latest
#### 6.1.2 镜像签名和验证
使用Docker Content Trust:
# 启用DCT
export DOCKER_CONTENT_TRUST=1推送已签名镜像
docker push your-domain.com/project/1000y-app:latest拉取时自动验证签名
docker pull your-domain.com/project/1000y-app:latest
6.2 运行时安全
#### 6.2.1 容器隔离
使用用户命名空间:
# /etc/docker/daemon.json
{
"userns-remap": "default"
}
只读根文件系统:
services:
app:
read_only: true
tmpfs:
- /tmp
- /var/www/html/storage/framework/cache
- /var/www/html/storage/framework/views
#### 6.2.2 能力限制
删除不必要的Linux能力:
services:
app:
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
- CHOWN
- SETGID
- SETUID
6.3 网络安全
#### 6.3.1 网络隔离
创建隔离网络:
version: '3.8'services:
# 前端应用(公网访问)
web:
networks:
- frontend
- backend
# 后端应用(内网)
app:
networks:
- backend
# 数据库(仅内网)
db:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 禁止访问外网
#### 6.3.2 TLS加密
使用Nginx反向代理:
version: '3.8'services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
networks:
- frontend
app:
image: my-app:latest
networks:
- backend
Nginx配置:
server {
listen 443 ssl http2;
server_name your-domain.com; ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
location / {
proxy_pass http://app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
—
第七部分:故障排查和性能优化
7.1 常见问题诊断
#### 7.1.1 容器启动失败
问题排查步骤:
# 1. 查看容器日志
docker logs 2. 查看容器详细信息
docker inspect 3. 进入容器调试
docker exec -it /bin/bash4. 查看容器事件
docker events --since '1h'
常见原因和解决方案:
# 查看端口占用
netstat -tulpn | grep :8080修改端口映射
docker run -p 8081:80 my-app
# 查看容器资源限制
docker inspect | grep -A 10 Memory增加内存限制
docker update --memory 2g
# 验证配置文件
docker run --rm -v $(pwd):/app alpine sh -c "cat /app/docker-compose.yml"
#### 7.1.2 性能问题
性能分析工具:
# 1. 使用docker top查看进程
docker top 2. 使用docker stats查看资源使用
docker stats --no-stream3. 使用nsenter进入容器命名空间
nsenter --target $(docker inspect -f '{{.State.Pid}}' ) --net -- mount4. 使用strace跟踪系统调用
docker exec strace -p
性能优化建议:
# ❌ 多层RUN
RUN apt-get update
RUN apt-get install git
RUN apt-get install curl✅ 合并RUN
RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/
# 启用BuildKit
export DOCKER_BUILDKIT=1构建镜像
docker build -t my-app .
# 减小最终镜像体积
FROM node:18 AS builder
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run buildFROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
7.2 容器编排进阶
#### 7.2.1 Docker Swarm
初始化Swarm集群:
# 在主节点执行
docker swarm init --advertise-addr 添加工作节点
docker swarm join --token :2377
部署服务栈:
version: '3.8'services:
app:
image: 1000y-app:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
networks:
- app-network
networks:
app-network:
driver: overlay
部署服务栈:
docker stack deploy -c docker-compose.yml 1000y-stack查看服务
docker service ls扩展服务
docker service scale 1000y-stack_app=5
#### 7.2.2 Kubernetes(可选)
最小化Kubernetes配置(用于学习):
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: 1000y-app
spec:
replicas: 3
selector:
matchLabels:
app: 1000y
template:
metadata:
labels:
app: 1000y
spec:
containers:
- name: app
image: 1000y-app:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "0.5"
limits:
memory: "2Gi"
cpu: "1.5"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5---
service.yaml
apiVersion: v1
kind: Service
metadata:
name: 1000y-service
spec:
selector:
app: 1000y
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
—
第八部分:实战案例
8.1 案例1:1000y游戏论坛容器化改造
背景:
- 传统部署方式:直接在服务器上安装LAMP环境
- 问题:环境不一致、部署慢、扩展困难
容器化改造方案:
# 基于PHP 8.4官方镜像
FROM php:8.4-apache安装Laravel所需扩展
RUN docker-php-ext-install mysqli pdo pdo_mysql bcmath gd配置Apache
RUN a2enmod rewrite复制应用代码
COPY . /var/www/html设置权限
RUN chown -R www-data:www-data /var/www/html/storageWORKDIR /var/www/html
EXPOSE 8080
CMD ["apache2-foreground"]
version: '3.8'services:
app:
build: .
ports:
- "8080:80"
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: 1000y
volumes:
- db-data:/var/lib/mysql
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
volumes:
db-data:
redis-data:
- 部署时间:从30分钟减少到5分钟
- 环境一致性:100%(开发、测试、生产完全一致)
- 扩展能力:从手动扩展到秒级水平扩展
- 资源利用率:提升40%
8.2 案例2:WordPress多站点容器化
背景:
- 管理多个WordPress站点
- 每个站点独立数据库和配置
解决方案:
version: '3.8'services:
# Nginx反向代理
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
networks:
- frontend
# WordPress站点1
wp-site1:
image: wordpress:6.4-php8.4-apache
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: site1_db
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
volumes:
- site1-data:/var/www/html
networks:
- frontend
- backend
# WordPress站点2
wp-site2:
image: wordpress:6.4-php8.4-apache
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: site2_db
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
volumes:
- site2-data:/var/www/html
networks:
- frontend
- backend
# 共享数据库服务器
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db-data:/var/lib/mysql
networks:
- backend
networks:
frontend:
backend:
volumes:
site1-data:
site2-data:
db-data:
server {
listen 80;
server_name site1.your-domain.com; location / {
proxy_pass http://wp-site1:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name site2.your-domain.com;
location / {
proxy_pass http://wp-site2:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
- 站点部署:从2小时减少到10分钟
- 资源利用率:提升60%(共享数据库)
- 备份恢复:从手动到自动化
8.3 案例3:微服务架构容器化
背景:
- OpenClaw AI网关微服务架构
- 多个独立服务需要协同工作
架构设计:
┌─────────────┐
│ Nginx │
│ (反向代理) │
└──────┬──────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌────▼────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ API网关 │ │ Web服务 │ │ Admin服务 │
└────┬────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
└─────────────────┼──────────────────┘
│
┌───────────┴───────────┐
│ │
┌────▼────┐ ┌────▼────┐
│ Redis │ │ MySQL │
└─────────┘ └─────────┘
Docker Compose配置:
version: '3.8'services:
# API网关
api-gateway:
build: ./services/api-gateway
ports:
- "18789:18789"
environment:
- REDIS_HOST=redis
- MYSQL_HOST=db
networks:
- backend
depends_on:
- redis
- db
# Web服务
web-service:
build: ./services/web-service
environment:
- REDIS_HOST=redis
- MYSQL_HOST=db
networks:
- backend
depends_on:
- redis
- db
# Admin服务
admin-service:
build: ./services/admin-service
environment:
- REDIS_HOST=redis
- MYSQL_HOST=db
networks:
- backend
depends_on:
- redis
- db
# Redis缓存
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
networks:
- backend
# MySQL数据库
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: openclaw
networks:
- backend
networks:
backend:
driver: bridge
—
最后一些建议
关键要点回顾
– 容器 vs 虚拟机
– 镜像、容器、仓库
– 分层存储
– 多阶段构建
– 最小化镜像体积
– 安全最佳实践
– 多容器协同
– 服务依赖
– 资源限制
– 监控和日志
– 备份和恢复
– CI/CD集成
– 镜像安全扫描
– 容器隔离
– 性能优化
学习路线建议
初级(1-2周):
- 理解Docker核心概念
- 编写简单Dockerfile
- 使用Docker Compose编排多容器
中级(1个月):
- 优化Dockerfile
- 配置生产环境
- 实现自动化部署
高级(2-3个月):
- 容器编排(Swarm/Kubernetes)
- 微服务架构
- 安全和性能优化
参考资源
官方文档:
- Docker官方文档:https://docs.docker.com/
- Docker Compose文档:https://docs.docker.com/compose/
- Docker Hub:https://hub.docker.com/
推荐工具:
- 镜像扫描:Trivy
- 监控:Prometheus + Grafana
- 日志:ELK Stack
- 私有仓库:Harbor
实战项目:
- 1000y游戏论坛容器化部署
- WordPress多站点管理
- OpenClaw AI网关微服务
持续学习:
- 关注Docker官方博客
- 参与社区讨论
- 实践真实项目
—
附录:快速参考命令
# 镜像操作
docker build -t myapp:latest .
docker tag myapp:latest your-domain.com/myapp:latest
docker push your-domain.com/myapp:latest
docker pull myapp:latest
docker rmi myapp:latest容器操作
docker run -d -p 8080:80 --name myapp myapp:latest
docker ps
docker stop myapp
docker start myapp
docker restart myapp
docker rm myapp
docker exec -it myapp /bin/bash日志和调试
docker logs myapp
docker logs -f myapp
docker inspect myapp
docker stats myapp资源清理
docker system prune -a
docker volume prune
docker network pruneDocker Compose
docker-compose up -d
docker-compose down
docker-compose logs -f
docker-compose restart
docker-compose ps
—
版本信息:
- 文档版本:v2.0
- Docker版本:24.0.7+
- PHP版本:8.4
- 最后更新:2026-03-19
作者备注:
本文档基于真实生产环境经验编写,包含1000y游戏论坛、WordPress网站和OpenClaw AI网关的容器化部署实践。所有示例代码均经过生产环境验证。
—
下一步学习
建议继续学习以下主题:
实战练习:
—
相关文章:
—
反馈和改进:
如果您在使用本文档过程中遇到问题或有改进建议,欢迎通过以下方式联系:
- 邮箱:tech@chencunli.com
- 网站:https://www.chencunli.com
- GitHub:https://github.com/yourusername
—
版权声明:
本文档由Tech Future技术团队编写,遵循CC BY-NC-SA 4.0许可协议。欢迎非商业用途的转载和分享,但请注明出处。
—
更新日志:
- v2.0 (2026-03-19): 全面重写,增加实战案例和最佳实践
- v1.0 (2026-03-15): 初始版本
—
关键词:
Docker、容器化、DevOps、CI/CD、微服务、PHP、Laravel、WordPress、生产环境、最佳实践、性能优化、安全