用 Docker Compose 一键搭建 LNMP 本地开发环境
前言
上周接手一个老项目,本地环境折腾了整整一下午:PHP 版本和扩展对不上、Nginx 配置互相冲突、MySQL 字符集一不留神又是乱码。痛定思痛,决定把本地开发环境彻底容器化。这篇文章记录我用 Docker Compose 搭建 LNMP 环境的全过程,照着做,十分钟就能跑起来。
一、环境准备
只需要一台装好 Docker 的 Linux 机器(我用的是一台华为云 ECS,CentOS 系统)。先确认 Docker 和 Compose 插件已经就绪:
docker --version
docker compose version
还没装的话,CentOS 上可以用官方脚本一键安装:
curl -fsSL https://get.docker.com | sh
sudo systemctl enable --now docker
再把当前用户加入 docker 组,避免每条命令都加 sudo:
sudo usermod -aG docker $USER
重新登录后跑个 Hello World 验证:
docker run --rm hello-world
看到 “Hello from Docker!” 就说明 Docker 已经就绪。
二、规划目录结构
先建一个项目目录,把配置、数据和代码分开存放,结构清晰,后面维护也方便:
mkdir -p ~/lnmp/{nginx/conf.d,mysql/data,php,www}
cd ~/lnmp
nginx/conf.d/:存放 Nginx 站点配置mysql/data/:MySQL 数据持久化目录php/:PHP 相关配置(比如自定义 php.ini)www/:网站代码根目录
三、编写 docker-compose.yml
这是整个环境的核心,一个文件定义三个服务:
version: "3.8"
services:
nginx:
image: nginx:1.25
container_name: lnmp-nginx
ports:
- "8080:80"
volumes:
- ./www:/var/www/html
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- php
networks:
- lnmp-net
php:
image: php:8.2-fpm
container_name: lnmp-php
volumes:
- ./www:/var/www/html
networks:
- lnmp-net
mysql:
image: mysql:8.0
container_name: lnmp-mysql
environment:
MYSQL_ROOT_PASSWORD: "Root@123456"
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: "App@123456"
volumes:
- ./mysql/data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- lnmp-net
networks:
lnmp-net:
driver: bridge
几个细节值得注意:Nginx 和 PHP 共享 ./www 目录,Nginx 把 PHP 请求转发给 php-fpm 处理;MySQL 的数据目录挂载到宿主机,重建容器数据也不会丢;三个服务挂在同一个自定义网络里,互相用服务名就能通信。
四、配置 Nginx 站点
在 nginx/conf.d/ 下新建 default.conf:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
关键点是 fastcgi_pass php:9000,这里的 php 是 compose 里定义的服务名,Docker 内置 DNS 会自动解析到 PHP 容器的地址,不用写死 IP,容器重建也不怕。
五、启动并验证
一条命令启动所有服务:
docker compose up -d
查看容器状态:
docker compose ps
三个容器都显示为 Up 之后,在 www/ 下放一个探针文件验证 PHP 是否正常:
echo "<?php phpinfo();" > www/index.php
curl http://localhost:8080
如果返回了 PHP 信息页,说明 Nginx + PHP 已经打通。再验证数据库连接:
docker compose exec mysql mysql -uappuser -p'App@123456' -e "SHOW DATABASES;"
能看到 appdb 数据库,就大功告成了。
六、日常运维命令
环境跑起来之后,这几个命令几乎每天都会用到,记下来能省不少事:
# 查看所有服务日志,排查问题首选
docker compose logs -f
# 只看某一个服务的日志
docker compose logs -f nginx
# 进入 PHP 容器执行命令,比如安装扩展
docker compose exec php bash
# 停止并删除容器(数据卷保留,代码不受影响)
docker compose down
# 修改配置后重建并启动
docker compose up -d --build
七、踩过的几个坑
- 端口冲突:宿主机 80 端口经常被占用,我习惯把 Nginx 映射到 8080,省得每次去停系统服务。
- 文件权限:宿主机用户和容器内 www-data 用户 UID 不一致时,挂载的代码目录可能出现写权限问题,开发环境图省事可以在 php 服务里加一行
user: "1000:1000"对齐。 - MySQL 字符集:建库建表记得指定
utf8mb4,不然 emoji 存进去就是问号,这个坑我踩过两次。 - 数据持久化:一定要把
/var/lib/mysql挂载出来,否则手一抖敲了docker compose down -v,数据就全没了。
结语
容器化之后,换电脑、重装系统都不再可怕:代码和 docker-compose.yml 一拷,up -d 一敲,环境原地复活。新人入职也不用再对着二十页的环境搭建文档抓狂了。如果你也在为本地环境头疼,不妨试试这套方案,十分钟换一整个下午的清净,还是很值的。
- 点赞
- 收藏
- 关注作者
评论(0)