前言
前面章节,我们学习了如何构建自己的镜像文件,如何保存自己的镜像文件。大多都是一个镜像启动。当一个系统需要多个子系统进行配合时,若每个子系统也就是镜像需要一个个手动启动和停止的话,那估计实施人员也会崩溃的,而且效率也很低,维护的量也就很大了。所以,本章节就来了解下,如何利用官方提供的
Compose
编排工具按一定的业务规则来合理的进行容器启停工作。
Compose介绍
Compose是一个用于定义和运行多个
Docker
容器的编排工具。可以一条命令启动多个容器。主要是解决了容器与容器之间如何管理编排的问题。
按官网的说明,使用Compose
基本上也就分成三步:
- 利用
Dockerfile
定义运行环境 - 使用
docker-compose.yml
定义组成应用的各服务 - 运行
docker-compose up
启动应用
题外话:我所理解的就是,其实就是个批量工具,如批处理命令一样。
Compose实现原理图:
Compose 中有两个重要的概念:
- 服务 (service) :一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目 (project) :由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。
一个项目可以由多个服务(容器)关联而成,Compose
面向项目进行管理,通过子命令对项目中的一组容器进行便捷地生命周期管理。
Compose
项目由 Python
编写,实现上调用了 Docker
服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API
,就可以在其上利用 Compose
来进行编排管理。
题外话:关于Docker API
会在下一章节进行详细说明。
Compose安装
本身
Compose
是一个独立的产品,所以需要独立安装的。
按官网的说明,Compose
可以在Mac
、Windows
、Linux
等操作系统,本章节主要讲解下关于Linux
的安装,其他操作系统可以查看官网的安装指南:https://docs.docker.com/compose/install/#install-compose
二进制文件直接安装
此安装方式简单,但可能会有网络连接问题。或者直接去
gitHub
上的资源列表下载到本地也可以的。笔者下载过程(11M左右)还是很顺利的,╰( ̄▽ ̄)╮
下载
1
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
授权
1
sudo chmod +x /usr/local/bin/docker-compose
查看版本验证是否成功
1
docker-compose --version
可看见控制台输出:1
docker-compose version 1.22.0, build f46880fe
说明已经安装成功了。当然大家可以选择不同的安装版本了,直接去github
上下载即可。
使用pip(Python包管理工具)安装
这种安装方式就是不会受限于网络,但安装比较麻烦。
1 | #安装pip |
命令补齐
命令补齐功能可以提高输入效率,所以需要安装命令补齐功能的,可以照着官网:https://docs.docker.com/compose/completion/#install-command-completion 说明了相应配置,这里就不进行阐述了。
Compose常用命令
在控制窗口,直接输入
docker-compose
可以看见,其命令的组成及命令的集合了。
1 | Define and run multi-container applications with Docker. |
这里简单说明下一些常用的:
build
构建或者重新构建服务。
kill
通过发送SIGKILL信号来强制停止服务容器。支持通过参数来指定发送的信号,如:docker-compose kill -s SIGINT
logs
查看服务的日志输出。
port
打印绑定的公共端口
ps
列出所有的容器或者指定的容器
pull
拉取镜像
rm
输出容器
run
在一个服务上执行一个命令。如docker-compose run ubuntu ping docker.com
将会启动一个 ubuntu 服务,执行 ping docker.com
命令。默认情况下,所有关联的服务将会自动被启动,除非这些服务已经在运行中。
该命令类似启动容器后运行指定的命令,相关卷、链接等等都将会按照期望创建。
两个不同点:
- 给定命令将会覆盖原有的自动运行命令;
- 不会自动创建端口,以避免冲突。
如果不希望自动启动关联的容器,可以使用 --no-deps
选项,例如1
$ docker-compose run --no-deps web python manage.py shell
将不会启动 web 容器所关联的其它容器。
start
启动一个已经存在的服务容器。
stop
停止一个已经运行的容器,但不删除它。
up
构建,(重新)创建,启动,链接一个服务相关的容器。链接的服务都将会启动,除非他们已经运行。
默认情况, docker-compose up
将会整合所有容器的输出,并且退出时,所有容器将会停止。如果使用 docker-compose up -d
,将会在后台启动并运行所有的容器。
默认情况,如果该服务的容器已经存在, docker-compose up
将会停止并尝试重新创建他们(保持使用 volumes-from
挂载的卷),以保证 docker-compose.yml
的修改生效。如果你不想容器被停止并重新创建,可以使用 docker-compose up --no-recreate
。如果需要的话,这样将会启动已经停止的容器。
pause
暂停容器服务
其他的命令,可直接通过帮助查询下。
docker-compose.yml模版文件常用命令
compose的默认模版文件为:docker-compose.yml
。和Dockerfile
一样,它也是有自己的语法命令的。其中定义的每个服务都必须通过image指令指定镜像或build指令(需要 Dockerfile)来自动构建。其它大部分指令都跟docker run中的类似。
如果使用build指令,在Dockerfile中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在docker-compose.yml中再次设置。
模版文件有多种写法,例如Version 1 file format
、Version 2 file format
、Version 2.1 file format
、Version 3 file format
等。其中,Version 1 file format
将逐步被被弃用;Version 2.x
及Version 3.x
基本兼容,是未来的趋势。
具体说明可查看:https://docs.docker.com/compose/compose-file/
各版本对应的支持的模版文件如下:
Compose file format | Docker Engine release |
---|---|
3.7 | 18.06.0+ |
3.6 | 18.02.0+ |
3.5 | 17.12.0+ |
3.4 | 17.09.0+ |
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
2.4 | 17.12.0+ |
2.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
image
指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose
将会尝试拉去这个镜像。
例如:
1 | image: frolvlad/alpine-glibc |
build
指定 Dockerfile
所在文件夹的路径。 Compose
将会利用它自动构建这个镜像,然后使用这个镜像。
1 | build: /opt/docker |
其中build还有一些小选项。1
2
3
4
5
6build:
context: ./webapp
dockerfile: Dockerfile-alternate
args:
- buildno=1
- user=someuser
context
上下文是docker build
中很重要的一个概念。构建镜像必须指定context
。context
是 docker build
命令的工作目录。默认情况下,如果不额外指定 Dockerfile
的话,会将Context
下的名为 Dockerfile
的文件作为 Dockerfile
。
dockerfile
选项是值得备选的dockerfile
。args
是一些提供的参数。
command
覆盖容器启动后默认执行的命令。
1 | command: bundle exec thin -p 3000 |
links
链接到其它服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS)
格式都可以。
1 | links: |
使用的别名将会自动在服务容器中的 /etc/hosts
里创建。例如:
1 | 172.17.2.186 db |
相应的环境变量也将被创建。
dns
配置 DNS 服务器。可以是一个值,也可以是一个列表。
1 | dns: 8.8.8.8 |
environment
设置环境变量。你可以使用数组或字典两种格式。
只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。
1 | environment: |
env_file
从文件中获取环境变量,可以为单独的文件路径或列表。
如果通过 docker-compose -f FILE
指定了模板文件,则 env_file
中路径会基于模板文件路径。
如果有变量名称与 environment
指令冲突,则以后者为准。
1 | env_file: .env |
环境变量文件中每一行必须符合格式,支持 #
开头的注释行。
1 | # common.env: Set Rails/Rack environment |
expose
暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数
1 | expose: |
volumes
卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER
) 或加上访问模式 (HOST:CONTAINER:ro
)。
1 | volumes: |
volumes_from
从另一个服务或容器挂载它的所有卷。
1 | volumes_from: |
其他相关命名了或者了解命令的其他配置项,可到官网查看,包括一些选项等,真的蛮多的。。
官网:https://docs.docker.com/compose/compose-file
Compose编排实践
讲了命令后,大家估计和我一样一头雾水,接下来,就以一个实际的启动例子,进行讲解下。这里启动两个先前章节编写过的
SpringBoot
项目,进行api调用进行举例说明。
0.编写docker-compose.yml
文件:
1 | # 表示该文件使用Version 3 文件格式 |
1.在docker-compose.yml
文件所在目录执行1
2# -d 说明是后台运行
docker-compose up -d
此时可以看见,启动成功了:1
2
3[root@izbp16chpwsnff41nrjtfhz java]# docker-compose up -d
Creating java_springboot-demo-1_1 ... done
Creating java_springboot-demo-2_1 ... done
利用ps
命令查看,说明已经启动成功了。1
2
3
4
5[root@izbp16chpwsnff41nrjtfhz java]# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------
java_springboot-demo-1_1 java -Djava.security.egd=f ... Up 0.0.0.0:1222->8080/tcp
java_springboot-demo-2_1 java -Djava.security.egd=f ... Up 0.0.0.0:1333->8080/tcp
或者查看下日志说出,可以看见SpringBoot
已经启动成功:
访问下服务,可以看见能正常输出了:
示例就简单的利用images
和ports
进行简单的运行了一个Comoose
示例,大家对于复杂的可以自己试着编写下,对于一个后端的我来说,这块用到的机会还是很少了,毕竟都是自己一个微服务,自己启停了。⊙﹏⊙‖∣
参考资料
官方的文档还是很齐全的,建议大家还是直接去官网查看相关资料。
- https://docs.docker.com/compose/install
- https://docs.docker.com/compose/reference/
- https://docs.docker.com/compose/compose-file
- https://www.hi-linux.com/posts/12554.html
总结
本章节主要介绍了关于
Compose
编排工具的使用。使用了编排工具后,提供了应用系统部署各个管理应用的便捷性。学习后,大家就可以根据自己的业务需求,业务系统进行合理的编排工作了。一般上还是利用在微服务的编排上,一般上一个应用系统可能存在这几十个微服务的,所以说合理的利用编排工具可以提供部署效率,同时也能减少出错遗漏的机率。
最后
鉴于作者也是个初学者,水平有限,若文中有错误或者遗漏之处,还望指出,共同进步!
老生常谈
- 个人QQ:
499452441
- 微信公众号:
lqdevOps
个人博客:http://blog.lqdev.cn