前言
前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build
、docker run
等命令操作容器。
然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知
使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具
安装 Docker Compose
安装
1 | apt install docker.io |
查看版本
1 | docker --version |
设置Docker镜像
针对Docker客户端版本大于 1.10.0 的用户
创建或修改 /etc/docker/daemon.json
文件
1 | vi /etc/docker/daemon.json |
添加或修改
1 | { |
重启Docker
1 | systemctl daemon-reload |
查找可用的Java8镜像
1 | docker search java8 |
拉取镜像
1 | docker pull williamyeh/java8 |
部署Jar服务
假如我们的项目是helloworld-0.0.1-SNAPSHOT.jar
,对应端口是8080
把服务的jar放到 /root/helloworld/
目录下
在 jar 包所在路径创建 Dockerfile
文件,添加以下内容
1 | FROM williamyeh/java8 |
测试下 Dockerfile
文件是否可用
1 | docker build -t psvmc/helloworld /root/helloworld/ |
在 jar 包所在路径创建文件 docker-compose.yml
,添加以下内容
1 | version: '2' |
注意
hello-world
是指定服务名称
build
指定 Dockerfile 所在文件夹路径
在 docker-compose.yml
所在路径下执行该命令 Compose 就会自动构建镜像并使用镜像启动容器
1 | docker-compose -f docker-compose.yml up -d hello-world |
这样服务就可以访问了
网络
官方文档:https://docs.docker.com/compose/networking/
查看网络
查看网络列表
1 | docker network ls |
上面的示例中没有设置网络,就会产生
NETWORK ID NAME DRIVER SCOPE
a327e58d7a47 helloworld_default bridge local
也就是说它会根据文件所在文件夹的名称_default
作为网络名
查看指定的网络设置
1 | docker network inspect helloworld_default |
注意这里的helloworld_default
可以传网络的ID或者是网络的名称
从返回的信息中我们可以看到容器内的网络
网络互通
上面的例子中我们的服务是单独的,但是实际上我们的服务之间需要互相能访问,比如我们的接口和数据库,这样该如何设置呢?
在 /root/nettest
下创建 docker-compose.yml
1 | version: '2' |
启动
1 | docker-compose -f docker-compose.yml up -d |
这样就可以访问
http://www.psvmc.cn:6061
http://www.psvmc.cn:6062
http://www.psvmc.cn:6063
执行
1 | docker network ls |
我们可以看到
NETWORK ID NAME DRIVER SCOPE
423fc9d510c3 nettest_dev bridge local
a2c26563c23e nettest_pro bridge local
其实上面的本质上相当于创建了对应的网络
1 | docker network create nettest_dev |
或者
1 | docker network create --driver=bridge --subnet=172.25.0.1/16 --gateway=172.25.0.1 mynet |
查看指定的网络设置
1 | docker network inspect nettest_dev |
可以看到
和
可以看出
web1和web2在一个内网中
web2和web3在一个内网中
复用之前的网络
在 /root/nettest2
下创建 docker-compose.yml
1 | version: '2' |
启动
1 | cd /root/nettest2 |
这时再查看网络
1 | docker network inspect nettest_dev |
如下图
会发现web1
、web2
、web4
已经在同一个网段下了。
links
示例
1 | version: "3" |
这样我们就可以在web的服务中用db
和database
就可以访问到数据库了
也就是说在web容器中可以用类似于mysql://db:3306
或者 mysql://database:3306
来代替之前的mysql://{DOCKER_IP}:3306
来访问数据库
depends_on
当使用 depends_on
来定义服务之间的依赖关系时会造成下面的影响2
docker-compose up
会依据依赖顺序启动服务docker-compose up
启动时 SERVICE 会自动包括 SERVICE 的依赖
看这个例子:
1 | version: '2' |
这个例子中 db ,redis 容器启动顺序要优先于 web 容器;当启动 web 容器时会自动创建 redis 和 db 容器。
不过需要注意的是, depends_on
不会等到 db 和 redis 容器 ready
再启动,web 容器仅仅等到 redis 和 db 容器启动就开始启动。
使用aliases代替link
还是上面的例子
1 | version: '2' |
web
依赖于db
这样我们就可以在web的服务中用database
就可以访问到数据库了
也就是说在web容器中可以用类似于 mysql://database:3306
来代替之前的mysql://{DOCKER_IP}:3306
来访问数据库.
在网络dev
中可以用类似于 mysql://database:3306
来访问
在网络pro
中可以用类似于 mysql://mydb:3306
来访问
必要条件
- 两者有依赖关系
- 在同一个网段下
- 被依赖的例如db设置网络的别名
常见命令
ps:列出所有运行容器
1 | docker-compose ps |
logs:查看服务日志输出
1 | docker-compose logs |
port:打印绑定的公共端口,下面命令可以输出 web1 服务 8761 端口所绑定的公共端口
1 | docker-compose port web1 8761 |
build:构建或者重新构建服务
1 | docker-compose build |
start:启动指定服务已存在的容器
1 | docker-compose start web1 |
stop:停止已运行的服务的容器
1 | docker-compose stop web1 |
注意
这里的web1是服务名,不是容器名
rm:删除指定服务的容器
1 | docker-compose rm web1 |
up:构建、启动容器
1 | docker-compose up |
更新容器
当服务的配置发生更改时,可使用 docker-compose up 命令更新配置
此时,Compose 会删除旧容器并创建新容器,新容器会以不同的 IP 地址加入网络,名称保持不变,任何指向旧容起的连接都会被关闭,重新找到新容器并连接上去
kill:通过发送 SIGKILL 信号来停止指定服务的容器
1 | docker-compose kill web1 |
pull:下载服务镜像
scale:设置指定服务运气容器的个数,以 service=num 形式指定
在 /root/nettest2
下创建 docker-compose.yml
1 | version: '2' |
然后执行
1 | docker-compose up --scale web1=3 -d |
和之前的配置不一样的地方有
- 端口设置只设置内部端口,外部端口自动分配
- 不能设置
container_name
run:在一个服务上执行一个命令
1 | docker-compose run web4 bash |