前言:
    阅读以下知识,确保你已对 docker 有了初步的认识,并且了解基础的命令。
    现在来想象这个场景:你是否每次在项目上线后,为搭建新环境和调试而感到烦恼?只有一个项目还好。但如果有N个这样的项目呢?那岂不是要搭建N次环境?浪费时间不说。而且不能保证每次都顺利的搭建环境,可以中途会遇到许多的问题。
    这时候docker 运应而生,它将每个环境看作是一个容器,让其在容器里运行,不仅保证了像: mysqlnginxphp 之间能独立运行。同时也保证了它们之间是相互隔离的,并且可移植性强。

    下面来看下整个 **Docker-compose** 目录结构:

    1. .
    2. ├── README.md
    3. ├── config
    4. ├── mysql
    5. └── my.cnf
    6. ├── nginx
    7. └── conf.d
    8. ├── default.conf
    9. ├── docker.conf
    10. └── laravel.conf
    11. └── php
    12. ├── database
    13. └── mysql
    14. ├── backup
    15. └── store
    16. ├── docker-compose.yml
    17. ├── kernel
    18. ├── mysql-8.0.26
    19. └── Dockerfile
    20. ├── nginx-1.21.3
    21. └── Dockerfile
    22. └── php-8.0.11
    23. └── Dockerfile
    24. ├── logs
    25. ├── mysql
    26. ├── nginx
    27. └── php
    28. └── www
    29. └── index.php

    DockerCompose 的方便之处在于,将布署过程写入到配置文件,只需运行一句 docker-compose up -d 命令,docker 就会根据配置文件来进行构建所需容器。非常方便!而配置文件则好比面向对象,像以前手动安装各种依赖就好比面向过程。有关 docker 的命令操作这里就不过多的赘述。下面贴出关于我自己编写的 dockerfile ,祝你撸码愉快~

    **PHP****dockerfile**

    1. FROM php:8.0.11-fpm
    2. LABEL df="df@dto.cc"
    3. # 更改容器时区
    4. ENV TZ=Asia/Shanghai
    5. RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
    6. && apt-get clean \
    7. # 安装所需依赖
    8. && apt-get update && apt-get install -y \
    9. autoconf \
    10. libxml2-dev \
    11. libsqlite3-dev \
    12. libcurl4-openssl-dev \
    13. libssl-dev \
    14. libonig-dev \
    15. zlib1g-dev \
    16. libpng-dev \
    17. libjpeg-dev \
    18. libbz2-dev \
    19. libxml2-dev \
    20. libxslt1-dev \
    21. libfreetype6-dev \
    22. libjpeg62-turbo-dev \
    23. libpng-dev \
    24. libzip-dev \
    25. unzip \
    26. m4 \
    27. gcc \
    28. make \
    29. git \
    30. # 配置 gd 库
    31. && docker-php-ext-configure gd \
    32. --with-freetype --with-jpeg \
    33. && docker-php-ext-install -j$(nproc) gd \
    34. # 安装并启用扩展
    35. && docker-php-ext-install bcmath dba filter opcache gd shmop zip pdo_mysql \
    36. && docker-php-ext-install exif pcntl bz2 intl gettext xsl pdo mysqli \
    37. && pecl install xdebug redis xlswriter \
    38. && docker-php-ext-enable xdebug redis xlswriter \
    39. && curl -sS https://getcomposer.org/installer | php \
    40. && mv composer.phar /usr/local/bin/composer \
    41. # 更改php时区
    42. && printf '[PHP]\ndate.timezone = Asia/Shanghai\n' > /usr/local/etc/php/conf.d/tzone.ini \
    43. # 清理舞台
    44. && rm -rf /var/lib/apt/lists/*
    45. EXPOSE 9000
    46. CMD ["php-fpm"]

    注意:配置文件中的扩展是需要上面的依赖的。如果去掉某一项依赖库,在构建容器时会报错。dockerfile 的方便之处在于把平时手动配置的过程给整合了一下。尽量使用一个 RUN 命令。你如果想构建属于自己的 PHP 容器,尽量去看看 PHP 编译安装的过程。因为它和使用 apt 的方式截然不同。 php 官方镜像也提供了 docker-php-ext-install 来安装扩展 、php-ext-configure 配置扩展。而 php-ext-enable 主要针对于使用 pecl 命令安装的扩展来手动开启。如果是使用php-ext-install 方式安装的扩展。则不需要担心这个问题,它内部会自动帮助你开启这些扩展。

    相对于 nginxmysql 以及 redis , php 的dockerfile 足以让我在编写过程中踩了许多坑,因为使用官方镜像必须按照它的那套规则来安装。
    以上 dockerfile 已安装了常用的 composergit。所以不需要在宿主机上额外再安装这些软件。

    Nginx 的 **dockerfile**

    1. FROM nginx:1.21.3
    2. LABEL df="df@dto.cc"
    3. ENV TZ=Asia/Shanghai
    4. CMD ["nginx","-g","daemon off;"]

    Mysql 的 **dockerfile**

    1. FROM mysql:8.0.26
    2. LABEL df="df@dto.cc"
    3. ENV TZ=Asia/Shanghai
    4. CMD ["mysqld"]

    这里 nginxmysql 均是使用官方最新镜像,并没有对它俩做过多的配置。只需要更改它内部的时区就行了。因为时区不一致,会导致很多麻烦。这里为了演示,就没有下载 redis ,因为笔者现在对 redis 还不是很熟悉。

    **docker-compose.yml** 文件的内容

    1. version: '3.1'
    2. services:
    3. nginx:
    4. build: kernel/nginx-1.21.3
    5. ports:
    6. - "80:80"
    7. restart: always
    8. tty: true
    9. container_name: nginx
    10. volumes:
    11. - ./www:/var/www/html:ro
    12. - ./logs/nginx:/var/log/nginx:rw
    13. - ./config/nginx/conf.d:/etc/nginx/conf.d:ro
    14. networks:
    15. - lnmp-networks
    16. php8:
    17. build: kernel/php-8.0.11
    18. tty: true
    19. restart: always
    20. container_name: php8
    21. volumes:
    22. - ./www:/var/www/html:rw
    23. - ./logs/php:/var/log/php:rw
    24. depends_on:
    25. - nginx
    26. networks:
    27. - lnmp-networks
    28. mysql:
    29. build: kernel/mysql-8.0.26
    30. container_name: mysql
    31. tty: true
    32. restart: always
    33. ports:
    34. - "3306:3306"
    35. volumes:
    36. - ./databases/mysql/store:/var/lib/mysql:rw
    37. - ./logs/mysql:/var/log/mysql:rw
    38. - ./databases/mysql/backup:/data/mysqlback:rw
    39. - ./config/mysql/my.cnf:/etc/mysql/my.cnf:ro
    40. environment:
    41. MYSQL_ROOT_PASSWORD: 123456
    42. networks:
    43. - lnmp-networks
    44. networks:
    45. lnmp-networks:

    注意: docker-compose.yml 是docker官方约定俗成默认的文件名。当在某个拥有此文件的目录下运行 docker-compose up -d 命令时,它会在当前目录寻找此文件。

    踩的坑:docker-compose.yml 文件中的 volumes 配置项中的路径,一定要基于你当前整个项目目录绝对路径,
    笔者就是因为这个原因构建了很多次镜像,都发现映射的目录里根本没有宿主机里的文件,最后发现目录被映射到 / 目录(因为笔者是在 wsl2 运行的 docker)所以这是一个巨坑。整个目录一开始就用思维图画出来了。

    还要注意,php和nginx一定要相连结。这样才能相互协调工作 ,注意这句代码:

    1. depends_on:
    2. - nginx

    关于如何运行:
    如果上面的工作你已完成,跟着进入到目录的docker-compose/docker/bin/ ,执行以下命令:

    1. docker-compose up -d

    这句命令的意思是:构建完容器后,在后台运行,而不继续在终端显示。构建完之后,打开docker,就会看到构建好的容器及镜像:

    容器:
    image.png

    镜像:
    image.png

    打开你的浏览器,访问 WSL2 IP ,则会出现我预先映射到容器 /var/www/htmlindex.php 文件
    image.png

    写在最后:
    笔者使用的是 windows 11 操作系统,安装的是 Docker Desktop for Windows ,而 Docker 则是在子系统 WSL2 中运行的。所以使用的也是 WSL2 的架构,关于 WSL2 的配置方法,这里请参考我之前写下的笔记:

    WSL2三部曲(下)
    此内容主要是针对 WSL2 IP 不固定的问题。其它配置问题,请参阅我之前记录的一些笔记。关于更多的 Dockerfile优化请参阅 谷歌或百度。

    附上项目 github 地址:

    1. https://github.com/dt112/docker-lnmp

    关于 Laravel 连接数据库,配置参数请设定为:DB_HOST = mysql,因为连接的是容器,非 ip 地址