Compose介绍
Compose项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。Compose 是一个用户定义和运行多个容器的 Docker 应用程序。在 Compose 中你可以使用YAML文件来配置你的应用服务。然后,只需要一个简单的命令,就可以创建并启动你配置的所有服务。
在Docker镜像构成和定制介绍中,我们可以使用Dockerfile文件很方便定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project)。
docker-compose三大概念
docker-compose.yml示例
version: '3.3'
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
version指的是docker-compose的version,建议3以上版本, 详见docker-compose version
安装docker-compose
通过github安装
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
sudo chmod +x /usr/local/bin/docker-compose
通过pip安装
#安装依赖
yum -y install epel-release
#安装PIP
yum -y install python-pip
#升级PIP
pip install --upgrade pip
#安装docker-compose
pip install docker-compose
docker-compose命令
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
选项:
-f,–file FILE指定Compose模板文件,默认为docker-compose.yml,可以多次指定。
-p,–project-name NAME指定项目名称,默认将使用所在目录名称作为项目名。
-x-network-driver 使用Docker的可拔插网络后端特性(需要Docker 1.9+版本)
-x-network-driver DRIVER指定网络后端的驱动,默认为bridge(需要Docker 1.9+版本)
-verbose输出更多调试信息
-v,–version打印版本并退出
docker-compose up
启动容器、网络、卷等。docker-compose.yml为默认文件名,执行docker-compose up会默认寻找docker-compose.yml文件。
docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...]
选项:
-d 在后台运行服务容器
–no-color 不使用颜色来区分不同的服务的控制输出
–no-deps 不启动服务所链接的容器
–force-recreate 强制重新创建容器,不能与–no-recreate同时使用
–no-recreate 如果容器已经存在,则不重新创建,不能与–force-recreate同时使用
–no-build 不自动构建缺失的服务镜像
–build 在启动容器前构建服务镜像
–abort-on-container-exit 停止所有容器,如果任何一个容器被停止,不能与-d同时使用
-t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒)
–remove-orphans 删除服务中没有在compose文件中定义的容器
–scale SERVICE=NUM 设置服务运行容器的个数,将覆盖在compose中通过scale指定的参数
docker-compose down
停用移除所有容器以及网络相关
docker-compose down [options]
选项:
–rmi type,删除镜像,类型必须是:all,删除compose文件中定义的所有镜像;local,删除镜像名为空的镜像
-v, –volumes,删除已经在compose文件中定义的和匿名的附在容器上的数据卷
–remove-orphans,删除服务中没有在compose中定义的容器
docker-compose logs
查看服务容器的输出。
默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过–no-color来关闭颜色。
docker-compose logs [options] [SERVICE...]
docker-compose build
构建(重新构建)项目中的服务容器。
docker-compose build [options] [--build-arg key=val...] [SERVICE...]
选项:
–compress 通过gzip压缩构建上下环境
–force-rm 删除构建过程中的临时容器
–no-cache 构建镜像过程中不使用缓存
–pull 始终尝试通过拉取操作来获取更新版本的镜像
-m, –memory MEM为构建的容器设置内存大小
–build-arg key=val为服务设置build-time变量
服务容器一旦构建后,将会带上一个标记名。可以随时在项目目录下运行docker-compose build来重新构建服务
docker-compose pull
拉取服务依赖的镜像。
docker-compose pull [options] [SERVICE...]
拉取服务依赖的镜像。
选项包括:
–ignore-pull-failures,忽略拉取镜像过程中的错误
–parallel,多个镜像同时拉取
–quiet,拉取镜像过程中不打印进度信息
docker-compose restart
重启项目中的服务。
docker-compose restart [options] [SERVICE...]
选项:
-t, –timeout TIMEOUT,指定重启前停止容器的超时(默认为10秒)
docker-compose rm
删除所有(停止状态的)服务容器。推荐先执行docker-compose stop命令来停止容器。
docker-compose rm [options] [SERVICE...]
选项包括:
–f, –force,强制直接删除,包括非停止状态的容器
-v,删除容器所挂载的数据卷
docker-compose start
启动已经存在的服务容器。
docker-compose start [SERVICE...]
docker-compose run
在指定服务上执行一个命令。
docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
docker-compose scale
设置指定服务运行的容器个数。
docker-compose scale web=3 db=2
通过service=num的参数来设置数量
docker-compose pause
暂停一个服务容器
docker-compose pause [SERVICE...]
docker-compose kill
通过发送SIGKILL信号来强制停止服务容器。
docker-compose kill [options] [SERVICE...]
支持通过-s参数来指定发送的信号,例如通过如下指令发送SIGINT信号:
docker-compose kill -s SIGINT
dokcer-compose config
验证并查看compose文件配置。
docker-compose config [options]
选项:
–resolve-image-digests 将镜像标签标记为摘要
-q, –quiet 只验证配置,不输出。 当配置正确时,不输出任何内容,当文件配置错误,输出错误信息
–services 打印服务名,一行一个
–volumes 打印数据卷名,一行一个
docker-compose create
为服务创建容器。
docker-compose create [options] [SERVICE...]
选项:
–force-recreate:重新创建容器,即使配置和镜像没有改变,不兼容–no-recreate参数
–no-recreate:如果容器已经存在,不需要重新创建,不兼容–force-recreate参数
–no-build:不创建镜像,即使缺失
–build:创建容器前,生成镜像
docker-compose exec
在某个容器中执行命令
docker-compose exec [options] SERVICE COMMAND [ARGS...]
选项包括:
-d 分离模式,后台运行命令。
–privileged 获取特权。
–user USER 指定运行的用户。
-T 禁用分配TTY,默认docker-compose exec分配TTY。
–index=index,当一个服务拥有多个容器时,可通过该参数登陆到该服务下的任何服务。
例如:docker-compose exec –index=1 web /bin/bash ,web服务中包含多个容器
docker-compose port
显示某个容器端口所映射的公共端口。
docker-compose port [options] SERVICE PRIVATE_PORT
选项:
–protocol=proto,指定端口协议,TCP(默认值)或者UDP
–index=index,如果同意服务存在多个容器,指定命令对象容器的序号(默认为1)
docker-compose push
推送服务依的镜像。
docker-compose push [options] [SERVICE...]
选项包括:
–ignore-push-failures 忽略推送镜像过程中的错误
docker-compose version
打印版本信息。
docker-compose version
docker-compose.yml V3.x 指令详解
目前k8s已经一统江湖,未来不把关键字混淆,这里只对顶级的关键字做了解即可。
- version 定义了版本信息
- services 定义了服务的配置信息
- networks 定义了网络信息,提供给 services 中的 具体容器使用
- volumes 定义了卷信息,提供给 services 中的 具体容器使用
- services 的定义包含应用于为该服务启动的每个容器的配置,非常类似于将命令行的 docker container create。
- networks 的定义类似于命令行的 docker network create。
- volumes 的定义类似于命令行的 docker volume create。
关于顶级 services 配置参考
container_name
指定容器名称。默认将会使用 项目名称服务名称序号 这样的格式。
container_name: docker-web-container
注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。
labels
为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息。
labels:
com.startupteam.description: "webapp for a startup team"
com.startupteam.department: "devops department"
com.startupteam.release: "rc3 for v1.0"
bulid
指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。
类似于命令行的 docker build .
version: '3'
services:
webapp:
build: ./dir
你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径。
同时使用 dockerfile 指令指定 Dockerfile 文件名。
version: '3'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
image
指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。
image: ubuntu
image: orchardup/postgresql
image: a4bc65fd
如果同时指定了 image和 build,, image 不在具有单独使用它的意义,而是指定了目前要构建的镜像的名称。 也就是说 Compose 构建的镜像则使用 image 中指定的名字webapp:tag命名
build: ./dir
image: webapp:tag
command
使用 command 可以覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000
depends_on
解决容器的依赖、启动先后的问题。以下例子中会先启动 db、redis 再启动 web
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: mysql:5.7
注意:web 服务不会等待 redis 和 db 「完全启动」之后才启动。
environment
设置环境变量。你可以使用数组或字典两种格式。
只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据。
environment:
RACK_ENV: development
SESSION_SECRET:
environment:
- RACK_ENV=development
- SESSION_SECRET
如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括
y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF
expose
暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定容器内部的端口为参数
expose:
- "3000"
- "8000"
ports
暴露端口信息。
使用宿主端口:容器端口 (HOST:CONTAINER) 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"
注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。
extra_hosts
类似 Docker 中的 --add-host 参数,指定额外的 host 名称映射信息。
extra_hosts:
- "googledns:8.8.8.8"
- "dockerhub:52.1.157.61"
会在启动后的服务容器中 /etc/hosts 文件中添加如下两条条目。
8.8.8.8 googledns
52.1.157.61 dockerhub
networks
要加入的网络,使用顶级networks 定义下的条目。
services:
some-service:
networks:
- some-network
- other-network
networks:
some-network:
other-network:
alias
网络上此服务的别名(备用主机名)。同一网络上的其他容器可以使用服务名称或此别名连接到其中一个服务的容器。
由于aliases是网络范围的,因此相同的服务可以在不同的网络上具有不同的别名。
注意:网络范围的别名可以由多个容器共享,甚至可以由多个服务共享。如果是,则无法保证名称解析为的容器。
一般格式如下所示。
services:
some-service:
networks:
some-network:
aliases:
- alias1
- alias3
other-network:
aliases:
- alias2
healthcheck
通过命令检查容器是否健康运行。
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
动态扩容与负载均衡
web代码
from flask import Flask
from redis import Redis
import os
import socket
app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())
if __name__ == "__main__":
app.run(host="0.0.0.0", port=80, debug=True)
dockerfile
FROM python:2.7
LABEL maintaner="Peng Xiao xiaoquwl@gmail.com"
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 80
CMD [ "python", "app.py" ]
docker-compose.yml
version: "3"
services:
redis:
image: redis
web:
build:
context: .
dockerfile: Dockerfile
environment:
REDIS_HOST: redis
lb:
image: dockercloud/haproxy
links:
- web
ports:
- 8080:80
volumes:
- /var/run/docker.sock:/var/run/docker.sock
HAProxy是免费、极速且可靠的用于为TCP和基于HTTP应用程序提供高可用、负载均衡和代理服务的解决方案。
启动1个web服务
docker compose up -d
docker compose ps
把web服务扩容到3个
docker compose up --scale web=3 -d
docker-compose实战
一个多语言的微服务项目:
- Python webapp 让你在两种选择之间投票
- Redis queue 队列任务,收集新选票
- Java worker 异步任务,消费队列中的选票
- Postgres database 存储数据
- Node.js webapp 实时显示投票结果
相关代码:
https://github.com/ddkwing/road2testops.git 下 /c6/example-voting-app/
网友评论