docker-compose使用
介绍
我们平时使用docker的时候,可以需要启动很多服务(容器),编写很多Dockerfile,例如 docker run mysql
, docker run redis
, docker run nginx
等等。
服务少了还好,手动一个一个启动就是了。但是服务一旦多了,并且服务之前还有依赖(比如启动微服务前先得启动网关吧,启动网关前先得启动nacos,nacos配置又在mysql,得先启动mysql。),就比较麻烦了。
那么docker-compose就是为此而生的。它是用于定义和运行多容器Docker应用程序的工具。以一个ocker-compose.yml文件来配置所有的服务。
docker-compose里的两个概念:
1 服务(service):一个应用容器实例,比如一个nginx实例,一个mysql实例。
2 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
不用compose例子
假设我们要启动容器mysql, redis, nacos, gateway.jar, biz.jar,需要依次执行
1 mysql容器
build mysql Dockerfile:
# 基础镜像
FROM mysql:5.7
# author
MAINTAINER tenny
# 执行sql脚本
ADD ./db/*.sql /docker-entrypoint-initdb.d/
启动mysql
docker run --name mysql -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/logs:/logs -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
2 redis容器
build redis Dockerfile:
# 基础镜像
FROM redis
# author
MAINTAINER tenny
# 挂载目录
VOLUME /home/redis
# 创建目录
RUN mkdir -p /home/redis
# 指定路径
WORKDIR /home/redis
# 复制conf文件到路径
COPY ./conf/redis.conf /home/redis/redis.conf
启动redis
docker run --name redis -p 6379:6379 -v /home/redis/conf/redis.conf:/home/redis/redis.conf -v /home/redis/data:/data -d redis:6.0.8 redis-server /home/redis/redis.conf
3 nacos容器
build nacos Dockerfile:
# 基础镜像
FROM nacos/nacos-server
# author
MAINTAINER tenny
# 复制conf文件到路径
COPY ./conf/application.properties /home/nacos/conf/application.properties
启动nacos
docker run --name nacos -p 8848:8848 -v /home/nacos/logs/:/home/nacos/logs -v /home/nacos/conf/application.properties:/home/nacos/conf/application.properties --env MODE=standalone -d nacos/nacos-server
4 gateway容器
build gateway Dockerfile:
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER tenny
# 挂载目录
VOLUME /home/gateway
# 创建目录
RUN mkdir -p /home/gateway
# 指定路径
WORKDIR /home/gateway
# 复制jar文件到路径
COPY ./jar/gateway.jar /home/gateway/gateway.jar
# 启动网关服务
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=stage","gateway.jar"]
启动gateway
docker run --name gateway -p 8080:8080 -v /home/gateway/jar:/home/gateway -d gateway
5 biz容器
build biz Dockerfile:
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER tenny
# 挂载目录
VOLUME /home/biz
# 创建目录
RUN mkdir -p /home/biz
# 指定路径
WORKDIR /home/biz
# 复制jar文件到路径
COPY ./biz/jar/microservice-biz.jar /home/biz/microservice-biz.jar
# 启动系统服务
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=stage","microservice-biz.jar"]
启动biz
docker run --name microservice-biz -p 8081:8081 -v /home/microservice/biz/jar:/home/biz -d biz
问题提出
其实容器不多,就这样一个一个编排启动也没什么。不过这里有几个值得改进的地方:
1 我们得执行很多次docker run
2 容器启动顺序是有要求的,比如要先启动mysql 才能启动nacos,先启动redis nacos才能启动gateway,先启动mysql redis nacos才能启动biz等等
3 容器宕机重启可能会导致ip变化,那么在nacos里的相关配置(例如mysql和redis的ip)可能就得改,当然可以把ip写死,但这样做不方便移植
接下来使用compose改进这三点。
使用compose例子
1 安装docker-compose
下载
curl -SL https://github.com/docker/compose/releases/download/v2.14.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
授权
chmod +x /usr/local/bin/docker-compose
测试
docker-compose --version
卸载:
rm /usr/local/bin/docker-compose
2 编写docker-compose.yml
创建文件夹DockerCompose, 编写docker-compose.yml文件:
version : '3.8'
services:
compose-mysql:
container_name: compose-mysql
image: mysql:5.7
build:
context: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'test'
MYSQL_ROOT_PASSWORD: 123456
networks:
- tenny-net
compose-redis:
container_name: compose-redis
image: redis
build:
context: ./redis
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/redis/redis.conf
compose-nacos:
container_name: compose-nacos
image: nacos/nacos-server
build:
context: ./nacos
environment:
- MODE=standalone
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
ports:
- "8848:8848"
depends_on:
- compose-mysql
networks:
- tenny-net
compose-gateway:
container_name: compose-gateway
build:
context: ./gateway
dockerfile: dockerfile
ports:
- "8080:8080"
volumes:
- ./gateway/jar:/home/gateway
depends_on:
- compose-redis
links:
- compose-redis
networks:
- tenny-net
compose-microservice-biz:
container_name: compose-microservice-biz
build:
context: ./microservice/biz/
dockerfile: dockerfile
ports:
- "8081:8081"
volumes:
- ./microservice/biz/jar:/home/biz
depends_on:
- compose-redis
- compose-mysql
links:
- compose-redis
- compose-mysql
networks:
- tenny-net
networks:
tenny-net:
name: tenny-net
driver: bridge
配置项说明:
-
version:描述Compose文件的版本信息,当前最新版本为3.8,对应的Docker版本为19.03.0+,可以去官网查看 https://docs.docker.com/compose/compose-file/compose-file-v3/
-
services:定义服务,可以多个,每个服务中定义了创建容器时所需的镜像、参数、依赖等
-
container_name: 容器名
-
image: 镜像名称标签,创建容器时所需的镜像名称标签或者镜像ID。如果镜像在本地不存在,会去远程拉取。
-
build: 构建容器, 基于指定的镜像或者基于Dockerfile文件构建。此例基于Dockerfile。
-
context: Dockerfile文件的绝对路径,或者相对路径(相对于docker-compose.yml文件所在目录),或者远程Git仓库的URL。
-
ports: 暴露端口。格式:左边宿主机端口:右边容器端口
-
volumes:数据卷,用于实现目录挂载
-
command:容器启动后默认执行命令
-
environment: 环境变量
-
networks: 所属网络。引用networks下的条目
-
depends_on: 容器依赖,启动时会先检查所依赖容器是否启动,若没有则先启动依赖容器,再启动本容器
-
links: 链接到其他容器中,这样通过容器名如compose-mysql就能访问到mysql容器。此例中不需要,因为已经设置同一网络。
-
networkds:定义网络,可以多个,根据DNS server让相同网络中的容器可以直接通过容器名称进行通信
DockerCompose目录结构
3 修改业务ip配置
修改nacos地址为容器名
spring:
config:
activate:
on-profile: stage
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: compose-nacos:8848
namespace: 9373d87d-6bbc-4f5c-a6f6-f928f9623281
config:
# 配置中心地址
server-addr: compose-nacos:8848
namespace: 9373d87d-6bbc-4f5c-a6f6-f928f9623281
修改mysql redis的ip为相应容器名
spring:
datasource:
url: jdbc:mysql://compose-mysql:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring:
redis:
host: compose-redis
4 启动容器
到docker-compose.yml所在目录执行
docker-compose up -d
该命令会启动docker-compose.yml配置里的所有容器。
ps: 后续如果更新了业务代码,只需要上传jar包到指定目录,执行docker-compose restart compose-microservice-biz
即可。
问题解决
这样,就解决了上面提到的三个改进问题:
1 只需执行一个命令就可以启动多个容器
2 容器之间依赖配置好后,不会再有启动顺序问题
3 容器之间通过容器名联系,不再固定ip。不用担心容器重启ip变换的问题,并且移植到另一台服务器也用修改ip。
常用命令
最后列出常用命令
pull 拉取镜像
docker-compose pull
只拉取某一个
docker-compose pull compose-mysql
up 启动容器
docker-compose up -d
只启动单个
docker-compose up compose-mysql -d
logs 查看日志
docker-compose logs
查看某一个容器日志并跟踪
docker-compose logs -f compose-gateway
exec 进入容器
docker-compose exec compose-redis bash
restart 重启容器
docker-compose restart
重启某一个
docker-compose restart compose-mysql
stop 停止容器
docker-compose stop
停止某一个
docker-compose stop compose-gateway
ps 列出容器
docker-compose ps
images 查看镜像
docker-compose images
rm 删除(停止状态)容器
docker-compose rm
down 停止并删除
docker-compose down
总结
首先提出多个docker容器的启停的重复性和可能存在的顺序问题,引出docker-compose。
然后举例说明单独启动多个docker容器的不便之处,再使用docker-compose改进这些问题,统一管理,一键部署,一键停止。
感谢阅读。