使用Docker Compose来简化多容器应用的复杂性
Docker Compose 是一个用来帮助定义和分享多容器应用的工具。有了 Compose,我们就能创建一个 YAML 文件来定义服务,只需要一个命令,就能够启动所有东西,也能够把所有东西销毁掉。
使用 Compose 的最大优点是,能够在一个文件中定义你的应用栈,把它放在项目库文件的根目录,就能轻易地让其他人对你的项目做贡献了。别人只需要克隆你的库,启动 compose 应用就行。事实上,你可能在 GitHub 或 GitLab 上,已经看到很多项目都在这么做了。
那么,我们该怎么做呢?
安装 Docker Compose#
如果你在 Windows 或 Mac 上安装了 Docker Desktop/Toolbox 的话,你就已经安装了 Docker Compose !Play-with-Docker 实例也已经安装了 Docker Compose 。如果你使用的是 Linux 机器,你需要根据文档安装 Docker Compose 。
在安装之后,你就能运行以下命令查看版本信息了。
docker-compose version
创建我们的 Compose 文件#
1、在应用项目根路径,创建名为 docker-compose.yml 的文件。
2、在 compose 文件中,我们最先是要定义约定版本。在大多数情况下,最好使用所支持的最新版本。你可以在 Compose 文件参考资料查看当前的约定版本和兼容性矩阵。
version: “3.7”
3、然后,我们会定义服务(或者说容器)列表,这些服务构成了我们的应用。
version: “3.7”
services:
接着我们就可以开始一个一个地把服务迁移进 compose 文件中了。
定义应用服务#
记住,以下是我们用来定义应用容器的命令
docker run -dp 3000:3000
-w /app -v “$(pwd):/app”
–network todo-app
-e MYSQL_HOST=mysql
-e MYSQL_USER=root
-e MYSQL_PASSWORD=secret
-e MYSQL_DB=todos
node:12-alpine
sh -c “yarn install && yarn run dev”
如果你用的是 Power Shell 的话,把命令中的 \ 替换成 ` 即可。
1、首先,定义我们的服务入口,以及容器的镜像。我们可以给服务随便起名。服务名称会自动变成网络别名,这在定义 MySQL 服务的时候会特别有用。
2、我们经常会看到,紧随 image 定义之后的是 command。不过其实对于顺序来说没有特别要求。把命令放进来就变成了:
3、通过定义服务的 ports 来把命令的 -p 3000:3000 部分迁移进 compose 。我们使用的是短语法,不过也有更加啰嗦的长语法。
4、然后,我们把工作目录(-w /app)和卷映射(-v “$(pwd):/app”)使用 working_dir 和 volumes 定义来做迁移。卷也有短语法和长语法。Docker Compose 卷定义的优势是,我们可以使用基于当前路径的相对路径。
5、最后,我们需要使用 environment 键把环境变量定义迁移过来。
定义 MySQL 服务#
到了我们定义 MySQL 服务的时间了。以下是用于 MySQL 容器的命令:
docker run -d
–network todo-app –network-alias mysql
-v todo-mysql-data:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=secret
-e MYSQL_DATABASE=todos
mysql:5.7
如果你用的是 Power Shell 的话,把命令中的 \ 替换成 ` 即可。
1、首先定义一个新服务,服务名称为 mysql ,这样它就会自动获得网络别名了。我们同样需要指定要使用的镜像。
2、定义卷映射。当我们使用 docker run 运行容器的时候,具名卷是自动创建的。不过,使用 Compose 的话,就不会了。我们需要在顶级 volumes: 段落定义卷,然后在服务配置中指定挂载点。只要提供卷名,选项部分都是默认的。不过也有许多其它选项可以用。
3、最后,我们只需要指定环境变量即可。
现在,完整版的 docker-compose.yml 应该看起来是这样的:
运行我们的应用栈#
我们已经有了 docker-compose.yml 文件了,让我们来启动它吧!
1、首先,确保没有其它 应用或数据库 的拷贝在运行,可以使用 docker ps 搭配 docker rm -f <容器 id> 来删除容器。
2、使用 docker-compose up 命令来启动应用栈。我们加上 -d 旗标以确保所有东西在后台运行。我整个流程都在 vscode 中操作,所以我直接唤起 vscode 的集成终端,执行命令,这样就不用切换独立终端的工作路径了。如果你的操作和我不一样的话,务必确保切换到项目所在的路径,也就是 docker-compose.yml 文件所在的路径执行命令。
docker-compose up -d
运行的时候,我们应该能够看到如下输出:
你会注意到卷和网络都被创建了!默认情况下,Docker Compose 自动会专为应用栈创建网络,这就是为什么我们在 compose 文件中并没有定义网络的原因。
3、咱们来用 docker-compose logs -f 命令来看下日志。你会发现来自于不同服务的日志会交织在一个流中。这对于你在分析时序相关的问题时,会非常有用。-f 旗标会跟踪日志,这样就能够实时地展示生成的日志。
服务名会展示在每一行的开头,一般都会自带颜色,来帮你区分消息来源。如果你想要查看某个服务的日志,你可以在日志命令的最后,跟上服务名,比如:docker-compose logs -f app
专家提醒 - 在启动应用之前,等待数据库#
当应用启动时,它实际上在等待 MySQL 启动完毕,然后才会尝试连接它。Docker 本身并没有自带任何对一个容器等待另一个容器启动完毕后再启动的等待机制。对于 Node 的项目,你可以使用 wait-port 依赖。其它语言和框架中,也都有类似的项目。
4、现在,你应该能够打开应用,看到它在运行了。而且,我们现在只需要运行一个命令就可以了。
在 Docker 仪表盘中查看我们的应用栈#
如果我们在 Docker 仪表盘中查看的话,我们会看到有一个名为 app 的组。这个名字来自于 Docker Compose 的项目名,这个名字也用来将容器组合在了一起。默认情况下,项目名是 docker-compose.yml 文件所在路径的路径名。
如果展开 app 的话,你会看到在 compose 文件中定义的 2 个容器。从名字看,也是比较浅显易懂的。因为名字都遵从 <项目名称><服务名称><拷贝名> 的规律。很容易辨认出哪个容器是应用,哪个容器是 mysql 数据库。
销毁#
当你准备要销毁的时候,只需要运行 docker-compose down 或者点击仪表盘中,整个应用的垃圾桶图标。容器就会停止,网络也会被删掉。
移除卷#
默认情况下,compose 文件中的具名卷是不会在运行 docker-compose down 的时候删除的。如果你想要删除卷的话,需要加上 –volumes 旗标。
当你删除应用栈的时候,Docker 仪表盘也不会删除卷。
销毁之后,你可以切换到另一个项目,运行 docker-compose up 就能对那个项目做贡献了。真的不能再简单了!
回顾#
本文中,我们学习了 Docker Compose,它能够帮助我们大大简化多服务应用的定义和分享。我们通过把之前使用的命令,转换成对应的 compose 格式的方式,创建了一个 Compose 文件。现在,我们要给教程收尾了。不过,我们还要谈一下关于镜像构建的最佳实践,因为我们一直使用的 Dockerfile 有一个大问题。那么,我们下一期不见不散。
如果本文对你有所帮助,欢迎长按点赞鼓励支持。如果有任何问题,也欢迎评论区留言或私信给我。我看到以后会第一时间回复。:)
推荐文章: