Docker-Compose简介
Compose是用于定义和运行多容器Docker应用程序的工具。通过Compose,可以使用YAML文件来配置应用程序的服务。然后使用一个命令,就可以从配置中创建并启动所有服务。Compose可在所有环境中工作:生产、模拟、开发、测试以及CI工作流。
使用Compose基本上是三步流程:
- 使用Dockerfile定义应用程序的环境,以便可以在任何地方复制它。
- 在docker-compose.yml中定义组成您的应用程序的服务,以便它们可以在隔离的环境中一起运行。
- 运行docker-compose up,然后Compose启动并运行整个应用程序。
Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
参考文档:
安装Compose
在CentOS7机器上,假设已经了Docker,参考Install Docker Compose安装Compose-Docker。如果没有安装Docker,那么参考Docker入门进行安装。
1、安装docker-compose 1.24.1 版本
1 | sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose |
2、添加执行权限
1 | sudo chmod +x /usr/local/bin/docker-compose |
3、验证安装
1 | docker-compose --version |
Hello World
1、创建测试目录
1 | mkdir composetest |
2、在项目目录中创建一个名为app.py的文件,内容为:
1 | import time |
在此示例中,redis是应用程序网络上的redis容器的主机名,使用默认端口6379。
3、创建requirements.txt文件,内容为:
1 | flask |
4、创建Dockerfile,内容为:
1 | FROM python:3.7-alpine |
该文件说明:
- 从Python 3.7镜像像开始构建镜像。
- 将工作目录设置为/code。
- 设置flask命令使用的环境变量。
- 安装gcc,以便诸如MarkupSafe和SQLAlchemy之类的Python包可以编译加速。
- 复制requirements.txt并安装Python依赖项。
- 复制当前目录中的所有文件到工作目录。
- 将容器的默认命令设置为flask run。
有关如何编写Dockerfile的更多信息,参考Docker用户指南和Dockerfile参考。
5、创建docker-compose.yml,内容为:
1 | version: '3' |
该Compose文件定义了两个服务:Web和Redis。
Web服务从Dockerfile构建镜像,启动后容器在5000端口提供服务,然后将容器端口5000绑定到主机端口15000。
6、使用Compose构建和运行应用
1 | docker-compose up |
7、测试应用
1 | curl http://127.0.0.1:15000 |
Hello World 2.0
1、编辑docker-compose.yml,挂载当前目录到/code
1 | version: '3' |
2、运行应用
1 | docker-compose up |
3、修改app.py
1 | import time |
4、测试应用
1 | curl http://127.0.0.1:15000 |
常用命令
创建/销毁容器
1 | # 创建并运行容器 |
启动/停止容器
1 | # 关闭容器但不删除容器 |
查看容器
1 | # 查看容器 |
volume说明
docker使用持久化存储的时候,有两种方式:
- bind mount方式:挂载宿主机的绝对路径(目录和文件都可以)到容器
- volume方式:挂载volume(本质是目录)到容器
使用bind mount方式,如果宿主文件夹是空的,不光容器内的文件不会被复制到宿主机器上,容器的内容还会被覆盖为空,对于一些容器内路径文件夹存放config文件的情况,宿主目录为空会导致容器内的对应目录被清空,造成启动错误的问题。
使用volume方式,容器内的文件会被保留在volume中(对应的_data文件夹)内部,也就是文件被复制到宿主机器上.
两种方式都可以使用-v(–volume)和–mount参数,但是,在创建bind mount的时候,使用–volume会自动创建宿主方的文件夹,而–mount不会,因此使用–mount映射不存在的目录,会报错。
docker-compose指定的时候,有一些区别:
- 使用bind mount的时候,宿主这边可以使用相对路径了(
./
),不需要显示指定($PWD
) - 可以在指定volume名称的同时创建volume,需要使用
volume:
的配置项
1 | services: |
参考文档:
expose和ports
参考文档:
expose
expose暴露的端口,可由连接到同一网络的其他服务访问,但不会在宿主机上发布。
例如:
1 | services: |
docker ps
结果如下:
1 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
ports
ports暴露的端口,可由连接到同一网络的其他服务访问,并在宿主机上发布。
例如:
1 | services: |
docker ps
结果如下:
1 | CONTAINER ID ... PORTS NAMES |
ports长语法:
1 | services: |
小结
这两种暴露方式,最大的区别在于是否在宿主机上暴露端口,是否对外部网络提供服务。
使用docker ps
查看容器时,根据PORTS
字段,我们也能判断出该容器是否在宿主机上暴露端口。
但是,个别情况下,虽然我们看到的是端口是3000/tcp
,但是依然可能在宿主机上暴露端口。可能是docker/docker-compose某个版本的bug,也可能是yaml文件中的version不匹配,也可能是其他什么原因。
这种情况下,只能找到docker-compose.yml,查看端口映射关系,然后查看宿主机端口开放情况。
Docker-Compose网络问题
docker-compose up
的时候,会自动创建一个网桥,占用一个网段,并且添加路由规则。
如果这个网段和现有网段发生了冲突,就会导致一些非预期的网络问题,比如主机突然访问不通了。
解决办法是指定网段,详情参考docker-compose up使用自定义的网段的两种方式
查看路由:
1 | ip route |
查看docker网段使用情况:
1 | docker network list |