假如有这样一个项目,在家开发需要搭建环境,在公司开发需要搭建环境,到测试需要搭建环境,到线上还需要搭建环境。而且搭建环境的时候,还要安装各种依赖,还可能出现,本地能用,测试不能用等各种情况。这个情况下,我们只需要在系统中装上Docker,写好Dockerfile,运行docker-compose.yml 就自动完成部署,保证了在各个平台上的一致性,岂不是既方便又高效。
搭建PHP环境,必需要启动的容器: nginx、php。当然,除了这些容器,还可能涉及到如:mysql、redis、Memcached 等相关扩展。
相比采用单容器部署(原生安装lnmp),多容器部署比较灵活,比如 在安装nginx的时候,出现了未知错误,而又不能解决,只能重装的时候,这时,我们只需要删除旧的ngxin容器,启动一个新nginx容器就行了,php等相关容器,不受任何影响。但是采用单容器部署,就相当于删除了整个环境,所有的东西都要重新安装部署。当然,单容器也好处,在保证正常运行的情况下,可以将此容器构建成一个新的镜像,每次使用的时候,只需要以此镜像启动一个容器就可以了。
关于本次搭建涉及的相关文件跳转:资源
关于docker的安装跳转:docker安装
关于docker的使用命令跳转:
拉取需求镜像
docker pull php:7.2-fpm
docker pull nginx
docker pull mysql:5.7
docker pull redis:3.2
#版本号可根据实际需求选择
通过redis镜像启动一个redis容器
docker run --name master-redis -p 6379:6379 -d redis:3.2
通过mysql镜像启动一个mysql容器
docker run --name master-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
# -e MYSQL_ROOT_PASSWORD 给mysql设置初始密码
通过php镜像启动一个php容器
docker run -d -p 9000:9000 --name master-php -v d:/dnmp/www:/var/www/html -v d:/dnmp/php:/usr/local/etc/php --link master-db:master-db --link master-redis:master-redis --privileged=true php:7.2-fpm
通过ngxin镜像启动一个nginx容器
docker run --name master-nginx -d -p 80:80 -v d:/dnmp/www:/usr/share/nginx/html -v d:/dnmp/nginx:/etc/nginx -v d:/dnmp/logs/nginx.logs:/var/log/nginx --link master-php:master-php --privileged=true nginx
参数说明:
# --name 容器别名,此名将用于建立容器之间的连接、ngxin配置、PHP代码中连接配置等,因此,一旦变更容器名,则使用该容器名的地方也必须更改。
# -v 启动PHP容器时,需映射容器内部某些路径 到 宿主机路径,保证文件同步。(挂载一个空文件夹是会覆盖容器中的内容,所以配置文件要事先准备好。这里要注意当前项目的路径,不要直接拷贝使用)。
# --link 使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,解除了容器之间通信对容器IP的依赖。
# --privileged=true 给容器特权,在挂载目录后容器可以访问目录以下的文件或者目录若修改了–name 容器名,需修改对应配置文件。
PHP扩展库安装
#进入master-php容器
docker exec -it master-php /bin/bash
#安装pdo_mysql扩展
docker-php-ext-install pdo pdo_mysql
#由于php源码中没有redis,则需要手动拉取redis包
#拉取redis扩展包
curl -L -o /tmp/redis.tar.gz https://github.com/phpredis/phpredis/archive/4.2.0.tar.gz
#解压包
tar zxvf /tmp/redis.tar.gz
#删除包
rm -r /tmp/redis.tar.gz
#创建执行目录
mkdir -p /usr/src/php/ext
#将解压后的redis扩展移到执行目录
mv phpredis-4.2.0 /usr/src/php/ext/redis
#安装redis
docker-php-ext-install redis
#退出容器
exit
#重启容器
docker restart master-php
docker-compose是编排容器的。
如,有一个php镜像,一个mysql镜像,一个nginx镜像。如果没有docker-compose,那么每次启动的时候,你需要敲各个容器的启动参数,环境变量,容器命名,指定不同容器的链接参数等等一系列的操作,相当繁琐。而用了docker-composer之后,你就可以把这些命令一次性写在docker-composer.yml文件中,以后每次启动这一整个环境(含3个容器)的时候,你只要敲一个docker-composer up命令就ok了。
1.编写docker-compose.yml文件
version: "2"
services:
master-db:
container_name: "master-db"
restart: always
ports:
- "3306:3306"
volumes:
- d:/dnmp/mysql/conf.d/:/etc/mysql/conf.d/
environment:
MYSQL_ROOT_PASSWORD: 123456
image: mysql:5.7
master-redis:
container_name: "master-redis"
restart: always
ports:
- "6379:6379"
volumes:
- d:/dnmp/redis:/data
image: redis:3.2
master-php:
container_name: "master-php"
restart: always
ports:
- "9000:9000"
volumes:
- d:/dnmp/www:/var/www/html
- d:/dnmp/php:/usr/local/etc/php
links:
- "master-db"
- "master-redis"
image: php:7.2-fpm
master-nginx:
container_name: "master-nginx"
restart: always
ports:
- "80:80"
links:
- "master-php"
volumes:
- d:/dnmp/www:/usr/share/nginx/html
- d:/dnmp/nginx:/etc/nginx
- d:/dnmp/logs/nginx.logs:/var/log/nginx
image: nginx:latest
#container_name 指定一个自定义容器名称,而不是生成的默认名称。
#restart: always 容器重新启动参数,always:容器总是重新启动
#ports: 暴露端口信息
#volumes: 卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro),挂载数据卷的默认权限是读写(rw),可以通过ro指定为只读
#environment: 添加环境变量
#MYSQL_ROOT_PASSWORD: 设置数据库默认密码
#image: 指定镜像
2.执行docker-compose.yml
进入docker-compose.yml文件目录,执行命令
docker-compose up -d
一键创建对应容器,但是PHP扩展还得手动安装
上面docker-compose实现一键式操作 但问题是PHP的扩展库还是得自己单独装
这里用Dockerfile来构建自定义容器镜像实现真正的一键完成
mysql/Dockerfile
FROM mysql:5.7
MAINTAINER qyh "qinyihao@2980.com"
# set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
redis/Dockerfile
FROM redis:4.2
MAINTAINER qyh "qinyihao@2980.com"
# set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
nginx/Dockerfile
FROM nginx
MAINTAINER qyh "qinyihao@2980.com"
# set timezome
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
php/Dockerfile
FROM php:7.2-fpm
MAINTAINER qyh "qinyihao@2980.com"
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install zip \
&& docker-php-ext-install pdo_mysql \
&& docker-php-ext-install opcache \
&& docker-php-ext-install mysqli
RUN pecl install redis && docker-php-ext-enable redis \
&& pecl install xdebug && docker-php-ext-enable xdebug
RUN echo "" >> /usr/local/etc/php/php.ini
RUN usermod -u 1000 www-data
docker-compose.yml
version: "2"
services:
master-db:
build: ./mysql
container_name: "master-db"
restart: always
ports:
- "3306:3306"
volumes:
- d:/dnmp/mysql/conf.d/:/etc/mysql/conf.d/
environment:
MYSQL_ROOT_PASSWORD: 123456
master-redis:
build: ./redis
container_name: "master-redis"
restart: always
ports:
- "6379:6379"
volumes:
- d:/dnmp/redis:/data
master-php:
build: ./php
container_name: "master-php"
restart: always
ports:
- "9000:9000"
volumes:
- d:/dnmp/www:/var/www/html
- d:/dnmp/php:/usr/local/etc/php
links:
- "master-db"
- "master-redis"
master-nginx:
build: ./nginx
container_name: "master-nginx"
restart: always
ports:
- "80:80"
links:
- "master-php"
volumes:
- d:/dnmp/www:/usr/share/nginx/html
- d:/dnmp/nginx:/etc/nginx
- d:/dnmp/logs/nginx.logs:/var/log/nginx
将docker-compose.yml文件放置和各Dockerfile目录同级下
进入该目录 并执行命令
docker-compose up -d
docker-compose.yml和前面不同的是,当采用Dockerfile创建时,不再需要指定官方镜像image:,而是直接build:./目录 来引用目录中配置好的Dockerfile来创建新的镜像。
注意:一旦创建,下次docker-compose会直接取已有镜像而不会build创建 若你修改了Dockerfile配置请记得删除之前镜像
如宿主机上需要用shell调度php执行脚本,可以执行下面命令
docker exec -it master /bin/bash -c '/usr/local/bin/php /var/www/html/blog/public/index.php