别再手动改配置了!用Docker Compose一键部署你的第一个Web应用(附完整YAML文件)

每次部署Web应用都要重复安装Nginx、配数据库、调环境变量?试试这个:把整个基础设施打包成代码。想象一下,你刚写完一个博客系统,本地测试完美,但部署到服务器时发现PHP版本不匹配、MySQL配置出错、Nginx代理规则写错——这些困扰开发者多年的"环境玄学"问题,其实早该被扔进技术历史的垃圾桶。

1. 为什么你的开发环境总在"闹脾气"?

传统部署方式就像用纸质地图导航:每次换车(服务器)都得重新折纸。我见过团队里最夸张的案例——某个Java应用在A同事电脑跑得飞快,到B同事那里直接OOM崩溃,最后发现是 .bashrc 里一个隐藏的环境变量在作祟。而Docker Compose给出的解决方案是:把整个运行时环境(包括操作系统层)打包成 声明式清单

环境不一致的三大元凶

  • 系统依赖库版本差异(比如OpenSSL 1.1 vs 3.0)
  • 配置文件散落各处(/etc/nginx vs ~/project/conf)
  • 隐性状态污染(残留的临时文件、未清理的缓存)
# 典型的问题场景:本地用MySQL 8.0,服务器却是5.7
# 传统做法:手动降级或升级,处理兼容性问题
# Docker方案:明确指定镜像版本
services:
  db:
    image: mysql:8.0.32
    environment:
      MYSQL_ROOT_PASSWORD: my-secret-pw

提示:Docker Compose的 environment 配置项会自动处理环境变量注入,比手动 export 更可靠

2. 解剖你的第一个Docker Compose文件

让我们从一个最小化的LAMP栈开始。这个配置不到30行的YAML文件,抵得上过去3小时的部署工作量:

version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  php:
    build: ./php
    volumes:
      - ./html:/var/www/html

  db:
    image: mariadb:10.6
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: myapp
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

关键组件解析

服务 技术选择 优化点
Web服务器 Nginx Alpine版 轻量(仅5MB),自动配置反向代理
应用运行时 自定义PHP镜像 可预装扩展(如gd、pdo_mysql)
数据库 MariaDB 10.6 完全兼容MySQL,更小的内存占用

3. 从零到一的完整操作流

3.1 准备你的战场

  1. 安装Docker Desktop(Mac/Windows)或Docker Engine(Linux)
  2. 创建项目目录结构:
    /myapp
    ├── docker-compose.yml
    ├── nginx.conf
    ├── php/
    │   └── Dockerfile
    └── html/
        └── index.php
    

3.2 编写构建指令

PHP容器的Dockerfile示例:

FROM php:8.1-fpm
RUN docker-php-ext-install pdo_mysql
COPY php.ini /usr/local/etc/php/conf.d/

注意:生产环境应该使用 docker-php-ext-configure 精细控制扩展编译参数

3.3 启动与验证

运行这组命令见证魔法:

# 启动所有服务(后台模式)
docker-compose up -d

# 查看实时日志
docker-compose logs -f web

# 验证服务状态
curl http://localhost:8080

4. 进阶技巧:让配置更专业

4.1 环境变量管理

把敏感信息从YAML中抽离:

# 原配置
environment:
  MYSQL_ROOT_PASSWORD: my-password

# 改进版
env_file:
  - .env

然后在 .env 文件中:

DB_ROOT_PASS=my-password
DB_NAME=production_db

4.2 多环境配置方案

通过override文件实现环境切换:

# docker-compose.yml (基础配置)
# docker-compose.prod.yml (生产环境扩展)
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

生产环境扩展示例:

services:
  web:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    logging:
      driver: "json-file"
      options:
        max-size: "10m"

5. 避坑指南:我踩过的那些雷

容器间通信失败 :确保使用 depends_on + 健康检查,而不是简单等待端口开放。曾经有个项目因为MySQL启动慢导致应用崩溃,后来改成这样:

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 5s
  timeout: 3s
  retries: 10

数据卷权限问题 :Linux主机上经常遇到容器用户无权写入挂载目录。解决方案是在Dockerfile中明确用户:

RUN chown -R www-data:www-data /var/www/html
USER www-data

镜像构建缓存污染 :当修改了 COPY 的文件后,记得 --no-cache 重建:

docker-compose build --no-cache php

现在打开你的终端,执行 docker-compose down && docker-compose up ,享受一杯咖啡的时间——过去这些时间你还在和apt-get打架呢。记住,好的开发者不应该像系统管理员那样工作,而应该让代码管理基础设施。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐