Docker Compose是一个用来定义和运行复杂应用的 Docker工具。一个使用 Docker 容器的应用 通常由多个容器组成,使用 Docker Compose 则不再需要使用 shell 脚本来启动容器。
Compose通过一个配置文件来管理多个 Docker容器,在配置文件中,所有的容器通过 services 来定义,然后使用 docker-compose 脚本来启动、停止和重启应用,并管理应用中的服务以及所有依 赖服务的容器,非常适合组合使用多个容器进行开发的场景。
Compose使用的3个步骤如下:
Compose模板文件是一个定义服务、网络和数据卷的 YAML 文件。Compose模板文件默认路 径是当前目录下的 docker-compose.yml,可以使用.yml 或.yaml作为文件扩展名。Docker Compose标准模板文件应该包含 version 、services 、networks三大部分,最关键的是services和networks两个部分。docker-compose.yml 的配置示例如下:
#YAML 配置实例
version:·3'
services:
web:
build:
ports:
- “5000:5000”
volumes:
- .:/code
-1ogvolume01:/var/1og
links:
-redis
redis:
image:redis
volumes:
1oqvolume01:
运行以下命令以下载Docker Compose的当前稳定版本:
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.23.3/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
sudo chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
看出是否下载成功:
[root@docker ~]# ll $DOCKER_CONFIG/cli-plugins
总用量 58304
-rwxr-xr-x. 1 root root 59699273 12月 10 13:38 docker-compose
[root@docker ~]#
测试是否安装成功:
[root@docker ~]# docker-compose -v
Docker Compose version v2.23.3
[root@docker ~]#
默认的模板文件是 docker-compose.yml,其中定义的每个服务都必须通过image指令来指定镜 像,也可以通过build指令(需要Dockerfile)来自动构建。
指定为镜像名称或镜像ID。如果镜像不存在,Compose 将尝试从网络拉取该镜像,例如:
services:
web:
image:nginx
build
指定 Dockerfile 所在文件夹的路径:
build:
./dir
Compose 将会利用这个路径自动构建镜像,然后使用该镜像。
覆盖容器启动后默认执行的命令:
command:bundle exec thin -p 3000
链接到其他服务容器,使用服务名称(同时作为别名)或服务别名(SERVICE:ALIAS) 都可以:
links:
-db
-db:database
-redis
注意: 使用别名时会自动在服务器中的/etc/hosts里创建,比如172.17.2.186 db, 相应的环 境变量也会被创建。
链接到 docker-compose.yml 外部的容器,甚至不是Compose管理的容器。参数格式和links
似。external_links 文件内容如下:
-redis_1
-project_db_1:mysql
-pr oject_db_2:sqlserver
ports 用于暴露端口信息。格式如下:
宿主机器端口:容器端口(HOST:CONTAINER)
或者仅仅指定容器的端口(宿主机将会随机分配端口)也可以:
ports:
- "3306" #指定容器端口
- "8080:80" #宿主机端口:容器端口
- "127.0.0.1:8090:8001"
注 意:当使用HOST:CONTAINER 格式来映射端口时,如果使用的容器端口小于60,则可 能会得到错误的结果,因为YAML 将会解析xx:yy这种数字格式为六十进制,所以建议采用字符串格式。
暴露端口,与posts 不同的是expose 只能暴露端口而不能映射到主机,只供外部服务连接使用;
仅可以指定内部端口为参数。
expose:
- "8000"
设置数据卷挂载的路径。格式为:
宿主机路径:容器路径(host:container)
还可以加上访问模式(host;container:ro), 其中ro 就是 readonly 的意思,表示只读模式。
volumes:
- /var/lib/mysql:/var/lib/mysql
- /configs/mysql:/etc/configs/:ro
挂载另一个服务或容器的所有数据卷。
volunes_from:
- services_name
- container_name
设置环境变量,可以是数组或字典两种格式。
如果只给定变量的名称,则会自动加载它在Compose主机上的值,可以用来防止泄露不必要的数据 。
environment:
- RACK_ENV=development
- SESSION_SECRET
从文件中获取环境变量,可以为单独的文件路径或列表。如果通过docker-compose-f FILE指定了模板文件,则env_file中路径会基于模板文件路径。如果有变量名称与 environment 指令冲突,以后者为准。
env_file:.env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
环境变量文件中每一行都必须有注释,支持#开头的注释行:
#common.env:Set Rails/Rack environment
RACK_ENV=development
基于已有的服务进行服务扩展。比如,已经有了一个webapp服务,模板文件为common.yml:
#common.yml
webapp:
build: ./webapp
environment:
- DEBUG=false
- SEND_EMAILS=false
编写一个新的 development.yml文件,使用common.yml 中的webapp 服务进行扩展。
development.yml 文件内容如下:
web:
extends:
file: common.yml
service:
webapp:
ports:
- "8080:80"
links:
- db
envelopment:
- DEBUG=true
db:
image: mysql:5.7
后者会自动继承 common.yml 中 的webapp 服务及相关的环境变量。
设置网络模式,使用和docker client 命令的–net 参数一样的值。
#容器默认链接的网络,是所有 Docker 安装时都默认安装的docker0 网络
net:"bridge"
#容器定制的网格栈
net:"none"
#使用另一个容器的网络配置
net:"container:[name or id]"
#在宿主机网络栈上添加一个容器,容器中的网络配置会与宿主机的一样
net:"host"
Docker 会为每个节点自动创建三个网络:
● bridge:容器默认连接的网络,是所有Docker安装时都默认安装的docker0网 络 。
● none:容器定制的网络栈。
● host:在宿主机网络栈上添加一个容器,容器中的网络配置会与宿主机的一样。
和宿主机系统共享进程命名空间,打开该选项的容器可以通过进程id 来相互访问和操作。
pid: "host"
配置 DNS 服务器,可以是一个值,也可以是一个列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 114.114.114.114
添加或放弃容器的Linux 能力(Capability)。
cap_add:
- ALL
cap_drop:
- NET_ADMIN
- SYS_ADMIN
配置 DNS 搜索域,可以是一个值也可以是一个列表。
dns_search: example.com
dns_search:
- domain1.example,com
\ - domain2.example.com
working_dir,entrypoint,user,hostname,domainname,mem_limit,privileged,restart,stdin_open,tty,cpu_shares
这些都和 docker run命令支持的选项类似。
cpu_shares: 73
working_dir: /code
entrypoint: /code/entrypoint,sh
user: postgresql
hostname: foo
domainname: foo.com
mem_limit:1000000000
privileged: true
stdin_open: true
tty: true
健康检查,这是非常有必要的,等服务准备好以后再上线,避免更新过程中出现短暂的无法访 问的问题。
healthcheck:
test: ["CMD","curl","-f","http://localhost/alive"]
interval: 5s
timeout: 3s
其实大多数情况下健康检查的规则都会写在 Dockerfile 中:
FROM nginx
RUN apt-get update 6k apt-get install -y curl sk rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/alive || exit 1
依赖的服务,优先启动,示例如下:
depends_on:
- redis
都在这个节点下部署相关的配置,示例如下:
deploy:
mode: replicated
replicas: 2
restart_policy:
condition: on-failure
max_attempts: 3
update_config:
delay: 5s
order: start-first #默认为 stop-first,推荐设置先启动新服务再终止旧的
resources:
limits:
cpus: "0.50"
memory: 1g
deploy:
mode: global # 不推荐全局模式(仅个人意见)
placement:
constraints: [node.role == manager]
若非特殊服务,以上各节点的配置就能够满足大部分部署场景了。
version: '3.5'
services:
nacos1:
restart: always
image: nacos/nacos-server:$(NACOS_VERSION)
container_name: nacos1
privileged: true
ports:
- "8001:8001"
- "8011:9555"
deploy:
resources:
limits:
cpus: '0.50'
memory: 1024M
env_file:
- ./nacos.env
environment:
NACOS_SERVER_IP: $(NACOS_SERVER_IP_ 1)
NACOS_APPLICATION_PORT: 8001
NACOS_SERVERS: $(NACOS_SERVERS)
volumes:
- ./logs_01/:/home/nacos/logs/
- ./data_01/:/home/nacos/data/
- ./config/:/home/nacos/config/
networks:
- ha-network-overlay
nacos2:
restart: always
image: nacos/nacos-server:$(NACOS_VERSION)
container_name: nacos2
privileged: true
ports:
- "8002:8002"
- "8012:9555"
deploy:
resources:
limits:
cpus: '0.50'
memory: 1024M
env_file:
- ./nacos.env
environment:
NACOS_SERVER_IP: $(NACOS_SERVER_IP_2)
NACOS_APPLICATION_PORT: 8002
NACOS_SERVERS: $(NACOS_SERVERS)
volumes:
- ./1ogs_02/:/home/nacos/1ogs/
- ./data_02/:/home/nacos/data/
- ./config/:/home/nacos/config/
networks:
- ha-network-overlay
nacos3:
restart: always
image: nacos/nacos-server:$(NACOS_VERSION)
container_name: nacos3
privileged: true
ports:
- "8003:8003"
- "8012:9555"
deploy:
resources:
limits:
cpus: '0.50'
memory: 1024M
env_file:
- ./nacos.env
environment:
NACOS_SERVER_IP: $(NACOS_SERVER_IP_3)
NACOS_APPLICATION_PORT: 8003
NACOS_SERVERS: $(NACOS_SERVERS)
volumes:
- ./1ogs_03/:/home/nacos/1ogs/
- ./data_03/:/home/nacos/data/
- ./config/:/home/nacos/config/
networks:
ha-network-overlay:
external: true
使用 Compose 对 Docker 容器进行编排管理时,需要编写 docker-compose.yml文件,初次编写时容易遇到一些比较低级的问题,导致执行 docker-compose up 时出现解析 YAML 文件错误。
比较常见的原因是YAML对缩进的严格要求。YAML文件换行后的缩进不允许使用tab键字符, 只能使用空格,而空格的数量也有要求。经过实际测试,发现每一行增加一个空格用于缩进是正常的。
YAML是一种标记语言,它可以很直观地展示数据序列化格式,可读性高。YAML类似于XML数据描述语言,但语法比XML简单得多。YAML数据结构通过缩进来表示,连续的项目通过减号 来表示,键值对用英文冒号分隔,数组用方括号([])括起来hash用花括号({})括起来。
使用 YAML时需要注意以下事项:
命令格式为:
docker-compose [-f<arg?…] [options] [COMMAND] [ARGS…]
选项包括:
命令格式为:
docker-compose up [options][-scale SERVICE=NUM…][SERVICE…]
选项包括:
docker-compose up 启动所有服务。这个命令一定要记住,每次启动都要用到。
docker-compose up -d 在后台启动所有服务。-f 指定使用的Compose模板文件,默认为docker-compose.yml, 可以多次指定。
docker-compose -f docker-compose.yml up -d
命令格式为:
docker-compose ps [options][SERVICE…]
docker-compose ps 命令可以列出项目中目前的所有容器。
命令格式为:
docker-compose stop [options][SERVICE…]
选项包括:
命令格式为:
docker-compose -h
命令用于查看帮助。
用于停止和删除容器、网络、数据卷、镜像。
命令格式为:
docker-compose down [options]
选项包括:
命令格式为:
docker-compose logs [options][SERVICE…]
默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。可以通过–no-color
选项来关闭颜色。
选项包括:
用于构建(重新构建)项目中的服务容器。
命令格式为:
docker-compose build [options] [-build-arg key=val…] [SERVICE…]
选项包括:
服务容器一旦构建,就会带上一个标记名。可以随时在项目目录下运行 docker-compose build 来重新构建服务。
用于拉取服务依赖的镜像。
命令格式为:
docker-compose pull [options][SERVICE…]
选项包括:
用于重启项目中的服务。
命令格式为:
docker-compose restart [options][SERVICE…]
选项包括:
用于删除所有(停止状态的)服务容器。
命令格式为:
docker-compose rm [options][SERVICE…]
选项包括:
用于启动已经存在的服务容器。
命令格式为:
docker-compose start [SERVICE…]
用于在指定服务上执行一个命令。
命令格式为:
docker-compose run [options] [-v VOLUME…] [-p PORT…] [-e KEY=VAL…] [SERVICE] [COMMAND][ARGS…]
例如在指定容器上执行一个 ping 命令:
docker-compose run ubuntu ping www.baidu.com
用于删除所有(停止状态的)服务容器。
命令格式为:
docker compose scale [options] [SERVICE=NUM…]
通过 service=num的参数设置指定服务运行容器的个数,例如设置指定服务 web 、db 运行的容 器个数;
docker-compose scale web=3 db=2
选项包括:
提示:官方提示不推荐使用此命令。请使用带有-scale选项的up 命令。但需要注意,up 与-scale 选项一起使用时,与scale 命令有一些细微的差异,因为它包含了up 命令的行为。例如:
docker-compose up -scale web=2 db=3
用于暂停一个服务容器。
命令格式为:
docker-compose pause [SERVICE…]
用于通过发送 SIGKILL信号来强制停止服务容器。支持通过-s 参数来指定发送的信号,例如通 过如下指令发送SIGINT 信号:
docker-compose kill -s SIGINT
命令格式为:
docker-compose kill [options][SERVICE…]
用于验证并查看 Compose 文件配置。
命令格式为:
docker-compose config [options]
选项包括:
用于为服务创建容器。
命令格式为:
docker-compose create [options][SERVICE…]
选项包括:
命令格式为:
docker-compose exec [options]SERVICE COMMAND [ARGS…]
选项包括:
用于显示某个容器端口所映射的公共端口。
命令格式为:
docker-compose port [options] SERVICE PRIVATE PORT
选项包括:
用于推送服务依赖的镜像。
命令格式为:
docker-compose push [options][SERVICE…]
选项包括:
用于恢复处于暂停状态中的服务。
命令格式为:
docker-compose unpause [SERVICE…]
用于打印版本信息。
命令格式为:
docker-compose version
通过docker-compose命令构建一个在Docker中运行的基于Python Flask框架的Web应用。
Docker 镜像提供了Python或Redis, 不需要重复安装。
创建目录如下:
[root@docker ~]# mkdir -p composetest
[root@docker ~]# mkdir -p composetest/src
[root@docker ~]# mkdir -p composetest/docker
目录结构如下:
[root@docker ~]# tree composetest
composetest
├── docker
│ └── docker-compose.yml
├── Dockerfile
└── src
├── app.py
└── requirements.txt
2 directories, 4 files
[root@docker ~]#
在文件最下放添加
[root@docker ~]# vi composetest/src/app.py
[root@docker ~]# cat composetest/src/app.py
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis',port=6379)
@app.route('/')
def hello():
count= redis.incr('hits')
return 'Hello World!I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True)
[root@docker ~]#
[root@docker ~]# vi composetest/src/requirements.txt
[root@docker ~]# cat composetest/src/requirements.txt
flask
redis
[root@docker ~]#
上面已经介绍了示例项目的目录结构,现在可在 composetest/目录中创建 Dockerfile 文件:若不使用默认的 docker-compose.yml 文件名:S docker-compose -f server.yml up -d然后在浏览器中输入 http://0.0.0.0:5000/ 查看运行的应用程序。
[root@docker ~]# vi composetest/Dockerfile
[root@docker ~]# cat composetest/Dockerfile
FROM python:3.7
COPY src /opt/src
WORKDIR /opt/src
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
[root@docker ~]#
Dockerfile文件描述了如下信息:
在composetest/docker/目录下创建docker-compose.yml文件,并在里面定义服务,内容如下:
[root@docker ~]# vi composetest/docker/docker-compose.yml
[root@docker ~]# cat composetest/docker/docker-compose.yml
version: "3"
services:
web:
build: ../
ports:
- "5000:5000"
volumes:
- ../src:/opt/src
redis:
image: "redis:3.0.7"
[root@docker ~]#
该Compose文件定义了两个服务,即定义了web和redis两个容器。
在composetest/docker/目录下执行docker-compose.yml文件:
[root@docker docker]# docker-compose up
[+] Running 2/0
✔ Container docker-redis-1 Created 0.0s
✔ Container docker-web-1 Created 0.0s
Attaching to redis-1, web-1
redis-1 | 1:C 10 Dec 08:18:14.652 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-1 | _._
redis-1 | _.-``__ ''-._
redis-1 | _.-`` `. `_. ''-._ Redis 3.0.7 (00000000/0) 64 bit
redis-1 | .-`` .-```. ```\/ _.,_ ''-._
redis-1 | ( ' , .-` | `, ) Running in standalone mode
redis-1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis-1 | | `-._ `._ / _.-' | PID: 1
redis-1 | `-._ `-._ `-./ _.-' _.-'
redis-1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis-1 | | `-._`-._ _.-'_.-' | http://redis.io
redis-1 | `-._ `-._`-.__.-'_.-' _.-'
redis-1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis-1 | | `-._`-._ _.-'_.-' |
redis-1 | `-._ `-._`-.__.-'_.-' _.-'
redis-1 | `-._ `-.__.-' _.-'
redis-1 | `-._ _.-'
redis-1 | `-.__.-'
redis-1 |
redis-1 | 1:M 10 Dec 08:18:14.653 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis-1 | 1:M 10 Dec 08:18:14.653 # Server started, Redis version 3.0.7
redis-1 | 1:M 10 Dec 08:18:14.653 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis-1 | 1:M 10 Dec 08:18:14.653 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis-1 | 1:M 10 Dec 08:18:14.653 * DB loaded from disk: 0.000 seconds
redis-1 | 1:M 10 Dec 08:18:14.653 * The server is now ready to accept connections on port 6379
web-1 | * Serving Flask app 'app'
web-1 | * Debug mode: on
web-1 | WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
web-1 | * Running on all addresses (0.0.0.0)
web-1 | * Running on http://127.0.0.1:5000
web-1 | * Running on http://172.18.0.3:5000
web-1 | Press CTRL+C to quit
web-1 | * Restarting with stat
web-1 | * Debugger is active!
web-1 | * Debugger PIN: 692-582-753
web-1 | 192.168.40.1 - - [10/Dec/2023 08:18:18] "GET / HTTP/1.1" 200 -
web-1 | 192.168.40.1 - - [10/Dec/2023 08:18:18] "GET /favicon.ico HTTP/1.1" 404 -
web-1 | 192.168.40.1 - - [10/Dec/2023 08:18:22] "GET / HTTP/1.1" 200 -
若是要后台运行:s docker-compose up -d
若不使用默认的 docker-compose.yml 文件名:S docker-compose -f server.ym up -d
黄色部分是文件名
使用更新的 Compose 文件构建应用程序,运行以下命令:
docker-compose up -d
使用 docker-compose ps 来查看当前正在运行的内容:
[root@docker docker]# docker-compose up -d
[+] Running 2/2
✔ Container docker-redis-1 Started 0.0s
✔ Container docker-web-1 Started 0.0s
[root@docker docker]# docker-compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-redis-1 redis:3.0.7 "docker-entrypoint.s…" redis 8 minutes ago Up 6 seconds 6379/tcp
docker-web-1 docker-web "python app.py" web 8 minutes ago Up 6 seconds 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp
[root@docker docker]#
停止docker-compoer
[root@docker docker]# docker-compose down
[+] Running 3/3
✔ Container docker-redis-1 Removed 0.2s
✔ Container docker-web-1 Removed 0.3s
✔ Network docker_default Removed 0.2s
[root@docker docker]#