尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Linux下使用Docker Compose搭建LNMP环境全攻略

Linux下使用Docker Compose搭建LNMP环境全攻略 1. 项目缘起为什么要在Linux上用Docker搭LNMP如果你是一个后端开发者、运维工程师或者正在学习Web开发那么“LNMP”这个词对你来说肯定不陌生。它指的是Linux、Nginx、MySQL、PHP这套经典的Web服务栈无数网站和应用都跑在这套环境上。过去我们要么在物理服务器上一个个手动编译安装这些软件要么用集成包比如宝塔面板过程繁琐不说环境还容易“污染”不同项目依赖的软件版本冲突更是家常便饭。我最近接手了一个老项目的维护需要在本地复现一个和生产环境一模一样的测试环境。生产环境是CentOS 7 Nginx 1.18 MySQL 5.7 PHP 7.4。如果我在自己的Ubuntu 22.04开发机上直接安装这些先不说版本能不能对齐光是处理系统自带的PHP 8.1和项目需要的7.4之间的冲突就够我喝一壶了。这时候Docker的优势就体现出来了它能把应用和它所需要的环境包括库、依赖、配置文件打包成一个独立的“集装箱”。这个集装箱可以在任何安装了Docker的Linux机器上运行并且与宿主机环境完全隔离。所以这次的目标很明确在Linux系统上利用Docker容器技术快速、干净、可复现地搭建一套LNMP环境并部署一个简单的PHP项目进去。整个过程就像搭积木每个服务Nginx, MySQL, PHP都是一个独立的容器它们之间通过Docker网络通信互不干扰。这样做的好处是环境配置变成了代码Dockerfile和docker-compose.yml可以纳入版本管理迁移和重建环境只需要几条命令不同项目可以使用完全不同版本的服务栈彻底告别“一台机器一个环境”的窘境。2. 环境准备Linux与Docker的安装与基础配置在开始搭建积木之前我们得先确保手上有“积木”和“搭建平台”。这里的平台就是我们的Linux操作系统和Docker引擎。2.1 操作系统选择与准备理论上任何主流的Linux发行版都可以比如Ubuntu、CentOS、Debian、AlmaLinux等。我个人更倾向于使用Ubuntu Server LTS版本因为其社区活跃软件包新Docker支持也好。本文将以Ubuntu 22.04 LTS作为宿主机操作系统进行演示。如果你的系统是CentOS或其它大部分命令是相通的只是包管理工具aptvsyum/dnf和少数系统服务命令有所不同。首先确保系统是最新的sudo apt update sudo apt upgrade -y2.2 Docker引擎的安装与验证Docker的安装其实非常简单官方提供了非常清晰的脚本。但为了稳定和可控我推荐使用官方仓库安装而不是用snap。卸载旧版本如果有这是一个好习惯避免冲突。sudo apt remove docker docker-engine docker.io containerd runc安装依赖工具sudo apt install -y apt-transport-https ca-certificates curl software-properties-common添加Docker官方GPG密钥和仓库curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null安装Docker引擎sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin这里安装的docker-compose-plugin是Docker Compose V2它已经集成到Docker CLI中命令是docker compose注意没有横杠比旧的docker-compose工具更好用。验证安装并设置开机自启# 启动Docker服务 sudo systemctl start docker # 设置开机自启 sudo systemctl enable docker # 验证安装运行hello-world镜像 sudo docker run hello-world如果看到“Hello from Docker!”等欢迎信息说明Docker安装成功。可选但重要将当前用户加入docker组为了避免每次运行docker命令都要加sudo我们可以把当前用户加入docker用户组。sudo usermod -aG docker $USER注意执行此命令后你需要完全退出当前终端会话并重新登录或者重启系统用户组变更才会生效。之后你就可以直接使用docker ps而不是sudo docker ps了。2.3 解决一个常见启动问题虚拟化支持在安装过程中你可能会遇到一个报错尤其是在一些虚拟机或老旧硬件上运行Docker Desktop for Linux时错误信息类似于“Virtualization support not detected”或“Docker Desktop failed to start because virtualisation support wasn’t detected”。这个问题根源在于Docker Desktop依赖于Linux的KVM虚拟化技术来运行其内置的虚拟机。但对于我们绝大多数使用Linux服务器场景来说我们安装的是Docker Engine社区版而不是Docker Desktop。Docker Engine直接运行在Linux内核上利用内核的cgroups和namespaces特性来实现容器化不需要硬件虚拟化支持如Intel VT-x/AMD-V。因此在标准的Linux服务器上安装Docker Engine通常不会遇到这个“虚拟化支持未检测到”的问题。这个报错是Docker Desktop特有的。所以请确认你安装的是docker-ce社区引擎而不是去下载Docker Desktop的.deb包。如果你是在个人电脑的Linux发行版上并且确实想用Docker Desktop的图形界面那么你需要确保BIOS中已开启CPU的虚拟化支持VT-x/AMD-V并且系统已安装KVM。但对于本文的LNMP环境搭建我们强烈建议使用无图形界面的Docker Engine它更轻量、更稳定也更适合服务器环境。3. 核心概念与架构设计理解我们的“容器积木”在动手写配置文件之前我们先花几分钟理解一下我们要搭建的架构。这能让你在后面配置时清楚地知道每一行代码是干什么的。传统的LNMP是“all in one”所有软件装在一台机器上。而Docker化之后变成了“微服务”架构Nginx容器充当Web服务器和反向代理。它对外暴露80/443端口接收用户请求。对于PHP请求它不自己处理而是“转发”代理给后面的PHP容器。PHP-FPM容器运行PHP-FPMFastCGI Process Manager服务。它专门负责执行PHP代码。它和Nginx之间通过FastCGI协议通信通常是一个网络端口或Unix Socket。MySQL容器运行MySQL数据库服务。PHP程序通过数据库驱动如PDO, mysqli连接它。这三个容器如何通信它们需要在一个共同的Docker自定义网络中。这样容器之间可以使用容器名称作为主机名互相访问比如PHP容器里连接数据库可以使用mysql这个主机名而不是复杂的IP地址。数据如何持久化容器本身是无状态的停止后里面的数据就没了。所以我们必须把需要持久化的数据“挂载”到宿主机上网站代码挂载到Nginx和PHP容器的网站根目录如/var/www/html。Nginx配置挂载自定义的Nginx站点配置文件到容器的/etc/nginx/conf.d/目录。MySQL数据挂载一个宿主机目录到容器的/var/lib/mysql目录。PHP配置挂载自定义的php.ini文件到容器的/usr/local/etc/php/conf.d目录。我们将使用docker-compose.yml文件来定义和运行这三个容器。它就像一个蓝图描述了每个容器的镜像、端口、数据卷、网络和环境变量。使用docker compose up -d一条命令就能启动整个环境。4. 实战搭建编写Docker Compose蓝图理解了架构我们现在开始“写蓝图”。在你的项目目录下例如~/projects/lnmp-docker创建以下文件和目录结构。4.1 创建项目目录与文件结构mkdir -p ~/projects/lnmp-docker cd ~/projects/lnmp-docker mkdir -p nginx/conf.d mysql/data mysql/init www/htmlnginx/conf.d/: 存放我们自定义的Nginx配置文件。mysql/data/: 用于持久化MySQL数据库文件。mysql/init/: 可选如果需要容器启动时自动执行SQL脚本可以放在这里。www/html/: 我们的网站项目代码就放在这里它将被同时挂载给Nginx和PHP容器。4.2 编写Docker Compose配置文件创建docker-compose.yml文件这是整个环境的核心定义。version: 3.8 services: # MySQL 服务 mysql: image: mysql:5.7 container_name: lnmp-mysql restart: always environment: MYSQL_ROOT_PASSWORD: your_strong_root_password_here # 请务必修改 MYSQL_DATABASE: myapp_db # 可选自动创建的数据库 MYSQL_USER: myapp_user # 可选自动创建的用户 MYSQL_PASSWORD: your_strong_user_password_here # 请务必修改 volumes: - ./mysql/data:/var/lib/mysql # 持久化数据 - ./mysql/init:/docker-entrypoint-initdb.d # 初始SQL脚本目录 networks: - lnmp-network # 不对外暴露端口仅在内部网络访问更安全 # ports: # - 3306:3306 # PHP-FPM 服务 php: image: php:7.4-fpm container_name: lnmp-php restart: always volumes: - ./www/html:/var/www/html # 挂载项目代码 - ./php/custom.ini:/usr/local/etc/php/conf.d/custom.ini # 自定义PHP配置 depends_on: - mysql networks: - lnmp-network # 可以在这里安装额外的PHP扩展例如 # build: # context: . # dockerfile: Dockerfile-php # Nginx 服务 nginx: image: nginx:1.18-alpine container_name: lnmp-nginx restart: always ports: - 80:80 # 将宿主机的80端口映射到容器的80端口 - 443:443 # 如果需要HTTPS映射443端口 volumes: - ./www/html:/var/www/html # 挂载项目代码必须和PHP容器路径一致 - ./nginx/conf.d:/etc/nginx/conf.d # 挂载自定义站点配置 - ./nginx/logs:/var/log/nginx # 持久化Nginx日志可选 depends_on: - php networks: - lnmp-network # 定义自定义网络 networks: lnmp-network: driver: bridge关键点解析与选型理由版本选择我固定了镜像标签mysql:5.7,php:7.4-fpm,nginx:1.18-alpine。强烈建议在生产或重要开发环境中这样做而不是使用latest标签以避免因镜像更新导致的不兼容问题。alpine版本的Nginx镜像更小巧。环境变量MySQL容器通过环境变量设置root密码、创建数据库和用户。MYSQL_ROOT_PASSWORD是必须的且务必改为强密码数据卷挂载volumes部分将宿主机的目录映射到容器内实现数据持久化。注意Nginx和PHP容器挂载的是同一个./www/html目录这样它们才能访问相同的代码文件。网络所有服务都加入了自定义的lnmp-network。在这个网络里PHP容器可以通过服务名mysql访问数据库Nginx可以通过服务名php端口9000转发PHP请求。依赖与启动顺序depends_on确保了启动顺序先启动mysql再php最后nginx但并不保证服务已完全就绪比如MySQL初始化完成。对于更复杂的就绪检查需要额外的健康检查配置。端口映射只有Nginx将80端口暴露给了宿主机MySQL和PHP的服务端口3306, 9000仅在Docker网络内部可访问这更安全。4.3 配置Nginx以处理PHP请求Nginx默认配置不会处理PHP。我们需要创建一个站点配置文件来告诉它当遇到.php结尾的请求时转发给PHP-FPM容器处理。在./nginx/conf.d/目录下创建文件default.conf文件名任意以.conf结尾即可server { listen 80; server_name localhost; # 或你的域名 root /var/www/html; index index.php index.html index.htm; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location / { try_files $uri $uri/ /index.php?$query_string; } # 关键配置将PHP请求转发给PHP-FPM容器 location ~ \.php$ { fastcgi_pass php:9000; # “php”是docker-compose中定义的服务名 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.ht { deny all; } }配置解读fastcgi_pass php:9000;这是最核心的一行。它告诉Nginx对于PHP文件使用FastCGI协议将请求转发到名为php的主机的9000端口。这里的php正是我们在docker-compose.yml里定义的PHP服务名称Docker的网络DNS会自动将其解析为PHP容器的IP地址。fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;这个参数告诉PHP-FPM要执行的文件的具体路径。$document_root对应root /var/www/html$fastcgi_script_name是请求的PHP文件名。try_files $uri $uri/ /index.php?$query_string;这是一个常用的美化URL规则常用于Laravel等框架。它会尝试按顺序访问请求的文件 - 请求的目录 - 最后都交给index.php处理并将查询字符串传递过去。4.4 创建测试PHP项目现在我们在共享的代码目录./www/html/下创建一个最简单的PHP文件来测试环境。创建文件./www/html/index.php?php phpinfo(); // 尝试连接MySQL数据库 $host mysql; // 使用服务名作为主机名 $dbname myapp_db; $user myapp_user; $pass your_strong_user_password_here; // 替换为docker-compose.yml中设置的密码 try { $pdo new PDO(mysql:host$host;dbname$dbname;charsetutf8mb4, $user, $pass); $pdo-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); echo h2 stylecolor: green;MySQL连接成功/h2; } catch (PDOException $e) { echo h2 stylecolor: red;MySQL连接失败: /h2 . $e-getMessage(); } ?这个文件做了两件事1. 调用phpinfo()显示PHP配置信息验证PHP环境是否正常。2. 尝试用PDO连接MySQL数据库验证网络连通性和数据库配置是否正确。记得把密码换成你docker-compose.yml里设置的MYSQL_PASSWORD。4.5 可选自定义PHP配置有时我们需要修改PHP的默认配置比如上传文件大小限制upload_max_filesize、内存限制memory_limit等。我们可以通过挂载自定义的ini文件来实现。首先创建目录和文件mkdir -p ./php touch ./php/custom.ini然后编辑./php/custom.ini加入你需要的配置例如; 开发环境可以适当放宽限制 upload_max_filesize 50M post_max_size 55M memory_limit 256M max_execution_time 120 ; 显示错误便于调试生产环境应关闭 display_errors On display_startup_errors On error_reporting E_ALL这个文件会被挂载到PHP容器的/usr/local/etc/php/conf.d/目录该目录下的所有.ini文件都会被自动加载覆盖默认配置。5. 启动、验证与日常操作蓝图和材料都准备好了现在开始搭建并验收。5.1 一键启动LNMP环境在包含docker-compose.yml的目录下运行docker compose up -d-d参数代表“detached”让服务在后台运行。你会看到Docker开始拉取镜像如果本地没有然后依次创建网络、卷并启动三个容器。这个过程只需要几分钟。启动完成后使用以下命令检查状态docker compose ps你应该看到三个服务的状态都是“Up”。如果某个服务是“Exit”或不断重启就需要查看日志排查。5.2 验证环境是否正常工作访问PHP信息页打开你的浏览器访问http://你的服务器IP地址或http://localhost。你应该能看到标准的phpinfo()页面里面详细列出了PHP的版本7.4、已加载的扩展等信息。这证明Nginx和PHP-FPM协作正常。验证数据库连接在phpinfo()页面往下翻或者直接看我们index.php页面的输出。如果配置正确你应该能看到绿色的“MySQL连接成功”字样。这说明PHP容器能够通过Docker网络使用“mysql”这个主机名成功连接到MySQL容器。进入容器进行调试如果上述步骤失败我们需要进入容器内部查看。查看Nginx日志docker compose logs nginx查看PHP-FPM日志docker compose logs php查看MySQL日志docker compose logs mysql进入PHP容器测试连接docker compose exec php bash # 进入容器后安装mysql客户端工具镜像默认可能没有 apt update apt install -y default-mysql-client # 尝试连接MySQL使用服务名‘mysql’作为主机 mysql -h mysql -u myapp_user -p输入密码后如果能进入MySQL命令行说明网络和数据库服务本身是通的问题可能出在PHP代码的PDO连接字符串或权限上。5.3 常用Docker Compose管理命令掌握了这些命令你就能轻松管理整个环境了启动服务docker compose up -d停止服务docker compose down。注意这会停止并删除容器、网络默认创建的网络但不会删除数据卷如./mysql/data。如果你想同时删除数据卷加-v参数docker compose down -v慎用会丢失所有数据库数据。停止服务但保留容器和卷docker compose stop启动已停止的服务docker compose start重启服务docker compose restart查看服务状态docker compose ps查看服务日志实时docker compose logs -f [service_name]例如docker compose logs -f php。在运行中的容器内执行命令docker compose exec [service_name] [command]例如docker compose exec mysql bash进入MySQL容器。重建并启动服务修改了Dockerfile或docker-compose.yml后需要docker compose up -d --build。查看镜像、容器、卷占用空间docker system df6. 进阶配置与深度优化基础环境跑通只是第一步。在实际项目中我们还需要考虑更多。6.1 为PHP容器安装额外扩展官方的php:7.4-fpm镜像只包含了一些核心扩展。像gd图像处理、pdo_mysqlMySQL驱动、zip、redis等扩展需要手动安装。有两种主流方法方法一在docker-compose.yml中使用build指令推荐这种方法更灵活可以固化配置。在项目根目录创建Dockerfile-phpFROM php:7.4-fpm # 安装系统依赖和PHP扩展 RUN apt-get update apt-get install -y \ libpng-dev \ libjpeg-dev \ libfreetype6-dev \ libzip-dev \ zip \ unzip \ docker-php-ext-configure gd --with-freetype --with-jpeg \ docker-php-ext-install -j$(nproc) gd pdo_mysql zip opcache # 安装ComposerPHP包管理工具 COPY --fromcomposer:latest /usr/bin/composer /usr/bin/composer # 设置工作目录 WORKDIR /var/www/html修改docker-compose.yml中php服务的定义将image: php:7.4-fpm替换为build指令php: build: context: . dockerfile: Dockerfile-php container_name: lnmp-php # ... 其他配置保持不变之后运行docker compose up -d --build就会根据你的Dockerfile构建PHP镜像。方法二进入容器手动安装仅用于临时测试进入容器后使用docker-php-ext-install等命令安装但容器重启后修改会丢失。不推荐用于生产。6.2 配置MySQL字符集与性能调优默认的MySQL镜像可能使用非UTF-8的字符集。我们可以通过挂载自定义配置文件来修改。在./mysql/目录下创建my.cnf文件[mysqld] character-set-serverutf8mb4 collation-serverutf8mb4_unicode_ci default-authentication-pluginmysql_native_password # 一些基本的性能调优根据服务器内存调整 innodb_buffer_pool_size 256M max_connections 200 query_cache_size 64M修改docker-compose.yml中mysql服务的volumes部分增加配置挂载volumes: - ./mysql/data:/var/lib/mysql - ./mysql/init:/docker-entrypoint-initdb.d - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf:ro # 挂载自定义配置只读:ro表示只读挂载防止容器内进程误写。6.3 使用环境变量文件管理敏感信息把数据库密码明文写在docker-compose.yml里不安全也不利于不同环境开发、测试、生产的配置切换。我们可以使用环境变量文件。在项目根目录创建.env文件注意文件名以点开头# MySQL 环境变量 MYSQL_ROOT_PASSWORDYourSuperSecretRootPassword123! MYSQL_DATABASEmyapp_db MYSQL_USERmyapp_user MYSQL_PASSWORDYourStrongUserPassword456! # 其他环境变量... # TZAsia/Shanghai修改docker-compose.yml引用环境变量environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD}重要将.env文件添加到.gitignore中避免密码泄露。在团队协作时可以提供一个.env.example模板文件。6.4 配置Nginx与PHP-FPM的进程优化默认配置可能不适合高并发场景。我们可以通过调整容器内的Nginx和PHP-FPM配置文件来优化。Nginx Worker进程可以创建自定义的Nginx全局配置文件挂载。例如创建./nginx/nginx.conf覆盖容器的默认配置调整worker_processes通常设置为CPU核心数和worker_connections。PHP-FPM进程池PHP-FPM的配置通常在/usr/local/etc/php-fpm.d/www.conf。我们可以通过挂载一个修改后的www.conf文件来覆盖它。例如调整pm进程管理器模式为dynamic并设置pm.max_children,pm.start_servers等参数。这需要你先从运行的PHP容器中复制出默认配置然后修改并挂载。这些优化需要根据服务器的实际硬件资源和应用负载进行测试调整属于更进阶的内容。7. 项目部署实战以WordPress为例现在我们用搭建好的LNMP Docker环境实际部署一个流行的PHP应用——WordPress来串联所有流程。7.1 准备WordPress代码与数据库清空测试文件将之前测试用的./www/html/index.php删除或备份。rm ~/projects/lnmp-docker/www/html/index.php下载WordPress进入代码目录下载最新版WordPress并解压。cd ~/projects/lnmp-docker/www/html wget https://wordpress.org/latest.tar.gz tar -xzvf latest.tar.gz --strip-components1 rm latest.tar.gz--strip-components1参数会将解压后的wordpress文件夹内的所有内容直接放到当前目录html下。设置文件权限WordPress需要向wp-content目录写入文件如插件、主题、上传的文件。# 回到项目根目录 cd ~/projects/lnmp-docker # 将html目录的所有者改为www-dataNginx/PHP-FPM进程默认用户但宿主机的当前用户保留写权限 # 更精细的做法是设置组权限这里用一个简单通用的方法 docker compose exec php chown -R www-data:www-data /var/www/html docker compose exec php find /var/www/html -type d -exec chmod 755 {} \; docker compose exec php find /var/www/html -type f -exec chmod 644 {} \; # 单独给上传目录写权限 docker compose exec php chmod -R 775 /var/www/html/wp-content7.2 调整Nginx配置以支持WordPressWordPress使用了固定链接Permalink功能需要Nginx支持重写。修改./nginx/conf.d/default.conf将location /块替换为WordPress推荐的配置server { listen 80; server_name localhost; # 替换为你的域名或IP root /var/www/html; index index.php index.html index.htm; # 增加客户端最大上传大小匹配PHP设置 client_max_body_size 50M; location / { # WordPress固定链接支持 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; # 增加FastCGI超时时间处理大文件上传 fastcgi_read_timeout 300; } location ~ /\.ht { deny all; } # 禁用敏感文件访问 location ~* /(?:wp-config\.php|readme\.html|license\.txt) { deny all; } }修改配置后需要重启Nginx容器使其生效docker compose restart nginx7.3 运行WordPress安装向导确保所有服务正在运行docker compose ps。打开浏览器访问http://你的服务器IP地址。你应该会看到WordPress的著名“五分钟安装”页面。数据库配置数据库名填写docker-compose.yml或.env文件中设置的MYSQL_DATABASE例如myapp_db。用户名填写MYSQL_USER例如myapp_user。密码填写MYSQL_PASSWORD。数据库主机这是关键。因为WordPress运行在PHP容器里而PHP容器和MySQL容器在同一个Docker网络所以这里填MySQL的服务名mysql。表前缀默认wp_即可为了安全可以改成别的。点击“提交”如果一切配置正确WordPress会提示“可以连接数据库成功”。接下来设置站点标题、管理员账号密码就完成安装了。至此一个基于Docker的、完全容器化的WordPress站点就成功部署在你的Linux服务器上了。你可以用同样的方法部署Laravel、ThinkPHP等任何PHP项目只需将代码放入./www/html/目录并根据框架要求微调Nginx配置即可。8. 踩坑实录与经验心得在无数次搭建和调试Docker化LNMP环境的过程中我积累了一些“血泪教训”分享出来希望能帮你少走弯路。8.1 文件权限的“幽灵”问题这是Docker新手最容易踩的坑。宿主机上的用户比如你的ubuntu用户UID可能是1000和容器内运行进程的用户比如Nginx/PHP-FPM的www-dataUID通常是33或82不一致导致容器内的进程没有权限读写挂载的宿主机目录。现象网站出现“403 Forbidden”、“500 Internal Server Error”或者WordPress无法安装主题插件、无法上传文件。查看Nginx或PHP日志常有“Permission denied”错误。解决方案推荐在容器内统一用户就像前面WordPress部署步骤里做的在容器启动后进入容器内部或通过docker compose exec命令用chown和chmod命令修改目录所有权和权限让容器内的www-data用户有权读写。开发环境便捷法调整宿主机目录权限直接将宿主机项目目录权限设为777chmod -R 777 ./www/html。这种方法极不安全仅用于本地开发测试绝对不要在生产环境使用。高级在Dockerfile中指定UID构建自定义镜像时可以创建一个与宿主机用户UID相同的用户来运行服务。这需要更深入的Docker知识。我的心得对于团队协作的开发环境我倾向于在项目的README.md或启动脚本中明确给出容器内修改权限的命令如docker compose exec php chown -R www-data:www-data /var/www/html作为标准流程的一部分。这比让每个人去改自己宿主机的权限更可控。8.2 容器间网络连通性排查现象PHP页面可以访问但连接数据库失败报错“SQLSTATE[HY000] [2002] Connection refused”或“No route to host”。排查步骤确认服务是否运行docker compose ps确保mysql和php服务状态都是“Up”。从PHP容器内测试网络docker compose exec php bash apt update apt install -y iputils-ping default-mysql-client ping mysql # 看是否能解析IP并ping通 mysql -h mysql -u myapp_user -p # 尝试连接检查Docker网络docker network ls # 查看网络列表确认lnmp-network存在 docker network inspect lnmp-docker_lnmp-network # 查看该网络详情确认两个容器都在这个网络中并且有正确的IP地址。检查MySQL容器是否监听正确端口进入MySQL容器netstat -tlnp确认3306端口在监听并且监听地址是0.0.0.0允许所有IP连接而不是127.0.0.1只允许本机。根本原因最常见的原因是docker-compose.yml中服务没有连接到同一个自定义网络或者PHP代码里连接数据库的主机名写错了应该是mysql而不是localhost或127.0.0.1。8.3 性能与资源监控容器化后如何监控资源使用情况查看容器资源占用docker stats命令可以实时查看所有容器的CPU、内存、网络IO使用情况。查看容器日志docker compose logs -f [service]跟踪日志。生产环境建议将日志驱动配置为json-file或syslog并配合ELK等工具进行日志收集。进入容器使用传统工具docker compose exec php top或docker compose exec mysql mysqladmin status。8.4 数据备份与迁移这是容器化架构的生命线。你的数据库数据在./mysql/data网站代码在./www/html。数据库备份# 使用mysqldump从容器内导出 docker compose exec mysql mysqldump -u root -p[你的root密码] myapp_db backup_$(date %Y%m%d).sql完整环境迁移将整个项目目录lnmp-docker/打包。在新服务器上安装好Docker和Docker Compose解压目录修改.env文件中的配置如密码然后运行docker compose up -d。因为所有配置端口、卷挂载、网络都定义在docker-compose.yml中所以环境可以完美复现。最后我个人最大的体会是Docker Compose将基础设施变成了代码。这份docker-compose.yml和相关的配置文件就是你这个LNMP环境的“源代码”。把它放进Git仓库你的开发、测试、生产环境的一致性就有了最基础的保障。从手动配置到声明式配置虽然前期需要多一些学习成本但后期在效率、可靠性和可维护性上带来的回报是巨大的。
返回列表