六、Docker Compose详解与项目构建

Docker Compose详解与项目构建

前言

通过之前的文章,我们知道了Docker的安装、镜像操作、容器操作,也初步了解了Dockerfile构建自己的镜像,接下来需要从一个项目的角度考虑如何通过Docker部署了。

我们先考虑一种简单的项目(SpringBoot+MySQL+Redis),这里我们需要部署三个服务

  • 基于JDK的SpringBoot服务
  • 基于MySQL 5.7.37的服务
  • 基于Redis的服务

如果只是通过Docker和Dockerfile我们可以做到

  • Dockerfile构建部署基于JDK的SpringBoot服务
  • Docker部署基于MySQL 5.7.37的服务
  • Docker部署基于Redis的服务

但是这个过程是每个服务都需要单独进行操作,为了应对这种局面,Docker Compose出现了

Docker Compose通过编写yaml配置文件,将这一系列操作集于一身,一次性实现一个项目所有服务的镜像构建和运行。

接下来,我们先学习下Docker Compose的安装、语法、命令,最后进行一下项目实战

一、Docker Compose安装

在安装Docker Compose之前,请先安装Docker

1、下载

# 这里下载到了/usr/local/bin
curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

2、授权

chmod +x /usr/local/bin/docker-compose

3、创建软链接

这样就可以在任何目录使用docker-compose命令了

ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

4、测试

docker-compose --version

显示版本号则表示安装成功

二、Docker Compose配置文件语法

1、配置文件说明

version: '3.0'							# Compose版本
services:								# 定义所有的 service 信息, services 下面的第一级别的 key 既是一个 service 的名称
  web:									# 自定义的一个服务名,名称自己区
    build: 								# 指定包含构建上下文的路径, 或作为一个对象,该对象具有context和指定的dockerfile文件以及args参数值
      context: ./web					# dockerfile所在路径,如果其他参数默认,可以将其作为build的值
      dockerfile: Dockerfile			# 指定context目录下Dockerfile文件名称,默认Dockerfile
      args: 							# Dockerfile在build过程中使用的参数,(等同于 docker build --build-arg 的作用)
      cache_from:            			# v3.2中新增的参数, 指定缓存的镜像列表 (等同于 docker build --cache_from 的作用)
      labels:                			# v3.3中新增的参数, 设置镜像的元数据 (等同于 docker build --labels 的作用)
      shm_size:              			# v3.5中新增的参数, 设置容器 /dev/shm 分区的大小 (等同于 docker build --shm-size 的作用)
  	container_name: my-web				# 容器名,(等同于 docker run --name 的作用),不建议指定,自动生成会带(项目名_服务名),防止重复
  	image:                 				# 指定 docker 镜像, 可以是远程仓库镜像、本地镜像,(等同于 docker build 镜像名:标签名 的作用)
    ports:								# 端口映射,(等同于 docker run -p 的作用)
      - "8000"							# 暴露容器的 8000 端口, 宿主机的端口由 docker 随机映射一个没有被占用的端口
      - "8001-8010"						# 暴露容器的 8001-8010 端口, 宿主机的端口由 docker 随机映射没有被占用的端口
      - "5000:5000"					    # 暴露容器的 5000 端口, 宿主机5000端口映射容器端口
      - "9090-9091:8080-8081"			# 批量暴露容器端口,指定宿主机多端口与之映射
      - "127.0.0.1:8001:8001"           # 指定映射宿主机的指定地址的
      - "127.0.0.1:5000-5010:5000-5010" # 同上类似
      - "6060:6060/udp"                 # 指定协议,默认tcp协议
    command: ["bundle", "exec", "thin", "-p", "3000"]    # 覆盖容器启动的默认命令, 支持 shell 格式和 [] 格式
    depends_on:							# 依赖服务,依赖服务启动之后才会启动
      - redis
      - mysql
    entrypoint:							# 覆盖容器的默认 entrypoint 指令 (等同于 docker run --entrypoint 的作用)
      - java
      - -jar
      - demo.jar
    env_file:						    # 从文件加载环境变量
  	  - ./common.env
      - ./apps/web.env
      - /opt/secrets.env
    environment:					    # 环境变量, environment 的值可以覆盖 env_file 的值 (等同于 docker run --env 的作用)
    expose:								# 暴露端口, 但不映射宿主机, 同 Dockerfile 的 EXPOSE 指令
      - "8000"
      - "8001"
    network_mode: "bridge"				# 网络模式 (等同于 docker run --net 的作用)
    networks:							# 将容器加入指定网络,
      network-name:						# 加入下面网络中定义的网络
         - aliase-name					# 网络别名,容器之间可以通过别名访问
    restart: always						# 重启策略,no:禁止自动重启,always:无论如何都重启,on-failure:当出现on-failure错, 容器重启
    volumes: 							# 挂在卷,注意:docker-compose目录必须存在,不会自动创建
      - /var/lib/mysql                  # 映射容器内的 /var/lib/mysql 到宿主机的一个随机目录中
      - /opt/data:/var/lib/mysql        # 映射容器内的 /var/lib/mysql 到宿主机的 /opt/data
      - ./cache:/tmp/cache              # 映射容器内的 /var/lib/mysql 到宿主机 compose 文件所在的位置
      - ~/configs:/etc/configs/:ro      # 映射容器宿主机的目录到容器中去, 权限只读
      - datavolume:/var/lib/mysql       # datavolume 为 volumes 自定义的目录
    deploy:                				# 指定与部署和运行服务相关的配置, 详情待
    devices:               				# 指定设备映射列表 (等同于 docker run --device 的作用)
    dns:                   				# 设置 DNS 地址(等同于 docker run --dns 的作用)
    dns_search:            				# 设置 DNS 搜索域(等同于 docker run --dns-search 的作用)
    tmpfs:                 				# v2 版本以上, 挂载目录到容器中, 作为容器的临时文件系统(等同于 docker run --tmpfs 的作用)
    links:                 				# 链接到其它服务中的容器,可以不用IP访问其他容器, 目前已被用户自定义网络名称空间取代
    external_links:        				# 连接不在 docker-compose.yml 中定义的容器或者不在 compose 管理的容器
    extra_hosts:           				# 添加 host 记录到容器中的 /etc/hosts 中 (等同于 docker run --add-host 的作用)
    healthcheck:            			# v2.1 以上版本, 定义容器健康状态检查, 类似于 Dockerfile 的 HEALTHCHECK 指令
    pid: 'host'           				# 共享宿主机的 进程空间(PID)
    logging:               				# 设置容器日志服务
networks:								# 网络定义
  network-name:							# 网络名称
    driver: bridge						# 网络模式
volumes:								# 数据卷定义
  volume-name:							# 数据卷名称

2、配置文件理解

  • Compose配置文件有四个一级属性

    # version
    	Compose和Docker兼容性: Compose 文件格式有3个版本,分别为1, 2.x 和 3.x,目前主流的为 3.x 其支持 docker 1.13.0 及其以上的版本
    # services
    	服务,配置文件的核心,有多少服务,则配置多少个服务,如一个项目由SpringBoot、MySQL、Redis组成,则其下配置三个服务
    # networks
    	定义网络,事先定义好在services中需要使用的网络,servcies中用到的网络如果不存在,不会自动创建
    # volumes
    	定义数据卷,事先定义好在services中需要使用的数据卷,servcies中用到的数据卷如果不存在,不会自动创建
    
  • Services

    服务由两种方式创建,一种是build,另一种是镜像。其中大部分命令可以理解为docker run的另一种表现形式,如:

    -p -> ports
    -v -> volumns
    --network -> networks
    --name -> container_name
    -e -> enviroment
    ...
    

三、Docker Compose构建命令

1、up

格式:

docker-compose up [options] [SERVICE...]

说明:

​ 重新构建镜像并启动服务

选项:

  • -d后台运行
  • -f指定compse文件
  • -t多少秒后启动服务

示例:

docker-compose up
docker-compose up -d
docker-compose up -f xxx.yml -d
docker-compose up -d mysql redis

2、ps

格式:

docker-compose ps [options]

说明:

​ 列出所有运行的服务

选项:

  • -q仅仅显示服务的ID
  • -a显示所有的服务,包含未运行的服务

示例:

docker-compose ps
docker-compose ps -q

3、down

格式:

docker-compose down [options]

说明:

​ 停止服务,会删除容器、网络,不会删除数据卷

选项:

  • -v指定停止容器时删除的卷
  • -t多少秒后t停止服务

示例:

docker-compose down

4、rm

格式:

docker-compose rm [options] [SERVICE...]

说明:

​ 删除停止状态的的服务

选项:

  • -v指定停止容器时删除的卷
  • -f强制删除,包括运行中的容器
  • -s在删除前,先停止容器

示例:

docker-compose rm redis
docker-compose rm -f redis

5、run

格式:

docker-compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]

说明:

​ 运行一个服务

选项:

  • 同docker run -v -p -d -e -l -w

示例:

docker-compose run -p 3306:3306 -v mysqlData:/var/lib/mysql mysql

6、start

格式:

docker-compose start [SERVICE...]

说明:

​ 启动一个已经存在的容器

选项:

示例:

docker-compose start mysql redis

7、stop

格式:

docker-compose stop [options] [SERVICE...]

说明:

​ 停止已运行的服务的容器

选项:

  • -t多少秒之后停止服务

示例:

docker-compose stop mysql
docker-compose stop -t 20 mysql

8、restart

格式:

docker-compose restart [options]

说明:

​ 重启容器

选项:

  • -t多少秒之后停止服务,并启动

示例:

docker-compose restart
docker-compose restart -t 20

7、pause/unpause

格式:

docker-compose pause [SERVICE...]
docker-compose unpause [SERVICE...]

说明:

​ 暂停已运行的服务

​ 恢复服务

选项:

示例:

docker-compose pause mysql
docker-compose unpause mysql

8、kill

格式:

docker-compose kill [options] [SERVICE...]

说明:

​ 杀死指定的服务

选项:

  • -s SIGNAL to send to the container. (default “SIGKILL”)

示例:

docker-compose kill mysql

9、logs

格式:

docker-compose logs [options] [SERVICE...]

说明:

​ 查看服务日志

选项:

  • -f Follow log output
  • -t显示时间

示例:

docker-compose logs mysql
docker-compose logs -t mysql

10、port

格式:

docker-compose port [options] [--] SERVICE PORT

说明:

​ 查看服务端口号的映射

选项:

示例:

docker-compose port mysql 3306

11、其他

其他命令暂时略过了

  • pull
  • push
  • scale
  • build
  • convert
  • cp

四、一个简单的项目示例

有过上面的学习之后,接下来用一个简单项目进行实战,还是以之前Docker部署SpringBoot为例子,现在使用Docker Compose进行部署运行

1、项目目录及部署文件准备

└── demo
    ├── docker-compose.yml
    └── sboot
        ├── demo-0.0.1-SNAPSHOT.jar
        └── Dockerfile
  • 项目目录:demo,最好是项目名称
  • Compose配置文件:docker-compose.yml
  • SpringBoot项目构建目录:sboot,里面包含项目包和Dockerfile文件

2、Docker Compose文件编写

version: "3.0"
services:
  web:
    build: ./sboot
    ports:
      - 8000:8000
    networks:
      - demo
    restart: always
  mysql:
    image: mysql:5.7.37
    ports:
      - 3306:3306
    networks:
      - demo
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    restart: always
    volumes:
      - mysql_data:/var/lib/mysql
  redis:
    image: redis:alpine
    ports:
      - 6379:6379
    networks:
      - demo
    restart: always
networks:
  demo:
volumes:
  mysql_data:

3、执行

docker-compose up -d

执行成功后,请求自己的地址,如果能够成功则OK了

4、可能遇到的问题

# 端口占用
	服务端端口映射可能被其他容器占用

# 错误:services.mysql.volumes.0 type is required
	注意yaml语法,端口映射和数据源映射的值,冒号后面不要由空格,如mysql_data:/var/lib/mysql,不要写成mysql_data: /var/lib/mysql

# 其他语法错误
	其他模板语法错误都可能导致构建失败

五、总结

至此,我们已经初步掌握了Docker Compose构建项目的方式了。但是,真实的项目往往比这复杂的多,比如上面的项目示例中可以继续考虑如下问题:

  • MySQL
    • 第一次MySQL数据初始化问题?
    • 后续项目迭代,数据库增量问题?
    • 重启数据是否能保留?
  • Redis
    • 自定义配置文件?
    • 重启数据是否能保留?
  • SpringBoot项目
    • 项目功能迭代,单独更新?

接下来会写一篇针对上面问题的深入优化偏,后续可能会继续往里面追加MQ、文件存储等其他中间件。


感谢大家的阅读,如果有什么建议或者意见可以留下评论哦! ~ 不负热爱 奔赴山海 ~


版权声明:本文为A10714075原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。