Docker桌面版安装LNMP


Docker桌面版安装LNMP


引言

一直在windows中开发,为了便捷开发,不用搭建虚拟机等,可以使用桌面版docker解决这个问题。下面是多项目开发使用的LNMP环境。

WSL开头

如果没有启用WSL2,需要在命令行中执行以下命令。命令行以管理员身份打开:

1、启用WSL
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

2、启用虚拟机功能
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

wsl常用命令:

# 更新WSL2内核(报错0x800701bc时执行)
wsl --update

# 查看WSL状态
wsl --status

# 设置WSL2为默认
wsl --set-default-version 2

# 查看可安装发行版列表
wsl -l -o

# 安装指定版本
wsl --install -d Ubuntu-22.04

# 查看wsl已安装列表
wsl -l -v

# 终止Ubuntu22.04
wsl --terminate Ubuntu-22.04

# 卸载Ubuntu22.04
wsl --unregister Ubuntu-22.04

在文件资源管理器地址栏中通过 \\wsl$ 查看WSL安装的所有linux。

# 启动进入Ubuntu 22.04
wsl -d Ubuntu-22.04

# WSL中设置默认版本,以后直接wsl即可启动Ubuntu 22.04
wsl --set-default Ubuntu-22.04
wsl

# 查看版本(在Ubuntu中执行)
hostnamectl

如果不能访问外网,需要在命令行手动安装。命令行以管理员身份打开:

echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
echo "nameserver 114.114.114.114" | sudo tee -a /etc/resolv.conf

DNS有问题,临时解决一下:

baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.19.160.1
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$ echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf
nameserver 8.8.8.8
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$ echo "nameserver 114.114.114.114" | sudo tee -a /etc/resolv.conf
nameserver 114.114.114.114
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$ cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 114.114.114.114
baiyang@DESKTOP-PSDQHMG:/mnt/c/Windows/system32$

Docker开头

命令 作用
docker system df 查看磁盘占用
docker system df -v 查看磁盘占用明细
docker system prune 清理停止的容器、悬空镜像、未使用的网络和构建缓存
docker system prune -a 额外清理所有未使用的镜像
docker builder prune 只清理构建缓存
docker image prune -a 清理所有未使用的镜像
docker container prune 清理停止的容器
docker volume prune 清理未使用的卷
docker build --no-cache 单次构建跳过缓存

在 Docker 中,“清理缓存”通常指清理构建缓存未使用的镜像容器网络等占用的磁盘空间。

0、查看磁盘使用情况

# 查看磁盘使用情况
docker system df

- 显示镜像、容器、卷和构建缓存占用的磁盘空间。
- 加上 `-v` 可查看更详细的列表:
docker system df -v

1、清理所有未使用的资源(最常用)

docker system prune

- 清理**停止的容器**、**未使用的网络**、**悬空镜像**(dangling images)和**构建缓存**。
- 加上 `-a` 会额外删除所有未使用的镜像(不只是悬空镜像),释放更多空间。
docker system prune -a

- 加上 `-f` 跳过确认提示,直接执行。
docker system prune -a -f

2、单独清理构建缓存

docker builder prune

- 删除所有构建缓存。
- 加上 `-a` 强制删除所有缓存(包括当前正在使用的)。
docker builder prune -a

3、清理镜像

docker image prune

- 删除悬空镜像(`<none>:<none>`)。
- 加上 `-a` 删除所有未使用的镜像(即没有被任何容器引用的镜像)。

docker image prune -a

4、清理容器

docker container prune

- 删除所有已停止的容器。

5、清理卷(Volume)

docker volume prune

- 删除所有未使用的卷(volume 未被任何容器使用)。**注意**:卷存储数据,删除可能丢失持久化数据,谨慎操作。

6、清理网络

docker network prune

- 删除所有未被任何容器使用的网络。

7、构建时忽略缓存(不清理,仅跳过缓存)

如果您只是想让本次 `docker build` 不使用缓存,而不是删除所有历史缓存,可以使用 `--no-cache` 选项:

docker build --no-cache -t your-image .

这只会临时跳过缓存,不会影响其他构建的缓存。

8、一键彻底清理(慎用)

docker system prune -a --volumes -f

- 删除所有未使用的**容器**、**镜像**、**网络**、**卷**(包括未使用的卷)和**构建缓存**。
- **危险**:会永久删除所有未被使用的资源,可能导致数据丢失。

正文

条件准备

正常从 Docker https://www.docker.com/ 官网下载安装即可。

修改为国内源加速,在docker desktop的设置中setting配置即可,Docker Engine中写入下面内容,然后Apply应用并重启Docker Desktop:

{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "registry-mirrors": [
    "https://docker.xuanyuan.me",
    "https://docker.1ms.run",
    "https://docker.m.daocloud.io",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

需要说明 docker config set --global registry-mirrors命令无效,不可用。

项目的目录结构如下:

D:\develop
├── DockerEnv
    ├── docker-multi-web
        ├── dockerfile                # PHP+Nginx基础镜像构建文件
        ├── nginx
            ├── nginx.conf            # Nginx主配置
            └── vhost                 # 多站点虚拟主机配置目录
                ├── site1.conf        # 站点1配置
                └── site2.conf        # 站点2配置
    ├── mysql-server
        ├── mysql-data                # MySQL持久化数据
├── www
    ├── site1                 # 项目1:test1.local
    │   └── index.php
    └── site2                 # 项目2:test2.local
        └── index.php

搭建网桥

搭建网桥docker network create web-net,如:

D:\develop\DockerEnv>docker network create web-net
2b27ad41e8489e7765f93e2fec27eb9321cf88e0d65969f438f7d3ea844d8de6

D:\develop\DockerEnv>

安装MySQL

MySQL 不要放进自定义 Image。如果把 MySQL 打包进镜像,删除容器会丢失数据库数据,无法持久化;分离容器更灵活,可单独重启、备份、更换 MySQL 版本。

Docker Hub 官方已经提供好现成的 mysql:8.0 官方镜像,直接 docker run 拉取启动即可,不需要自己打包 MySQL。

启动MySQL容器:

docker run -d --name mysql8 --network web-net -v D:/develop/DockerEnv/mysql-server/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=testdb -e MYSQL_ROOT_HOST=% -p 3306:3306 mysql:8.0

加上 MYSQL_ROOT_HOST=%,否则外部 Windows、PHP 容器无法连接数据库。-e MYSQL_ROOT_HOST=% 允许 PHP 容器、本机 Navicat 全部访问,本地开发必备。

运行完成后在Docker Desktop中查看MySQL容器是否启动成功,Container、Image等。

外部连接时,连接地址不要使用 127.0.0.1,而要使用 mysql8 。

Nginx 配置

nginx.conf 内容:

user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /var/log/nginx/access.log main;
    sendfile on;
    keepalive_timeout 65;
    # 加载所有站点虚拟主机配置
    include /etc/nginx/conf.d/*.conf;
}

项目配置

下面看几个项目的配置。

项目一

site1.conf 内容:

server {
    listen 80;
    server_name test1.local www.test1.local;
    root /usr/share/nginx/www/site1;
    index index.html index.htm index.php;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

www/site1/index.php 内容:

<?php

echo "<h2>站点1 test1.local</h2>";
phpinfo();

项目二

site2.conf 内容:

server {
    listen 80;
    server_name test2.local www.test2.local;
    root /usr/share/nginx/www/site2;
    index index.html index.htm index.php;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

www/site2/index.php 内容:

<?php

echo "<h2>站点2 test2.local</h2>";
// 测试mysql连接
$dsn = 'mysql:host=mysql8;dbname=testdb;charset=utf8';
try {
    $db = new PDO($dsn, 'root', '123456');
    echo "<p>MySQL连接成功</p>";
}catch (PDOException $e){
    echo "<p>数据库连接失败:".$e->getMessage()."</p>";
}

www/site2/index.php 内容:

<?php
    echo "hello world";
?>

hosts 配置

在宿主机的 C:\Windows\System32\drivers\etc\hosts 文件中添加:

127.0.0.1 test1.local
127.0.0.1 test2.local

如果提示无权限修改,可以用管理员权限打开记事本,然后用记事本打开该文件进行修改并保存。

安装 Nginx + PHP

接下来安装Nginx+PHP。

dockerfile 内容:

FROM quay.io/centos/centos:stream9-minimal

# 1. 替换 CentOS 基础源为阿里云
RUN sed -e 's|mirror.centos.org|mirrors.aliyun.com|g' \
        -e 's|mirror.stream.centos.org|mirrors.aliyun.com|g' \
        -i /etc/yum.repos.d/centos*.repo && \
    microdnf clean all && microdnf makecache

# 2. 强制移除 curl-minimal,再安装 dnf 和 curl
RUN rpm -e --nodeps curl-minimal && \
    microdnf install -y dnf curl && \
    microdnf clean all

# 3. 安装 epel-release 并替换为阿里云 EPEL 镜像
RUN dnf install -y epel-release && \
    sed -e 's|https://download.fedoraproject.org/pub|https://mirrors.aliyun.com/fedora-epel|g' \
        -i /etc/yum.repos.d/epel*.repo && \
    dnf clean all && dnf makecache

# 4. 安装 Remi 源并替换为清华镜像(国内唯一完整同步Remi)
RUN dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm && \
    sed -e 's|https://rpms.remirepo.net|https://mirrors.tuna.tsinghua.edu.cn/remi|g' \
        -i /etc/yum.repos.d/remi*.repo && \
    dnf clean all && dnf makecache

# 5. 安装 Nginx + 启用 php:remi-7.4 模块并安装全部组件 + 系统底层时区库
RUN dnf module enable -y php:remi-7.4 && \
    dnf install -y \
        nginx \
        php-fpm \
        php-cli \
        php-bcmath \
        php-mysqlnd \
        php-pdo \
        php-gd \
        php-zip \
        php-curl \
        php-mbstring \
        php-opcache \
        php-fileinfo \
        php-xml \
        php-redis \
        php-intl \
        php-sodium \
        vim unzip && \
    dnf clean all

# 6.安装 tzdata 并重装确保时区数据文件存在
RUN dnf install -y tzdata && \
    dnf reinstall -y tzdata

# 7. 新增创建www-data用户组和用户
RUN groupadd www-data && useradd -g www-data www-data

# 8. 修改 php-fpm 运行用户为 www-data,解决页面403权限
RUN sed -i 's/^user = apache/user = www-data/' /etc/php-fpm.d/www.conf && \
    sed -i 's/^group = apache/group = www-data/' /etc/php-fpm.d/www.conf && \
    sed -i 's/^listen = .*/listen = 127.0.0.1:9000/' /etc/php-fpm.d/www.conf

# 9. 统一设置系统时区+PHP时区配置,彻底消除时区报错
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo 'date.timezone = Asia/Shanghai' > /etc/php.d/99-timezone.ini

# 10. 安装 Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# 11. 手动创建 Composer 全局配置文件(阿里云镜像)
RUN mkdir -p /root/.composer && \
    echo '{"config": {"repositories": {"packagist": {"type": "composer", "url": "https://mirrors.aliyun.com/composer/"}}}}' > /root/.composer/config.json

# 12. 复制本地Nginx主配置 + 多站点虚拟主机目录
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf

# 13. 创建站点根目录并授权www-data读写权限
RUN mkdir -p /usr/share/nginx/www && \
    chown -R www-data:www-data /usr/share/nginx/www


EXPOSE 80

# 启动php-fpm + 前台运行nginx,防止容器自动退出
CMD ["sh", "-c", "mkdir -p /run/php-fpm && chown www-data:www-data /run/php-fpm && php-fpm -F & nginx -g 'daemon off;'"]

这一块用了好长时间,说一下里面的注意点。基础镜像用的是centos:stream9精简版,为了国内加速,CentOS 基础源换为了阿里云。里面多处安装用到了dnf,但基础镜像 quay.io/centos/centos:stream9-minimal 默认的仓库配置中,没有可用的 dnf 包(尽管 microdnf 是内置的,但microdnf 本身是轻量级包管理器,好多包的安装还是要用到dnf),有些地方也要用到curl(尽管 curl-minimal 是内置的,但有些下载是要用到curl的,而curl 包与 curl-minimal 冲突),我们需要强制移除 curl-minimal,再安装 dnf 和 curl。还有centos:stream9精简版底层是缺少系统底层时区库,安装Composer会用到。Composer 全局配置文件改为阿里云,命令行总是无法执行,无奈改为手动创建。php-fpm 一般是用socket实现,绑定地址 /run/php-fpm/www.sock,这是一个临时目录,在容器启动时需要创建该目录;但这里改下来有问题,最后改为了 127.0.0.1:9000 端口监听。php-fpm -F前台运行会阻塞后面nginx -g 'daemon off;'的执行,所以不能用&&,而是改为&

centos:stream9-minimal 为精简镜像,有意删除了 /usr/share/zoneinfo,导致tzdata安装不完整,需要重新安装dnf reinstall -y tzdata。之后 第10步 可以修改看一下能否正常安装:

# 11. 设置 Composer 全局为阿里云镜像
php -d date.timezone=Asia/Shanghai composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

生成镜像:

docker build -t centos9-nginx-php74 .

创建容器:

docker run -d --name centos9-nginx-php74 --network web-net -v D:/develop/www:/usr/share/nginx/www -v D:/develop/DockerEnv/docker-multi-web/nginx/vhost:/etc/nginx/conf.d -p 8080:80 centos9-nginx-php74

浏览器访问,查看效果:

  • 站点 1:http://test1.local:8080
  • 站点 2:http://test2.local:8080

另外php可以安装的几个拓展:

连接协议
soap
swoole

进程管理
sysvsem
posix
shmop

新项目配置

和第二个项目一样,除了项目文件,另外需要写site3.conf配置,修改hosts文件。

重启容器:

docker restart centos9-nginx-php74

PHP8.3 安装

dockerfile 内容:

FROM quay.io/centos/centos:stream9

# 1. 替换 CentOS 基础源为阿里云
RUN sed -e 's|mirror.centos.org|mirrors.aliyun.com|g' \
        -e 's|mirror.stream.centos.org|mirrors.aliyun.com|g' \
        -i /etc/yum.repos.d/centos*.repo && \
    microdnf clean all && microdnf makecache

# 2. 强制移除 curl-minimal,再安装 dnf 和 curl
RUN rpm -e --nodeps curl-minimal && \
    microdnf install -y dnf curl && \
    microdnf clean all

# 3. 安装 epel-release 并替换为阿里云 EPEL 镜像
RUN dnf install -y epel-release && \
    sed -e 's|https://download.fedoraproject.org/pub|https://mirrors.aliyun.com/fedora-epel|g' \
        -i /etc/yum.repos.d/epel*.repo && \
    dnf clean all && dnf makecache

# 4. 安装 Remi 源并替换为清华镜像(国内唯一完整同步Remi)
RUN dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm && \
    sed -e 's|https://rpms.remirepo.net|https://mirrors.tuna.tsinghua.edu.cn/remi|g' \
        -i /etc/yum.repos.d/remi*.repo && \
    dnf clean all && dnf makecache

# 5. 安装 Nginx + 启用 php:remi-7.4 模块并安装全部组件 + 系统底层时区库
RUN dnf module enable -y php:remi-7.4 && \
    dnf install -y \
        nginx \
        git \
        php-fpm \
        php-cli \
        php-bcmath \
        php-mysqlnd \
        php-pdo \
        php-gd \
        php-zip \
        php-curl \
        php-mbstring \
        php-opcache \
        php-fileinfo \
        php-xml \
        php-redis \
        php-intl \
        php-sodium \
        vim unzip && \
    dnf clean all

# 6.安装 tzdata 并重装确保时区数据文件存在
RUN dnf install -y tzdata && \
    dnf reinstall -y tzdata

# 7. 新增创建www-data用户组和用户
RUN groupadd www-data && useradd -g www-data www-data

# 8. 修改 php-fpm 运行用户为 www-data,解决页面403权限
RUN sed -i 's/^user = apache/user = www-data/' /etc/php-fpm.d/www.conf && \
    sed -i 's/^group = apache/group = www-data/' /etc/php-fpm.d/www.conf && \
    sed -i 's/^listen = .*/listen = 127.0.0.1:9000/' /etc/php-fpm.d/www.conf

# 9. 统一设置系统时区+PHP时区配置,彻底消除时区报错
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo 'date.timezone = Asia/Shanghai' > /etc/php.d/99-timezone.ini

# 10. 安装 Composer
RUN curl -sS https://mirrors.aliyun.com/composer/composer.phar | php -- --install-dir=/usr/local/bin --filename=composer

# 11. 手动创建 Composer 全局配置文件(阿里云镜像)
RUN mkdir -p /root/.composer && \
    echo '{"config": {"repositories": {"packagist": {"type": "composer", "url": "https://mirrors.aliyun.com/composer/"}}}}' > /root/.composer/config.json

# 12. 复制本地Nginx主配置 + 多站点虚拟主机目录
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf

# 13. 创建站点根目录并授权www-data读写权限
RUN mkdir -p /usr/share/nginx/www && \
    chown -R www-data:www-data /usr/share/nginx/www


EXPOSE 80

# 启动php-fpm + 前台运行nginx,防止容器自动退出
CMD ["sh", "-c", "mkdir -p /run/php-fpm && chown www-data:www-data /run/php-fpm && php-fpm -F & nginx -g 'daemon off;'"]

centos:stream9-minimal 为精简镜像,缺少好多东西,我们直接用centos:stream9,需要时我们也可以把git安装上。

生成镜像:

docker build -t centos9-nginx-php83 .

创建容器:

docker run -d --name centos9-nginx-php83 --network web-net -v D:/develop/www:/usr/share/nginx/www -v D:/develop/DockerEnv/docker-multi-web/nginx/vhost:/etc/nginx/conf.d -p 8081:80 centos9-nginx-php83

安装Redis

在 D:\develop\DockerEnv\redis-server 目录下创建 redis.conf 文件,内容如下:

# 允许远程连接(Docker环境下通常注释掉 bind 或设为 0.0.0.0)
# bind 127.0.0.1 
bind 0.0.0.0

# 关闭保护模式(如果设置了密码,可以保持 yes;若需兼容旧客户端可设 no)
protected-mode no

# 设置密码
requirepass 123456

# 开启 AOF 持久化
appendonly yes

# 内存限制与淘汰策略(防止内存溢出)
maxmemory 256mb
maxmemory-policy allkeys-lru

# 日志级别
loglevel notice

执行命令启动 Redis 容器:

docker run -d  --name redis74  --network web-net  -v D:/develop/DockerEnv/redis-server/redis-data:/data -v D:/develop/DockerEnv/redis-server/redis.conf:/usr/local/etc/redis/redis.conf  -p 6379:6379  redis:7.4 redis-server /usr/local/etc/redis/redis.conf

外部连接时,宿主机连接地址要使用 127.0.0.1:6379,同一个宿主机内的其他docker容器中使用 web-net:6379连接。


返回