本地开发环境一键搭建:Docker Compose 编排 MySQL + Redis + Nginx

概述

做 Web 开发,本地环境搭起来最头疼。装 MySQL 要配路径,装 Redis 要记参数,装 Nginx 还要改 conf 文件。换个电脑重来一遍,浪费时间还容易出错。

用 Docker Compose 就不一样了。一个 yaml 文件,一行命令,三个服务全部跑起来。今天这篇手把手教你搭一套完整的本地开发环境。

准备工作

你需要两样东西:

  • 一台能联网的电脑(macOS / Windows / Linux 都行)
  • 已安装 Docker Desktop(或 Docker Engine),版本 20.10 以上

验证一下 Docker 有没有装好:

docker --version
docker compose version

两个命令都返回版本号就说明没问题。如果没装,去 docker.com 下载安装就行,跟着向导下一步就行。

步骤

第一步:创建项目目录

找个顺手的文件夹,新建一个目录:

mkdir ~/dev-env
cd ~/dev-env

第二步:写 docker-compose.yml

在当前目录下创建 docker-compose.yml,内容如下:

services:
  mysql:
    image: mysql:8.0
    container_name: dev-mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: app_db
      MYSQL_USER: dev
      MYSQL_PASSWORD: dev123
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - dev-net

  redis:
    image: redis:7-alpine
    container_name: dev-redis
    restart: always
    ports:
      - "6379:6379"
    command: redis-server --requirepass redis123
    volumes:
      - redis_data:/data
    networks:
      - dev-net

  nginx:
    image: nginx:alpine
    container_name: dev-nginx
    restart: always
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./public:/usr/share/nginx/html:ro
    depends_on:
      - mysql
      - redis
    networks:
      - dev-net

volumes:
  mysql_data:
  redis_data:

networks:
  dev-net:
    driver: bridge

这里起了三个服务:MySQL 8.0、Redis 7 精简版、Nginx Alpine 版。数据都挂载了卷,容器删了数据不会丢。

第三步:写 MySQL 初始化脚本

在同级目录创建 init.sql

CREATE DATABASE IF NOT EXISTS app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE app_db;

CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO users (username, email) VALUES ('admin', 'admin@example.com');

这个脚本会在 MySQL 第一次启动时自动执行,建好数据库和一张示例表。

第四步:写 Nginx 配置文件

创建 nginx.conf

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://localhost:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

第五步:创建一个简单的欢迎页

创建 public/index.html

<!DOCTYPE html>
<html>
<head><title>Dev Environment Ready</title></head>
<body>
    <h1>🎉 环境搭建成功!</h1>
    <p>MySQL: localhost:3306</p>
    <p>Redis: localhost:6379</p>
    <p>Nginx: localhost:80</p>
</body>
</html>

第六步:启动服务

回到 ~/dev-env 目录,执行:

docker compose up -d

-d 是后台运行。第一次会拉取镜像,可能需要几分钟。之后每次都是秒开。

看状态:

docker compose ps

应该看到三个容器都是 Up 状态。

验证

验证 MySQL

docker exec -it dev-mysql mysql -uroot -proot123 -e "SHOW DATABASES;"

能看到 app_db 和默认的几个库就说明 MySQL 正常。再查一下表:

docker exec -it dev-mysql mysql -uroot -proot123 app_db -e "SELECT * FROM users;"

应该能看到刚才插入的那条 admin 数据。

验证 Redis

docker exec -it dev-redis redis-cli -a redis123 ping

返回 PONG 就对了。

验证 Nginx

浏览器打开 http://localhost,或者用命令行:

curl http://localhost

应该能看到你写的欢迎页面。

常见问题

Q: docker compose 命令报错说找不到?

试试 docker-compose(中间带横杠)。旧版 Docker 用的是这个命令。新版已经改成空格分隔了。

Q: 端口被占用怎么办?

ports 里的宿主机端口改掉就行。比如 "3307:3306" 就是把 MySQL 映射到 3307 端口。

Q: 怎么停止服务?

docker compose down

-v 会连数据卷一起删,慎用。

Q: 换了电脑怎么迁移?

把整个 dev-env 文件夹复制过去,确保 Docker 装好了,直接 docker compose up -d 就行。不用重新配置任何参数。

Q: 想加个 PHPMyAdmin 管理 MySQL 怎么办?

在 docker-compose.yml 里加一个服务:

  phpmyadmin:
    image: phpmyadmin:latest
    container_name: dev-phpmyadmin
    restart: always
    ports:
      - "8080:80"
    environment:
      PMA_HOST: mysql
      PMA_PORT: 3306
    depends_on:
      - mysql
    networks:
      - dev-net

然后访问 http://localhost:8080,用户名 root,密码 root123。


这套环境搭好之后,不管做什么项目都能直接用。MySQL 连 3306,Redis 连 6379,静态资源走 Nginx 80 端口。省下来的时间多喝两杯咖啡不香吗?

试试在你的项目里跑一下,遇到端口冲突或者其他问题,随时回来翻这篇教程。