Docker从入门到实战：个人站长的容器化部署完全指南
Docker从入门到实战：个人站长的容器化部署完全指南Docker是过去五年最重要的运维技术之一。对个人站长来说，它最大的价值是让环境部署变得简单且可重复。本文从零开始带你掌握Docker。什么是DockerDocker把应用程序和它需要的所有依赖包打包成一个标准化的容器。这意味着无论你是在自己的电脑上、公司的服务器上还是云服务器上，应用运行的环境完全一致。对站长来说解决了什么问题：再也不用在不同环境之间调试兼容性问题了。安装Docker在Ubuntu或Debian上安装Docker只需要三条命令：更新包管理器、安装必要依赖、执行Docker官方安装脚本。整个过程不超过5分钟。第一个Docker容器docker run hello-world 这条命令会下载并运行一个测试镜像。如果看到Hello from Docker的提示，说明安装成功了。用Docker部署网站以Typecho博客为例，使用docker-compose.yml文件定义Typecho和MySQL两个服务，一条命令docker-compose up -d就能启动整个博客系统。配置文件不到20行，但涵盖了所有需要的配置。数据持久化Docker容器重启后数据会丢失，所以必须把数据库和上传文件的目录映射到宿主机上。这是新手最容易踩的坑。常用命令docker ps查看运行中的容器、docker logs查看日志、docker-compose up -d启动服务、docker-compose down停止服务。掌握这4个命令就够日常使用了。进阶：多服务编排当你需要同时运行网站、数据库、缓存、消息队列等多个服务时，docker-compose.yml在一个文件里定义所有服务及其依赖关系，一条命令搞定全部部署。总结Docker的入门曲线确实比宝塔面板陡峭，但一旦掌握你就能在任何服务器上10分钟内搭建一个完整的网站环境。建议先在本地虚拟机里练习，熟练后再应用到生产环境。
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.ymlversion: '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 -aDocker 网络详解：让容器之间自由通信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 nginxnamed volume：Docker 管理的卷，存储在 /var/lib/docker/volumes/ 下。docker volume create mydata docker run -v mydata:/data nginxtmpfs：临时文件系统，存储在内存中，容器停止就没了。仅用于缓存等临时数据。对于生产环境，我推荐用 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 端口。常见坑和解决方案端口冲突：如果 80 端口被占用，改 docker-compose.yml 里的端口映射，比如 "8080:80"。权限问题：PHP 容器里默认是 www-data 用户（UID 33），宿主机文件权限要匹配。执行 chown -R 33:33 ./html 解决。MySQL 连接失败：容器之间用服务名通信，比如 MySQL 的主机名是 mysql 而不是 localhost。磁盘空间不足：定期执行 docker system prune 清理无用的镜像和容器。Docker 的镜像层会累积占用大量磁盘空间。容器启动顺序：depends_on 只保证启动顺序，不保证服务就绪。对于 MySQL 这种需要时间初始化的服务，可以在应用容器里加个等待脚本。日志爆炸：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 集群等高级内容。但千万别一开始就追求完美，先用起来，在实践中学习，这才是最有效的路径。如果你在实践过程中遇到问题，欢迎在评论区交流。