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