事情起因:临近期末,课程老师让使用docker-compose来搭建一个nginx+mysql+php+redis相互分离的环境,木的法子,上网看了几个案例和官方文档,总算是把环境搭建完成,让程序可以正常运行,话不多说,开始进入正题
(1)、事前准备
宿主机:Ubuntu18.04
项目目录结构
nginx:nginx的镜像文件和虚拟主机配置
php:php的镜像文件
mysql:mysql的镜像文件和挂载目录(data:一个完整的MySQL目录)
redis:redis的镜像文件
code:代码目录
确定虚拟机内网络畅通
(2)、开始搭建(这里我是将所有镜像文件和docker-compose.yaml文件全部给出,一次性编排完成环境搭建,建议是一步一步的来搭建环境,并在搭建过程中进行测试)
nginx:直接使用官方最新的nginx镜像
FROM nginx:latest
php:因为官方镜像缺少一些代码中所使用的扩展(pdo,redis等),所以需要在镜像中安装一些扩展
FROM php:7.2-fpm
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng12*-dev \
vim \
curl \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install mysqli \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install gd \
&&curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/3.1.3.tar.gz \
&& cd /tmp \
&& tar xfz /tmp/redis.tar.gz \
&& mkdir -p /usr/src/php/ext \
&& mv phpredis-3.1.3 /usr/src/php/ext/redis \
&& docker-php-ext-install redis \
这里在构建php镜像时建议分两次来构建,将安装redis扩展与安装其他扩展分开,可以方便测试,节省时间
redis:直接使用官方最新的redis镜像
FROM redis:latest
mysql:使用mysql:5.7的官方镜像
FROM mysql:5.7
编排文件docker-compose.yaml的编写
version: "2.2" #版本
services: #开启的容器服务
web: #服务名
image: nginx #使用镜像(先从本地查看,若没有则从仓库获取)
restart: always #是否启动容器是重启
ports: #映射端口号
- "80:80"
- "443:443"
volumes: #挂载文件 宿主机文件:容器文件
- /root/composeTest/code/redis:/var/www/html/test
- /root/composeTest/nginx/default.conf:/etc/nginx/conf.d/default.conf
networks: #网络
webnet:
ipv4_address: 172.21.0.1 #ip
environment: #环境配置
- TZ=Asia/Shanghai
php:
image: php-pdo-redis:7.2-fpm
ports:
- "9000:9000"
volumes:
- /root/composeTest/code/redis:/var/www/html/test
networks:
webnet:
ipv4_address: 172.21.0.2
redis:
image: redis
ports:
- "6379:6379"
networks:
webnet:
ipv4_address: 172.21.0.4
environment:
- TZ=Asia/Shanghai
mysql:
image: mysql:5.7
ports:
- "3306:3306"
volumes:
- /root/composeTest/mysql/data:/var/lib/mysql
networks:
webnet:
ipv4_address: 172.21.0.3
environment:
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=123456
networks:
webnet:
ipam:
config:
- subnet: 172.21.0.0/16 #网段 必须是未使用的网段
gateway: 172.21.250.250
在使用镜像构建容器有两种方法
#第一种
version: "2.2"
services:
web:
image: nginx
#第二种
version: "2.2"
services:
web:
build: . #Dockerfile文件所在目录
(3)、其他配置
nginx:default.conf
因为nginx和php-fpm不再同一台服务器上,因此需要添加php-fpm所在的位置
server {
listen 80;
index index.php index.html;
server_name _;
root /var/www/html/test;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000; #php-fpm的位置 php是服务名,代表着php-fpm所在服务器的ip
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
mysql:data是我的mysql数据库下面的所有文件和目录,就是将原来数据库挂载到容器中
(4)、注意事项
a、各个服务器内时间的统一
搭建的每个服务器内,时间要完成统一,可以与外界时间不同,但是服务器内的时间必须一致
b、构建php镜像时,要注意插件的位置
在构建php镜像的时候,我没有事先创建插件位置(mkdir -p /usr/src/php/ext)导致构建镜像的时候不断出错,浪费了好多时间,到这里再说一句,使用Dockerfile来构建镜像的时候,可以一步一步来构建,只要使用构建好的镜像来构建下一个镜像即可,建议大家在不确定配置是否完全正确的时候,这样来做,既可以排查错误又可以节省时间
c、代码的部署
首先注意,在nginx容器和php-fpm中,都必须有一份代码(nginx中可以只有静态文件,php-fpm中可以只有PHP文件),否则可能导致404文件找不到的错误
第二个就是权限问题,在linux下,运行程序的时候可能由于权限不足而导致程序运行失败
最后就是重写问题(rewrite),在使用框架来作为项目的mvc模板时,往往为了方便使用而在框架内定义并且使用路由,但是在nginx的默认配置下时无法识别这些自定义的路由的,所以需要nginx相应的配置,这里给出一个简单而实用的配置
server{
#其他配置省略
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
break;
}
}
配置之后,即可识别路由
d、在编排的时候出现版本错误时,可将version:"2.2"改为version:"2"
e、注意linux下面的大小写问题
(5)、编排
进入到docker-compose.yaml所在的目录,执行命令:
docker-compose up -d #编排镜像,启动后将其放入后台
到此,环境搭建已经完成