文章目录
- 第一章:Docker基础
-
- [1.1 Docker是什么?](#1.1 Docker是什么?)
- [1.2 安装Docker](#1.2 安装Docker)
-
- [macOS(Intel / Apple Silicon)](#macOS(Intel / Apple Silicon))
- [Linux(CentOS 7 / Ubuntu)](#Linux(CentOS 7 / Ubuntu))
- 验证Docker能否正常工作
- [1.3 Docker核心概念](#1.3 Docker核心概念)
- 第二章:Docker常用命令(附实例)
-
- [2.1 镜像管理](#2.1 镜像管理)
- [2.2 容器管理](#2.2 容器管理)
- [2.3 数据卷管理](#2.3 数据卷管理)
- [2.4 网络管理](#2.4 网络管理)
- 第三章:Docker镜像迁移与架构兼容
-
- [3.1 为什么要迁移?](#3.1 为什么要迁移?)
- [3.2 镜像迁移的正确操作](#3.2 镜像迁移的正确操作)
- [3.3 跨架构迁移(ARM64 ↔ AMD64)](#3.3 跨架构迁移(ARM64 ↔ AMD64))
-
- [实战:从Mac M1迁移镜像到AMD64服务器](#实战:从Mac M1迁移镜像到AMD64服务器)
- [第四章:实战Nginx + PHP-FPM 容器化部署](#第四章:实战Nginx + PHP-FPM 容器化部署)
-
- [4.1 基础配置](#4.1 基础配置)
- [4.2 启动Nginx容器](#4.2 启动Nginx容器)
- [4.3 启动PHP-FPM容器](#4.3 启动PHP-FPM容器)
- [4.4 验证容器间通信](#4.4 验证容器间通信)
- [4.5 创建测试 PHP 文件](#4.5 创建测试 PHP 文件)
- [4.6 查看是否影响了本地环境](#4.6 查看是否影响了本地环境)
- [第五章:使用Docker Compose](#第五章:使用Docker Compose)
-
- [5.1 项目基础配置](#5.1 项目基础配置)
- [5.2 PHP扩展安装](#5.2 PHP扩展安装)
- [5.3 MySQL自定义配置](#5.3 MySQL自定义配置)
- [5.4 启动与验证完整流程](#5.4 启动与验证完整流程)
- [5.5 在宿主机访问docker中的资源](#5.5 在宿主机访问docker中的资源)
- [5.6 Docker Compose 带来的改变](#5.6 Docker Compose 带来的改变)
- 简单总结
Docker已成为现代软件开发的基础工具,无论是本地开发、测试还是生产部署,掌握Docker都必不可少。 Docker官网:https://www.docker.com/
本篇文章,我将从零开始,详细讲解Docker的安装、核心概念、常用命令、镜像迁移与跨架构部署,并手把手搭建PHP、Go、Nginx、MySQL、Redis、MongoDB等常用开发环境。所有操作均在MacOS(M1芯片)和CentOS 7.9双平台验证,踩坑经验一并附上。
文章特点:
- 部分内容由Ai生成,但每一行命令都亲自测试和验证
- 覆盖ARM64(M1)与AMD64(传统Linux服务器)架构
- 包含大量实际案例和错误解决方案
- 可直接作为工作笔记复用
第一章:Docker基础
1.1 Docker是什么?
Docker是一个开源的应用容器引擎,让开发者可以打包应用及其依赖到一个轻量级、可移植的容器中,然后发布到任何Linux机器上。
核心优势:
- 环境一致性:开发、测试、生产环境完全一致
- 快速部署:秒级启动
- 资源隔离:进程、网络、文件系统隔离
- 生态丰富:Docker Hub有海量官方镜像
1.2 安装Docker
macOS(Intel / Apple Silicon)
推荐使用Docker Desktop,它自带图形界面和命令行工具。
-
下载 :访问 Docker官网的docker-desktop页面,选择对应芯片的版本(Apple Silicon 或 Intel)。
-
安装 :双击
Docker.dmg,将Docker图标拖入Applications,安装时勾选"Use recommended settings",它会自动配置环境变量和资源限制。 -
启动:打开Launchpad,点击Docker图标,等待菜单栏出现🐳图标(绿色表示运行中:Docker Desktop is running)。
-
验证:
bashdocker --version docker compose --version示例输出:
Docker version 29.2.0, build 0b9d198 Docker Compose version v5.0.2 -
配置镜像加速:由于国内网络的原因,直接拉取Docker Hub镜像可能超时,因此可能需要配置国内镜像源:
点击菜单栏Docker图标 → Settings → Docker Engine,修改配置文件,添加以下镜像地址:
json{ "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com", "https://mirror.baidubce.com" ] }然后,点击 Apply & Restart
备注:这里的镜像源可能随时发生变化或不可访问,因此,当你看到这篇文章的时候,有可能以上镜像已经失效了,你可以自行查找其他可用的镜像地址,或者自行解决国内访问的网络问题!
Linux(CentOS 7 / Ubuntu)
以CentOS 7为例(服务器环境):
bash
cat /etc/centos-release
CentOS Linux release 7.9.2009 (Core)
# 卸载旧版本(如果有的话)
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装yum-utils
sudo yum install -y yum-utils
# 可选:添加阿里云镜像源(国内网络推荐)
# sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装Docker
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 验证
docker --version
docker compose version
💡 权限问题:Linux下执行docker命令需要sudo。可将当前用户加入docker组:
sudo usermod -aG docker $USER newgrp docker
验证Docker能否正常工作
docker run hello-world
看到如下信息表示成功:
Hello from Docker!
This message shows that your installation appears to be working correctly.

1.3 Docker核心概念
| 概念 | 说明 |
|---|---|
| 镜像 | 一个只读模板,包含创建容器的指令。如ubuntu:22.04、nginx:latest |
| 容器 | 镜像的运行实例。可被启动、停止、删除。容器之间相互隔离 |
| 仓库 | 存放镜像的地方。Docker Hub是默认公共仓库 |
| 数据卷 | 持久化存储,独立于容器生命周期 |
| 网络 | 容器间通信的虚拟网络,支持bridge、host、overlay等驱动 |
第二章:Docker常用命令(附实例)
2.1 镜像管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker pull |
拉取镜像 | docker pull nginx:latest |
docker images |
列出本地镜像 | docker images |
docker rmi |
删除镜像 | docker rmi nginx:latest |
docker tag |
给镜像打标签 | docker tag nginx:latest my-nginx:v1 |
docker save |
保存镜像为tar文件 | docker save -o nginx.tar nginx:latest |
docker load |
从tar文件加载镜像 | docker load -i nginx.tar |
docker inspect |
查看镜像详细信息 | docker inspect nginx:latest |
示例:备份与恢复镜像的操作
bash
# 保存镜像
docker save -o ~/nginx-backup.tar nginx:latest
# 压缩(可选)
gzip ~/nginx-backup.tar
# 传输到另一台机器
scp ~/nginx-backup.tar.gz user@192.168.1.100:/tmp/
# 目标机加载
gunzip -c /tmp/nginx-backup.tar.gz | docker load
2.2 容器管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker run |
创建并启动容器 | docker run -d --name nginx -p 80:80 nginx |
docker ps |
列出运行中容器 | docker ps -a(显示所有) |
docker start/stop/restart |
启动/停止/重启 | docker stop nginx |
docker rm |
删除容器 | docker rm -f nginx(强制) |
docker exec |
进入运行中容器 | docker exec -it nginx bash |
docker logs |
查看容器日志 | docker logs -f nginx(实时跟踪) |
docker cp |
容器与主机间复制文件 | docker cp nginx:/etc/nginx/nginx.conf ./ |
docker commit |
将容器保存为新镜像 | docker commit nginx my-nginx-custom |
示例:运行一个Nginx容器
bash
# 拉取镜像
docker pull nginx:alpine
# 运行容器
docker run -d \
--name my-nginx \
-p 8080:80 \
-v ~/www:/usr/share/nginx/html \
nginx:alpine
# 在 ~/www 下放一个 index.html,访问 http://localhost:8080
2.3 数据卷管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker volume create |
创建数据卷 | docker volume create mydata |
docker volume ls |
列出数据卷 | docker volume ls |
docker volume inspect |
查看卷详情 | docker volume inspect mydata |
docker volume rm |
删除数据卷 | docker volume rm mydata |
示例:使用数据卷持久化MySQL数据
bash
# 创建数据卷
docker volume create mysql-data
# 运行MySQL容器并挂载数据卷
docker run -d \
--name mysql8 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql-data:/var/lib/mysql \
-p 3306:3306 \
mysql:8.0
2.4 网络管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker network create |
创建网络 | docker network create mynet |
docker network ls |
列出网络 | docker network ls |
docker network inspect |
查看网络详情 | docker network inspect mynet |
docker network connect |
将容器连接到网络 | docker network connect mynet nginx |
docker network disconnect |
断开容器 | docker network disconnect mynet nginx |
示例:容器间通过自定义网络通信
bash
# 创建网络
docker network create app-net
# 运行一个Redis容器,连接到app-net
docker run -d --name redis --network app-net redis:alpine
# 运行一个PHP容器,也连接到app-net,并通过容器名访问Redis
docker run -it --rm --network app-net alpine ping redis
第三章:Docker镜像迁移与架构兼容
3.1 为什么要迁移?
- 开发环境(Mac M1)与生产环境(AMD64服务器)架构不同
- 无法直接拉取镜像的离线环境
- 团队共享镜像,避免重复拉取

3.2 镜像迁移的正确操作
1、导出镜像(必须用save,不要用export)
bash
docker save -o redis.tar redis:alpine
错误示范 :
docker export只会导出容器文件系统,丢失元数据(如环境变量、工作目录、CMD等),导致启动失败。
2、压缩与传输
bash
gzip redis.tar
scp redis.tar.gz user@目标IP:/tmp/
3、导入镜像
bash
gunzip -c /tmp/redis.tar.gz | docker load
# 或
docker load -i redis.tar
3.3 跨架构迁移(ARM64 ↔ AMD64)
这是最常踩坑的地方。Docker镜像基于不同CPU架构编译,ARM64镜像不能在AMD64机器上直接运行,反之亦然。
如何查看镜像架构?
bash
docker inspect <镜像名 或者 镜像ID> | grep Architecture
输出示例:
"Architecture": "arm64", 或者 "Architecture": "amd64",

【解决方案】
方案1:拉取对应架构的镜像(推荐)
bash
# 在AMD64机器上拉取AMD64版
docker pull --platform linux/amd64 nginx:alpine
# 在ARM64机器上拉取ARM64版
docker pull --platform linux/arm64 nginx:alpine
方案2:使用Docker Desktop的模拟层(仅限Mac)
Docker Desktop for Mac(包括M1)自动支持运行AMD64镜像------它会通过QEMU模拟,但性能稍差,且部分特殊指令可能出错。
方案3:构建多架构镜像(高级)
使用docker buildx构建同时支持多种架构的镜像,并推送到仓库。这适合镜像维护者。
方案2 和 方案3 我没有尝试,只是查阅到了相关资料,你可以自己试下,或者忽略。
实战:从Mac M1迁移镜像到AMD64服务器
错误做法 :在M1上直接docker save镜像,上传到AMD64服务器docker load,然后运行 → 可能报错exec format error。
正确流程:
bash
# 1. 在Mac上拉取AMD64版镜像
docker pull --platform linux/amd64 nginx:alpine
# 2. 验证架构
docker inspect nginx:alpine | grep Architecture # 应输出 "Architecture": "amd64"
# 3. 保存并传输
docker save -o nginx-amd64.tar nginx:alpine
gzip nginx-amd64.tar
scp nginx-amd64.tar.gz root@服务器:/tmp/
# 4. 服务器加载
gunzip -c /tmp/nginx-amd64.tar.gz | docker load
docker run -d --name nginx -p 80:80 nginx:alpine
第四章:实战Nginx + PHP-FPM 容器化部署
我本地MacOS机器已经安装了nginx(80端口)和PHP7.1版本,现在我需要再docker中安装nginx(8088端口)和PHP7.4版本,和本地机器互不影响。关键要求 :不干扰本地已运行的 Nginx/PHP,通过 http://localhost:8088 访问。
核心原则:
- 宿主机 8088 端口 → Docker Nginx 80 端口
- Docker Nginx → Docker PHP(容器名通信)
- 宿主机原有的 80、9000 端口完全不受影响
4.1 基础配置
目录结构初始化:
bash
# 创建独立项目目录
cd ~
mkdir -p docker-project/nginx/conf.d
mkdir -p docker-project/www
# 查看目录结构
tree docker-project
预期输出:
docker-project/
├── nginx
│ └── conf.d
└── www
创建 Docker 自定义网络:
容器之间必须通过自定义网络才能用容器名通信。
bash
# 创建自定义网络
docker network create lnmp
## 输出示例: dbaa58d7ed0853f0838d757b6096c0eea937282fb7446dc4c2bc2d4c53e01847
# 验证网络:
docker network ls | grep lnmp
## 输出示例: dbaa58d7ed08 lnmp bridge local
4.2 启动Nginx容器
创建配置文件 vim ~/docker-project/nginx/conf.d/default.conf
nginx
server {
listen 80;
server_name localhost;
# 网站根目录(容器内路径)
root /usr/share/nginx/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP 请求转发给 php-fpm 容器(用容器名通信)
location ~ \.php$ {
fastcgi_pass php74-fpm:9000; # 关键:容器名:端口, 这里的 php74-fpm:9000 必须与PHP容器名和端口一致
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
}
}
特别注意:
fastcgi_pass后面是php74-fpm:9000,不是localhost,不是127.0.0.1php74-fpm是我们稍后要运行的 PHP 容器名- 两个容器必须在同一网络(lnmp)才能解析容器名
接下来,启动 Nginx 容器:
此时 PHP 还没启动,虽然 PHP 还没运行,但我们可以先把 Nginx 跑起来,配置文件会生效,只是访问 PHP 时会报 502。
即使 PHP-FPM 容器尚未运行,Nginx 容器依然可以正常工作------它可以正常提供静态文件服务,只有访问 PHP 文件时才会报 502 错误。
你也可以先配置PHP,再配置Nginx,都可以。
bash
docker run -d \
--name nginx8088 \
-p 8088:80 \
-v ~/docker-project/nginx/conf.d:/etc/nginx/conf.d \
-v ~/docker-project/www:/usr/share/nginx/html \
--network lnmp \
nginx:alpine
参数说明:
| 参数 | 说明 |
|---|---|
--name nginx8088 |
容器名,便于管理 |
-p 8088:80 |
宿主机 8088 端口 → 容器 80 端口(不影响本地 80) |
-v nginx/conf.d |
挂载 Nginx 配置文件 |
-v www |
挂载网站代码目录 |
--network lnmp |
加入自定义网络 |
验证 Nginx 是否运行:
bash
docker ps | grep nginx8088
## 输出示例:d89a191041c6 nginx:alpine "/docker-entrypoint...." 25 minutes ago Up 11 minutes 0.0.0.0:8088->80/tcp, [::]:8088->80/tcp nginx8088
# 创建静态 HTML 文件测试 Nginx 是否正常工作:
echo "<h1>Nginx is running with HTML</h1>" > ~/docker-project/www/index.html
浏览器访问 http://localhost:8088/index.html,应该看到 Nginx is running with HTML

4.3 启动PHP-FPM容器
执行命令:
bash
docker run -d \
--name php74-fpm \
-p 9000:9000 \
-v ~/docker-project/www:/var/www/html \
-e TZ=Asia/Shanghai \
--network lnmp \
php:7.4-fpm
参数说明:
| 参数 | 说明 |
|---|---|
--name php74-fpm |
容器名,必须与 Nginx 配置中的一致 |
-p 9000:9000 |
宿主机 9000 端口映射(不影响你本地 PHP 7.1 的 9000 端口吗? → 等下验证) |
-v www:/var/www/html |
挂载同一份代码目录 |
--network lnmp |
加入同一网络 |
php:7.4-fpm |
官方 PHP 7.4 镜像 |
验证 PHP 容器:
bash
docker ps | grep php74-fpm
## 输出示例:48118b15725e php:7.4-fpm "docker-php-entrypoi..." 21 minutes ago Up 21 minutes 0.0.0.0:9000->9000/tcp, [::]:9000->9000/tcp php74-fpm
4.4 验证容器间通信
Nginx 和 PHP 必须在同一网络,且能通过容器名互通。
bash
# 从 Nginx 容器内 ping PHP 容器
docker exec nginx8088 ping php74-fpm -c 2

看到 64 bytes from 表示网络通信正常。
如果提示 ping: php74-fpm: Name or service not known,可能得问题:
- 容器不在同一网络
- 容器名拼写错误
- Nginx 容器启动时没有加入
--network lnmp
两个容器的挂载关系:
| 容器 | 宿主机目录 | 容器内目录 | 作用 |
|---|---|---|---|
| Nginx | ~/docker-project/www |
/usr/share/nginx/html |
存放静态文件、PHP 文件 |
| PHP | ~/docker-project/www |
/var/www/html |
执行 PHP 脚本 |
Nginx 配置中的路径必须严格对应:
root /usr/share/nginx/html; # Nginx 容器内的根目录
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # PHP 容器内的文件路径
这两个路径指向的是同一个宿主机目录 ,但在各自容器内的挂载点不同,不能写错。
4.5 创建测试 PHP 文件
bash
echo "<?php phpinfo();" > ~/docker-project/www/index.php
浏览器打开:http://localhost:8088/index.php,应该就能看到 PHP 7.4 的 phpinfo 信息页面了:

4.6 查看是否影响了本地环境
本地 Nginx 是否受影响?
bash
# 如果你本地有 Nginx 在运行
curl -I http://localhost:80 # 应该依然返回正常,因为 Docker Nginx 只占用了 8088 端口。
本地 PHP 7.1 是否受影响?
bash
php -v # 没受影响,还是原来的 PHP 7.1.33 (cli) (built: Nov 6 2025 20:44:48) ( NTS )
本地 PHP 完全独立,不受容器内 PHP 7.4 影响。
本地 9000 端口是否冲突?
bash
lsof -i :9000

如果你本地 PHP-FPM 已经占用了 9000 端口,Docker 映射时会报错:
Error response from daemon: driver failed programming external connectivity on endpoint php74-fpm: Bind for 0.0.0.0:9000 failed: port is already allocated
解决方案(二选一):
方案1:停止本地 PHP-FPM(如果你不需要)
bash
brew services stop php@7.1
方案2:修改 Docker PHP 映射端口和Nginx配置
bash
# 先删除已创建的容器
docker rm -f php74-fpm
# 重新运行,映射到 9001 端口
docker run -d \
--name php74-fpm \
-p 9001:9000 \ # 宿主机 9001 → 容器 9000
-v ~/docker-project/www:/var/www/html \
-e TZ=Asia/Shanghai \
--network lnmp \
php:7.4-fpm
# 同时需要修改 Nginx 配置
# 宿主机端口映射改变不影响容器间通信,Nginx 容器仍然通过 `php74-fpm:9000` 访问 PHP 容器。
fastcgi_pass php74-fpm:9000; # 这里仍然是 9000,因为这是容器内的端口
第五章:使用Docker Compose
什么是Docker Compose?
Docker Compose 是 Docker 官方推出的多容器编排工具,通过一个 docker-compose.yml 文件,用代码定义整个服务栈,实现一键启动、一键停止、一键重建。
为什么要用 Docker Compose?
在上一章中,我们手动执行了:
bash
docker network create lnmp
docker run -d --name nginx8088 -p 8088:80 --network lnmp ...
docker run -d --name php74-fpm -p 9001:9000 --network lnmp ...
每次重启、迁移、重建环境都要重复这些命令,非常容易遗漏或写错参数。
使用 Docker Compose 的核心价值:
| 痛点 | Compose 解决方案 |
|---|---|
| 命令太长,记不住 | 写在 YAML 文件里,一行命令启动 |
| 网络要手动创建 | Compose 自动创建项目专属网络 |
| 容器启动顺序 | depends_on 控制依赖 |
| 环境不一致 | 配置文件版本化管理,团队共享 |
| 迁移部署 | 复制 docker-compose.yml 即可 |
接下来,我们基于 Docker Compose 来搭建LNMP环境。
5.1 项目基础配置
项目根目录是:~/docker-project/,整个LNMP容器的结构如下:
~/docker-project/
├── docker-compose.yml # Compose 核心配置文件
├── www/ # 网站根目录(PHP代码、静态文件)
│ └── index.php
├── nginx/
│ └── conf.d/
│ └── default.conf # Nginx 虚拟主机配置
├── mysql/
│ └── conf.d/ # MySQL 自定义配置
├── redis/ # Redis 持久化数据
└── logs/
└── nginx/ # Nginx 日志
这个目录结构是长期维护的基础,所有配置文件、代码、日志都在这里,方便备份、迁移、版本控制。
接下来,创建完整的 LNMP(Nginx+PHP+MySQL+Redis)的 docker-compose.yml 配置。
创建 ~/docker-project/docker-compose.yml:
yaml
version: '3.8'
services:
# ---------- PHP-FPM 服务 ----------
php:
image: php:7.4-fpm
container_name: php74-fpm
restart: always
ports:
- "9001:9000" # 宿主9001 → 容器9000,避免与本地PHP冲突
volumes:
- ./www:/var/www/html # 代码目录(核心挂载)
environment:
TZ: Asia/Shanghai
networks:
- lnmp
# ---------- Nginx 服务 ----------
nginx:
image: nginx:alpine
container_name: nginx8088
restart: always
ports:
- "8088:80" # 宿主8088 → 容器80,不影响本地Nginx
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d # Nginx配置文件
- ./www:/usr/share/nginx/html # 同一份代码目录
- ./logs/nginx:/var/log/nginx # Nginx日志
depends_on:
- php # 确保PHP先启动
networks:
- lnmp
# ---------- MySQL 服务 ----------
mysql:
image: mysql:8.0
container_name: mysql8
restart: always
ports:
- "3307:3306" # 宿主3307 → 容器3306,避免与本地MySQL冲突
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: demo
MYSQL_USER: demo
MYSQL_PASSWORD: demo123
TZ: Asia/Shanghai
volumes:
- mysql-data:/var/lib/mysql # 数据持久化
- ./mysql/conf.d:/etc/mysql/conf.d # 自定义配置
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
networks:
- lnmp
# ---------- Redis 服务 ----------
redis:
image: redis:7-alpine
container_name: redis7
restart: always
ports:
- "6380:6379" # 宿主6380 → 容器6379
volumes:
- redis-data:/data # 数据持久化
command: redis-server --appendonly yes
networks:
- lnmp
# ---------- 持久化卷 ----------
volumes:
mysql-data:
redis-data:
# ---------- 自定义网络 ----------
networks:
lnmp:
driver: bridge
创建Nginx 配置文件(必须与挂载路径严格对应) vim ~/docker-project/nginx/conf.d/default.conf:
nginx
server {
listen 80;
server_name localhost;
# 这是 Nginx 容器内的路径,对应宿主机的 ~/docker-project/www
root /usr/share/nginx/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP 请求转发给 php-fpm 容器
location ~ \.php$ {
fastcgi_pass php74-fpm:9000; # 关键:用容器名通信
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; # PHP容器内的路径
include fastcgi_params;
}
}
路径对应关系(十分重要!):
| 容器 | 宿主机目录 | 容器内目录 | 用途 |
|---|---|---|---|
| Nginx | ~/docker-project/www |
/usr/share/nginx/html |
Nginx 读取静态文件、PHP文件 |
| PHP | ~/docker-project/www |
/var/www/html |
PHP 执行脚本 |
这两个容器内目录不同,但指向同一个宿主机目录,绝对不能写错。
5.2 PHP扩展安装
官方的 php:7.4-fpm 镜像只包含核心扩展,实际项目中通常需要额外安装,因此,使用自定义 Dockerfile。
创建 ~/docker-project/php/Dockerfile:
dockerfile
FROM php:7.4-fpm
# 安装系统依赖
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd
# 安装常用扩展
RUN docker-php-ext-install \
pdo_mysql \
mysqli \
bcmath \
opcache
# 安装 Redis 扩展
RUN pecl install redis && docker-php-ext-enable redis
# 安装 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
然后,修改 docker-compose.yml:
yaml
# ---------- PHP-FPM 服务 ----------
php:
# image: php:7.4-fpm # 使用了下面的 build: ./php,这里就不需要了
build: ./php
container_name: php74-fpm
restart: always
ports:
- "9001:9000" # 宿主9001 → 容器9000,避免与本地PHP冲突
volumes:
- ./www:/var/www/html # 代码目录(核心挂载)
environment:
TZ: Asia/Shanghai
networks:
- lnmp
5.3 MySQL自定义配置
创建 ~/docker-project/mysql/conf.d/my.cnf:
ini
[mysqld]
max_allowed_packet=16M
max_connections=1000
slow_query_log=1
slow_query_log_file=/var/log/mysql/slow.log
long_query_time=2
5.4 启动与验证完整流程
备注:Docker Compose 常用命令
| 命令 | 作用 | 示例 |
|---|---|---|
docker-compose up -d |
后台启动所有服务 | docker-compose up -d |
docker-compose down |
停止并删除容器、网络 | docker-compose down -v(同时删卷) |
docker-compose ps |
查看服务状态 | docker-compose ps |
docker-compose logs -f |
实时查看日志 | docker-compose logs -f nginx |
docker-compose exec |
进入运行中的容器 | docker-compose exec php bash |
docker-compose restart |
重启某个服务 | docker-compose restart nginx |
docker-compose pull |
拉取最新镜像 | docker-compose pull |
docker-compose build |
重新构建自定义镜像 | docker-compose build php |
备注:在某些版本的docker中,docker-compose 命令可能不存在,需要使用 docker compose命令,也可以通过alias自定义映射命令。

启动所有服务
bash
# 先删除之前的旧容器(如果有)
docker rm -f php74-fpm
docker rm -f nginx8088
# 启动服务
cd ~/docker-project
docker-compose up -d
# 验证容器状态
docker-compose ps ## 预期输出(所有服务均为 Up)

【测试 PHP 解析】
bash
echo "<?php phpinfo();" > ~/docker-project/www/index.php
浏览器访问:http://localhost:8088,应看到 phpinfo。
【测试 MySQL 连接】
创建 ~/docker-project/www/mysql_test.php
php
<?php
$mysqli = new mysqli('mysql8', 'demo', 'demo123', 'demo'); //账号密码在 docker-compose.yml 中配置了
if ($mysqli->connect_error) {
die('连接失败: ' . $mysqli->connect_error);
}
echo 'MySQL 连接成功';
$mysqli->close();
浏览器访问:http://localhost:8088/db_test.php,应看到:MySQL 连接成功。
【测试 Redis 连接】:
创建 ~/docker-project/www/redis_test.php:
php
<?php
$redis = new Redis();
$redis->connect('redis7', 6379);
$redis->set('test', 'Hello Redis');
echo 'Redis写入成功: ' . $redis->get('test');
浏览器访问:http://localhost:8088/redis_test.php,应看到:Redis 写入成功。
5.5 在宿主机访问docker中的资源
最直接的方式就是临时进入容器执行:
bash
# 进入 PHP 容器
docker exec -it php74-fpm bash
# 在容器内执行任意 PHP 命令
php -v
composer --version
php -m

进入nginx不能用bash,而要用sh,因为nginx:alpine 镜像基于 Alpine Linux,没有 bash,只有 sh,redis也是只有sh:
bash
docker exec -it nginx8088 sh
docker exec -it mysql8 bash # 或 docker exec -it mysql8 sh
docker exec -it redis7 sh

也可以通过修改~/.zshrc创建别名,在文件末尾添加::
bash
# Docker命令配置
# ---------- PHP 7.4 (容器名: php74-fpm) ----------
alias php74-bash='docker exec -it php74-fpm bash'
alias php74='docker exec -i php74-fpm php'
alias composer74='docker exec -i php74-fpm composer'
# ---------- Nginx (容器名: nginx8088) ----------
alias nginx-bash='docker exec -it nginx8088 sh'
alias nginx-reload='docker exec nginx8088 nginx -s reload'
alias nginx-logs='docker exec nginx8088 tail -f /var/log/nginx/error.log'
alias nginx-access='docker exec nginx8088 tail -f /var/log/nginx/access.log'
# ---------- MySQL 8 (容器名: mysql8) ----------
# 注:密码为 root123,数据库为 demo,用户为 demo/demo123
alias mysql8-bash='docker exec -it mysql8 bash'
alias mysql8='docker exec -it mysql8 mysql -uroot -proot123'
alias mysql8-dump='docker exec mysql8 mysqldump -uroot -proot123'
alias mysql8-logs='docker logs mysql8 --tail 50'
alias mysql8-show='docker exec -it mysql8 mysql -uroot -proot123 -e "SHOW DATABASES;"' # 直接查看数据库列表
# ---------- Redis 7 (容器名: redis7) ----------
# 端口映射:宿主机 6380 → 容器 6379
alias redis7-bash='docker exec -it redis7 sh'
alias redis7='docker exec -it redis7 redis-cli'
alias redis7-logs='docker logs redis7 --tail 50'
然后:source ~/.zshrc 立即生效。
5.6 Docker Compose 带来的改变
以前(手动模式):
bash
# 每次重启都要敲这一堆,还容易漏
docker network create lnmp
docker run -d --name php74-fpm -p 9001:9000 -v ... --network lnmp ...
docker run -d --name nginx8088 -p 8088:80 -v ... --network lnmp ...
docker run -d --name mysql8 -p 3307:3306 -v ... --network lnmp ...
docker run -d --name redis7 -p 6379:6379 -v ... --network lnmp ...
现在(Compose 模式):
bash
# 一键启动
docker-compose up -d
# 一键停止
docker-compose down
# 一键重建
docker-compose up -d --build
更重要的:docker-compose.yml 可以提交到 Git,团队共享,新人拉下来直接 docker-compose up -d,5 分钟还原一整套开发环境。这就是容器化开发的终极目标:环境即代码。
如下:就是我把docker的代码仓库在云服务器上git pull下来之后,一条命令(有些版本需要用docker compose up -d)就可以还原出和我本地一样的开发环境了,如果是另一个同事的电脑,也是一样的。

等待完成后,所有的一些系统环境和代码都和原来本地的一样了。

源代码我放到了文末,你可以直接clone项目&&切换Tag:
bash
git clone https://gitee.com/rxbook/docker-demo-2026.git
cd docker-demo-2026
git checkout v0.1.0
然后 docker-compose up -d 就拥有了和我本次演示的内容完全一致的系统环境了,快去试试吧!
简单总结
本篇从Docker的安装、核心命令、镜像迁移、跨架构部署到常用软件的Docker化配置,完整覆盖了Docker在日常开发中的高频场景和踩坑点。掌握了这些,你已经可以:
- 在任何机器上快速部署Docker环境
- 熟练使用docker命令管理镜像、容器、网络、数据卷
- 在不同架构间迁移镜像并保证可用
- 编写
docker-compose.yml一键启动复杂服务栈 - 搭建LNMP开发环境(其他环境也是类似,后续再讲)
写在最后 :本文所有命令均在MacOS M1和CentOS 7.9验证通过,后续我将持续基于这个docker-project搭建和实现更多软件的配置和部署,欢迎关注。原创不易,如果本文对你有帮助,请点赞收藏,让更多人看到。
本文中的
docker-project源代码:https://gitee.com/rxbook/docker-demo-2026Tag: v0.1.0