文章目录

  • 一、introduce
  • 二、安装compose
  • 三、compose 初探
  • 四、compose yml细看
  • 五、docker-compose命令


一、introduce

  • docker compose 和 docker 是docker 公司的两个项目
  • why docker compose?
    docker compose定位:定义和运行多个容器应用。典型场景:一个 web项目,除了web应用本身,还需要 数据库、缓存LB 的配合(依赖项)。如果一个个起,实际很费事。Docker compose 允许用户通过一个docker compose yaml模板定义一组相关联的容器共同构成一个项目。但要注意,资源的调度compose是搞不定的,要靠K8S

Compose中的两个概念:

  • 服务 service:就是一组由相同镜像拉起来的容器
  • 项目 project:一组关联应用组成的一个完整业务单元,可在docker-compose.yml 文件中定义

Compose的管理对象是项目,通过命令对一组容器进行生命周期管理。不过还要注意Compose的项目和我们说的一套代码的项目(工程)是两个东西。

Compose由Python写就,本质上是调用了 docker API。只要平台支持 Docker API,就能利用Compose编排管理。

二、安装compose

下面描述基于Linux(centos7)安装:

[root@localhost helloapp]# sudo curl -L "https://github.com/docker/compose/releases/download/1.28.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   633  100   633    0     0    406      0  0:00:01  0:00:01 --:--:--   406
100 11.6M  100 11.6M    0     0  1849k      0  0:00:06  0:00:06 --:--:-- 2652k
[root@localhost helloapp]# sudo chmod +x /usr/local/bin/docker-compose
[root@localhost helloapp]# docker compose -v
Docker version 20.10.3, build 48d30b5

为啥要放到 usr/local/bin? 主要是这样会自动配置环境变量。

三、compose 初探

创建测试目录,创建docker-compose.yml 文件(内容如下),并启动docker-compose up;宿主机测试 curl localhost:8081;宿主机测试docker ps -a发现有新起的服务。

version: "3.9"
services:
  tomcat-service:
    image: "tomcat:9.0"
    ports:
      - "8080:8080"
  tomcat-service-1:
    image: "tomcat:9.0"
    ports:
      - "8081:8080"

四、compose yml细看

第一步:以下面这段 yml作为说明材料

version: "3.9"
services:
  tomcat-service:
    image: "tomcat:8.0"
    ports:
      - "8080:8080"
    volumes:
#    【数据卷挂载的第一种方式:  指定路径 挂载】
#      - /home/hello:/usr/local/tomcat/webapps
#    【第二种方式: 具名挂载】
      - tomcatapps:/usr/local/tomcat/webapps

volumes:
  tomcatapps: # 【使用具名挂载时一定要 声明 这个 名字;也可以使用 external 指定,但感觉也没啥必要】

先说明一下【volumes】:

  • 使用 具名挂载 时一定要声明 卷名
  • 使用具名挂载的容器,产生的卷名为 项目名_卷名, 而非卷名

    使用docker inspect ContainerID,查看挂载信息:

    进入到宿主机挂载目录,可见已形成映射:

下面我们制作了一个几乎囊括了所有常用 模板指令的 docker-compose.yml文件。

version: "3.9"
services:
# ########################## 在docker-compose 之前 build 一个镜像,并直接拉起容器#######
  mywebapp:
    build:
      context: ./mywebapp # 【docker build 上下文,其实就是 一个目录(相对于本 docker-compose.yml文件)】
      dockerfile: Dockerfile #【指定 DockerFile,如果是 默认的,不写也成】
    container_name: hello
    ports:
      - "8082:8080"
    networks:
      - hello
    depends_on:
      - tomcat01 #【我们就 假如 tomcat01 是一个 被依赖的服务】

# ##########################下方使用的都是现成 的docker images##########################
  tomcat01:  #【服务 id ,id当然是必须   唯一 的 】
    container_name: tomcat01 # 【指定容器启动的名字,否则就是 项目名_tomcat01】
    image: "tomcat:8.0"
    ports:  #【类似 这种 格式,在yml 中是一个 数组 ; 有的指令支持 KV 对】
      - "8080:8080"
    volumes:
#    【数据卷挂载的第一种方式:  指定路径 挂载】
#      - /home/hello:/usr/local/tomcat/webapps
#    【第二种方式: 具名挂载】
      - tomcatapps01:/usr/local/tomcat/webapps
    networks:  # 【指定Tomcat01 所在的网络,注意  指定的网络并不会自动创建,需要首先手动创建】
      - hello
 # 【真正能体现 编排 作用的指令,表示 tomcat01 这个服务依赖了 mysql01 redis01两个服务,不过,"依赖" 不代表
#  mysql01 redis01 启动完成后才会启动 Tomcat01. docker-compose 会 在两者启动到一定程度(?)时就会启动tomcat01】
    depends_on:
      - mysql01   # 【这里是  服务名 ,不是  容器名】
      - redis01
#【 健康检查 ;这里 只定义了健康检查,但是并没有 指明 假如不健康会怎么处理。hc 不是必须的】
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080"]
      interval: 1m30s
      timeout: 10s
      retries: 3
      start_period: 40s

# 【内核参数修改: 非必须的。少数 应用需要改内核配合】
#    sysctls:
#      - net.core.somaxconn=1024
#      - net.ipv4.tcp_syncookies=0

# 【Override the default ulimits for a container; 其实就是Linux的 ulimit 参数】
    ulimits:
      nproc: 65535
      nofile:
        soft: 20000
        hard: 40000
        
  tomcat02:
      container_name: tomcat02
      image: "tomcat:8.0"
      ports:
        - "8081:8080"
      volumes:
        - tomcatapps02:/usr/local/tomcat/webapps
      networks:
        - hello
  mysql01:
      container_name: mysql01
      image: "mysql:5.7"
      ports:
        - "3306:3306"
      volumes:
        - mysqldata:/var/lib/mysql
        - mysqlconf:/etc/mysql
      networks:
        - hello
#      environment:
#        - MYSQL_ROOT_PASSWORD=root
#      使用 environment 和 env_file 都能实现环境变量的set,但是 通过 environment 指令会将一些敏感信息暴露到
#       环境变量里,而 env_file 会相对安全(当然到底是否安全还是要看如何使用env_file.
#     env_file 中的格式,推荐写成 K=V ,文件 以 .env 结尾; 支持相对和绝对路径
      env_file:
        - ./mysql.env

  redis01:  # 起一个单实例的redis容器
     container_name: redis01
     image: "redis:5.0.10"
     ports:
        - "6379:6379"
     volumes:
        - redisdata:/data
    # 默认是 不开启持久化,通过【override】掉默认命令来开启持久化
     command: "redis-server --appendonly yes"
     networks:
        - hello
volumes:
  tomcatapps01: # 【使用具名挂载时一定要 声明 这个 名字】
  tomcatapps02:
  mysqldata:
  mysqlconf:
  redisdata:

networks:  # 定义网桥
  hello:  # 【定义服务用到的网桥名称,默认创建的 是 bridge 】
    external:
      true  # 【指定外部网桥,当然前提是 网桥 必须存在】

上述docker-compose.yml中指定的docker build的Dockerfile 如下:

FROM java:8
WORKDIR /home/hello
ADD hello-world-0.0.1-SNAPSHOT.jar mywebapp.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar"]
CMD ["mywebapp.jar"]

对应的文件目录(这个十分重要,目录就是docker build 上下文):

docker 启动prometheus的时候指定配置文件_docker

五、docker-compose命令

最常用、最强大的是 docker-compose updocker-compose up [options] [--scale SERVICE=NUM...] [--] [SERVICE...]

  • --scale SERVICE=NUM Scale SERVICE to NUM instances. Overrides the "scale" setting in the Compose file if present. 【居然可以 扩容的!!!】
  • 默认 docker-compose 起的项目跑在前台,如果 -d (生产推荐)表示后台跑

另外还有:

  • docker-compose --verbose 方便调试
  • docker-compose -v 显示版本
  • docker-compose -p ProjectName 再取个项目名字
  • docker-compose ps 【只显示项目中的容器】
  • docker-compose exec
  • docker-compose down
  • docker-compose restart
  • docker-compose start
  • docker-compose stop
  • docker-compose top 【执行项目中所有服务的 top】
  • docker-compose unpause
  • docker-compose pause
  • docker-compose rm 【删除某个项目中的服务】
  • -v [干掉数据卷]
  • -f
  • docker-compose logs 【看日志,方便调试】

注意: 上面所有的命令都 针对 service 的。