Michael.W谈Docker 第六期-docker-compose的编写
1 docker-compose是啥?
docker-compose简单地理解就是一个docker的编排和管理的工具,可以定义和运行多容器的应用。docker-compose可以一条命令启动多个容器,从此告别使用shell脚本来启动容器 。一般当我在部署一个大的项目时,只要里面用到了docker容器,那么我就会写一个docker-compose来对其进行管理。
docker-compose 通过一个配置文件来管理多个Docker容器。在配置文件中,所有的容器通过services来定义。
这个docker-compose是用python写了,所以在安装docker-compose的时候就需要先安装python的支持。
2 docker-compose的安装
#安装python依赖工具
$ sudo apt-get install python-pip -y
#安装编排工具
$ sudo pip install docker-compose
#查看编排工具版本
$ docker-compose version
#查看docker-compose的相关命令帮助
$ docker-compose --help
输入docker-compise version出现上图表明安装成功。
注:如果是linux系统按照以上步骤安装是没问题的,但是mac用户会出问题。(我的系统是ubuntu18.4)
3 yaml文件格式(yml)
docker-compose的配置文件是yaml文件格式,也可以成为yml文件格式。
再次强调:yaml(yml)是文件格式,不是语言!
3.1 yaml(yml)文件的基本规则
- 对大小写敏感 ;
- 使用缩进表示层级关系 。这点跟python很像;
- 千万不要使用tab键来缩进,只能使用空格键;
- 对每行的缩进长度没有严格限制,只要元素在缩进上对齐就表示这些元素属于一个层级;
- #用来注释;
- 字符串可以用双引号、单引号或者不用引号。
注:
- 基本上这辈子你能接触到的90%的配置文件都是用#来做注释;
- 123456789123456,这个到底是字符串还是整形数字?如果特别长,超过了整形的最大限度即会被认作是字符串;
- 建议,字符串还是用双引号引起来最好。这样可以避免不必要的麻烦。
3.2 yaml(yml)中的数据结构
3.2.1 map - 散列表
使用冒号:
来表示键值对。同一缩进的所有键值对属于一个map。
# 例子
name:michael.w
age:18
sex:male
对应的json对象是:{“name”:“michael.w”, “age”:“huang”,“sex”:“male”}
3.2.2 list - 数组
使用连字符-
表示:
# 例子
- 1
- 2
- 3
- a
- b
- c
对应的json对象:[1,2,3,“a”,“b”,“c”]
3.2.3 scalar - 纯量
常用的纯量包括:字符串、布尔值、整数、浮点数等
# 字符串
"blockchain"
blockchain
#布尔值
true
# 整数
1
# 浮点数
1.1
# NULL,表示空,什么都没有
~
举几个例子:
websites:
YAML: yaml.org
Ruby: ruby-lang.org
Python: python.org
Perl: use.perl.org
# 整体是个map,一个键为websites,他对应的值是一个map。这个小map中包含四个键值对。
languages:
- Golang
- C++
- Solidity
- Nodejs
# 整体是个map,一个键为languages,他对应的值是一个list。这个小list中包含四个字符串。
-
- Kobe
- James
- McGrady
-
- Iverson
- Yao
- Jordan
# 整体是个list,里面的元素也是list。每个list里面分别包含三个字符串。
-
id: 1024
name: bitcoin
-
id: 2048
name: ethereum
# 整体是个list,里面的元素是map。每个map之中有两个键值对。
4 docker-compose的配置文件
一般一个标准的docker-compose配置文件应该包含三个部分
- version
- services
- networks
这三个部分是处于缩进层级的最顶级。
version表示版本。services表示你要开启的服务,即一个服务对应一个容器。networks是声明docker-compose开启的所有服务都存在于的网络。如果我这个docker-compose中的服务对应两个网络,那么这两个网络都必须在netwroks下被事先声明出来。
4.1 yaml(yml)中的一些常用关键字
Image
services:
web:
image: 镜像名/镜像ID
command
使用 command 可以覆盖容器启动后默认执行的命令。
command: mdkri /tmp
# 也可以写成Dockerfile中的shell格式
command: [mkdir,/tmp]
container_name
container_name: 容器启动之后的名字
depends_on
表明该服务依赖于其他什么服务,如果所依赖的服务写在该服务的下面,会先启动所依赖的服务。
services:
web:
image: ubuntu
depends_on:
- redis
redis:
image: redis
docker-compose会按照yaml(yml)文件从上到下的顺序执行。在启动一个服务的时候,会先查看yaml中该服务是否包含depend_on选项。如果有先启动depend_on中提及的服务。
environment
设置环境变量。同Dockerfile 中的 ENV 指令一样,会将变量一直保存在镜像和容器中。
environment:
RACK_ENV: development
SHOW: 'true'
一般,环境变量名要大写。
ports
ports:
# 3000为容器对外开放的端口,宿主机端口随机分配。
- "3000"
# 宿主机端口:容器端口
- "30000:80"
# 宿主机IP:宿主机端口:容器端口
- "127.0.0.1:8001:8001"
volumes
挂载数据卷
volumes:
# 按照绝对路径挂载
- /opt/bakcup:/tmp/backup
# 按照绝对路径挂载
- ./bakcup:/tmp/backup
# 指定容器对挂载文件操作的权限(ro为只读,rw为读写),默认为rw
- /opt/bakcup:/tmp/backup:ro
volumes_from
如果说volumes是产生数据卷容器,那么volumes_from就是去挂载数据卷容器。
volumes_from:
# 服务名(该服务对应的容器挂载可数据卷)
- service_name
# 以只读的方式挂载数据卷
- service_name:ro
extends
可以理解为该服务继承与另外一个服务。被继承的服务可以使在当前文件中,也可以是来自其他文件。该服务会享有被继承服务的环境变量等。
extends:
file: xxx.yml
service: sv1
该容器是xxx.yml文件sv1的拓展。
networks
该服务对应的容器处于那写网络
services:
service1:
#服务service1处于network1和network2两个网络中。
networks:
# 网络驱动默认为bridge
- network1
- network2
# network2网络还有个别名叫network2alias
aliases:
- network2alias
extra_hosts
增加主机名与其IP地址的映射, 最终被添加到hosts文件中。
extra_hosts:
# 主机名(域名):IP
- "host1:111.242.190.88"
- "host2:55.39.219.211"
只有在多机多节点的时候才用使用,单机多节点不需要。
插一嘴,关于网络的域名解析的步骤:
- 首先查询本地的hosts文件,看那里面是否存在你在浏览器输入的域名解析。ubuntu的hosts文件位置:/etc/hosts;
- 如果在hosts中没找到,接着去本地的dns缓存中查找;
- 如果在本地的dns缓存中也没找到,就连接到dns服务器上去查询。
4.2 一个例子学会通读yaml(yml)文件
我找了一个yaml文件解读一下大家就懂了:
# 固定写法,就是表名你这个docker-compose的版本
version: '2'
# 服务,其内部就是所有你要开启的服务(对应容器)
services:
# 服务1名称,自定义。一个服务对应一个容器
web:
# 这个web服务对应的容器是基于哪个基础镜像生成的
image: nginx:latest
# web服务对应容器的名字,自定义
container_name: web_con
# extends表示一个类似继承的关系。比如我这个web服务需要的一些环境变量跟xxx.yml(该文件中只有一个服务)中的环境变量一样。那么,我们就可以使得这个web服务extends于xxx.yml文件,此时web服务会用拥有xxx.yml中的服务所设置的所有环境变量等。
extends:
file: xxx.yml
# xxx.yml文件中的唯一拥有的服务名称,这个需要根据xxx.yml文件的服务名称进行填写
service: webapp
# 容器web_con启动之后, 默认执行的命令
command: /urs/local/nginx -g daemon off
# 容器web_con启动之后所处的网络
networks:
- network1
# 容器web_con的端口映射
ports:
# 宿主机端口:容器端口。
- "6789:8080"
# 注意:建议将端口的映射关系写成一个字符串,而不要用一个冒号与前后两个数字组成。因为用数字的话,在文件解析上有时候会出错!
# 主机名与IP的映射关系。一般在部署多机多节点网络会使用,单机多节点是不会使用的。
extra_hosts:
# 主机名(域名):IP
- "host1:111.242.190.88"
- "host2:55.39.219.211"
# extra_hosts中写的内容,计算机会自动将其写入系统的hosts文件中
# 服务2名称
sql:
image: mysql
# 挂载数据卷,与宿主机产生映射
volumes:
- /home/test:/root/workdir
ports:
- "9999:3306"
# 服务sql对应的容器处于两个网络,网络名分别为network1和network2
networks:
- network1
- network2
# 服务的依赖关系
depend_on:
- web
- redis
# 表示服务sql依赖于服务web和redis。所以在docker-compose执行yaml文件的时候,会先启动web和redis服务,然后再启动sql服务
redis:
image: redis
volumes:
- /home/go/redis.conf:/redis/redis.conf
ports:
- 8989:6379
networks:
- network1
# 对网络的声明,即该yaml配置文件中所有服务所涉及到的网络
networks:
# 网络名1
network1:
# 网络使用的驱动类型。默认为bridge
driver: bridge
# 网络名2
network2:
driver: bridge
# xxx.yml文件
version: '2'
services:
# 服务名
webapp:
# 环境变量(键值对)
environment:
# 环境变量名,自定义
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET: docker-compose
5 docker-compose命令
推荐将yaml的配置文件名设置成docker-compose.yaml或docker-compose.yml。如果你设置了其他的名字,那么在docker-compose的命令中需要加参数-f来指明该文件。
5.1 创建并启动容器
$ docker-compose up
# 参数 -d 表示启动的容器以守护进程的方式启动,此时看不到打印的信息。
$ docker-compose up -d
# 如果配置文件自定义为xxx.yaml
$ docker-compose -f xxx.yaml up
一般调试的时候选择不加-d的方式,可以进入容器进行操作。
5.2 关闭并删除容器
$ docker-compose down
# 如果配置文件自定义为xxx.yaml
$ docker-compose -f xxx.yaml down
该指令会关闭配置文件启动的容器,并删除容器、对应生成的网络和挂载的数据卷。
5.3 查看当前的容器
$ docker-compose ps
# 如果配置文件自定义为xxx.yaml
$ docker-compose -f xxx.yml ps
注意:这个命令只能查看由该配置文件创建并启动的容器,其他的容器是查看不到的。
5.4 服务的开启、关闭和删除
这三个指令使用的比较少,在这里我就提一下
# 启动配置文件里的某一个服务
$ docker-compose start 配置文件中的服务名
# 关闭配置文件里的某一个服务
$ docker-compose stop 配置文件中的服务名
# 删除配置文件里的某一服务对应的容器
$ docker-compose rm 配置文件中的服务名
注意:使用docker-compose rm
是必须保证该服务已经被关闭,否则无法删除成功。
ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
公众号名称:后现代泼痞浪漫主义奠基人