Docker容器化部署实战:草根站长零基础入门指南

引言

作为一个跑了十几年网站的草根站长,我深知一个痛点:服务器环境搭建太费劲了。从 LAMP 到 LNMP,从 PHP 5.6 到 PHP 8.2,每次换服务器都是一场灾难。直到我接触了 Docker,才真正体会到"一次配置,到处运行"的快感。

这篇文章不扯原理,不讲架构,就用一个草根站长的视角,带你从零开始用 Docker 部署一个完整的网站环境。我保证:看完你就能上手。

为什么草根站长应该学 Docker

很多站长一听到 Docker 就觉得是高大上的东西,是大厂才用的。其实恰恰相反,Docker 对个人站长来说可能是性价比最高的技术投资。

先说几个真实场景:

场景一:换服务器。你有没有遇到过这种崩溃:旧服务器 PHP 5.6,新服务器 PHP 8.1,网站直接白屏?用 Docker 的话,你只需要把配置文件复制过去,一条命令启动,环境一模一样。

场景二:多站点管理。一个服务器上跑 5 个网站,A 站需要 PHP 7.4,B 站需要 PHP 8.2,C 站还需要特定版本的 MySQL。传统方式你得装多个 PHP 版本,各种配置冲突到怀疑人生。Docker 每个容器独立运行,互不干扰。

场景三:本地测试。在本地电脑上搭一个和线上完全一致的环境,改完代码测试没问题再上线。告别"我本地好好的啊"的尴尬。

安装 Docker

先说最基础的安装。我用的是 Debian/Ubuntu 系统,CentOS 的命令也差不多。

# 一键安装脚本(推荐)
curl -fsSL https://get.docker.com | bash

# 启动 Docker 并设置开机自启
systemctl start docker
systemctl enable docker

# 把当前用户加入 docker 组,省得每次都 sudo
usermod -aG docker $USER

安装完成后验证一下:

docker --version
docker run hello-world

看到 "Hello from Docker!" 就说明安装成功了。

Docker Compose:管理多个容器的神器

单独用 Docker 命令管理容器已经很方便了,但如果你的网站需要 Nginx + PHP + MySQL 三个服务一起跑,用 Docker Compose 会让你爽到飞起。一个 YAML 文件定义所有服务,一条命令全部启动。

# 安装 Docker Compose
apt install docker-compose -y

实战:用 Docker 部署一个 Typecho 博客

下面我们真刀真枪来一遍,用 Docker 部署一个完整的 Typecho 博客。Typecho 是国内站长常用的轻量博客系统,对个人站长非常友好。

第一步:创建项目目录

mkdir -p /opt/typecho && cd /opt/typecho
mkdir nginx mysql typecho

第二步:编写 docker-compose.yml

version: '3.8'

services:
  nginx:
    image: nginx:alpine
    container_name: typecho_nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/ssl:/etc/nginx/ssl
      - ./typecho:/var/www/html
    depends_on:
      - php
    restart: always

  php:
    image: php:8.1-fpm-alpine
    container_name: typecho_php
    volumes:
      - ./typecho:/var/www/html
    restart: always

  mysql:
    image: mysql:8.0
    container_name: typecho_mysql
    environment:
      MYSQL_ROOT_PASSWORD: your_strong_password
      MYSQL_DATABASE: typecho
      MYSQL_USER: typecho
      MYSQL_PASSWORD: typecho_password
    volumes:
      - ./mysql/data:/var/lib/mysql
    restart: always

第三步:配置 Nginx

创建 Nginx 配置文件 nginx/conf.d/default.conf

server {
    listen 80;
    server_name your-domain.com;
    root /var/www/html;
    index index.php index.html;

    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;
    }
}

第四步:下载 Typecho 并启动

# 下载 Typecho
wget https://github.com/typecho/typecho/releases/latest/download/typecho.zip
unzip typecho.zip -d typecho/
chown -R 33:33 typecho/

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

# 查看运行状态
docker-compose ps

就这么简单!访问你的域名就能看到 Typecho 安装界面了。

Docker 常用命令速查

作为站长,下面这些命令你一定会经常用到:

# 查看所有运行中的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 启动/停止/重启容器
docker start 容器名
docker stop 容器名
docker restart 容器名

# 查看容器日志(排查问题必备)
docker logs -f 容器名
docker logs --tail 100 容器名

# 进入容器内部
docker exec -it 容器名 /bin/sh

# 删除容器
docker rm 容器名

# 删除镜像
docker rmi 镜像名

# 清理无用的镜像和容器(释放磁盘空间)
docker system prune -a

Docker 网络详解:让容器之间自由通信

Docker 的网络模型对新手来说容易搞混,但理解了就很简单。Docker 默认创建三种网络:

bridge 网络:默认模式。每个容器获得一个内网 IP,通过宿主机端口映射对外提供服务。适合单机部署。

host 网络:容器直接使用宿主机的网络栈,性能最好但端口不能冲突。适合对网络性能要求极高的场景。

overlay 网络:跨主机通信,适合 Docker Swarm 集群。个人站长一般用不到。

对我们草根站长来说,99% 的场景用默认的 bridge 网络就够了。Docker Compose 会为每个项目自动创建一个独立的 bridge 网络,同一个 docker-compose.yml 里的容器可以互相通过服务名通信。

# 查看所有网络
docker network ls

# 创建自定义网络(多个 compose 文件共用)
docker network create my-network

# 查看网络详情
docker network inspect my-network

数据卷深入:保证数据不丢失的关键

Docker 容器是无状态的,容器删除后里面的数据就没了。数据卷(Volume)就是解决这个问题的。

Docker 有三种挂载方式:

bind mount:把宿主机目录挂载到容器内。最灵活,也是最常用的方式。

docker run -v /host/path:/container/path nginx

named volume:Docker 管理的卷,存储在 /var/lib/docker/volumes/ 下。

docker volume create mydata
docker run -v mydata:/data nginx

tmpfs:临时文件系统,存储在内存中,容器停止就没了。仅用于缓存等临时数据。

对于生产环境,我推荐用 named volume 存储数据库数据,用 bind mount 存储网站代码。原因是 named volume 的性能更好(直接操作本地文件系统),bind mount 更方便修改代码。

services:
  mysql:
    volumes:
      - mysql_data:/var/lib/mysql  # named volume
  nginx:
    volumes:
      - ./html:/usr/share/nginx/html  # bind mount

volumes:
  mysql_data:

数据备份:Docker 环境下的备份策略

很多人担心 Docker 环境下数据不安全,其实 Docker 的数据备份反而更简单。因为数据都通过 Volume 映射到了宿主机目录,你只需要备份宿主机上的目录就行了。

# 备份 MySQL 数据
docker exec typecho_mysql mysqldump -u root -p typecho > /backup/typecho_$(date +%Y%m%d).sql

# 备份网站文件
tar -czf /backup/typecho_files_$(date +%Y%m%d).tar.gz /opt/typecho/typecho/

# 设置定时任务(每天凌晨 3 点自动备份)
echo "0 3 * * * /opt/scripts/backup.sh" | crontab -

进阶技巧:使用 Watchtower 自动更新镜像

安全问题不能忽视。容器里的软件也需要更新补丁。Watchtower 可以自动检测并更新 Docker 镜像:

docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower \
  --interval 86400

这样每天自动检查一次,有更新就自动拉取新镜像并重启容器。

多站点部署实战:一机运行五个网站

草根站长经常面临一个需求:一台服务器跑多个网站。用 Docker 实现这个非常简单。

核心思路:每个网站一个独立的 docker-compose.yml,用 Nginx 反向代理统一入口。

# 目录结构
/opt/sites/
├── site-a/
│   ├── docker-compose.yml
│   └── html/
├── site-b/
│   ├── docker-compose.yml
│   └── html/
└── proxy/
    ├── docker-compose.yml
    └── nginx/
        └── conf.d/

代理 Nginx 的配置:

server {
    listen 80;
    server_name site-a.com;

    location / {
        proxy_pass http://site-a-nginx: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;
    }
}

每个网站的 nginx 监听内部端口,不对外暴露。只有代理 Nginx 对外暴露 80 和 443 端口。

常见坑和解决方案

  1. 端口冲突:如果 80 端口被占用,改 docker-compose.yml 里的端口映射,比如 "8080:80"
  2. 权限问题:PHP 容器里默认是 www-data 用户(UID 33),宿主机文件权限要匹配。执行 chown -R 33:33 ./html 解决。
  3. MySQL 连接失败:容器之间用服务名通信,比如 MySQL 的主机名是 mysql 而不是 localhost
  4. 磁盘空间不足:定期执行 docker system prune 清理无用的镜像和容器。Docker 的镜像层会累积占用大量磁盘空间。
  5. 容器启动顺序depends_on 只保证启动顺序,不保证服务就绪。对于 MySQL 这种需要时间初始化的服务,可以在应用容器里加个等待脚本。
  6. 日志爆炸:Docker 默认不限制日志大小,时间长了日志文件可能把你的磁盘占满。在 docker-compose.yml 中配置日志轮转:
services:
  nginx:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

总结

Docker 不是什么高深的技术,它就是帮你把环境打包起来的工具。对草根站长来说,学会 Docker 意味着:

  • 换服务器不再是一场噩梦
  • 多站点管理不再混乱
  • 本地测试和线上环境完全一致
  • 一条命令就能在新服务器上重建整个网站

花一个下午学会 Docker,将来能省下无数个折腾环境的通宵。个人觉得这笔投资非常值得。

Docker 安全加固要点

容器化环境虽然隔离性好,但也不是绝对安全的。作为站长,部署上线前有几件事必须做:

使用非 root 用户运行容器。默认情况下很多镜像以 root 运行,一旦容器被攻破,攻击者就能获得宿主机的 root 权限。

FROM php:8.1-fpm-alpine
RUN addgroup -g 1000 app && adduser -u 1000 -G app -s /bin/sh -D app
USER app

限制容器资源。防止某个容器占用全部 CPU 或内存导致其他服务不可用。

services:
  php:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

定期扫描镜像漏洞。使用 Docker Scout 或 Trivy 检查镜像中的已知漏洞:

docker scout quickview nginx:alpine
# 或者
trivy image nginx:alpine

不要暴露不必要的端口。MySQL 容器只需要让 PHP 容器访问,不需要映射到宿主机。docker-compose.yml 中只暴露 Nginx 的端口就行。

最后的建议

Docker 的世界很大,但对于草根站长来说,掌握这篇文章里的内容已经足够应对 90% 的场景了。后续如果你感兴趣,可以继续学习 Dockerfile 编写、多阶段构建、Docker Swarm 集群等高级内容。但千万别一开始就追求完美,先用起来,在实践中学习,这才是最有效的路径。

如果你在实践过程中遇到问题,欢迎在评论区交流。

Last modification:July 12th, 2026 at 11:41 am

Leave a Comment