Docker容器化部署实战:从入门到个人网站生产环境

前言

容器化技术已经从一个新兴概念变成了现代网站部署的标准方案。对于个人站长来说,Docker 不仅仅是一个"高大上"的技术名词,它实际上能解决很多实际问题:环境不一致导致的"在我机器上能运行"问题、服务器迁移时的重复配置痛苦、多站点隔离的安全需求。本文将从零开始,带你一步步掌握 Docker 容器化部署的核心技能,最终搭建一套可直接用于生产环境的个人网站架构。

一、Docker 基础概念

1.1 什么是 Docker

Docker 是一个开源的容器化平台,它允许你将应用程序及其所有依赖打包到一个标准化的单元中——这个单元就是"容器"。与传统的虚拟机不同,容器共享宿主机的操作系统内核,因此更轻量、启动更快、资源占用更少。

容器 vs 虚拟机对比:

  • 启动时间:容器毫秒级,虚拟机分钟级
  • 磁盘占用:容器 MB 级别,虚拟机 GB 级别
  • 性能损耗:容器几乎无损耗,虚拟机有约 5-15% 的性能开销
  • 隔离级别:容器为进程级隔离,虚拟机为硬件级虚拟化

1.2 核心组件

  • Docker Daemon(dockerd):后台守护进程,负责管理容器的生命周期
  • Docker Client(docker CLI):与守护进程通信的命令行工具
  • Docker Image(镜像):一个只读模板,包含运行应用所需的文件系统和配置
  • Docker Container(容器):镜像的运行实例,可读写
  • Docker Registry(仓库):存储和分发镜像的服务,Docker Hub 是最流行的公共仓库

1.3 安装 Docker

在 Ubuntu/Debian 服务器上安装 Docker 非常简单:

# 更新包索引
sudo apt update

# 安装依赖
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker 仓库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 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 组(避免每次使用 sudo)
sudo usermod -aG docker $USER

# 验证安装
docker --version

安装完成后,运行 docker info 可以查看系统信息,运行 docker run hello-world 测试容器能否正常工作。

二、Dockerfile 编写指南

Dockerfile 是一个文本文件,包含了构建镜像所需的指令序列。下面以一个典型的 PHP + Nginx 个人网站为例。

2.1 基础 Dockerfile 示例

# 使用 PHP 8.2 官方镜像作为基础
FROM php:8.2-fpm-alpine AS php-base

# 安装必要的 PHP 扩展
RUN docker-php-ext-install pdo_mysql mysqli bcmath

# 安装 Redis 扩展
RUN pecl install redis && docker-php-ext-enable redis

# 复制应用代码
COPY . /var/www/html

# 设置工作目录
WORKDIR /var/www/html

# 设置权限
RUN chown -R www-data:www-data /var/www/html

# Nginx 阶段
FROM nginx:alpine AS nginx

# 复制 Nginx 配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 从 PHP 阶段复制静态文件
COPY --from=php-base /var/www/html /var/www/html

2.2 多阶段构建

多阶段构建可以显著减小最终镜像的体积,这是生产环境部署的最佳实践:

# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

通过多阶段构建,最终镜像只包含 Nginx 和编译后的静态文件,体积从 1GB+ 缩小到不到 100MB。

三、Docker Compose 编排多容器

对于个人网站,通常需要多个服务协同工作:Nginx(反向代理)、PHP-FPM(应用处理)、MySQL(数据库)、Redis(缓存)。Docker Compose 可以一站式管理这些服务。

3.1 编写 docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
      - app_data:/var/www/html:ro
    depends_on:
      - php
    networks:
      - webnet
    restart: unless-stopped

  php:
    build:
      context: .
      dockerfile: Dockerfile.php
    volumes:
      - app_data:/var/www/html
    environment:
      - DB_HOST=mysql
      - DB_NAME=myblog
      - DB_USER=myuser
      - DB_PASS=secret
      - REDIS_HOST=redis
    depends_on:
      - mysql
      - redis
    networks:
      - webnet
    restart: unless-stopped

  mysql:
    image: mysql:8.0
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=rootpass
      - MYSQL_DATABASE=myblog
      - MYSQL_USER=myuser
      - MYSQL_PASSWORD=secret
    networks:
      - webnet
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    networks:
      - webnet
    restart: unless-stopped

volumes:
  app_data:
  mysql_data:
  redis_data:

networks:
  webnet:
    driver: bridge

3.2 常用 Compose 命令

# 启动所有服务
docker compose up -d

# 查看日志
docker compose logs -f

# 重启某个服务
docker compose restart php

# 重新构建并启动
docker compose up -d --build

# 停止所有服务
docker compose down

# 停止并删除数据卷(谨慎操作)
docker compose down -v

四、生产环境最佳实践

4.1 镜像优化

  • 尽量使用 Alpine 版本的基础镜像,体积小且安全
  • 合并 RUN 命令减少镜像层数
  • 使用 .dockerignore 文件排除不必要的文件
  • 通过多阶段构建分离构建环境和运行环境

.dockerignore 示例:

.git
node_modules
.env
*.md
tests/
logs/

4.2 数据持久化

容器的文件系统是临时的,容器删除后数据会丢失。必须使用卷(volume)来持久化重要数据:

# 创建命名卷
docker volume create myblog_data

# 使用命名卷
docker run -v myblog_data:/var/lib/mysql mysql:8.0

# 使用绑定挂载(直接映射主机目录)
docker run -v /host/path:/container/path nginx:alpine

4.3 安全加固

  • 不要以 root 用户运行容器内的进程
  • 使用只读文件系统(read_only: true
  • 限制容器资源使用(CPU/内存限制)
  • 定期更新基础镜像以修复安全漏洞
# docker-compose 中的安全配置示例
services:
  php:
    read_only: true
    tmpfs:
      - /tmp
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M

4.4 日志管理

Docker 默认将日志存储在 JSON 文件中,长期运行会占用大量磁盘空间。建议配置日志轮转:

# 全局配置 /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
# 或者在 compose 中按服务配置
services:
  nginx:
    logging:
      driver: "json-file"
      options:
        max-size: "5m"
        max-file: "3"

五、实际部署案例

5.1 Typecho 博客容器化

以 Typecho 博客系统为例,完整部署流程:

# 1. 创建项目目录
mkdir typecho-docker && cd typecho-docker

# 2. 下载 Typecho
wget https://github.com/typecho/typecho/releases/latest/download/typecho.zip
unzip typecho.zip

# 3. 创建 docker-compose.yml(参考上面的配置)
vim docker-compose.yml

# 4. 创建 Nginx 配置
cat > nginx.conf << 'EOF'
server {
    listen 80;
    server_name yourdomain.com;
    root /var/www/html;
    index index.php;
    
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
EOF

# 5. 启动
docker compose up -d

# 6. 查看日志确认启动成功
docker compose logs

5.2 备份策略

容器化部署后,数据库备份仍然至关重要:

#!/bin/bash
# docker-backup.sh
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 备份 MySQL
docker exec typecho-mysql-1 mysqldump -u root -prootpass myblog | gzip > $BACKUP_DIR/db_$DATE.sql.gz

# 保留最近 30 天的备份
find $BACKUP_DIR -name "db_*.sql.gz" -mtime +30 -delete

echo "Backup completed: $BACKUP_DIR/db_$DATE.sql.gz"

将备份脚本加入 crontab,每天凌晨自动执行:

0 3 * * * /root/scripts/docker-backup.sh

六、常见问题排查

6.1 容器无法启动

# 查看容器日志
docker logs container_name

# 检查容器状态
docker ps -a

# 进入容器调试
docker exec -it container_name /bin/sh

6.2 端口冲突

# 检查端口占用
netstat -tlnp | grep 80

# 修改映射端口
# 在 docker-compose.yml 中将 "80:80" 改为 "8080:80"

6.3 磁盘空间不足

# 清理未使用的镜像、容器和数据卷
docker system prune -a

# 查看磁盘使用情况
docker system df

# 仅清理数据卷
docker volume prune

结语

容器化部署已经成为个人网站运维的必备技能。通过 Docker,你可以实现环境一致性、快速部署、轻松迁移和高效资源利用。本文涵盖了从基础概念到生产环境部署的完整路径,希望能帮助你在实践中少走弯路。

记住,容器化是一个持续学习的过程,每次遇到问题都是一次提升的机会。建议从一个小项目开始,逐步将现有网站迁移到容器化架构,在实践中积累经验。

Last modification:July 24th, 2026 at 08:07 am

Leave a Comment