程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • 容器部署 - Docker

    • Docker - 介绍
    • Docker - 安装
    • Docker - 常用命令
    • Docker - 镜像原理
    • Docker - 网络网桥
    • Docker - 数据卷
    • Docker - 软件安装
    • Docker - Dockerfile
    • Docker - Compose
      • 1. 简介
      • 2. Docker Compose 使用
      • 3. 安装与卸载
        • 安装方式一:通过 GitHub 下载二进制文件
        • 安装方式二:通过 `curl` 直接下载
        • 安装方式三:通过包管理器
        • 安装完成后的常见问题
        • 问题 1:权限不足
        • 问题 2:命令未找到
      • 4. Idea 工具
      • 5. 模板文件
        • 启动指令
        • image(镜像)
        • ports(端口)
        • container_name(容器名称)
        • volumes(数据卷)
        • networks(网络)
        • build(构建)
        • depends_on(依赖)
        • environment(环境变量)
        • env_file(环境变量文件)
        • command(命令)
        • healthcheck(健康检查)
        • sysctls(系统控制参数)
        • ulimits(资源限制)
        • 模板文件参考
      • 6. 常用指令
        • 模板指令和常用指令的区别
        • 命令对象格式
        • 命令选项
        • up(启动)
        • down(停止并移除)
        • exec(执行命令)
        • ps(列出服务)
        • restart(重启)
        • rm(删除)
        • start(启动已存在的服务)
        • stop(停止运行的服务)
        • top(查看进程)
        • pause(暂停服务)
        • unpause(恢复服务)
        • logs(查看日志)
    • Docker - Ideal集成
  • 持续集成 - Jenkins

  • 容器管理 - kubernetes

  • 运维工具
  • 容器部署 - Docker
scholar
2023-11-22
目录

Docker - Compose

  • 1. 简介
  • 2. Docker Compose 使用
  • 3. 安装与卸载
    • 安装方式一:通过 GitHub 下载二进制文件
    • 安装方式二:通过 `curl` 直接下载
    • 安装方式三:通过包管理器
    • 安装完成后的常见问题
  • 4. Idea 工具
  • 5. 模板文件
    • 启动指令
    • image(镜像)
    • ports(端口)
    • container_name(容器名称)
    • volumes(数据卷)
    • networks(网络)
    • build(构建)
    • depends_on(依赖)
    • environment(环境变量)
    • env_file(环境变量文件)
    • command(命令)
    • healthcheck(健康检查)
    • sysctls(系统控制参数)
    • ulimits(资源限制)
    • 模板文件参考
  • 6. 常用指令
    • 模板指令和常用指令的区别
    • 命令对象格式
    • 命令选项
    • up(启动)
    • down(停止并移除)
    • exec(执行命令)
    • ps(列出服务)
    • restart(重启)
    • rm(删除)
    • start(启动已存在的服务)
    • stop(停止运行的服务)
    • top(查看进程)
    • pause(暂停服务)
    • unpause(恢复服务)
    • logs(查看日志)

# 1. 简介

Docker-compose 官网 (opens new window)

Docker-compose 指令地址 (opens new window)

Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的 快速编排。从功能上看,跟 OpenStack 中的 Heat 十分类似。

其代码目前在 GitHub (opens new window) 上开源。

Compose 定位是「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。

在第一部分中的介绍,我们知道使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡。

Compose 恰好满足了这样的需求。它允许用户通过一个单独的 docker-compose.yml 模板文件(HAML格式)来定义一组相关联的应用容器为一个项目(project)。

Compose 中有两个重要的概念:

  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。

  • 项目( project):由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。

Compose 项目由 Python 编写,实现上调用了 Docer 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker APl,就可以在其上利用 Compose 来进行编排管理。

笔记

Compose 就是一个 yml 文件,利用文件来替代 docker run 指令,大部分指令该指令存在的选项如 --name 等,Compose 都有。

2024-01-10 @scholar

# 2. Docker Compose 使用

首先介绍几个术语:

  • 服务 (service):一个服务就是一个应用容器,实际上可以运行多个相同镜像的实例。
  • 项目 (project):由多个服务共同组成一个具有相同业务逻辑的单元,项目在 docker-compose.yml 文件中定义。

使用 Docker Compose 基本上是一个三步过程:

  1. 定义应用程序的环境:使用 Dockerfile 定义您的应用程序环境,以便它可以在任何地方复制。
  2. 定义组成应用程序的服务:使用 docker-compose.yml 定义应用程序的服务,以便它们可以在隔离的环境中一起运行。
  3. 启动并运行应用程序:运行 docker compose up 或使用 Docker Compose 命令 (opens new window) 启动并运行整个应用程序。您也可以使用 docker-compose up 通过 docker-compose 二进制文件运行。

一个典型的 docker-compose.yml 文件看起来像这样:

version: "3.9"  # 3.9 版本要求 Docker 版本大于等于 v1.27.0
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • version: 定义 Docker Compose 文件的版本,这里使用的是 3.9 版本,要求 Docker 版本大于等于 v1.27.0。
  • services: 定义应用程序中的服务。
    • web:
      • build: 指定 Dockerfile 所在的路径,这里是当前目录 .。
      • ports: 定义容器内部端口和主机端口的映射,这里将容器的 5000 端口映射到主机的 5000 端口。
      • volumes: 定义数据卷,将主机的当前目录挂载到容器的 /code 目录,并将 logvolume01 挂载到容器的 /var/log 目录。
      • links: 定义容器之间的依赖关系,这里表示 web 服务依赖 redis 服务。
    • redis:
      • image: 指定使用的镜像,这里使用官方的 redis 镜像。
  • volumes: 定义数据卷,logvolume01 是一个命名卷。

通过上述步骤和配置,你可以使用 Docker Compose 轻松地定义和管理多容器应用程序。

# 3. 安装与卸载


# 安装方式一:通过 GitHub 下载二进制文件

1.1 从 GitHub 下载 Docker Compose

  1. 打开 GitHub Docker Compose 官方发布页面:
    • 地址:https://github.com/docker/compose/releases
  2. 找到需要的版本,下载适合你的系统架构的二进制文件(如 Linux 的 docker-compose-linux-x86_64)。

image-20241222023045876

提示: 如果最新版没有提供二进制文件,可以选择较低版本,直到找到对应的文件。


1.2 上传到 Linux

  1. 将下载的文件通过工具(如 scp 或 WinSCP)上传到 /usr/local/bin 目录:

    scp docker-compose-linux-x86_64 root@<your-server-ip>:/usr/local/bin/
    
    1
  2. 上传后,将文件重命名为 docker-compose:

    mv /usr/local/bin/docker-compose-linux-x86_64 /usr/local/bin/docker-compose
    
    1

1.3 添加执行权限

为二进制文件添加可执行权限:

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

1.4 验证安装

  1. 查看 Docker Compose 版本,验证是否安装成功:

    docker-compose version
    
    1
  2. 如果提示权限错误(如 Permission denied),需要重新添加可执行权限:

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

# 安装方式二:通过 curl 直接下载

如果服务器可以直接访问互联网,也可以通过 curl 命令下载 Docker Compose:

  1. 使用 curl 下载二进制文件:

    sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    
    1

    将 1.29.2 替换为需要安装的版本号。

  2. 添加可执行权限:

    sudo chmod +x /usr/local/bin/docker-compose
    
    1
  3. 验证安装:

    docker-compose version
    
    1

# 安装方式三:通过包管理器

3.1 使用 Homebrew(Mac)

Mac 用户可以通过 Homebrew 安装 Docker Compose:

brew install docker-compose
1

3.2 使用 pip 安装(Python 环境)

如果系统已安装 Python 和 pip,也可以通过 pip 安装 Docker Compose:

pip install docker-compose
1

注意:pip 安装的版本可能不如官方二进制文件更新,建议优先使用二进制文件。


# 安装完成后的常见问题

# 问题 1:权限不足

如果执行 docker-compose 时出现以下错误:

-bash: /usr/local/bin/docker-compose: Permission denied
1

解决方法:

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

# 问题 2:命令未找到

如果输入 docker-compose 时显示命令未找到:

-bash: docker-compose: command not found
1

解决方法:

  1. 确保二进制文件位于 /usr/local/bin 或其他已添加到系统 PATH 的目录中。

  2. 如果路径不对,可以移动文件:

    sudo mv docker-compose /usr/local/bin/docker-compose
    
    1

安装方法对比

安装方式 优点 缺点
GitHub 二进制文件 官方发布,版本最新,适合离线安装 需要手动下载、上传文件
curl 命令下载 简单快速,直接从官方获取 需要服务器有互联网访问权限
Homebrew 安装 Mac 用户推荐,自动更新方便 仅适用于 Mac 系统
pip 安装 可快速集成到 Python 环境 版本可能不如官方发布的更新

# 4. Idea 工具

这里介绍使用 Idea 来操作 yml 文件,因为在 Linux 里,编写 yml 文件非常麻烦,要注意缩进两个空格,并非四个空格。

使用 Idea 工具连接 Linux:

image-20211124172551111

然后右侧弹出内容,点击 ... 进入配置:

image-20211124172925371

再次按下 OK 即可。

我是在 /opt/docker-compose 里进行操作:

image-20211124173043725

利用 Idea 可以实现从 Linux 系统里拉取文件(直接拖动到项目里,无法拖动到 Idea 界面外面)、创建文件,读写文件(双击会在 Idea 界面自动打开)等操作。

image-20211124173503422

# 5. 模板文件

模板文件是使用 Compose 的核心,涉及到的指令关键字也比较多。但请不用担心,这里面大部分指令跟 docker run 相关参数的含义都是类似的。

# 启动指令

模板文件写好后需要启动。启动指令为 docker-compose up,如果需要后台启动,则使用 docker-compose up -d。更多详细指令可参考 常用指令。

默认的模板文件名称为 docker-compose.yml,格式为 YAML 格式。

version "3.0"

services:
  tomcat01:  # 服务名,唯一(自己随便定义,用于标识和管理该服务)
    image: tomcat:8.5.73   # 启动的镜像
    ports:  # 端口映射,类似于 docker run 的 -p
      - 8080:8080
    volumes:  # 数据卷,类似于 ,类似于 docker run 的 -v
      - /data     # 匿名目录挂载
      - aa:/data   # 默认目录挂载
      - /opt/aa:   # 具体目录挂载
    networks:     # 网桥
      - kele

volumes:   # 声明服务用到的数据卷
  aa:    
    external: true   # 开启指定数据卷名,否则数据卷名的前缀是项目名
networks:   # 声明服务用到的网桥
  kele:
    external: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

开头的 version 版本目前最高是 3.9。

注意事项

  • 每个服务必须通过 image 指令指定镜像,或者通过 build 指令(需要 Dockerfile)自动构建生成镜像。
  • 如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CND,EXPOSE,VOLUME,ENV 等)将会自动获取,无需在 docker-compose.yml 中重复设置。

下面分别介绍各个指令的用法和例子。

每一个指令的例子都是独立的,没有关联,所以服务名可能重复,一个例子的容器信息不会出现在下一个例子中等等。所以是独立的!

# image(镜像)

指定镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。

# 最新版
image: centos
# 版本号
image: centos:centos7
# 摘要
image: a4basdgv
1
2
3
4
5
6

示例:在 yml 文件里启动 tomcat 镜像

yml 文件内容:





 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
1
2
3
4
5

启动 yml 文件前,记得同步文件内容到 Linux。

启动 yml 文件的命令是 docker-compose up,如果后台启动,请加入 -d:docker-compose up -d:


 




# 启动 yml 文件
docker-compose up -d

# 返回结果
Starting docker-compose_tomcat01_1 ... done
1
2
3
4
5

查看容器是否启动:

# 查看启动容器
docker ps

# 返回结果
CONTAINER ID   IMAGE           COMMAND             CREATED          STATUS          PORTS      NAMES
38c797769cc4   tomcat:8.5.73   "catalina.sh run"   56 seconds ago   Up 42 seconds   8080/tcp   docker-compose_tomcat01_1
1
2
3
4
5
6

容器启动成功,并且容器的名字前缀加上了 docker-compose,不再是完全随机的。

# ports(端口)

暴露端口信息,等价于 docker run -p。

使用宿主端口∶容器端口(HOST:CONTAINER)格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

ports:
  - "3000"
  - "8000:8000"
  - "80:80"
  - "127.0.0.1:8080:8080"
1
2
3
4
5

注意

当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。

示例:启动 tomcat,并指定两个映射端口

yml 文件内容:






 
 
 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    ports:
    - "8081:8080"
    - "8082:8080"
1
2
3
4
5
6
7
8

启动 yml 文件,并验证是否启动:

# 启动 yml 文件
docker-compose up -d

# 返回结果
Starting docker-compose_tomcat01_1 ... done

# 查看启动的容器
docker ps

# 返回结果
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS                                                                                  NAMES
c06c886ec78b   tomcat:8.5.73   "catalina.sh run"   7 seconds ago   Up 6 seconds   0.0.0.0:8081->8080/tcp, 0.0.0.0:8082->8080/tcp, :::8081->8080/tcp, :::8082->8080/tcp   docker-compose_tomcat01_1
1
2
3
4
5
6
7
8
9
10
11
12

# container_name(容器名称)

指定容器名称。默认情况下,Docker Compose 会使用 项目名称_服务名称_序号 这样的格式为容器命名,等价于 docker run --name。

container_name: docker-web-container  # 相当于 docker run --name
1

注意:指定容器名称后,该服务将无法进行拓展(scale),因为 Docker 不允许多个容器具有相同的名称。

示例:启动 tomcat,指定容器名字

yml 文件内容:






 

version: "3.0"

services:
  tomcat01:  # 服务名称,唯一,用于标识和管理该服务
    image: tomcat:8.5.73
    container_name: tomcat01
1
2
3
4
5
6

在 docker-compose.yml 文件中,tomcat01 是服务名称,可以随意定义,用于标识和管理该服务。

启动 yml 文件,并查看容器是否启动:












 

# 启动 yml 文件
docker-compose up -d

# 返回结果
Starting tomcat01 ... done

# 查看启动容器
docker ps

# 返回结果
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS      NAMES
777df200aa36   tomcat:8.5.73   "catalina.sh run"   3 seconds ago   Up 2 seconds   8080/tcp   tomcat01
1
2
3
4
5
6
7
8
9
10
11
12

如果该容器已经在运行,则使用 yml 文件启动时,会将运行的容器停止,然后以新的 yml 文件配置重新启动。

# volumes(数据卷)

数挥卷所挂载路径设置。可以设置为宿主机路径(HOST:CONTAIMER)或者数据卷名称(VOLUNME:CONTATNER),并且可以设置访问模式(HOST:CONTAINER:ro)。该指令中路径支持相对路径,等价于 docker run -v

volumes:
  - /usr/local/tomcat   # 匿名目录挂载
  - aa:/usr/local/tomcat   # 默认目录挂载
  - /opt/aa:/usr/local/tomcat   # 具体目录挂载
  - ~/configs:/usr/local/tomcat:ro   # 指定容器的只读权限
1
2
3
4
5

如果是默认目录挂载,必须在文件中声明数据卷。






 
 


 
 

version "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    volumes: 
      - aa:/usr/local/tomcat

# 必须在这里进行声明,否则报错
volumes:
  aa:
1
2
3
4
5
6
7
8
9
10
11

但是默认目录挂载生成的数据卷名会加上项目名(yml 文件所在的目录名)。如上方文件生成的数据卷名叫 docker-compose_aa,注意这里的前缀不是服务名,而是项目名。

如果不希望数据卷名带有项目名前缀,则需要设置 external 为 true。












 

version "3.0"

services:
  my_src:
    image: tomcat:8.5.73
    volumes: 
      - aa:/usr/local/tomcat

# 必须在这里进行声明,否则报错
volumes:
  aa:  # 声明数据卷名
    external: true  # 确认使用指定的数据卷名,前缀不会加上项目名
1
2
3
4
5
6
7
8
9
10
11
12

设置 external 为 true 也会带来一个问题:如果该数据卷名不存在,则会报错。它不会主动创建不存在的数据卷,因此需要先手动创建数据卷。

例子 1:不加 external 为 true 的默认目录挂载

yml 文件内容:







 
 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    container_name: tomcat01
    volumes:
    - tomcat:/usr/local/tomcat
1
2
3
4
5
6
7
8

如果直接启动 yml 文件,它会报错,知道为什么吗?

之前说过,使用 volumes 必须要进行声明,否则会报错:

ERROR: Named volume "tomcat:/usr/local/tomcat:rw" is used in service "tomcat01" but no declaration was found in the volumes section.
1

所以正确的 yml 文件内容:(声明数据卷)










 
 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    container_name: tomcat01
    volumes:
    - tomcat:/usr/local/tomcat

volumes:  # 声明数据卷
  tomcat:
1
2
3
4
5
6
7
8
9
10
11

查看容器是否启动:

# 查看容器
docker ps

# 返回结果
CONTAINER ID   IMAGE           COMMAND             CREATED         STATUS         PORTS      NAMES
c8acd0e644ef   tomcat:8.5.73   "catalina.sh run"   4 seconds ago   Up 2 seconds   8080/tcp   tomcat01
1
2
3
4
5
6

查看数据卷是否会自动创建:



































 

# 查看数据卷
docker volume ls

# 返回结果
DRIVER    VOLUME NAME
local     docker-compose_tomcat

# 查看数据卷的宿主机位置
docker volume inspect docker-compose_tomcat 

# 返回结果
[
    {
        "CreatedAt": "2021-11-24T18:26:33+08:00",
        "Driver": "local",
        "Labels": {
            "com.docker.compose.project": "docker-compose",
            "com.docker.compose.version": "1.29.2",
            "com.docker.compose.volume": "tomcat"
        },
        "Mountpoint": "/var/lib/docker/volumes/docker-compose_tomcat/_data",
        "Name": "docker-compose_tomcat",
        "Options": null,
        "Scope": "local"
    }
]

# 进入数据卷的目录
cd /var/lib/docker/volumes/docker-compose_tomcat/_data

# 查看目录内容
ls

# 返回结果
bin  BUILDING.txt  conf  CONTRIBUTING.md  lib  LICENSE  logs  native-jni-lib  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  temp  webapps  webapps.dist  work
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

证明了创建的数据卷名带有项目名(yml 文件所在的目录名),并且说明了:默认目录挂载方式,容器的挂载目录内容覆盖了宿主机的挂载内容。

如果不想数据卷名带有项目名(yml 文件所在的目录名),请添加 external 为 true,看例子 2。

例子 2:加 external 为 true 的默认目录挂载

yml 文件:












 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    container_name: tomcat01
    volumes:
    - tomcat:/usr/local/tomcat

volumes:
  tomcat:
    external: true
1
2
3
4
5
6
7
8
9
10
11
12

如果直接启动 yml 文件,它会报错,知道为什么吗?

前面说过,虽然此时的数据卷确实叫做 tomcat 而不是带有项目名,但是目前的 tocmat 数据卷就不存在,而 external 为 true 时,不会创建不存在的数据卷名。所以我们必修先创建数据卷:

docker volume create tomcat
1

启动 yml 文件














 

# 启动 yml 文件
docker-compose up -d

# 返回结果
Recreating tomcat01 ... done

# 进入数据卷目录
cd /var/lib/docker/volumes/tomcat/_data

# 查看目录内容
ls

# 返回结果
bin  BUILDING.txt  conf  CONTRIBUTING.md  lib  LICENSE  logs  native-jni-lib  NOTICE  README.md  RELEASE-NOTES  RUNNING.txt  temp  webapps  webapps.dist  work
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# networks(网络)

配置容器连接的网络,等价于 docker run --network。

  • 使用 docker run 启动的容器,默认网桥名为 bridge。
  • 使用 docker-compose.yml 文件启动的容器,默认网桥名为 docker-compose_default。




 
 
 

 
 
 
 

version "3.0"

services:
  some-service:
    networks:
     - some-network
     - other-network

# 必须在这里进行声明,否则报错
networks:
  some-network
  other-network
1
2
3
4
5
6
7
8
9
10
11
12

和 volumes 一样:

  • 创建的网桥名默认会加上项目名(yml 文件所在的目录名)。如果不希望加上项目名,请添加 external 为 true。
  • 使用网桥需要在文件中进行声明,否则会报错。
  • 如果添加 external 为 true,该网桥必须先存在,否则会报错,不会主动创建不存在的网桥。
version "3.0"

services:
  some-service:
    networks:
     - some-network
     - other-network

# 必须在这里进行声明,否则报错
networks:
  some-network  # 网桥名不加上项目名
    external:
      true
  other-network   # 这个网桥名会带有项目名前缀
1
2
3
4
5
6
7
8
9
10
11
12
13
14

示例 :容器有两个网桥,一个网桥使用带有项目名,一个不带有项目名

yml 文件内容:







 
 
 

 
 
 
 
 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: tomcat:8.5.73
    container_name: tomcat01
    networks:
      - kele
      - bing

networks:
  kele:
    external: 
      true
  bing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

不演示 kele 网桥不存在报错的问题了,直接创建 kele 网桥:


 








 

# 创建网桥
docker network create kele

# 查看网桥
docker network ls

# 返回结果(部分)
NETWORK ID     NAME                     DRIVER    SCOPE
6a9007e442ce   bridge                   bridge    local
28f389726875   docker-compose_default   bridge    local
922ea0d2e922   kele                     bridge    local
1
2
3
4
5
6
7
8
9
10
11

启动 yml 文件:





 








 



# 启动 yml 文件
docker-compose up -d

# 返回结果
Creating network "docker-compose_bing" with the default driver
Creating tomcat01 ... done

# 查看网桥
docker network ls

# 返回结果(部分)
NETWORK ID     NAME                     DRIVER    SCOPE
6a9007e442ce   bridge                   bridge    local
6f723cfea57c   docker-compose_bing      bridge    local
28f389726875   docker-compose_default   bridge    local
922ea0d2e922   kele                     bridge    local
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

可以看到,yml 文件启动容器的默认网桥是 docker-compose_bing,而指定的 bing 网桥带有项目名(yml 文件所在的目录名):docker-compose_bing。

# build(构建)

指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径),Compose 将会利用它自动构建这个镜像,然后使用这个镜像,等价于 docker build。

version "3.0"

services:
  tomcat01:
    build: ./dir  # 当前目录下的 dir 目录为上下文目录(Dockerfile 所在的目录)
1
2
3
4
5
  • 使用 context 指令指定 Dockerfile 所在文件夹的路径

  • 使用 dockerfile 指令指定 Dockerfile 文件名

  • 使用 arg 指令指定构建镜像时的变量,等价 docker build --build-arg,即给 ARG 变量传参

version "3.0"

services:
  tomcat01:   # 服务名,唯一
    build:
      context: /xxx   # 上下文命令:Dockerfile 所在的目录
      dockerfile: Dockerfile-otherName    # 默认叫 Dockerfile,如果是其他名,这里设置 
      args:       # 给 ARG 变量传参
        变量名: 值
1
2
3
4
5
6
7
8
9

示例:创建一个 Dockerfile 文件,并构建

首先创建一个 Dockerfile 文件,添加内容:(内容较少,这里只是演示 yml 文件进行构建,详细 Dockfile 内容请看:Docker - Dockerfile)

FROM tomcat:8.5.73

ARG ARGS

RUN echo $ARGS
1
2
3
4
5

yml 文件内容:






 
 
 
 

version: "3.0"

services:
  container_name: tomcat01   #  容器名
  tomcat01:  # 服务名,唯一
    build:
      context: ./   # 指定上下文目录:Dockerfile 所在的目录
      args:
        ARGS: hello docker
1
2
3
4
5
6
7
8
9

启动 yml 文件,查看镜像是否生成和启动:









 






 

# 启动 yml 文件
docker-compose up -d

# 查看镜像
docker images

# 返回结果
REPOSITORY                TAG       IMAGE ID       CREATED        SIZE
docker-compose_tomcat01   latest    39e47af1a1c1   3 hours ago    249MB

# 查看运行的容器
docker ps

# 返回结果
CONTAINER ID   IMAGE                     COMMAND             CREATED         STATUS         PORTS      NAMES
c7f73ee44c49   docker-compose_tomcat01   "catalina.sh run"   2 minutes ago   Up 2 minutes   8080/tcp   tomcat01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

可以看出,镜像名也是基于项目名(yml 文件所处的目录名)而命名的。

args 是否生效呢,请看构建过程图例:

image-20211124205401613

# depends_on(依赖)

解决容器的依赖、启动先后的问题。

version "3.0"

services:
  服务名1:   
    image: 服务 1 镜像
    depends_on:
      - 服务名 2
      - 服务名 3
      
  服务名2:
    image: 服务 2 镜像
    
  服务名3:
    image: 服务 3 镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14

服务 1 启动前,先等服务 2 和服务 3启动后自己再启动。

注意: 服务 1 不会等待服务 2 和服务 3 「完全启动」之后才启动,两个服务启动过半即可。depends_on 必须是服务名

示例:先启动 redis、es 再启动 tomcat

yml 文件内容:





 
 
 
 
 
 
 
 
 

version "3"

services:
  tomcat:
    depends_on:
      - es
      - redis
      
  redis:
    image: redis
    
  es:
    image: elasticsearch
1
2
3
4
5
6
7
8
9
10
11
12
13

# environment(环境变量)

设置环境变量。你可以使用数组或字典两种格式。

只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据。

有两种形式:

  • key: value
  • - key=value
# 形式 1
environment:
  RACK_ENV: development
  SESSION_SECRET: 123456

# 形式 2
environment:
  - RACK_ENV=development
  - SESSION_SECRET=123456
1
2
3
4
5
6
7
8
9

如果变量名称或者值中用到 true | false,yes | no 等表达 布尔 含义的词汇,最好放到引号里 (如 "true" | "false"),避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括:

y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF
1

示例:启动 MySQL 时,需要密码

我们都知道,启动 MySQL 镜像,需要给 MySQL 密码,否则报错。给定密码格式 docker run -e MYSQL_ROOT_PASSWORD=密码 mysql。

yml 文件内容:







 


version: "3.0"

services:
  container_name: tomcat01   #  容器名
  tomcat01:  # 服务名,唯一
    image: mysql:8.0.27   # 启动的 MySQL 镜像
    environment:
      MYSQL_ROOT_PASSWORD: 123456   # 假设这是 MySQL 密码
1
2
3
4
5
6
7
8

# env_file(环境变量文件)

从文件中获取环境变量,可以为单独的文件路径或列表。其实就是把上面的 environment 变量(数据库密码)放到一个 .env 文件里,然后引用这个文件(就相当于引用变量)

如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。

如果镜像自带的变量名称与 environment 指令冲突,则按照惯例,以后者为准。

两种形式:

  • 单文件: .env
  • 多文件:- .env、- .env
# 单文件
env_file: .env

# 多文件
env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env
1
2
3
4
5
6
7
8

环境变量文件中有一个必须符合格式,支持 # 开头的注释行,且内容格式是 key=value

# common.env: Set development environment
PROG_ENV=development
1
2

示例:在 mysql.env 文件里加上 MySQL 密码

mysql.env 文件内容:(先创建 touch mysql.env)

# 这是一个 MySQL 环境变量文件
MYSQL_ROOT_PASSWORD=123456
1
2

yml 文件内容:






 
 

version: "3.0"

services:
  tomcat01:  # 服务名,唯一
    image: mysql:8.0.27   # 启动的 MySQL 镜像
    env_file:
      - ./mysql.env   # 存放 MySQL 密码的 .env 文件
1
2
3
4
5
6
7

# command(命令)

覆盖容器启动后默认执行的命令,等价于 docker run 镜像 command 的 command。

command: echo "hello docker"
1

例子 1:启动 redis,开启 AOP 持久化

我们知道,启动 redis 持久化的 docker 指令是:docker run redis redis-server --appendonly yes

yml 文件内容:











 




version: "3.0"

services:
  redis:   # 服务名,唯一
    image: redis  
    container_name: redis
    ports:    # 映射端口
      - "6379:6379"
    volumes:     # 数据卷
      - redisData:/data
    command: "redis-server --appendonly yes"    # 启动容器执行的命令
    
volumes:   # 声明数据卷
  redisData:
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# healthcheck(健康检查)

通过命令检查容器是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 发生请求
  interval: 1m30s   # 发送请求时间
  timeout: 10s  # 超时时间
  retries: 3  # 重试次数
1
2
3
4
5

例子 1:启动 tomcat,并不断检测检测健康运行







 
 
 
 
 

version: "3.0"

services:
  mysql01:  # 服务名,唯一
    image: mysql:8.0.27   # 启动的 MySQL 镜像
    container_name: mysql
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"] # 发生请求
      interval: 1m30s   # 发送请求时间  
      timeout: 10s  # 超时时间
      retries: 3  # 重试次数
1
2
3
4
5
6
7
8
9
10
11

启动后,Docker 每隔 1 分 30 秒发送一次 curl -f http://localhost 的 CMD 请求,如果 10 秒内不响应,则重试 3 次。

# sysctls(系统控制参数)

用来配置容器中系统内部参数﹒并不是必须有些服务启动受容器内操作系统参数限制可能会无法启动必须通过修改容器中参数才能启动。

sysctls:  
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

# 必须在这里进行声明,否则报错
sysctls:
  - net.core.somaxconn: 1024
  - net.ipv4.tcp_syncookies: 0
1
2
3
4
5
6
7
8

必须声明。

例子 1:

yml 文件内容:







 
 
 


 
 
 

version: "3.0"

services:
  mysql01:  # 服务名,唯一
    image: mysql:8.0.27   # 启动的 MySQL 镜像
    container_name: mysql
    sysctls:  
      net.core.somaxconn: 1024
      net.ipv4.tcp_syncookies: 0

# 必须在这里进行声明,否则报错
sysctls:
  - net.core.somaxconn: 1024
  - net.ipv4.tcp_syncookies: 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# ulimits(资源限制)

指定容器的 ulimits 限制值。

例如,指定最大进程数为 65535,指定文件句柄数为 20000 (软限制,应用可以随时修改,不能超过硬限制)和 40000 (系统硬限制,只能 root 用户提高)。

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000
1
2
3
4
5

示例:

yml 文件内容:







 
 
 
 
 

version: "3.0"

services:
  mysql01:  # 服务名,唯一
    image: mysql:8.0.27   # 启动的 MySQL 镜像
    container_name: mysql
    ulimits:
    nproc: 65535
    nofile:
      soft: 20000
      hard: 40000
1
2
3
4
5
6
7
8
9
10
11

# 模板文件参考

version: "3.0"

services:
  
  tomcat01:  # 服务名,唯一
    container_name: tomcat01  # 相当于 run 的 --name
    image: tomcat:8.5.73   # 启动镜像,相当于 run image
    ports:  # 用来完成 host 与容器的端口映射关系,相当于 run -p
      - "8080:8080"
    volumes:  # 完成宿主机与容器中目录数据卷共享相当于 run -v
    # - /root/apps:/usr/local/tomcat/webapps  # 使用具体目录挂载
      - tomcat01:/usr/local/tomcat  # 使用默认目录挂载
    networks:    # 代表当前服务使用哪个网络桥,相当于 run --network
      - kele
  
  tomcat02:  # 服务名,唯一
    container_name: tomcat02  # 容器名
    image: tomcat:8.5.73    # 镜像
    ports:     # 映射端口
      - "8081:8080"
    volumes:  # 宿主机和容器的数据卷共享
      - tomcat02:/usr/local/tomcat  # 使用默认目录挂载
    networks:   # 代表当前服务使用哪个网络桥
      - kele

  tomcat03:
    build:   # 构建模式,相当于 docker build 
      context: ./    # 指定上下文的路径:Dockerfile 所在的目录
      args:   # 传参,相当于 docker build --build-arg
        ARGS: hello docker     
  
  mysql:
    image: mysql:8.0.27
    container_name: mysql
    ports:
      - "3307:3306"
    volumes:
      - mysqlData:/var/lib/mysql
      - mysqlConf:/etc/myconf
    environment:
      - MYSQL_ROOT_PASSWORD=123456
    networks:
      - kele
  
  redis:
    image: redis:5.0.10
    container_name: redis
    ports:
      - "6379:6379"
    volumes:
      - redisData:/data
    networks:
      - bing
    command: "redis-server --appendonly yes"  # run 镜像之后来覆盖容器内默认命令
    
volumes:   # 声明上面的服务所使用的自带创建的数据卷名
  tomcat01:   # 声明指令的数据卷名,compose 自带创建该卷,但是会加入项目名作为前缀
    external:  # 使用自定义数据卷名
      true    # 代表确认使用指定的数据卷名,注意:一旦使用外部自定义数据卷名,启动服务前必须手动创建 
  tomcat02:
  mysqlData:
  mysqlConf:
  redisData:
    
networks:   # 声明服务用到的网桥
  kele:    # 定义上面的服务用到的网桥,默认创建时 bridge
    external:    
      true    # 使用外部指定的网桥,注意:启动前网桥必须存在
  bing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 6. 常用指令

# 模板指令和常用指令的区别

  • 模板指令:用来书写在 docker-compose.yml 文件中指令称之为模板指令用来为服务进行服务的
  • 常用指令:用来对整个 docker-compose.yml 对应的这个项目操作

# 命令对象格式

对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响。

执行 docker-compose [COMMAND] --help 或者 docker-compose help [CONMAND] 可以查看具体某个命令的使用格式。

docker-compose 命令的基本的使用格式是:

docker-compose [-f=<arg> ......] [options] [COMMAND] [ARGS ......]
1

# 命令选项

-f <模板文件名>
--file <模板文件名>
指定使用的 Conpose 模板文件,默认为 docker-compose.yml,可以多次指定
-p <项目名>
--project-name 项目名
指定项目名称,默认将使用所在目录名称作为项目名
--x-networking 使用 Docker 的可拔插网络后端特性
--x-network-driver <驱动名> 指定网络后端的驱动,默认为 bridge
--verbose 输出更多调试信息
-v
--version
打印版本并退出

例子 1:假设不叫 docker-compose.yml 文件,叫 kele.yml 文件,启动它

docker-compose -f kele.yml up
1

例子 2:虽然 docker-compose.yml 文件在 aa 目录下,但是我希望项目名不叫 aa 名,而是叫 bb,启动它

docker-compose -P bb up
1

# up(启动)

启动 yml 文件里的单个/所有服务,如果不指定服务 id,默认启动所有服务。

格式:docker-compose up [options] [ service ... ]。

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

# 后台启动
docker-compose up -d [ service ...]

# 指定 yml 文件所在的目录启动
docker-compose -f <文件路径> up
1
2
3
4
5
6
7
  • 该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作

  • 链接的服务都将会被自动启动,除非已经处于运行状态

  • 可以说,大部分时候都可以直接通过该命令来启动一个项目

  • 默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,可以很方便进行调试

  • 当通过 Ctrl-C 停止命令时,所有容器将会停止

  • 如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项

  • 默认情况,如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容

# down(停止并移除)

此命令将会停止 up 命令启动的单个/所有服务,并移除自己创建的网络,但不会移除数据卷。

格式:docker-compose down [ service ...]

docker-compose down [ service ...]
1

# exec(执行命令)

进入指定的服务,使用的是服务 id,并非容器 id。

格式:docker-compose exec [ service ] [窗口命令]

docker-compose exec [ service ] [窗口命令]
1

# ps(列出服务)

列出项目中目前的单个/所有服务,如果不指定服务 id,默认列出所有服务。

格式:docker-compose ps [options] [ service ...]

docker-compose ps [options] [ service ...]
1

选项:

  • -q:只打印容器的 ID 信息。

# restart(重启)

重启项目中的单个/所有服务,如果不指定服务 id,默认重启所有服务。

格式:docker-compose restart [options] [ service ...]

docker-compose restart [options] [ service ...]
1

选项:

  • 简写:-t,完整 --timeout 时间数:重启前停止容器的超时(默认为 10 秒)

# rm(删除)

删除单个/所有(停止状态的)服务,如果不指定服务 id,默认删除所有服务。推荐先执行 docker-compose stop 指令来停止容器给再删除。

格式:docker-compose rm [options] [ service ...]

docker-compose rm [options] [ service ...]
1

选项:

  • 简写 -f、完整 --force:强制直接删除,包括运行状态的容器,一般尽量不要使用该选项
  • -v:删除容器所挂载的数据卷,同样慎用

# start(启动已存在的服务)

启动已经存在的单个/所有服务。

格式:docker-compose start [service ...]

docker-compose start [service ...]
1

# stop(停止运行的服务)

停止已经处于运行状态的单个/所有服务,但不会删除它,如果不指定服务 id,默认停止所有服务。通过 docker-compose start 可以再次启动这些容器。

格式:docker-compose stop [options] [ service ...]

docker-compose stop [options] [ service ...]
1

选项:

  • 简写:-t,完整 --timeout 时间数:停止容器时候的超时(默认为 10 秒)

# top(查看进程)

查看单个/所有服务内运行的进程。

格式:docker-compose top [ service ...]

docker-compose top [ service ...]
1

# pause(暂停服务)

暂停单个/所有服务。

格式:docker-compose pause [ service ...]

docker-compose pause [ service ...]
1

# unpause(恢复服务)

恢复处于暂停状态的单个/所有服务。

格式:docker-compose unpause [ service ...]

docker-compose unpause [ service ...]
1

# logs(查看日志)

查看单个/所有服务的日志信息。

格式:docker-compose logs [ service ...]

docker-compose logs [ service ...]
1
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Docker - Dockerfile
Docker - Ideal集成

← Docker - Dockerfile Docker - Ideal集成→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式