Docker从入门到实践:安装配置、常用命令与开发环境搭建

文章目录

  • 第一章: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,它自带图形界面和命令行工具。

  1. 下载 :访问 Docker官网的docker-desktop页面,选择对应芯片的版本(Apple Silicon 或 Intel)。

  2. 安装 :双击Docker.dmg,将Docker图标拖入Applications,安装时勾选"Use recommended settings",它会自动配置环境变量和资源限制。

  3. 启动:打开Launchpad,点击Docker图标,等待菜单栏出现🐳图标(绿色表示运行中:Docker Desktop is running)。

  4. 验证

    bash 复制代码
    docker --version
    docker compose --version

    示例输出:

    复制代码
    Docker version 29.2.0, build 0b9d198
    Docker Compose version v5.0.2
  5. 配置镜像加速:由于国内网络的原因,直接拉取Docker Hub镜像可能超时,因此可能需要配置国内镜像源:

    点击菜单栏Docker图标 → SettingsDocker 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.04nginx: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.1
  • php74-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-2026

Tag: v0.1.0

相关推荐
未既1 小时前
linux以及docker修改文件描述符
linux·运维·docker
程序员一点2 小时前
第9章:软件包管理(DNF 与 RPM)
linux·运维·openeuler
Mr.小海2 小时前
Docker Compose 实战:多容器应用编排从入门到生产落地
运维·docker·容器
何中应2 小时前
Jenkins如何注册为CentOS7的一个服务
linux·运维·jenkins·开发工具
三点水-here2 小时前
基于 Prometheus 生态的 Kubernetes 全栈监控实战指南
云原生·容器·kubernetes·prometheus
Mr.小海2 小时前
Docker 镜像分层机制:从原理到生产环境的深度实践
运维·docker·容器
yttandb2 小时前
linux的基础命令
linux·运维·服务器
进击的雷神2 小时前
Cursor 浏览器自动化:Playwright MCP Server 使用指南
运维·自动化·cursor·playwright mcp
未来之窗软件服务2 小时前
服务器运维(三十五)数字证书TLS 版本设备对照表—东方仙盟
运维·服务器·服务器运维·仙盟创梦ide·东方仙盟