第一次听说docker可以一条指令部署一整套的运行环境的时候,心里是很好奇的,平时虽然用phpstudy或者lnmp也没多大的麻烦,但是开发中由于工作环境差异性,有时候在本地开发环境测试没问题的代码,到线上就莫名其妙的不行了。抱着好奇的心里决定一窥究竟。
跟学习一门新语言一样。先看一下什么是docker,工作原理是什么,运行要求等,开始整活,先搞个nginx,简单,几分钟ok。接下来就是nginx+php,花了点时间,每个docker容器,或者说是应用服务,都是一个独立的沙箱,通过特定的端口号互相作用,比如nginx的fastcgi_pass可以配置为127.0.0.1:9000(9000是php容器的端口号)来访问php-fpm。
docker-compose:一键执行搭建服务,非常方便,通过创建专有网络将一个个的nginx、php、mysql等等等都系统的管理起来,使用之前要准备好image字段所指明的镜像。
配合dockerfile:php、redis需要用到,例如php需要安装vim、(crul、mysqli等)扩展,需要先使用dockerfile来构建自定义预设镜像。上下文:实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
认知准备
1、运行:docker-compose up 或者docker-compose up -d,添加-d是后台运行不占用shell窗口,调试建议直接docker-compose up 能看到更多的错误信息。
2、docker-compose stop、docker-compose restart
3、mysql的配置文件my.cnf位于etc/mysql/my.cnf,值得注意的是mysql容器在没有启动时my.cnf是不存在的,所以在yml文件配置映射将会得到一个my.cnf的文件夹。volumes映射的时候应该 : - "`你的本地文件夹`:/etc/mysql"
4、端口的映射,对应所有容器来说只有一个端口有用,一般80:80类似这样就可以了,不建议搞特殊以免造成代码上不必要的麻烦。
5、对yml的修改,比如修改端口映射、文件夹映射,需要删掉容器重新执行docker-compose up,因为路径-容器上下文没有发生变更配置是不会刷新的
```
version: "2"
networks:#docker内核子局域网络注册
docker_composer_npmr_net:
services:
nginx: #服务名称,docker内核的互相识别
image: nginx:1.19.3 #镜像名:标签
restart: always
container_name: nginx #容器名称,docker ps -a显示的名称
volumes: #路径映射,物理地址:容器地址
- "/home/www/wwwroot/web:/www/home"
- "/home/www/docker-compose.d/nginx/nginx.conf:/etc/nginx/nginx.conf"
- "/home/www/docker-compose.d/nginx/conf.d:/etc/nginx/conf.d"
- "/home/www/docker-compose.d/nginx/logs:/var/log/nginx"
ports: #物理端口:容器端口
- "80:80"
depends_on: #依赖顺序性启动
- php
- mysql
- redis
networks:#绑定隶属子局域网
docker_composer_npmr_net:
aliases:#子局域网内别名,可有多个
- nginx1
- nginx2
php:
image: php:7.4.11-fpm
restart: always
ports:
- "9000:9000"
container_name: php
volumes:
- "/home/www/wwwroot/web:/www/home"
- "/home/www/docker-compose.d/php/php-fpm.d/www.conf:/opt/bitnami/php/etc/php-fpm.d/www.conf"
networks:
docker_composer_npmr_net:
aliases:
- php
mysql:
image: mysql:8.0.22
restart: always
container_name: mysql
volumes:
- "/home/www/docker-compose.d/mysql/conf:/etc/mysql/conf.d"
- "/home/www/docker-compose.d/mysql/logs:/logs"
- "/home/www/docker-compose.d/mysql/data:/var/lib/mysql"
ports:
- "3306:3306" #最好改成其他端口,避免黑客入侵
#command: -e MYSQL_ROOT_PASSWORD=123456
command: [
'--default-authentication-plugin=mysql_native_password',
'--character-set-server=utf8mb4', #设置数据库表的数据集
'--collation-server=utf8mb4_unicode_ci', #设置数据库表的数据集
]
environment:
MYSQL_ROOT_PASSWORD: "123456"
#MYSQL_USER: 'ylc'
#MYSQL_PASS: 'ylc123'
MYSQL_DATABASE: "wowonew"
networks:
docker_composer_npmr_net:
aliases:
- mysql
redis:
image: redis:6.0.8
restart: always
container_name: redis
volumes:
- "/home/www/docker-compose.d/redis/redis.conf:/etc/redis/redis.conf:rw"
- "/home/www/docker-compose.d/redis/data:/data:rw"
- "/home/www/docker-compose.d/redis/redis.log:/dev/null"
ports:
- "6379:6379" #最好改成其他端口,避免黑客入侵
command: redis-server /etc/redis/redis.conf --appendonly yes #数据持久化,启动的时候指定redis.conf。这边的redis.conf要是容器的地址
networks:
docker_composer_npmr_net:
aliases:
- resis
dockerfile:刚开始的时候有时候,测试要看一看容器里面的东西,发现直接执行vim .....,提示我“-bash:vim command not found”,想想也是,人家都把镜像往最小的做,怎么可能每个镜像都有一套linux的一套软件。于是就在容器里安装vim,但是每次重新生成容器后都要重新安装vim一次,实在是烦,其实主要的配置文件只需要通过映射目录volumes字段挂在出来就可以了,只是这引出了我的一些思考。
于是我发现了dockerfile,用户来在容器生成的时候执行相关的指令,我就想要把安装vim的shell指令写进去让执行而已,然后发现docker-compose.yml文件里有个build的字段用来指定dockerfile的。我就想每次只需要一条up就能安装各种各样的扩展,就很方便,可是光是在容器里安装一个vim都要花费五六分钟,每个容器安装一次半个钟都算少了。先实践一下,进入到安装了vim的容器确实是能使用vi了。但是也发现create完容器之后,仓库多了个$rootDir_$containerName命名的镜像,例如web_nginx($rootDir是我执行docker-compose up -d的目录,也就是根目录,$containerName是我的容器名称)。由此知道,docker-compose up -d的执行如果是指定了build:属性的时候会伴随一个自定义的镜像(根据dockerfile)生成。
然后当再次执行up的时候,重点来了,docker内核会根据镜像的上下文目录,一般是dockerfile所在的目录,来查看是否存在之前在该目录创建过的镜像,有则直接使用,无则创建(因为容器的上下文已经绑定在docker内核)。一般有两个方法创建镜像,1、docker build -t nginx:v3。2、在docker-compose.yml的build字段指定dockerfile的路径和context字段指定上下文路径,从而生成$rootDir_$containerName格式命名的镜像。也就是我用的方法。建议使用第一种,对强迫症来说可以舒服的控制一下镜像的命名。其实这么做对理解docker是很有意义的,直接拿别人的docker-compose来用,不如自己一个个推敲。还有一点,就是当存在以某个目录为上下文目录生成的镜像时,修改原有的dockerfile再执行up是不会生成新的镜像和容器的,up命令不负责镜像的更新。废话:好比dockerfile生成的镜像就是手动挡,上坡就降档高速就升档,完全使用compose.yml来代替dockerfile就是自动挡,加减档场景早已预设。
简而言之,较为合理的使用docker-compose搭建lnmpr有两个步骤,1、准备镜像,包括五花八门的自己定制的dockerfile生成的镜像。2、编写docker-compose.yml文件,并将各个挂载的目录、配置文件准备好。最后up。
文字多一点,可能无法准确表达遇到问题的解决方法,参考一下让大伙少走弯路。