前言:
阅读以下知识,确保你已对 docker 有了初步的认识,并且了解基础的命令。
现在来想象这个场景:你是否每次在项目上线后,为搭建新环境和调试而感到烦恼?只有一个项目还好。但如果有N个这样的项目呢?那岂不是要搭建N次环境?浪费时间不说。而且不能保证每次都顺利的搭建环境,可以中途会遇到许多的问题。
这时候docker 运应而生,它将每个环境看作是一个容器,让其在容器里运行,不仅保证了像: mysql 、nginx 、php 之间能独立运行。同时也保证了它们之间是相互隔离的,并且可移植性强。
下面来看下整个 **Docker-compose** 目录结构:
.├── README.md├── config│ ├── mysql│ │ └── my.cnf│ ├── nginx│ │ └── conf.d│ │ ├── default.conf│ │ ├── docker.conf│ │ └── laravel.conf│ └── php├── database│ └── mysql│ ├── backup│ └── store├── docker-compose.yml├── kernel│ ├── mysql-8.0.26│ │ └── Dockerfile│ ├── nginx-1.21.3│ │ └── Dockerfile│ └── php-8.0.11│ └── Dockerfile├── logs│ ├── mysql│ ├── nginx│ └── php└── www└── index.php
DockerCompose 的方便之处在于,将布署过程写入到配置文件,只需运行一句 docker-compose up -d 命令,docker 就会根据配置文件来进行构建所需容器。非常方便!而配置文件则好比面向对象,像以前手动安装各种依赖就好比面向过程。有关 docker 的命令操作这里就不过多的赘述。下面贴出关于我自己编写的 dockerfile ,祝你撸码愉快~
**PHP** 的 **dockerfile**
FROM php:8.0.11-fpmLABEL df="df@dto.cc"# 更改容器时区ENV TZ=Asia/ShanghaiRUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list \&& apt-get clean \# 安装所需依赖&& apt-get update && apt-get install -y \autoconf \libxml2-dev \libsqlite3-dev \libcurl4-openssl-dev \libssl-dev \libonig-dev \zlib1g-dev \libpng-dev \libjpeg-dev \libbz2-dev \libxml2-dev \libxslt1-dev \libfreetype6-dev \libjpeg62-turbo-dev \libpng-dev \libzip-dev \unzip \m4 \gcc \make \git \# 配置 gd 库&& docker-php-ext-configure gd \--with-freetype --with-jpeg \&& docker-php-ext-install -j$(nproc) gd \# 安装并启用扩展&& docker-php-ext-install bcmath dba filter opcache gd shmop zip pdo_mysql \&& docker-php-ext-install exif pcntl bz2 intl gettext xsl pdo mysqli \&& pecl install xdebug redis xlswriter \&& docker-php-ext-enable xdebug redis xlswriter \&& curl -sS https://getcomposer.org/installer | php \&& mv composer.phar /usr/local/bin/composer \# 更改php时区&& printf '[PHP]\ndate.timezone = Asia/Shanghai\n' > /usr/local/etc/php/conf.d/tzone.ini \# 清理舞台&& rm -rf /var/lib/apt/lists/*EXPOSE 9000CMD ["php-fpm"]
注意:配置文件中的扩展是需要上面的依赖的。如果去掉某一项依赖库,在构建容器时会报错。dockerfile 的方便之处在于把平时手动配置的过程给整合了一下。尽量使用一个 RUN 命令。你如果想构建属于自己的 PHP 容器,尽量去看看 PHP 编译安装的过程。因为它和使用 apt 的方式截然不同。 php 官方镜像也提供了 docker-php-ext-install 来安装扩展 、php-ext-configure 配置扩展。而 php-ext-enable 主要针对于使用 pecl 命令安装的扩展来手动开启。如果是使用php-ext-install 方式安装的扩展。则不需要担心这个问题,它内部会自动帮助你开启这些扩展。
相对于 nginx 和 mysql 以及 redis , php 的dockerfile 足以让我在编写过程中踩了许多坑,因为使用官方镜像必须按照它的那套规则来安装。
以上 dockerfile 已安装了常用的 composer 、git。所以不需要在宿主机上额外再安装这些软件。
Nginx 的 **dockerfile**
FROM nginx:1.21.3LABEL df="df@dto.cc"ENV TZ=Asia/ShanghaiCMD ["nginx","-g","daemon off;"]
Mysql 的 **dockerfile**
FROM mysql:8.0.26LABEL df="df@dto.cc"ENV TZ=Asia/ShanghaiCMD ["mysqld"]
这里 nginx 和 mysql 均是使用官方最新镜像,并没有对它俩做过多的配置。只需要更改它内部的时区就行了。因为时区不一致,会导致很多麻烦。这里为了演示,就没有下载 redis ,因为笔者现在对 redis 还不是很熟悉。
**docker-compose.yml** 文件的内容
version: '3.1'services:nginx:build: kernel/nginx-1.21.3ports:- "80:80"restart: alwaystty: truecontainer_name: nginxvolumes:- ./www:/var/www/html:ro- ./logs/nginx:/var/log/nginx:rw- ./config/nginx/conf.d:/etc/nginx/conf.d:ronetworks:- lnmp-networksphp8:build: kernel/php-8.0.11tty: truerestart: alwayscontainer_name: php8volumes:- ./www:/var/www/html:rw- ./logs/php:/var/log/php:rwdepends_on:- nginxnetworks:- lnmp-networksmysql:build: kernel/mysql-8.0.26container_name: mysqltty: truerestart: alwaysports:- "3306:3306"volumes:- ./databases/mysql/store:/var/lib/mysql:rw- ./logs/mysql:/var/log/mysql:rw- ./databases/mysql/backup:/data/mysqlback:rw- ./config/mysql/my.cnf:/etc/mysql/my.cnf:roenvironment:MYSQL_ROOT_PASSWORD: 123456networks:- lnmp-networksnetworks:lnmp-networks:
注意: docker-compose.yml 是docker官方约定俗成默认的文件名。当在某个拥有此文件的目录下运行 docker-compose up -d 命令时,它会在当前目录寻找此文件。
踩的坑:docker-compose.yml 文件中的 volumes 配置项中的路径,一定要基于你当前整个项目目录绝对路径,
笔者就是因为这个原因构建了很多次镜像,都发现映射的目录里根本没有宿主机里的文件,最后发现目录被映射到 / 目录(因为笔者是在 wsl2 运行的 docker)所以这是一个巨坑。整个目录一开始就用思维图画出来了。
还要注意,php和nginx一定要相连结。这样才能相互协调工作 ,注意这句代码:
depends_on:- nginx
关于如何运行:
如果上面的工作你已完成,跟着进入到目录的docker-compose/docker/bin/ ,执行以下命令:
docker-compose up -d
这句命令的意思是:构建完容器后,在后台运行,而不继续在终端显示。构建完之后,打开docker,就会看到构建好的容器及镜像:
容器:
镜像:
打开你的浏览器,访问 WSL2 IP ,则会出现我预先映射到容器 /var/www/html 的 index.php 文件
写在最后:
笔者使用的是 windows 11 操作系统,安装的是 Docker Desktop for Windows ,而 Docker 则是在子系统 WSL2 中运行的。所以使用的也是 WSL2 的架构,关于 WSL2 的配置方法,这里请参考我之前写下的笔记:
WSL2三部曲(下)
此内容主要是针对 WSL2 IP 不固定的问题。其它配置问题,请参阅我之前记录的一些笔记。关于更多的 Dockerfile优化请参阅 谷歌或百度。
附上项目 github 地址:
https://github.com/dt112/docker-lnmp
关于 Laravel 连接数据库,配置参数请设定为:DB_HOST = mysql,因为连接的是容器,非 ip 地址
