文章目录

什么是compose?定义“多个容器怎么一起跑”

把一整套多容器应用,写进一个配置文件里,然后用一条命令统一启动
compose 就是把“多个容器如何一起运行”写到一个 YAML 文件里,再用一条命令统一管理整套应用。

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

Docker Compose 的核心就干三件事,批量保存 docker run 的参数,建立容器间的“内部对讲机”(网络隔离与互通),严格控制启动顺序(Compose 里的 depends_on 参数可以指定)。参见docker compose章节

Docker 关注的是单个容器的打包和运行(怎么把我的 Python 代码连同环境塞进一个集装箱)。
Docker Compose 关注的是多容器的协同(怎么把网页、数据库、缓存这堆集装箱用一根线连起来,并且一键全部启动)

在这里插入图片描述

Docker Compose 的配置对象叫 services,但它最终会把每个 service 启动成一个或多个容器。service = 容器的启动模板 / 配置定义,container = 根据 service 真正启动出来的运行实例。参见docker compose章节

Compose 管理多个容器 是对最终运行结果说的;而 YAML 里写 services 是对“容器应该怎么启动”的抽象定义
然后根据每个 service 的配置去创建、启动、停止、管理对应的容器。

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

Compose 默认会给你的应用创建一个网络,每个服务的容器都会加入这个默认网络,并且容器之间可以直接通过服务名互相访问

为什么 Compose 也会创建网络,因为 Compose 的目标就是让一组服务一起运行并互相通信。Docker 官方说明,Compose 默认会为你的应用创建一个网络,每个服务对应的容器都会加入这个默认网络,并且能通过服务名互相发现和访问。

在这里插入图片描述

容器名(container name)/主机名(hostname)/服务名(service name,Compose 里)

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

通常说的主机名,不是部署 Docker 的那台真实宿主机名字

主机名的作用是:
👉 让别的容器“找到你在哪”(解析到 IP)
在这里插入图片描述
在这里插入图片描述

compose创建的默认网络,主机名,服务名的作用

Docker Compose 会创建一个默认网络(bridge 网络),把所有容器都加入到这个网络里( 同一个 compose 里的服务默认都在同一个网络),Docker 的网络驱动会给每个容器分配 IP(但注意:这个 IP 是 动态的每次重启可能变),并自动把 服务名注册到Docker 在容器网络里内置的DNS 服务即:
服务名(redis)
↓ Docker 自动注册
内部 DNS 表

容器 IP (172.x.x.x)
后续各个容器直接可以通过服务名访问

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

在 Docker 里:不是所有程序都默认监听 0.0.0.0。但在容器里,如果你想“外部/其他容器访问”,通常必须监听 0.0.0.0

在 Docker 网络里:“谁要被访问,谁就必须监听 0.0.0.0”

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

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

dns准确的说是,名字->ip的解析器

在这里插入图片描述

Docker Compose 中,Docker 自己内置了一个“局域网 DNS”,服务名 → 容器 IP

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

Compose 会创建默认网络,每个服务会用服务名注册到内部 DNS,容器之间可以直接通过服务名访问,容器名确实也会作为网络里的可解析名字之一,不推荐写容器名

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

既然已经可以用 service name 访问了,那主机名有啥用?

hostname 不是给网络用的
你要记住一句非常关键的话:
❗ 网络访问靠 service name(DNS)
❗ hostname 是“容器内部身份”
因为在 Docker Compose 默认模式下:
👉 service name ≈ hostname(经常一样)

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

宿主机怎么访问容器呢?通过端口映射

在 Docker 里:

👉 宿主机访问容器 = 通过端口映射(port mapping)

而不是 service name,也不是容器 IP

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

容器网络里只能有一个容器监听 5000,否则 Docker 不知道给谁”?错误

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

容器怎么访问宿主机?

在 Docker 里:
👉 容器访问宿主机,本质是:走宿主机的“特殊地址”或“网关”
不是 service name

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

在 Docker 里:
👉 host.docker.internal 是“宿主机的名字(别名)”
👉 host-gateway 是“Docker 自动帮你填的宿主机 IP”

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

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

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

在这里插入图片描述

在 Docker 网络里有三种访问方式

在这里插入图片描述

容器 → 容器(内部通信):用服务名

在这里插入图片描述

宿主机 → 容器:用端口映射

在这里插入图片描述

外部网络 → 宿主机 → 容器:用端口映射

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

Compose 创建的是什么网络

在这里插入图片描述

和你手动创建网络是什么关系

在这里插入图片描述

–driver:决定“网络是什么类型”,比如 bridge、overlay。容器互联:是“多个容器接到同一个网络里”

–driver 只解决第 1 步里的“这个网络是什么类型”,不等于“容器已经互联了”

在这里插入图片描述

总结

在这里插入图片描述

Compose 使用的三个步骤

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

使用 Dockerfile 定义应用程序的环境

第一步不一定非要有 Dockerfile。
如果某个服务直接使用现成镜像,比如 nginx、mysql,Compose 文件里写 image: 就够了;只有当你要从自己的源码构建镜像时,才通常会配合 Dockerfile 和 build: 使用。Docker 官方明确说明,Compose 里的 build 是可选的

使用 docker-compose.yml/compose.yaml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行

是配置文件,用来写“这套应用要启动哪些服务、每个服务怎么启动、端口怎么映射、卷怎么挂、网络怎么连”。Docker 官方把 Compose 文件定义成用来描述应用的服务、网络、卷等配置

docker-compose.yml 的配置案例

有两个服务:一个是自己从当前目录构建出来的 web,一个是直接用现成镜像的 redis;web 把宿主机当前目录挂到容器 /code,把一个叫 logvolume01 的卷挂到 /var/log,并把容器 5000 端口映射到宿主机 5000。 Compose 默认会给它们放进同一个网络里,服务之间通常可以直接按服务名通信

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

build: . 的意思是:不要直接使用现成镜像,而是用当前目录下的 Dockerfile 构建一个镜像,然后再用这个镜像启动容器

Docker 官方文档里也说明了:build 的路径可以是绝对路径或相对路径;如果是相对路径,就从 Compose 文件所在目录 来解析

Dockerfile 里的路径:
通常相对于 build context,也就是 build: . 指定的目录。
compose.yaml 里的 build: .:
相对于 compose.yaml 所在目录。

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

volumes(宿主机路径/卷名:容器内路径): - .:/code。把宿主机上的 . 这个目录,挂载到容器里的 /code 目录

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

最后,执行 docker-compose up/docker compose up 命令来启动并运行整个应用程序。docker compose up 可以理解成一句话:读取 compose.yaml 文件,然后按照里面的 services 配置,把需要的容器、网络、数据卷都创建并启动起来。也就是说,你不用自己写很多条 docker run,Compose 会根据配置文件自动帮你做

执行命令,会读取当前目录里的 Compose 配置,然后把这套应用构建、创建、启动起来
compose.yaml:图纸
docker compose up:按图纸开工
compose.yaml 负责“定义怎么跑”,docker compose up 负责“真正跑起来”
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

docker compose up 和 docker run 的区别

docker run:
我手动启动一个容器。
docker compose up:
我把一堆容器怎么启动写到 compose.yaml 里,
然后让 Docker Compose 自动帮我创建网络、拉镜像、建容器、启动容器。

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

Compose 安装

最简单的官方推荐安装方式是仓库安装,比如 Ubuntu / Debian:
sudo apt-get update
sudo apt-get install docker-compose-plugin
docker compose version
RPM 系发行版则是:
sudo yum update
sudo yum install docker-compose-plugin
docker compose version
这些都是官方当前写法

docker compose version
在这里插入图片描述
在这里插入图片描述

示例

composetest/app.py

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

Compose 默认会创建一个网络,每个服务加入后,都可以通过服务名被其他容器访问;容器可以把服务名解析成对应容器的 IP

在这里插入图片描述

host=‘redis’,去同一个 Compose 网络里,找名字叫 redis 的那个服务

详情见:compose创建的默认网络,主机名,服务名的作用 章节

创建 Dockerfile 文件

Dockerfile 通常不需要后缀。
标准写法就是文件名直接叫:
Dockerfile
不是:
Dockerfile.txt
Dockerfile.docker
Dockerfile.yml
默认推荐文件名就是 Dockerfile,没有后缀;如果你改了名字,就要用 -f 指定

为什么没有后缀也可以? 因为 Docker 默认找的就是这个固定名字: Dockerfile 所以你执行: docker build .
时,Docker 会默认在当前目录找这个文件。

如果你不用这个名字,也不是不行。 比如你写成: mydockerfile Dockerfile.dev Dockerfile.test
那构建时要手动指定: docker build -f Dockerfile.dev . 这里 -f 就是告诉 Docker: 这次用哪个
Dockerfile。

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

apk 是 Alpine Linux 的包管理器命令,相当于:
Ubuntu / Debian 里的 apt
CentOS / RHEL 里的 yum / dnf
Alpine 官方文档直接说明了,apk 是 Alpine Package Keeper,用来管理 Alpine 系统里的软件包

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

默认情况下,COPY . . 会把当前 build context 里的所有文件再复制一遍,其中也包括 requirements.txt

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

COPY . . COPY requirements.txt requirements.txt 重复了吧,为什么不只保留COPY . .

先单独 COPY requirements.txt,再 pip install,最后 COPY . .,是为了让“安装依赖”这一层尽量复用缓存;不是重复,而是优化构建速度

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

某一层一旦变了,后面所有层都要重新执行

Docker 看的是层有没有变,某一层一旦变了,后面所有层都要重新执行

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

Docker 缓存:“上次 build 做过、而且结果还能复用的那些中间结果。每一条指令都会变成最终镜像中的一层

上次 build 做过、而且结果还能复用的那些中间结果。”
Docker 官方说得很直接:Dockerfile 里的每一条指令都会变成最终镜像中的一层;当你再次构建同一个镜像时,只要某一层没有变化,Docker 就可以直接复用那一层,不必重新执行

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

创建 compose.yml

services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: redis:alpine

:用 Compose 一次启动两个服务:一个你自己构建的 web,一个现成的 redis。 Compose 会默认给这两个服务创建一个应用网络,服务之间可以直接用服务名互相访问

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

使用 Compose 命令构建和运行您的应用

docker compose up/docker-compose up

般要在 docker-compose.yml 或 compose.yaml 所在的目录执行 docker compose up
因为 docker compose up 默认会在当前目录查找 Compose 配置文件。Docker 官方当前说明,默认会查找 compose.yaml、compose.yml、docker-compose.yaml、docker-compose.yml
如果你不在这个目录里,也不是完全不能执行。可以显式指定文件

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

执行 docker compose up 之后,当前窗口会持续显示各个容器打印出来的输出。默认 attached mode 下,你会看到所有容器的日志

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

docker compose up -d

在这里插入图片描述

-d 之后怎么看日志,docker compose logs

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

容器启动后,只要程序还在往标准输出/标准错误里打印内容,这些都算容器日志

docker compose logs
看到的是:
从容器启动以来,到你执行这条命令这一刻为止的日志。

在这里插入图片描述

容器的日志

docker compose logs 看的主要就是容器进程写到 STDOUT(标准输出) 和 STDERR(标准错误) 的内容。 Docker 官方对
docker logs 的说明就是“获取容器的 STDOUT 和 STDERR 日志”,而 docker compose up
默认也是把各服务的输出聚合显示出来

主要能看到容器的标准输出和标准错误;Docker 默认使用日志驱动记录容器日志,默认通常是 json-file。如果程序只把日志写进容器内文件,而不输出到 stdout/stderr,那 docker logs / docker compose logs 一般看不到

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

单个容器查看日志:docker logs <容器名或容器ID>/docker logs -f <容器名或容器ID>

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

Compose 启动的一组容器

把这一组容器的日志一起看,用docker compose logs/docker compose logs -f

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

只看其中某一个服务的日志:docker compose logs/docker compose logs -f 服务名

在这里插入图片描述

容器日志:某一个具体容器的日志,服务日志:某个服务下面一个或多个容器的日志,Compose 帮你按服务名聚合着看

service 定义是:服务是一个抽象定义,背后由一组容器支撑。
Compose 看的是“服务”的日志
但这些日志来源仍然是服务对应容器的 stdout/stderr

Compose 不是不能看容器日志,而是它默认帮你按“服务”把容器日志组织起来看;单个容器的精确日志则更适合用 docker logs。

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

2者看起来有区别的例子

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

重新启动

docker compose restart/docker compose restart 服务名 重新启动现有服务/某个服务不会重新构建镜像

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

docker compose down 连容器一起删掉,再重新创建启动

把这套 Compose 应用停掉,并且把它创建出来的容器和网络删除掉。 Docker 官方对 down 的定义就是:停止容器并移除容器、网络。默认也会移除 Compose 项目里定义的默认网络
命名卷默认不会被删
匿名卷默认也不会被删
但如果你加 -v,卷也会一起删掉。Docker 官方对 down --volumes 的说明就是移除命名卷和匿名卷
docker compose down = 停掉并拆掉这套 Compose 应用的运行环境,但默认不删镜像,也不删卷

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

docker compose down --rmi local/–rmi all 把相关镜像也删掉

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

–rmi local,“tag”理解成镜像的“名字:版本”

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

docker compose down -v,docker compose rm -v,删除卷

在这里插入图片描述

查看卷 docker volume ls,docker volume inspect <卷名>

在这里插入图片描述

docker volume inspect 就是看“这个卷叫什么、什么时候建的、数据实际存在哪”

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

删除卷

如果你知道卷名,直接删:
docker volume rm <卷名>
这个是“删除一个或多个卷”。正在被容器使用的卷不能直接删,必要时可以加 -f 强制
docker volume prune
它会删除未使用的本地卷;默认只删匿名卷

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

代码或 Dockerfile 改了,要重新构建再启动,docker compose up -d --build

第一,先重新构建需要 build 的镜像。
这里的 --build 表示在启动容器前先 build 镜像。
第二,再把容器在后台启动起来。
这里的 -d 是 detached mode,也就是后台运行,不一直占着当前终端。
你可以把它翻成人话:
“我改了代码环境或 Dockerfile,先重新做镜像,再把这套服务启动起来,而且放到后台跑。”
–build = “该重做镜像的我先帮你重做”,不是“你得先自己停掉、删掉再执行”

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

redis 怎么查看

按 Compose 服务名进去 docker compose exec 服务名redis-cli。按具体容器名进去 docker exec -it <实际容器名/容器id> redis-cli

docker compose exec redis redis-cli
= 在 redis 服务 对应的容器里执行 redis-cli
docker exec -it 容器名 redis-cli
= 在 某个具体容器 里执行 redis-cli
docker exec -it 容器ID redis-cli
= 同上,只是把容器名换成了容器 ID

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

KEYS * 查看当前数据库里的所有键。看某个键的值 GET

在这里插入图片描述

看当前数据库有多少个键:

DBSIZE

看某个键是什么类型:

TYPE hits

删除某个键:

DEL hits
SCAN 0 是 Redis 的游标式遍历键命令

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

怎么判断redis有没有用卷做持久化

看 Compose 文件里 Redis 服务有没有 volumes:docker compose config

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

检查容器挂载信息:docker inspect <redis容器名/容器id>

在这里插入图片描述

Compose 文件redis没写 volumes:,检查结果里还是出现了 Mounts

没在 Compose 文件里手写 volumes:,但 Redis 还是挂了一个卷。原因是:

Redis 官方镜像自己就在镜像里声明了 /data 是一个 VOLUME。 Dockerfile 里的 VOLUME
会让容器运行时在这个位置创建挂载点;如果你没手动指定卷,Docker 会创建一个匿名卷。Redis
官方镜像文档明确提到,启用持久化时数据存放在 VOLUME /data

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

redis逻辑数据库

Redis 可以有多个逻辑库
编号从 0 开始
有多少个库是可配置的
很多情况下默认是 16 个,也就是 0 到 15

在这里插入图片描述

切换逻辑数据库 select x.怎么看当前 Redis 一共有多少个库 CONFIG GET databases

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

yml 配置指令参考

build在告诉 Compose,这个服务的镜像要怎么构建

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

context

在这里插入图片描述

dockerfile

在这里插入图片描述

args

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

target

在这里插入图片描述

cap_add,cap_dropcap_add 和 cap_drop 用来给容器增加或移除 宿主机Linux capabilities(内核能力)

cap_add / cap_drop 是在调容器的“内核能力清单”,不是简单的文件权限

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

cgroup_parent为容器指定父 cgroup 组,意味着将继承该组的资源限制。

cgroup 理解成:
Linux 用来管进程资源的一种分组机制

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

Compose 里的 command,就是在启动容器时改掉镜像默认的 CMD

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

container_name指定自定义容器名称,而不是生成的默认名称。不要让 Compose 自动生成容器名,而是强行把这个容器命名成xx

container_name 就是手动指定容器名;好处是名字固定好找,代价是这个服务不能方便地扩成多个副本

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

depends_on 主要管“启动/停止顺序”,不等于“等对方完全可用再启动”

depends_on 默认是“排队启动”,不是“等对方完全可用”;要等可用,得配 healthcheck + condition: service_healthy
不设置:别依赖顺序
设置 depends_on:有顺序
还想等服务真正可用:再加 healthcheck + condition: service_healthy

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

services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  redis:
    image: redis

  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      retries: 5
      start_period: 30s
      timeout: 10s

在这里插入图片描述

数据库容器启动后,先给它 30 秒热身;然后每 10 秒检查一次“Postgres 是否已经能接收连接”;单次检查最多等 10 秒;如果连续失败 5 次,就认为它不健康

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

deploy: 是“部署策略”配置,主要给编排平台用。

在 Compose 规范里它是可选部分;如果当前实现不支持,就会被忽略。在 Docker 的 Swarm 场景里,这一块最有用;而本地普通
docker compose up 下,很多 deploy 字段并不会按你想的那样生效

mode / replicas:决定跑几个实例
endpoint_mode:决定别人怎么访问这组实例
resources:决定资源上限和预留
restart_policy:决定失败后怎么重启
update_config / rollback_config:决定升级和回滚怎么做

devices 宿主机上的设备文件映射进容器里

devices 不是挂普通文件,而是把宿主机真实硬件设备“接”给容器用

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

dns:给这个服务对应的容器,单独指定它要用哪些 DNS 服务器

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

daemon.json 管“默认大家都用什么”,Compose 的 dns: 管“这个服务例外用什么”,容器里最终看到的是 /etc/resolv.conf 那一层的结果

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

dns_search 自定义 DNS 搜索域。可以是单个值或列表。

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

entrypoint覆盖容器默认的 entrypoint。

在 Compose 里,entrypoint 用来覆盖镜像原本的 ENTRYPOINT
Compose 里的 entrypoint 是用来改“容器启动时固定执行的入口程序”的;字符串形式像直接写一条入口命令,数组形式像把程序和参数一个个写清楚

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

env_file,env_file 用来把一个或多个环境变量文件里的键值,批量传给这个服务对应的容器

env_file = 从外部文件批量给容器注入环境变量;多个文件时后面的覆盖前面的,environment 又会覆盖 env_file
不用管谁写在前面或后面。
在 Compose 里,只要同一个服务同时设置了 env_file 和 environment,environment 一定优先,官方原话就是:environment has precedence over env_file

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

.env 文件本身怎么写?

在这里插入图片描述

environment 是在 Compose 里直接给容器设置环境变量

environment 就是直接在 Compose 文件里给容器设置环境变量;像 true、false 这种值最好加引号,避免被 YAML 当成布尔值

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

expose expose 只是在容器网络内部声明/开放端口,不映射到宿主机。暴露给其他服务访问的内部端口

expose 只是在容器网络内部声明/开放端口,不映射到宿主机。
Docker Compose 官方写得很清楚:expose 定义的是容器对外暴露给其他服务访问的内部端口,这些端口不应该发布到宿主机,而且这里只能写容器内部端口

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

extra_hosts 是手动往容器里的 /etc/hosts 加“名字 → IP”的映射

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

healthcheck:给这个服务定义一个健康检查。Compose 会定期运行检查命令,判断容器是不是 healthy。它的行为和 Dockerfile 里的 HEALTHCHECK 基本一致,默认值也一致。

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

CMD 是直接执行“程序 + 参数”,CMD-SHELL 是把整行命令交给 shell 去解释。

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

image:这个服务启动容器时要用的镜像来源

image = 这个服务启动容器时要用的镜像来源

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

logging 用来配置这个服务容器的日志怎么收集、存到哪、怎么轮转

在这里插入图片描述

driver表示用哪种日志驱动。

Compose 文档里说,logging.driver 指定服务容器使用的日志驱动;可用值跟平台有关。Docker Engine
层面默认日志驱动通常是 json-file。Docker 官方还特别提醒:json-file 默认不做日志轮转,而 local
驱动默认会做轮转,很多场景下更推荐 local

在这里插入图片描述

driver: local

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

driver: json-file 把容器日志保存成 JSON 文件

把容器日志保存成 JSON 文件。这是 Docker Engine 的默认日志驱动。它适合直接用 docker logs / docker compose logs 查看。官方同时提醒,如果不做轮转,日志文件可能越积越大

在这里插入图片描述

driver: syslog 把日志发到宿主机或远端的 syslog 系统

把日志发到宿主机或远端的 syslog 系统。Docker 官方说明,syslog 驱动会把日志写到 syslog facility,前提是宿主机上有可用的 syslog 服务

在这里插入图片描述

driver: none 完全不记录日志

options表示这个驱动自己的配置项,

不同驱动支持的选项不同。Compose 文档说明,驱动相关选项通过 options 这个键值对来传

即使你没在 Compose 里配置 logging:,docker compose logs 也通常能看到日志,因为 Docker daemon 本身有一个默认日志驱动

在这里插入图片描述

日志存到哪?

在这里插入图片描述

docker info --format '{{.LoggingDriver}}'
docker inspect -f '{{.HostConfig.LogConfig.Type}}' <容器名或容器ID>
docker inspect -f '{{.LogPath}}' <容器名或容器ID>

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

删除日志

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

logging 是“Docker 怎么收集和保存容器日志的配置”,而“容器的日志”通常指容器进程写到 STDOUT/STDERR 的那些输出

容器日志:程序往控制台打出来的内容
logging:Docker 用什么方式接住并保存这些内容

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

network_mode 这个服务容器用哪种网络模式

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

network_mode:none

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

network_mode: “host”

在这里插入图片描述

network_mode: “service:[service name]”

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

network_mode: “container:[container name/id]”

在这里插入图片描述

networks

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

顶层 networks:这是在定义有哪些网络,以及这些网络怎么创建,比如用什么驱动

在这里插入图片描述

顶层 networks: 里的 driver 是在指定这张网络用哪种网络驱动创建

在这里插入图片描述

服务里的 networks:这是在说:这个服务要接入哪些网络。如果一个服务接入同一网络,才能和这个网络上的其他服务通信

在这里插入图片描述

aliases 就是这个服务在某张网络上的别名。

在这里插入图片描述

restart :容器退出以后,要不要自动再拉起来。

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

secrets

先在顶层 secrets 里定义 secret,再在具体服务里通过 services..secrets 去引用它;而且 secret 的访问权限是按服务单独授予的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在 Compose 里,secrets 会把你本机文件里的内容,挂到容器里的 /run/secrets/<名字>
这个位置,而且是按服务单独授权的;只在顶层定义 secret 还不够,服务里还得显式写 secrets: 才能拿到

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

security_opt 给容器补充或修改安全限制

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

stop_grace_period

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

stop_signal 停止容器时,先发哪个信号。

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

sysctls

sysctls = 给容器自己的“内核参数空间”调参数;能调的前提是这个参数本身支持命名空间隔离,且不能影响宿主机

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

tmpfs 在容器里面挂一个“临时内存文件系统”

哪个目录被声明成 tmpfs,往那个目录及其子目录写文件,就是写到 tmpfs

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

ulimits 就是:覆盖这个容器默认的资源上限

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

volumes 将主机的数据卷或者文件挂载到容器里。

Docker 把容器外部存储大致分成 bind mounts、volumes、tmpfs;其中 bind mount 是“把宿主机上的某个真实文件或目录挂进容器”,而 volume 是“由 Docker 自己管理的持久化存储目录
volumes: 是 Compose 里声明“挂载”的地方;但具体挂载出来的东西,可能是 bind mount,也可能是 Docker volume

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

bind mount 短语法,宿主机目录 : 容器内目录

Docker Compose 官方文档说明:对于 bind mount,短语法会在宿主机 source path 不存在时自动创建目录,这是为了兼容旧版 docker-compose 行为;长语法里也有 create_host_path,默认是 true。

在这里插入图片描述

自动创建的是“目录”,不是文件

在这里插入图片描述

创建出来的目录通常是 root 权限

容器运行用户的 UID/GID 要和宿主机挂载目录的 owner 权限匹配

在这里插入图片描述

创建出来的目录通常是 root 权限”这句话的意思是:
虽然你是在宿主机上用普通用户执行:
docker compose up -d
但真正帮你创建 bind mount 宿主机目录的,往往不是你当前这个普通用户,而是 Docker daemon。
而 Docker daemon 通常是以 root 用户运行的。

在这里插入图片描述

在这里插入图片描述

Linux 权限本质上看的是 UID/GID,不是用户名

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

容器进程是哪个权限在运行
docker compose exec dev-extracting-context ps -o user,uid,gid,comm -p 1

在这里插入图片描述

Docker Compose 文档也说明,user 会覆盖容器进程使用的用户;如果 Compose 没设置,则使用镜像 Dockerfile 的 USER,如果镜像也没设置,则默认是 root

docker compose top dev-extracting-context
docker inspect codex-dev-extracting-context --format '{{.Config.User}}'

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

看 Compose 文件里有没有设置 user
Dockerfile 的 USER 指令就是用来设置后续构建步骤以及容器运行时 ENTRYPOINT / CMD 默认用户的【Dockerfile 里写了 USER 之后,
它后面的 RUN 命令会用这个用户执行;
并且容器启动时,ENTRYPOINT 或 CMD 里的主程序也默认用这个用户执行。】
USER app
意思是:从这一行开始,Dockerfile 后面的命令默认都用 app 这个用户执行;并且容器真正启动时,默认也用 app 这个用户运行程序。
USER 就是在 Dockerfile 里切换默认执行用户;它会影响后面的 RUN,也会影响容器启动时 CMD / ENTRYPOINT 里的主程序
Compose 里的 user 可以覆盖 Dockerfile 的 USER

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

可以在 docker-compose.yaml 里指定启动用户

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

如果不想让它自动创建,可以用长语法

在这里插入图片描述

Compose 文件里 ${VAR} 这种“变量替换”的来源

Compose 会先从你执行命令的 shell 环境里找变量。Docker 官方文档也说明,变量插值优先来自 shell environment
Compose 也会读取 .env,把 ${USERNAME} 替换掉。Docker 官方文档说明,.env 文件是 Compose 变量插值的默认方式之一
通过 --env-file 指定的 env 文件

对于 ${VAR} 这种 Compose 文件插值,优先级是:

  1. 当前 shell 环境变量
  2. 如果没有显式指定 --env-file,则读取当前工作目录 PWD 下的 .env
  3. –env-file 指定的文件,或者项目目录下的 .env

当前 shell 环境变量

在这里插入图片描述

.env 文件

在这里插入图片描述

通过 --env-file 指定的 env 文件

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

总结

Dockerfile 里的 ENV,构建镜像时,后面的 RUN/CMD/ENTRYPOINT 可以用;容器启动后,如果没有被覆盖,容器里也能看到。

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

compose 旁边的 .env。.env 默认主要是给 Compose 文件做变量替换 用的

.env 会被 Compose 用于插值
在这里插入图片描述
在这里插入图片描述

docker compose --env-file .env.dev。不要用默认 .env,改用 .env.dev 来做变量替换

environment 可以直接设置容器内的环境变量

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

compose 里的 environment,明确把这些变量传进容器

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

compose 里的 env_file,把文件里的变量作为环境变量批量传进容器

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

容器内环境变量的覆盖顺序

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

容器里的环境变量,本质上是:给容器内进程使用的一组配置参数

容器启动时,Docker 会把环境变量交给容器的 1 号进程。
之后由这个 1 号进程启动的子进程,默认都会继承这些环境变量

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

多个 Compose 文件合并时,核心规则是:前面的文件是基础配置;后面的文件在前面的基础上覆盖、追加、合并

Docker 官方说明:多个 -f 文件会按命令行顺序合并,后面的文件会 override 或 add 前面的配置

在这里插入图片描述

同名 service:合并。
单值字段:后面覆盖前面。
普通列表:后面追加前面。
environment:按变量名合并,同名后面覆盖。
ports:一般追加,唯一键冲突才合并。
volumes:按容器内 target 合并,同 target 后面覆盖。
command / entrypoint:后面直接覆盖,不追加。

1. 同名 service 会合并,不是整个替换。mapping规则

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

.environment:按变量名合并,同名覆盖

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

2. 普通单值字段:后面直接覆盖前面

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

3. 普通列表字段:后面追加到前面

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

ports:通常是追加,不是直接覆盖

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

ports 又不是普通列表那么简单,它属于 Compose 里的 特殊列表资源。因为端口映射有唯一标识,比如:宿主机端口 + 容器端口 + 协议

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

在这里插入图片描述

为了判断两条 ports 配置是不是“同一个端口资源”,Compose 会看这一组字段:ip + target + published + protocol

普通列表:
只知道一条一条往后加。
ports 这种 unique resources:
先看“唯一键”是不是同一个资源。
如果唯一键一样:认为是同一个资源,合并/覆盖。
如果唯一键不同:认为是不同资源,追加。

ip:绑定到宿主机哪个 IP
target:容器内部端口
published:宿主机暴露端口
protocol:协议,tcp 或 udp

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

volumes:按容器内挂载目标判断是否覆盖

volumes 在 YAML 里确实也是列表,所以它首先也有“追加”的特征。
但是它和普通列表不一样。volumes 属于 Compose 的 特殊唯一资源 unique resources。官方规则是:volumes 虽然写成 sequence/list,但它有唯一键,唯一键是 target,也就是容器内挂载路径。如果新条目不违反唯一性约束就追加;如果唯一键相同,就合并/覆盖

在这里插入图片描述

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

command、entrypoint 不会追加,只会整体覆盖

command、entrypoint 可以写成字符串,也可以写成列表,但在 Compose 多文件合并规则里,它们被当成 “shell command 类字段”,所以 后面的直接覆盖前面的,不追加。Docker Compose 规范明确说,command、entrypoint、healthcheck.test 这类字段的值由后一个文件覆盖,不会追加

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

新 service 会直接追加

在这里插入图片描述

所有相对路径都相对于第一个 compose 文件

在这里插入图片描述

想看最终合并结果,用 config

docker compose -f compose.yaml -f compose_dev.yaml config

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

Compose 是否会替换/删除容器,主要看 project name、service name

Docker Compose 会把一组服务当成一个 project 管理。默认情况下,project name 通常来自 compose 文件所在目录名;也可以通过 -p、COMPOSE_PROJECT_NAME、compose 顶层 name: 指定。官方文档说明了 Compose 项目名的优先级:-p 最高,其次是 COMPOSE_PROJECT_NAME,再是 compose 文件里的顶层 name:,然后才是项目目录名

Compose 创建的容器会带两个关键标签:
com.docker.compose.project = 项目名
com.docker.compose.service = 服务名
Docker 官方服务文档也说明,Compose 会给资源打上 com.docker.compose.project,给服务容器打上 com.docker.compose.service

1. project name 是什么?

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

docker ps -a \
  --format 'table {{.Names}}\t{{.Label "com.docker.compose.project"}}\t{{.Label "com.docker.compose.service"}}\t{{.Networks}}'

在这里插入图片描述

project name 通常来自 compose 文件所在目录名;也可以通过 -p、COMPOSE_PROJECT_NAME、compose 顶层 name: 指定

在这里插入图片描述

-p

在这里插入图片描述

COMPOSE_PROJECT_NAME

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

compose 顶层 name

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

在这里插入图片描述

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐