Docker Compose编排部署微服务项目

最近再弄波克城市的微服务项目。若按照以前一个个发布实在有点太麻烦,正好docker compose提供了项目编排部署功能,学习一下,以此记录。一下以130虚拟机为例。

往期文章:

  1. Dokcer简介与安装以及Springcloud部署
  2. Nginx部署前端VUE—docker-compose编排方式

1. Docker Compose介绍

使用微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例。如果每个微服务都要手动启停,那么效率之低、维护量之大可想而知。本节课将讨论如何使用 Docker Compose来轻松、高效地管理容器。为了简单起见将 Docker Compose简称为 Compose。
Compose 是一个用于定义和运行多容器的Docker应用的工具。使用Compose,你可以在一个配置文件(yaml格式)中配置你应用的服务,然后使用一个命令,即可创建并启动配置中引用的所有服务。

2. Docker Compose的安装

Compose的安装有多种方式,例如通过shell安装、通过pip安装、以及将compose作为容器安装等等。本文讲解通过shell安装的方式。其他安装方式如有兴趣,可以查看Docker的官方文档:

# docker compose安装步骤
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version

3. Docker Compose入门示例

Compose的使用非常简单,只需要编写一个docker-compose.yml,然后使用docker-compose 命令操作即可。docker-compose.yml描述了容器的配置,而docker-compose 命令描述了对容器的操作。我们首先通过一个示例快速入门:

上篇文章第九点 Dokcer简介与安装以及Springcloud部署
使用Dockerfile为项目microservice-eureka-server构建Docker镜像。以此为例

  • 我们在baoliewuqiu-eureka-server-8761.jar 所在目录的上一级目录,创建docker-compose.yml 文件。
    目录树结构如下:
    ├── docker-compose.yml
    └── eureka
    ├──── Dockerfile
    └──── baoliewuqiu-eureka-server-8761.jar

  • 然后在docker-compose.yml 中添加内容如下

version: '3'
services:
  eureka:             #指定服务名
    image: baoliewuqiu-eureka-server-8761:0.0.1  #指定镜像名称
    build: ./eureka   #指定Dockfile所在路径
    ports:
      - "8761:8761"   #指定端口映射
    expose:
      - 8761          #声明容器对外暴露的端口
  • 在docker-compose.yml 所在路径执行:
docker-compose up (后面加-d可以后台启动)

在这里插入图片描述
访问 http://192.168.73.130:8761 就ok

compose启动会做几件事:
1、创建一个默认的网络app_default,默认以compose所在文件目录名加"_default"命名,compose内的所有容器都会加入此网络,可以相互用服务名访问。
2、如果镜像 baoliewuqiu-eureka-server-8761:0.0.1 不存在先构建镜像,如果镜像存在则不构建,加上 –build 参数可以强制先构建镜像,如果镜像之前构建过且构建文件没有变化或构建的内容没有变化,就算加上 --build 参数也不会重新构建。
3、根据构建的镜像创建一个名称叫 zjq_eureka_1 的容器。
4、启动容器。

4. Docker Compose管理容器的结构

Docker Compose将所管理的容器分为三层,分别是工程( project)服务(service)以及容器( container)。 Docker Compose运行目录下的所有文件( docker-compose.yml、 extends文件或环境变量文件等)组成一个工程(默认为 docker-compose.yml所在目录的目录名称)。一个工程可包含多个服务,每个服务中定义了容器运行的镜像、参数和依赖,一个服务可包括多个容器实例。
上面的示例里工程名称是 docker-compose.yml 所在的目录名。该工程包含了1个服务,服务名称是 eureka,执行 docker-compose up时,启动了eureka服务的1个容器实例。
同一个docker compose内部的容器之间可以用服务名相互访问,服务名就相当于hostname,可以直接 ping 服务名,得到的就是服务对应容器的ip,如果服务做了扩容,一个服务对应了多个容器,则 ping 服务名 会轮询访问服务对应的每台容器ip ,docker底层用了LVS等技术帮我们实现这个负载均衡。

5. docker-compose.yml中常用指令

这里列出博主工作中常用的一些命令。

  1. image
    指定镜像名称或者镜像id,如果该镜像在本地不存在,Compose会尝试pull下来。
image: java
  1. build
    指定Dockerfile文件的路径。可以是一个路径,例如:
build: ./dir

也可以是一个对象,用以指定Dockerfile和参数,例如:

build:
  context: ./dir
  dockerfile: Dockerfile-alternate
  args:
    buildno: 1
  1. command
    覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000

也可以是一个list,类似于Dockerfile总的CMD指令,格式如下:

command: [bundle, exec, thin, -p, 3000]
  1. links
    显示链接到其他服务中的容器。可以指定服务名称和链接的别名使用SERVICE:ALIAS 的形式,或者只指定服务名称,示例:
web:
  links:
   - db
   - db:database
   - redis
  1. external_links
    表示链接到docker-compose.yml外部的容器,甚至并非Compose管理的容器,特别是对于那些提供共享容器或共同服务。格式跟links类似,示例:
external_links:
 - redis_1
 - project_db_1:mysql
 - project_db_1:postgresql
  1. ports
    暴露端口信息。使用宿主端口:容器端口的格式,或者仅仅指定容器的端口(此时宿主机将会随机指定端口),类似于docker run -p ,示例:
ports:
 - "3000"
 - "3000-3005"
 - "8000:8000"
 - "9090-9091:8080-8081"
 - "49100:22"
 - "127.0.0.1:8001:8001"
 - "127.0.0.1:5000-5010:5000-5010"
  1. expose
    暴露端口,只将端口暴露给连接的服务,而不暴露给宿主机,示例:
expose:
 - "3000"
 - "8000"
  1. volumes
    卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)。示例:
volumes:
  # Just specify a path and let the Engine create a volume
  - /var/lib/mysql

  # Specify an absolute path mapping
  - /opt/data:/var/lib/mysql

  # Path on the host, relative to the Compose file
  - ./cache:/tmp/cache

  # User-relative path
  - ~/configs:/etc/configs/:ro

  # Named volume
  - datavolume:/var/lib/mysql
  1. volumes_from
    从另一个服务或者容器挂载卷。可以指定只读或者可读写,如果访问模式没有指定,则默认是可读写。示例:
volumes_from:
 - service_name
 - service_name:ro
 - container:container_name
 - container:container_name:rw

  1. environment
    设置环境变量。可以使用数组或者字典两种方式。只有一个key的环境变量可以在运行Compose的机器上找到对应的值,这有助于加密的或者特殊主机的值。示例:
environment:
  RACK_ENV: development
  SHOW: 'true'
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SHOW=true
  - SESSION_SECRET
  1. env_file
    从文件中获取环境变量,可以为单独的文件路径或列表。如果通过 docker-compose -f FILE 指定了模板文件,则 env_file 中路径会基于模板文件路径。如果有变量名称与 environment 指令冲突,则以envirment 为准。示例:
env_file: .env

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env
  1. extends
    继承另一个服务,基于已有的服务进行扩展。

  2. net
    设置网络模式。示例:

net: "bridge"
net: "host"
net: "none"
net: "container:[service name or container name/id]"
  1. dns
    配置dns服务器。可以是一个值,也可以是一个列表。示例:
dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9
  1. dns_search
    配置DNS的搜索域,可以是一个值,也可以是一个列表,示例:
dns_search: example.com
dns_search:
  - dc1.example.com
  - dc2.example.com
  1. 其他
    docker-compose.yml 还有很多其他命令,这里仅挑选常用命令进行讲解,其它不作赘述。如果感兴趣的,可以参考docker-compose.yml文件官方文档

6. docker-compose常用命令

# 查看compose内的容器
docker-compose -f docker-compose-env.yml ps
# 关闭或启动或重启compose内的某个容器
docker-compose -f docker-compose-env.yml stop/start/restart <服务名> 
# 重构镜像启动
docker-compose -f docker-compose-app.yml up --build -d 
# 关闭或重启compose所有容器
docker-compose -f docker-compose-env.yml stop/restart
# 查看compose所有容器的运行日志
docker-compose -f docker-compose-app.yml logs -f
# 查看compose下某个容器的运行日志
docker-compose -f docker-compose-app.yml logs -f <服务名>
# 也可以把compose的容器日志输出到日志文件里去,然后用tail -f 随时查看
docker-compose -f docker-compose-app.yml logs -f >> myDockerCompose.log &
# 重新构建有变化的镜像并更新到容器再启动
docker-compose up --build -d
# 重新创建docker-compose.yml配置有变化的容器并启动
docker-compose up --force-recreate -d  

7. 用Docker Compose编排Spring Cloud微服务

这里博主就拿最近做的波克城市微服务项目举例,列出其中几个。

服务命介绍端口
boke-authcenter认证中心8899
boke-admin用户中心8082
boke-gateway网关8888
boke-api波克城市日志接口中心(kafka)8081

启动顺序:

  1. boke-admin
  2. boke-authcenter
  3. boke-gateway
  4. boke-api

gateway 在初始化时候调用 authcenter ,authcenter 又调用了 admin 的获取用户信息接口

编排波克项目依赖环境

这里博主是把所有微服务放在一个虚拟机上的,若分开部署,用到哪个部署哪个就行。若其他机器已经有了相应的环境,这步省略。

1、创建一个空目录docker-boke
2、在docker-boke目录下新建一个编排文件docker-compose-env.yml,内容如下:

version: '3'
services:
  mysql:
    image: mysql:5.7
    container_name: mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci  #覆盖容器启动后默认执行的启动mysql命令
    restart: always  #关机或者重启机器时,docker同时重启容器,一般mysql服务可以这么设置,保持服务一直都在
    environment:
      MYSQL_ROOT_PASSWORD: root #设置root帐号密码
    ports:
      - 3306:3306
    volumes:
      - /mydata/mysql/data/db:/var/lib/mysql #数据文件挂载
      - /mydata/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载
      - /mydata/mysql/log:/var/log/mysql #日志文件挂载
  redis:   
    image: redis:5.0
    container_name: redis
    command: redis-server --appendonly yes  
    volumes:
      - /mydata/redis/data:/data #数据文件挂载
    ports:
      - 6379:6379
  nginx:
    image: nginx:1.10 
    container_name: nginx 
    volumes:
      - /mydata/nginx/nginx.conf:/etc/nginx/nginx.conf #配置文件挂载,docker对单个文件的挂载需要先在宿主机建好对应文件才能挂载成功,可以先启动nginx容器,将容器里的nginx.conf文件复制出来修改好再挂载
      - /mydata/nginx/html:/usr/share/nginx/html #静态资源根目录挂载
      - /mydata/nginx/log:/var/log/nginx #日志文件挂载
    ports:
      - 80:80
  rabbitmq:
    image: rabbitmq:3.7.25-management
    container_name: rabbitmq
    volumes:
      - /mydata/rabbitmq/data:/var/lib/rabbitmq #数据文件挂载
      - /mydata/rabbitmq/log:/var/log/rabbitmq #日志文件挂载
    ports:
      - 5672:5672
      - 15672:15672
  nacos:
    image: nacos/nacos-server:1.1.4
    container_name: nacos
    environment:
      - MODE=standalone
    volumes:
      - /mydata/nacos/logs/:/home/nacos/logs
    ports:
      - "8848:8848"

编排波克城市微服务
1、在docker-mall目录下分别创建boke-authcenter,boke-gateway,boke-admin,boke-api目录。
2、修改电商项目上面这几个微服务配置文件里的环境配置为上面docker compose里的服务名,并打好jar包放入上面对应的文件夹。
以boke-authcenter 服务为例,对应修改后的配置文件如下(注意:大家按照自己下载项目的配置文件去修改,不要直接用我这里的配置,有可能版本不对)

spring:
  application:
    name: boke-authcenter
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.103:8848
        cluster-name: NJ-CLUSTER
        metadata:
          current-version: V1 # 版本
        namespace: b2b1af50-c82e-47c1-8fb2-7d46bae506bf # boke的
    # 数据库配置
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.1.103:3306/boke?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
    # Hikari 连接池配置
    hikari:
      minimum-idle: 10 # 最小空闲连接数量
      idle-timeout: 180000 # 空闲连接存活最大时间,默认600000(10分钟)
      maximum-pool-size: 10 # 连接池最大连接数,默认是10
      auto-commit: true # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
      pool-name: BokeApiHikariCP # 连接池名称
      max-lifetime: 1800000 # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
      connection-timeout: 30000 # 数据库连接超时时间,默认30秒,即30000
      connection-test-query: SELECT 1
mybatis:
  type-aliases-package: com.boke.auth.user.pojo
  mapper-locations: classpath:/mybatis-mappers/*
  configuration:
    mapUnderscoreToCamelCase: true
    call-setters-on-nulls: true
feign:
  httpclient:
    enabled: true   # #让feign底层使用HttpClient去调用
    max-connections: 200 #  最大连接数
    max-connections-per-route: 50 #  为每个url请求设置最大连接数
  client:
    config:
      dafult:
        connectTimeout: 500000
        readTime: 500000
      # 要调用服务的名称
      boke-admin:
        loggerLevel: FULL   # 也可以在这里配置 那么代码就不用配置了

boke:
    jwt:
      keyPairName: jwt.jks
      keyPairAlias: jwt
      keyPairSecret: 123456
      keyPairStoreSecret: 123456
server:
  port: 8899

  1. 在每个微服务目录下新建一个Dockerfile,内容如下,以boke-authcenter服务为例,其它微服务都类似修改:
# 基于哪个镜像
From java:8
# 复制文件到容器
ADD boke-authcentre-0.0.1-SNAPSHOT.jar /authcentre.jar
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-jar","/authcentre.jar","--spring.profiles.active=dc"]
  1. 在docker-boke目录下新建微服务编排文件docker-compose-app.yml,内容如下:
version: '3'
services:
  boke-admin:
    image: boke/boke-admin:0.0.1
    build: ./boke-admin
    container_name: boke-admin
    ports:
      - 8082:8082
    volumes:
      - /etc/localtime:/etc/localtime:ro #同步宿主机与容器时间
    restart: always
  boke-authcenter:
    image: boke/boke-authcenter:0.0.1  #指定镜像名称
    build: ./boke-authcenter  #指定Dockfile所在路径
    container_name: boke-authcenter  #指定启动容器名称
    ports:
      - 8899:8899
    volumes:
      - /etc/localtime:/etc/localtime:ro  #同步宿主机与容器时间,ro代表readonly只读
    external_links:  #访问不在同一个compose文件管理的服务需要用external_links,前提是这些服务都在同一个网络下才能正常访问 
      - nacos:nacos  #可以用nacos这个域名访问nacos服务
    depends_on:
      - boke-admin # authcenter 在 admin 启动之后再启动
    restart: always
  boke-gateway:
    image: boke/boke-gateway:0.0.1
    build: ./boke-gateway
    container_name: boke-gateway
    ports:
      - 8888:8888
    volumes:
      - /etc/localtime:/etc/localtime:ro #同步宿主机与容器时间
    depends_on:
      - boke-authcenter # gateway 在 authcenter 启动之后再启动
    restart: always
  boke-api:
    image: boke/boke-api:0.0.1
    build: ./boke-api
    container_name: boke-api
    ports:
      - 8081:8081
    volumes:
      - /etc/localtime:/etc/localtime:ro #同步宿主机与容器时间
    restart: always

关于启动顺序的问题,往上也有很多文章,博主这里直接用 restart: always 就可以解决。应该是版本问题 。我这是版本: docker-compose version 1.25.5, build 8a1c60f6

总体结构如下
在这里插入图片描述
├── docker-compose-app.yml
└── boke-admin
├──── Dockerfile
└──── boke-admin-0.0.1-SNAPSHOT.jar
└── boke-api
├──── Dockerfile
└──── boke-api-0.0.1-SNAPSHOT.jar
…以下省略

  1. 启动compose的所有微服务容器,在docker-boke目录执行如下命令:
#这里启动的微服务跟上面启动的mysql,redis这些中间件服务因为都在docker-mall目录下,
# 即都是同一个工程下,默认都在相同的网络下,可以相互访问
docker-compose -f docker-compose-app.yml up -d  
# 查看compose所有容器的运行日志
docker-compose -f docker-compose-app.yml logs -f
# 也可以把compose的容器日志输出到日志文件里去,然后用tail -f 随时查看
docker-compose -f docker-compose-app.yml logs -f >> myDockerCompose.log &

执行如下扩容命令,服务一旦扩容对应了多个容器,则访问服务名docker会自动帮我们负载均衡去访问服务对应的每台容器

docker-compose -f docker-compose-app.yml up -d     #必须先正常编排微服务,然后才能动态扩容
docker-compose -f docker-compose-app.yml scale boke-api=2 boke-admin=2   
#如果要缩容执行如下操作
docker-compose -f docker-compose-app.yml scale boke-api=1 boke-admin=1

启动截图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

8.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!
233333·····现在已经凌晨三点了好困~

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐