docker-compose的核心概念就记住一句话:
Docker Compose是一个用于定义和运行多容器 Docker 的应用程序工具。
用大白话来解释就是如果不使用docker-compose的话,我们想在同一台服务器上部署多个应用时候,我们一般需要手动创建网络驱动(网络相关后面章节讲解),手动创建数据卷(数据卷相关后面),手动执行docker build xxxx . 手动执行docker run -d xxxxxx。需要运行多少个容器,我们就需要按这种顺序执行多少次相同的操作。单机部署可能还稍微好些,后面如果是集群部署,使用docker-compose更能突显它的价值。
下面我们罗列一下docker-compose的常见特性:
1、同一个服务器上部署多个容器时,只需要编写一个xxxx.yml文件,在该文档内定义需要部署的服务/容器即可。类似配置如下:
version: "3"
services:
myhelloworld:
image: myhelloworld
myredis:
image: redis:alpine
上面的配置包含了两个容器,分别是myehelloworld和myredis。
关于docker-compose笔者不会每一个配置项去讲解,下面笔者通过简单的例子来驱动学习。这里先给出官方配置项说明参考地址:
https://docs.docker.com/compose/compose-file/
2、不同服务器上部署多个容器时,在后面章节讲解Swarm时,再具体演示例子。
3、docker-compose会为当前docker-xxx.yml文件内的所有容器创建数据卷,绑定到宿主机,而不需要我们自己手工通过-v去一个一个去绑定到宿主机。关于数据管理这块我们后面有专门章节讲解。
4、docker-compose会为当前docker-xxx.yml文件内的所有容器创建一个网络驱动,把所有容器都关联到该网络驱动中,使文件内配置的所有容器都能够通过容器名称进行访问。例如上面的myhelloworld应用中可以直接通过myredis:6379方式访问redis服务。不需要我们手工创建网络驱动。关于网络驱动这块我们后面有专门章节讲解。
5、docker-compose会缓存我们创建容器的配置内容,当启动的容器没有做任何更改时,compose会直接使用之前创建的现有容器。
6、compose默认允许编写一个基础文件(docker-xxxx.yml)和多个不同环境的覆盖文件(docker-xxxx.envyml)进行覆盖。
这种方式使用场景如下:
同一个应用不同的环境,统一使用相同的镜像,不同环境单独配置不同配置。
同一个公司不同团队,统一使用相同的镜像,不同团队单独配置不同端口或其它配置。
我们来看一下下面不同环境配置不同端口的例子:
基础配置(docker-compose-myhelloworld.yml)如下:
version: "3"
services:
myhelloworld:
image: myhelloworld
myredis:
image: redis:alpine
开发环境覆盖配置(docker-compose-myhelloworld.dev .yml)如下:
version: "3"
services:
myhelloworld:
build:
context: .
dockerfile: Dockerfile_helloworld
ports:
- 8200:8100
volumes:
- /var/myhelloworld/logs:/opt/applications/helloworld/logs
myredis:
ports:
- 6379
生产环境覆盖配置如下:
version: "3"
services:
myhelloworld:
build:
context: .
dockerfile: Dockerfile_helloworld
ports:
- 8300:8100
volumes:
- /var/myhelloworld/logs:/opt/applications/helloworld/logs
myredis:
ports:
- 6379
注意,它们端口的区别开发环境为:8200。生产环境为8300。配置完了后我们执行命令:
docker-compose \
-f docker-compose-myhelloworld.yml \
-f docker-compose-myhelloworld.dev.yml up
此时我们访问浏览器端口为:
http://node1:8200/visitor
如果我们执行:
docker-compose \
-f docker-compose-myhelloworld.yml \
-f docker-compose-myhelloworld.prod.yml up
此时我们访问浏览器端口为:
http://node1:8300/visitor
需要注意的是:基础文件在docker-compose命名-f选项的第一个位置,覆盖文件在后面。
7、compose早期2.1之前版本还可以使用extends继承某个容器配置的基础上进行叠加配置。但Compose版本3.x不支持该关键字。
从上面简单演示的配置读者应该可以感觉这些配置都很熟悉,可以猜到每个配置的含义,有时候学会猜也是一种学习效率和学习能力。
我们开始使用compose之前,需要先安装compose,Docker Compose依赖Docker Engine,安装compose之前需要先安装engine。在这之前我们已经安装好了Docker Engine,所以不必再次安装。接下来我们直接安装Compose。
安装方式Compose如下:
1、在节点1上执行命令如下:
curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
如果你的网络不稳定,通过上面的命令下载失败,还可以使用下面方式:
浏览器访问:https://github.com/docker/compose/releases
比如笔者就下载了1.24.0版本的docker-compose-Linux-x86_64文件,然后上传到/usr/local/bin目录下,重命名为docker-compose
2、为二进制文件赋予可执行权限:
chmod +x /usr/local/bin/docker-compose
3、执行docker-compose --version 如果提示命令不存在请执行:
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
4、docker-compose --version出现:
docker-compose version 1.24.0, build 0aa59064
证明安装成功了。
另外也可以通过python安装工具pip进行安装,这个就不演示,都比较简单。
卸载比较简单,直接rm -rf /usr/loca/bin/docker-compose即可。
我们直接拿前面部署好的myhelloworld通过docker-compose方式部署,同时将组件myredis部署上去,使整个应用程序跑通。这种情况恰好演示的是同一台服务器部署多个应用。
没有明确说明的情况下,下面所有命令均在node1上执行,步骤如下:
1、cd到我们之前的构建目录
cd /usr/local/docker/build/myhelloworld/
2、查看我们目前目录下文件列表如下
3、在当前目录下创建文件docker-compose-myhelloworld.yml,内容如下:
version: "3"
services:
myhelloworld:
build:
context: .
dockerfile: Dockerfile_helloworld
image: myhelloworld
ports:
- 8100:8100
volumes:
- /var/myhelloworld/logs:/opt/applications/helloworld/logs
myredis:
image: redis:alpine
ports:
- 6379
这里我们有必要解释下version: "3"代表含义
Compose文件格式有多个版本 - 1,2,2.x和3.x。下面给出不同docker engine版本需要配套的文件格式列表如下:
4、启动
docker-compose -f docker-compose-myhelloworld.yml up -d
5、浏览器访问
http://node1:8100/visitor
可以看到返回结果如下:
可以看到,redis服务已经可以用了。还记得我们配置文件配置的redis主键名称是什么吗?大家可以回头再看下入门篇-快速开始那个章节,我们配置的是myredis。恰好匹配services下的myredis容器名称。也就是说现在容器之间可以通过名称进行通信。类似DNS。
6、查看compose默认为我们创建的网络驱动
docker network ls
7、查看compose默认为我们创建的数据卷
docker volume ls
8、下线服务
docker-compose -f docker-compose-myhelloworld.yml down
9、当您更改应用程序代码时,需要重新构建镜像并重新创建容器,例如:
docker-compose build myhelloworld
docker-compose -f docker-compose-myhelloworld.yml up --no-des -d myhelloworld
--no-deps标志可以防止Compose重新创建web依赖于的任何服务
10、最后给出一份功能配置较多的示例:
version: "3"
services:
redis:
image: redis:alpine
ports:
- "6379"
networks:
- frontend
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
db:
image: postgres:9.4
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
deploy:
placement:
constraints: [node.role == manager]
vote:
image: dockersamples/examplevotingapp_vote:before
ports:
- "5000:80"
networks:
- frontend
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
restart_policy:
condition: on-failure
result:
image: dockersamples/examplevotingapp_result:before
ports:
- "5001:80"
networks:
- backend
depends_on:
- db
deploy:
replicas: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 1
labels: [APP=VOTING]
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 3
window: 120s
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
frontend:
backend:
volumes:
db-data:
compose简单使用我们应该都没什么问题,主要是配置项的含义可能需要多看下官方文档,笔者这里推荐方法是快速浏览一遍官方文档,然后需要时再次翻阅官方文档进行配置。
https://docs.docker.com/compose/compose-file/