Docker从零到一部署DNMP+Redis《全程干货》

Docker从零到一部署DNMPR

前几天把本机的mac格式化了,原因是环境太乱了,什么东西都往里装,格式化后就想着重新安装开发工具和部署环境,不想再去下载那些集成环境了(XAMPP+MAMP),就想着自己用Docker重新部署一套适合自己的环境。 (ps.真的很搞,我手里php项目有两个不同环境的,还有一个要准备升级)

混乱翻查资料的时候看到了一个博客,《十分钟部署PHP+NGINX+MYSQL+REDIS》,尝试跟着部署了一遍,没想到真的成了,转载大佬的笔记,并在这里重新梳理和总结记录一下,造福后人hh

首先安装Docker
json 复制代码
这个不用多说吧,自己去 https://www.docker.com/ 下载一个docker 版本自己选
安装完成后部署环境变量 输入命令 docker -v 查看版本
我的版本是Docker version 28.5.1, build e180ab8
在配置里直接新增以下国内加速地址
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com",
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.1panel.live",
"https://docker.m.ixdev.cn",
"https://hub.rat.dev",
"https://docker.xuanyuan.me",
"https://dockerproxy.net",
"https://image.cloudlayer.icu",
"https://docker-registry.nmqu.com",
"https://hub.amingg.com",
"https://docker.hlmirror.com",
"https://docker.kejilion.pro",
"https://docker.367231.xyz",
"https://hub.1panel.dev",
"https://docker.etcd.fun",
"https://docker.apiba.cn",
"https://proxy.vvvv.ee"
 ]
创建容器网络

docker network create --driver bridge haveyb

建立容器网络组

创建代码文件夹

mkdir -p ~/Code/{php,go,python,java,c}

这里是预先建立你Docker容器中和宿主机的文件映射

创建服务配置文件夹
js 复制代码
mkdir -p ~/Code/docker/php
mkdir -p ~/Code/docker/nginx/{conf.d,cert,logs}

这里是建立环境服务的配置文件地址,用于创建容器时设置文件映射和配置调整

拉取PHP镜像
bash 复制代码
docker pull haveyb/php《大佬》
该镜像是这个大佬以php官方php-fpm:8.4.12为基础,添加了一些常用扩展
yar、redis、swoole、pdo_mysql、gd、pcntl、sockets、igbinary、msgpack、zstd、pdo_pgsql、xsl、zip、
bcmath、sysvmsg、sysvsem、sysvshm
为debian apt设置了默认阿里国内镜像源
添加了composer为当前最新稳定版本2.8.11,并为composer也配置了阿里国内镜像源。
js 复制代码
docker run -itd --name temp-php haveyb/php bash
docker cp temp-php:/usr/local/etc/php/php.ini ~/Code/docker/php

创建临时容器 并将临时容器中的php.ini拷贝至映射目录下

bash 复制代码
docker rm -f temp-php

完成后清除目录

创建PHP正式容器
js 复制代码
docker run -itd --name php84 --privileged \
-p 9000:9000 -p 9501:9501 \
-v ~/Code/php/test:/data/php/test \
-v ~/Code/docker/php/php.ini:/usr/local/etc/php/php.ini \
--network=haveyb \
haveyb/php

这个命令解释一下

docker run

运行一个容器

-itd(三个选项的组合)

-i: 保持标准输入打开(interactive)

-t: 分配一个伪终端(tty)

-d: 在后台运行(detached mode)

组合效果: 让容器在后台运行,但保持交互能力

--name php

设置容器名称 而不是随机生成的容器ID

--privileged:

给容器赋予特权模式 容器内的进程几乎拥有宿主机的所有权限 可以访问所有设备、执行特权操作

-p 9000:9000 -p9501:9051 -p 宿主机端口:容器端口

通常 9000 用于 PHP-FPM,9501 可能用于 Swoole 或其他服务

-v ~/Code/php/test:/data/test 宿主机路径:容器内路径

将宿主机的 /Code/php/test目录挂载到容器的 /data/test目录

效果 : 容器内的 /data目录实际就是宿主机的代码目录,实现文件同步

--network=haveyb

将容器连接到自定义网络

复制代码
haveyb 是你创建的 Docker 网络
容器可以与该网络中的其他容器直接通信(通过容器名)
实现容器间的网络隔离和服务发现

拉取openresty镜像【lua加强版Nginx,几乎和Nginx最新稳定版保持一致,已经是非常成熟的项目了】

bash 复制代码
docker pull openresty/openresty

创建测试站点配置文件

bash 复制代码
cd ~/Code/docker/nginx/conf.d

创建gg.conf,内容如下:

展开

bash 复制代码
server {
    listen 80;
    server_name gg;
    root /data/php/test;
    index index.php index.html;

    # 安全头配置
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # 限制上传文件大小
    client_max_body_size 10M;

    # 静态资源处理
    location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public, max-age=2592000";
        try_files $uri =404;
    }

    # PHP脚本处理
    location ~ .php$ {
        try_files $uri =404;
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTP_HOST $host;
        fastcgi_param PHP_VALUE "date.timezone=Asia/Shanghai";
        include fastcgi_params;
    }

    # 伪静态支持
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # 日志配置
    access_log /var/log/nginx/gg_access.log;
    error_log /var/log/nginx/gg_error.log;
}

3、创建Nginx容器

创建临时nginx容器:

arduino 复制代码
docker run -itd --name temp-nginx openresty/openresty bash

拷贝临时nginx容器内的nginx.conf到宿主机:

javascript 复制代码
docker cp temp-nginx:/usr/local/openresty/nginx/conf/nginx.conf ~/Code/docker/nginx

删除临时nginx容器:

bash 复制代码
docker rm -f temp-nginx

创建正式nginx容器:

ruby 复制代码
docker run -itd --name nginx --privileged \
-p 80:80 -p 443:443 \
-v ~/Code:/data \
-v ~/Code/docker/nginx/conf.d:/etc/nginx/conf.d \
-v ~/Code/docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf \
-v ~/Code/docker/nginx/cert:/usr/local/openresty/nginx/cert \
-v ~/Code/docker/nginx/logs:/var/log/nginx \
--network=haveyb \
openresty/openresty

4、注意事项

本地宿主机修改nginx或php配置文件后,如何加载?重新启动容器

宿主机执行:
复制代码
docker restart nginx

docker restart php
或者进入相应容器内执行:
复制代码
nginx -s reload

php-fpm -s reload
需要特别谨慎的点:

由于目录映射的特性,如果宿主机的某个文件或目录与容器内的某个文件或目录通过-v进行了映射,那么在容器内对映射了的文件或目录进行删除,宿主机的文件或目录也会相应被删除。

因此为了安全起见,所有通过-v指定映射了的文件或目录,如果要执行删除操作,一定要宿主机执行,因为宿主机是可视化界面,误删的概率要小很多。

配置MySQL环境

1、进入宿主机待映射文件夹

bash 复制代码
cd ~/Code/docker

2、创建具体的映射文件夹

arduino 复制代码
mkdir -p mysqldata/{data,logs,conf,pems,conf.d}

3、自定义 my.cnf 文件

bash 复制代码
cd ~/Code/docker/mysqldata/conf
复制代码
vi my.cnf
ini 复制代码
[mysqld]
server-id = 1
log-bin = mysql-bin

4、拉取官方 MySQL9.4镜像

复制代码
docker pull mysql:9.4

5、创建容器

展开

ruby 复制代码
docker run -itd --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
-v ~/Code/docker/mysqldata/data:/var/lib/mysql \
-v ~/Code/docker/mysqldata/logs:/var/log/mysql \
-v ~/Code/docker/mysqldata/conf:/etc/mysql \
-v ~/Code/docker/mysqldata/conf.d:/etc/mysql/conf.d \
-v ~/Code/docker/mysqldata/pems:/etc/mysql/pems \
--restart unless-stopped \
--network=haveyb \
mysql:9.4

--restart unless-stopped除非手动停止,否则自动重启

当容器退出时,Docker 会自动重新启动它

6、测试MySQL连接

用navicat连接时,直接用127.0.0.1,端口号3306,用户名root,密码123456连接即可

如果在php文件中连接MySQL,host写MySQL容器的容器名称,在这里就是 mysql

配置Redis环境

1、拉取redis镜像

复制代码
docker pull redis:8.2

2、创建本地映射文件夹

bash 复制代码
mkdir -p ~/Code/docker/redis/data/logs
touch ~/Code/docker/redis/data/logs/notice.log

3、新建redis.conf文件

bash 复制代码
cd ~/Code/docker/redis
vi redis.conf
js 复制代码
# 设置允许所有ip来连接
bind 0.0.0.0

# 设置端口号
port 6379

# 密码
requirepass 123456

# 保护模式开关,开启时仅允许本地连接或认证连接
protected-mode yes

# 设置日志级别
loglevel notice

# 日志地址
logfile /data/logs/notice.log

# 设置最大内存容量为256MB
maxmemory 256MB

# 内存淘汰策略:从所有键中淘汰最近最少使用的键,最适合缓存场景
maxmemory-policy allkeys-lru

# TCP保活探测间隔(秒),用于检测无效连接
tcp-keepalive 300

# 是否以守护进程方式启动,docker需要配置为no
daemonize no

# 持久化设置
dir /data

# RDB 持久化配置(文件会存放在 /data/dump.rdb)
dbfilename dump.rdb
save 900 1

# AOF 持久化配置(文件会存放在 /data/appendonly.aof)
appendonly yes
# AOF文件存储路径
appendfilename appendonly.aof
# AOF 刷盘策略(每秒刷盘,推荐)
appendfsync everysec
#加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电等)
aof-load-truncated yes

# 开启RDB-AOF混合持久化格式
aof-use-rdb-preamble yes

# 当Aof log增长超过指定百分比例时,重写AOF文件
auto-aof-rewrite-percentage 100
# AOF 重写的最小文件大小(避免小文件频繁重写)
auto-aof-rewrite-min-size 64mb

# 客户端空闲超时时间(秒),0表示永不超时
timeout 0

# PID文件路径,记录Redis进程ID(仅守护进程模式有效)
pidfile /var/run/redis_6379.pid

# 可用数据库的数量,默认16个(编号0-15)
databases 16

# 超过此值的命令会被记录到慢查询日志(微妙,10000微妙=10毫秒=0.01秒,正常命令执行时间通常在1毫秒以内,简单的 GET/SET 甚至只需微秒级)
slowlog-log-slower-than 10000

# 慢查询日志的最大存储条数,超过此条数,新日志会覆盖最旧的日志(FIFO队列 First-In-First-Out Queue,先进先出队列)
slowlog-max-len 128

注:获取redis8.2默认配置,可通过访问 raw.githubusercontent.com/redis/redis... 获取

4、创建redis容器

javascript 复制代码
docker run -itd --name redis -p 6379:6379 \
  -v ~/Code/docker/redis/redis.conf:/etc/redis/redis.conf \
  -v ~/Code/docker/redis/data:/data \
  --network=haveyb \
  redis:8.2 \
  redis-server /etc/redis/redis.conf

redis-server /etc/redis/redis.conf 使用自定义配置文件启动 Redis 服务(而不是默认配置)

测试

1、增加宿主机对gg域名的本地解析

编辑本地hosts文件
bash 复制代码
vi /etc/hosts
添加下面代码
复制代码
127.0.0.1           gg

2、编辑php测试文件

javascript 复制代码
vi ~/Code/php/test/index.php
内容如下:

展开

php 复制代码
<?php
echo "<h1>PHP 环境测试</h1>";
echo "PHP 版本: " . phpversion() . "<br><br>";

// 测试MySQL连接
echo "<h2>MySQL 连接测试</h2>";
$serverName = "mysql";
$userName = "root";
$password = "123456";

try {
    $conn = new PDO("mysql:host=$serverName;charset=utf8mb4", $userName, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "MySQL 连接成功: " . $conn->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
} catch(PDOException $e) {
    echo "MySQL 连接失败: " . $e->getMessage();
}

echo "<br><br>";

// 测试Redis连接
echo "<h2>Redis 连接测试</h2>";
$redisHost = "redis";
$redisPort = 6379;
$redisPassword = "123456";

// 检查Redis扩展是否安装
if (!class_exists('Redis')) {
    echo "Redis 扩展未安装,请先安装 Redis 扩展";
} else {
    $redis = new Redis();
    try {
        // 连接Redis服务器
        $connectResult = $redis->connect($redisHost, $redisPort);
        if (!$connectResult) {
            throw new Exception("无法连接到Redis服务器");
        }

        // 使用ACL用户名和密码进行认证
        // 注意:Redis 6.0+ 支持用户名+密码认证,旧版本仅支持密码
        $authResult = $redis->auth($redisPassword);
        if (!$authResult) {
            throw new Exception("Redis 认证失败,用户名或密码错误");
        }

        // 执行一个简单命令测试连接
        $redis->set("test_key", "php_redis_test");
        $testValue = $redis->get("test_key");
        if ($testValue === "php_redis_test") {
            echo "Redis 连接成功,且可以正常执行命令<br>";
            echo "Redis 服务器版本: " . $redis->info()['redis_version'];
        } else {
            throw new Exception("Redis 命令执行失败");
        }
    } catch (Exception $e) {
        echo "Redis 连接失败: " . $e->getMessage();
    } finally {
        // 关闭连接
        if (isset($redis) && $redis->isConnected()) {
            $redis->close();
        }
    }
}

echo "<br><br>";
phpinfo();

访问http://gg/如果有phpinfo输出,说明LNMP环境配置成功

预期输出结果:
css 复制代码
PHP 环境测试
PHP 版本: 8.4.12

MySQL 连接测试
MySQL 连接成功: 9.4.0

Redis 连接测试
Redis 连接成功,且可以正常执行命令
Redis 服务器版本: 8.2.1

phpinfo()相关信息

结语

终于也是写完了,在这里要感谢大佬写出的文档,此文主要是总结分享和个人复习使用

以上

谢谢

相关推荐
wefly20171 小时前
免安装!m3u8live.cn在线 M3U8 播放器,小白也能快速上手
java·开发语言·python·json·php·m3u8·m3u8在线转换
独隅2 小时前
PyTorch 模型部署的 Docker 配置与性能调优深入指南
人工智能·pytorch·docker
luanma1509803 小时前
Laravel 10.x新特性全解析
php·laravel
yuzhuanhei5 小时前
docker常用命令
运维·docker·容器
我叫张小白。5 小时前
Dify系列(一):平台安装部署+界面操作
docker·ai·语言模型·大模型·dify·智能体
anarckk5 小时前
docker volume 导入导出命令
运维·docker·容器
Brandon汐5 小时前
从0开始搭建一主两节点k8s集群对接Ceph集群
ceph·容器·kubernetes
杨浦老苏6 小时前
音乐和有声读物播放器AudioDock
docker·群晖·多媒体·音乐·有声读物