由浅入深 docker 系列: (3) docker-compose

在第二篇文章中,我们学会了使用 dockerfile 构建 docker 镜像,看起来已经能够满足我们的日常需求了。无论需要什么环境,在 dockerfile 里逐步构建,然后 build、run,就 ok 了,也满足了我们 docker 隔离性、快速部署的要求,那为什么还会有这一节?
来看一个网站开发最常见的场景:我们要有数据库,网站应用,nginx,互相配合才是完整的环境。是的,我们完全可以以 ubuntu 为基础镜像,把这些一股脑全装进去,然后运行。但是这样有很多缺点,比如我们每次都要重新装 mysql 而不是直接利用 mysql 官方的基础镜像,升级维护不方便;如果我们的应用要扩展也很难,因为每个应用都连接的自己内部的数据库,无法共享数据;事实上,这种方式是典型的虚拟机的使用方式,不是 docker 的正确打开方式。
docker 是轻量化的应用程序,docker 官方推荐每个 docker 容器中只运行一个进程(下篇文章你将明白这是为什么),那么就是说,我们需要分别为我们的应用、数据库、nginx 创建单独的 docker 容器,然后分别启动它。想象一下,构建好 docker 之后,每次启动我们的网站,都要至少 docker run 三次,是不是很繁琐?而且此时这几个 docker 是分散独立的,很不方便管理。既然这几个 docker 都是为了同一个网站服务,是不是应该把它们放到一起?这就引出了 docker-compose 项目。
docker-compose 是 docker 官方的开源项目,使用 python 编写,实现上调用了 Docker 服务的 API 进行容器管理。其官方定义为为 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)),其实就是上面所讲的功能。

一:安装
默认情况下,windows 和 mac 下的 docker 已经自带了 docker-compose 工具,可以使用 docker-compose -v 命令查看。

对于 linux 系统,需要自己手动安装,可以直接下载二进制文件安装,参考官方文档,更酷的是,可以直接使用 pip 安装,甚至可以使用 docker-compose 容器(比较复杂,不推荐~)。

二:简介
类似 docker 的 Dockerfile 文件,docker-compose 使用 YAML 文件对容器进行管理。
对于 docker-compose 有两个基本的概念:
服务 (service):一个应用容器,即 docker 容器,比如之前所说的 mysql 容器、nginx 容器
项目 (project):由一组关联的应用容器组成的一个完整业务单元,比如上面所讲的由 mysql、web app、nginx 容器组成的网站。docker-compose 面向项目进行管理。
再简单说下 YAML 文件格式。

  • 大小写敏感,缩进表示表示层级关系
  • 缩进空格数不重要,相同层级左侧对齐即可。(不允许使用 tab 缩进!)
  • 由冒号分隔的键值对表示对象;一组连词线开头的行,构成一个数组;字符串默认不使用引号
    这些基本够我们使用了,详细的格式说明可参考这篇 YAML 语言教程 – 阮一峰。

三:构建
接下来我们使用 docker-compose 构建一个 php 网站项目,并逐步讲解其使用。
我们需要一个网站项目,这里以 summerblue 的 larabbs 论坛系统为例,这个项目使用了 mysql、redis,我们可以验证搭建是否成功。

  1. 从远程仓库把其克隆到本地,然后开始我们今天的工作。
  2. 在项目文件夹下创建 docker-compose.yml 文件。
  3. 先在 docker-compose.yml 文件里添加如下代码,构建我们的 php 应用。

    下面解释下我们的代码。

    • version: 表示我们的 compose 文件的版本,目前有 1,2,3,每个版本语法不尽相同,这里以版本 2 为例。
    • services: 即我们要开始定义服务,每个 docker 容器为一个服务。
    • app: 这里我们定义了第一个服务,app 为其名字
    • build: 指定该容器构建参数
    • volumes: 与 dockerfile 中 -v 参数相似,这里是将当前文件夹挂载到容器的 /var/www 目录下
    • working_dir: 指定容器工作目录
    • environment: 设置环境变量。由于 laravel 框架在环境变量已有值的情况下不会加载.env 配置,这里 DB_HOST 和 REDIS_HOST 就是.env 文件中配置数据库连接的参数,我们设置它以便连接 docker 的数据库,database 和 redis 是接下来定义的服务名称。

    这是 app.dockerfile 文件的内容,之前都讲过,不再细说。

  4. 创建一个 composer 服务以安装 composer 依赖,docker-compose.yml 文件添加以下内容

5.创建一个 nginx 服务,docker-compose.yml 文件添加以下内容

6.创建数据库服务,docker-compose.yml 文件添加以下内容

  • 这里 database 和 redis 是服务名,也即在 app 服务的 environment 变量设置的参数,因此 app 才能访问到我们容器中的数据库,当然你也可以使用其它名字。
  • environment 这里我们设置了 mysql 的数据库及用户名密码,即是 env 文件中配置的用户名密码,mysql 容器会自动初始化,然后应用才有权限连接。

到目前为止配置文件已经写完了。

四:使用

  1. 启动项目
    docker-compose 最常用的命令就是 docker-compose up 了,该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。
    因此,在项目文件夹下执行此命令。注意要在项目文件夹下,否则 docker-compose 找不到 docker-compose.yml 文件,也不知道你是如何配置的。
    时间可能较长,请耐心等待。如果遇到网络故障,可以重试。
    简单介绍下输出:

可以看到 此时 app 服务已启动,等待连接。

redis 服务已启动。

database 服务已启动,在 3306 端口等待连接。

composer 服务准备开始安装依赖。

composer 服务完成任务退出。

  1. 项目使用
    首先执行下 docker ps,可以看到目前有 4 个容器,容器名都加上了项目前缀。

    此时你可以使用 docker exec 命令进入相应容器执行初始化操作,因为 docker-compose 本身也是调用的 docker api,但是既然使用了 docker-compose 来管理项目,我们必然有更方便的方式。执行 docker-compose ps, 可以至查看当前项目的容器状态。

    可以看到,四个服务正在运行,而 composer 服务已经执行完任务退出。
    如果要容器执行命令,直接 docker-compose exec service_name command 更方便。
    比如,进入我们的 nginx 容器,nginx 即是 YAML 文件里定义的服务名。

    接下来,我们进行网站的初始化工作。即生成秘钥、初始化数据库等。
    app 也是 YAML 文件里定义的服务名。

    一切都顺利进行。
    对了,因为上面提到 sudo-su 的原因,你必须使用域名访问网站,在 host 文件添加 larabbs.test 到 127.0.0.1 的映射即可。
    然后,你应该就可以正常访问 http://larabbs.test 网站了。

  2. 容器的停止
    直接 control-c 或者 docker-compose stop 即可。
    注意下次 docker-compose up 默认仍会继续使用之前的容器和数据。
    必要时你可以添加 –build 参数重新构建镜像,或者 –force-recreate 参数重新创建容器。

« »

发表评论

电子邮件地址不会被公开。 必填项已用*标注

昵称 *