Docker Compose
- Docker Compose 以服务为单位, 将为每一个服务部署一个容器
- 默认以
应用名称-服务名称-数字 方式作为容器名称
- 默认以
应用名称_数据卷名 方式作为数据卷名称
- 默认以
应用名称_网络名 方式作为网络名称
Docker Compose 是定义和运行多容器 Docker 应用程序的工具, 运行部分命令时需要在 compose.yaml/docker-compose.yaml 文件所在目录中, 以 应用名称-服务名称-数字 编号为规则命名容器, 配置文件使用 yaml 语法, yaml 是一个可读性高,用来表达数据序列化的格式.
yaml 文件中不能使用 tab 缩进, 只能使用空格
1 2 3 4
| ${VAR:-default} 如果 变量名 对应的环境变量未设置或为空, 则使用 默认值, 否则使用环境变量的值 ${VAR-default} 仅当 变量名 对应的环境变量 完全未定义 时才用默认值(为空时不会替换) ${VAR:?error} 严格模式, 如果 变量名 对应的环境变量 未设置/为空, 则报错并显示错误信息 error ${VAR:+alternate} 反向逻辑, 如果 变量名 已设置且非空, 则使用 alternate 值
|
1 2 3 4
| docker compose -f -p -c --env-file .env.development up [service_name]
|
参数
--all-resources 引入所有的资源, 即使未被服务使用
-f, --file stringArray 指定配置文件
-p, --project-name string 指定项目名称
--project-directory string 指定项目工作目录
-c, --context 指定上下文环境名称
--env-file stringArray 指定环境变量配置文件
--parallel 设置并行
--compatibility 运行 compose 兼容模式
--profile 启用指定的服务, web 服务默认启动
1
| docker compose --profile db up -d
|
命令
attach 连接运行服务的标准输入输出
build 构建服务
commit 从服务容器创建一个新的镜像
- -a, --author 作者
- -m, --message string 提交信息
- -c, --change list 应用 Dockerfile 指令创建镜像
- --index int 指定如果有多个副本的服务的容器
- -p, --pause 提交过程中是否中断容器运行, 默认为 true
config 解析验证 compose.yaml 配置文件
--environment 打印环境变量的插值
--format string 格式化输出, 值可选 yaml(default) | json
--images 输出镜像名称
--hash 输出服务的配置 hash, 一个一行
--profiles 输出指定的服务名, 一个一行
-o, --output string 保存到指定文件中, 默认是标准输出流
-q, --quiet 仅验证配置项, 不输出任何信息
--services 输出服务名称
--volumes 输出数据卷名称
cp 在容器和本地文件系统之间拷贝文件
events 接收一个来自容器的真实的事件
export 导出容器文件系统为归档文件
images 列出创建容器的镜像
start 启动服务
restart 重启服务
wait 阻塞直到所有的服务容器停止
stop 停止服务
kill 强制停止容器
pause 暂停服务
unpasue 取消暂停服务
rm 移除已经停止的容器, 默认情况下附加到容器上的匿名数据卷不会被移除
- -f, --force 不询问确认操作直接移除
- -s, --stop 在移除之前停止容器
- -v, --volumes 移除所有附加到容器上的匿名数据卷
down 停止并移除容器, 网络
- --rmi string 移除服务使用的镜像
- -t, --timeout int 延迟关机的时长秒
- -v, --volumes 移除在 compose.yaml 中 volumes 顶层指令中声明的具名和匿名数据卷
logs 查看服务输出日志
- -f, --follow 监听日志输出
- --index int 指定哪个容器执行命令, 如果服务有多个副本时
- -n, --tail 输出容器日志的最后几行
- --since 显示指定时间开始的日志
- --until 显示截止到指定时间的日志
stats 查看容器资源的使用情况
ls 列出正在运行的 compose 项目
port 查看公共端口绑定信息
- --index int 指定如果有多个副本的服务的容器
- --protocol string 指定协议, tcp(default) | udp
ps 查看所有容器
- -a, --all 列出所有容器
- -f, --filter <FILTER_TYPE>=<VALUE> 根据指定条件过滤服务容器
- --format string 使用自定义模板格式化输出, table(default) | table TEMPLATE | json | TEMPLATE
- --services 显示服务名称
- --status stringArray 通过状态过滤服务, [paused | restarting | removing | running | dead | created | exited]
pull 拉取服务镜像
push 推送服务镜像
top 显示运行的进程信息
exec 在运行的容器中执行命令
- -d, --detach 后台运行命令
- -e, --env stringArray 设置环境变量
- --index int 指定哪个容器执行命令, 如果服务有多个副本时
- -T, --no-TTY 不分配伪 TTY, 默认每次执行命令时都分配 TTY
- -w, --workdir string 设置本次命令的工作目录
run 在服务上运行一次性命令
- --build 启动容器之前构建镜像
- -d, --detach
- -i, --interactive 交互式运行
- -e, --env stringArray 设置环境变量
- -l, --label stringArray 添加或覆盖 label
- -P, --service-ports 运行命令所有服务的端口都能映射到宿主机
- --name 给容器定义名字
- --pull 运行之前拉取镜像
- -p, --publish stringArray 发布容器的端口到宿主机
- --rm 当容器退出时自动移除
- -v, --volume stringArray 挂载数据卷
- -w, --workdir string 设置容器内的工作目录
scale 调整服务
version 查看版本信息
watch 监听文件系统更新时服务容器重构/重启的构建上下文
create 为服务创建容器
- --build 启动容器之前构建镜像
- --no-build 不构建镜像即使镜像不存在
- --force-recreate 即使配置项或镜像没有改变也要重新创建容器
- --no-recreate 如果容器存在则不创建新的容器
- --pull 创建之前拉取镜像
- --scale scale 调整服务实例数量, 并覆盖
compose.yaml 配置文件中的 scale 配置
up 创建服务并启动容器
-d, --detach 后台运行容器
--attach 连接服务的输出
--no-attach 不连接服务的输出
--build 启动容器之前构建镜像
--no-build 不构建镜像即使镜像不存在
--no-start 创建服务之后不启动它
--no-deps 不启动关联的服务
--pull 启动之前拉取镜像
--scale scale 调整服务实例数量, 覆盖 compose.yaml 配置文件中的 scale 配置
--no-log-prefix 打印日志时不适用前缀
--no-recreate 如果容器存在则不创建新的容器
-y 非交互式运行命令, 所有的提示都回答 yes
-t, --timeout int 延迟关闭容器
1 2 3 4
| [root@localhost ~]# docker compose up service_id
[root@localhost ~]# docker compose up --scale web=5 -d
|
配置文件
- 使用副本不能指定容器名称, Compose 自动使用 应用名称-服务名称-数字 形式命名容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
| version: 3.9 name: myapp services: web: annotations: com.example.foo: bar attach: false build: context: './web' dockerfile: Dockerfile command: ['bundle', 'exec', 'thin', '-p', '3000'] ports: - '5000:5000' - '0.0.0.0:80:80/tcp' - target: 80 host_ip: 127.0.0.1 published: 8080 protocol: tcp mode: host privileged: true read_only: true restart: always container_name: my-web env_file: .env environment: RACK_ENV: development SHOW: 'true' USER_INPUT: entrypoint: - php - -d - vendor/bin/phpunit external_links: - redis - database:mysql - database:postgresql extra_hosts: - 'somehost:162.242.195.82' - 'otherhost:50.31.209.229' volumes: - type: volume source: db-data target: /data read_only: true volume: nocopy: true subpath: sub tempfs: size: 1024 mode: 755 - type: bind source: /home/workspace target: /home/workVolume - /home/workspace:/var/workspace tmpfs: - /run - /tmp volumes_from: - service_name - service_name:ro - container:container_name - container:container_name:rw network_mode: "host|none|service:[service name]" networks: - my-web-network platform: linux/amd64 depends_on: db: condition: service_healthy restart: true redis: condition: service_healthy deploy: endpoint_mode: vip labels: com.example.description: 'This label will appear on the web server' mode: replicated replicas: 6 restart_policy: condition: on-failure delay: 5s max_attempts: 3 window: 120s rollback_config: update_config: parallelism: 2 delay: 10s order: stop-first dns: - 8.8.8.8 extends: file: common.yml labels: - 'com.example.description=Accounting webapp' develop: devices: dns: dns_opt: dns_search: healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 1m30s timeout: 10s retries: 3 start_period: 40s start_interval: 5s
redis: pull_policy: always never missing build image: redis cpuset: '0,2,4,6' build: context: redis dockerfile: /redis.Dockerfile volumes: - /home/workspace - db-data:/var/lib/redis networks: - my-web-network links: - db:mysql scale: 6 profiles: - 'db'
db: image: mysql ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: test MYSQL_USER: test MYSQL_PASSWORD: test123 volumes: - db-data:/var/lib/mysql networks: - my-web-network profiles: - 'debug'
volumes: db-data: data: name: 'my-app-data'
networks: front-tier: back-tier: backend: driver: custom-driver my-web-network: driver: bridge name: myapp-network attachable: true enable_ipv6: true external: true configs: http_config: file: ./httpd.conf secrets: server-certificate: file: ./server.cert token: environment: 'OAUTH_TOKEN'
|
volumes
使用路径方式挂载数据卷
使用卷名方式挂载数据卷, 需要在 一级配置项 中声明, compose 会自动创建以项目名为前缀的卷名, 如果不需要卷名前缀, 则使用 external: true 指定卷名, 但是需要手动创建该卷名
多实例 Web 应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| name: myapp service: nginx: image: nginx:latest port: - '80:80' volumes: - ./nginx.conf:/etc/nginx/nginx.conf depends_on: - web network: - webnet web: build: context: web dockerfile: ./my-web-app.Dockerfile deploy: replicas: 3 environment: - ENV=production network: - webnet networks: webnet: driver: bridge
|
nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| # nginx.conf http { upstream web_backend { server web:80; server web:80; server web:80; } server { listen 80; location / { proxy_pass http://web_backend;
proxy_set_header Host $host; proxy_set_header X-Reap-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } }
|
web 应用
1 2 3 4 5 6 7 8 9 10
| from flask import Flask
app = Flask(__name__)
@app.route('/') def hello_world(): return 'Hello, World!'
if __name__ == '__main__': app.run(host='0.0.0.0', port=80)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt
COPY . . EXPOSE 80 CMD ["python", "app.py"]
|
docker compose 数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| name: myapp services: redis: image: redis:7
ports: - '6379:6379' command: ['redis-server', '--appendonly yes', '--logfile /data/redis.log'] volumes: - /var/lib/redis:/data - /var/lib/redis/redis.conf:/usr/local/etc/redis/redis.conf networks: - my-app-network
mysql: image: mysql:latest container_name: mysql-container ports: - '3306:3306' environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: test MYSQL_USER: test MYSQL_PASSWORD: test123 volumes: - /var/lib/mysql:/var/lib/mysql networks: - my-app-network mongodb:
image: mongo:latest container_name: mongodb-container ports: - '27017:27017' environment: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: 123456 MONGODB_BIND_IP: 0.0.0.0 command: ['mongod', '--logpath', '/var/log/mongodb/mongod.log'] volumes: - /var/lib/mongodb:/data/db - /var/lib/mongodb/logs:/var/log/mongodb networks: - my-app-network
tmpfs: - /tmp
volumes: db-data: labels: - 'com.myapp.volumes.description=share data vaolume' networks: my-app-network: driver: bridge name: myapp-network attachable: true enable_ipv6: true
|