使用 Docker Compose

Docker Compose 是一个帮助您定义和共享多容器应用程序的工具。使用 Compose,您可以创建一个 YAML 文件来定义服务,并通过一个命令启动或停止所有内容。

使用Compose的最大优势是,你可以在一个文件中定义你的应用程序堆栈,将其保存在项目仓库的根目录下(现在它已经版本控制了),并轻松地让其他人对你的项目做出贡献。其他人只需要克隆你的仓库并使用Compose启动应用程序。事实上,你可能会在GitHub/GitLab上看到很多项目现在正是这样做的。

创建Compose文件

getting-started-app目录中,创建一个名为compose.yaml的文件。

├── getting-started-app/
│ ├── Dockerfile
│ ├── compose.yaml
│ ├── node_modules/
│ ├── package.json
│ ├── spec/
│ ├── src/
│ └── yarn.lock

定义应用服务

第6部分中,您使用了以下命令来启动应用程序服务。

$ docker run -dp 127.0.0.1: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:18-alpine \
  sh -c "yarn install && yarn run dev"

你现在将在compose.yaml文件中定义这个服务。

  1. 在文本或代码编辑器中打开compose.yaml,首先定义您想要作为应用程序一部分运行的第一个服务(或容器)的名称和镜像。 该名称将自动成为网络别名,这在定义您的MySQL服务时将非常有用。

    services:
      app:
        image: node:18-alpine
  2. 通常,你会看到 command 接近 image 定义,尽管对顺序没有要求。将 command 添加到你的 compose.yaml 文件中。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
  3. 现在通过为服务定义ports来迁移命令中的-p 127.0.0.1:3000:3000部分。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
  4. 接下来,通过使用working_dirvolumes定义来迁移工作目录(-w /app)和卷映射(-v "$(pwd):/app")。

    Docker Compose 卷定义的一个优势是你可以使用当前目录的相对路径。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
  5. 最后,你需要使用environment键迁移环境变量定义。

    services:
      app:
        image: node:18-alpine
        command: sh -c "yarn install && yarn run dev"
        ports:
          - 127.0.0.1:3000:3000
        working_dir: /app
        volumes:
          - ./:/app
        environment:
          MYSQL_HOST: mysql
          MYSQL_USER: root
          MYSQL_PASSWORD: secret
          MYSQL_DB: todos

定义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:8.0
  1. 首先定义新服务并将其命名为mysql,以便它自动获取网络别名。同时指定要使用的镜像。

    
    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
  2. 接下来,定义卷映射。当你使用docker run运行容器时,Docker会自动创建命名卷。然而,在使用Compose运行时,这种情况不会发生。你需要在顶层的volumes:部分定义卷,然后在服务配置中指定挂载点。只需提供卷名称,就会使用默认选项。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
    
    volumes:
      todo-mysql-data:
  3. 最后,您需要指定环境变量。

    services:
      app:
        # The app service definition
      mysql:
        image: mysql:8.0
        volumes:
          - todo-mysql-data:/var/lib/mysql
        environment:
          MYSQL_ROOT_PASSWORD: secret
          MYSQL_DATABASE: todos
    
    volumes:
      todo-mysql-data:

此时,您的完整 compose.yaml 应如下所示:

services:
  app:
    image: node:18-alpine
    command: sh -c "yarn install && yarn run dev"
    ports:
      - 127.0.0.1:3000:3000
    working_dir: /app
    volumes:
      - ./:/app
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos

  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

volumes:
  todo-mysql-data:

运行应用程序堆栈

现在你已经有了compose.yaml文件,你可以启动你的应用程序了。

  1. 首先确保没有其他容器副本在运行。使用 docker ps 列出容器,并使用 docker rm -f 删除它们。

  2. 使用docker compose up命令启动应用程序堆栈。添加-d标志以在后台运行所有内容。

    $ docker compose up -d
    

    当你运行前面的命令时,你应该看到如下输出:

    Creating network "app_default" with the default driver
    Creating volume "app_todo-mysql-data" with default driver
    Creating app_app_1   ... done
    Creating app_mysql_1 ... done

    你会注意到Docker Compose不仅创建了卷,还创建了一个网络。默认情况下,Docker Compose会自动为应用程序堆栈创建一个专门的网络(这就是为什么你没有在Compose文件中定义一个网络的原因)。

  3. 使用docker compose logs -f命令查看日志。您将看到来自每个服务的日志交错成一个单一的流。这在您想要观察与时间相关的问题时非常有用。-f标志会跟随日志,因此会在日志生成时提供实时输出。

    如果您已经运行了该命令,您将看到如下输出:

    mysql_1  | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections.
    mysql_1  | Version: '8.0.31'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
    app_1    | Connected to mysql db at host mysql
    app_1    | Listening on port 3000

    服务名称显示在行的开头(通常带有颜色)以帮助区分消息。如果您想查看特定服务的日志,可以将服务名称添加到日志命令的末尾(例如,docker compose logs -f app)。

  4. 此时,你应该能够在浏览器中打开你的应用程序,访问 http://localhost:3000 并看到它正在运行。

在 Docker Desktop 仪表板中查看应用堆栈

如果你查看Docker Desktop仪表板,你会看到一个名为getting-started-app的组。这是来自Docker Compose的项目名称,用于将容器分组。默认情况下,项目名称就是compose.yaml所在目录的名称。

如果你展开堆栈,你会看到你在Compose文件中定义的两个容器。名称也更具描述性,因为它们遵循-的模式。因此,很容易快速看出哪个容器是你的应用程序,哪个容器是mysql数据库。

全部拆掉

当你准备全部拆除时,只需运行docker compose down或在Docker Desktop Dashboard上点击垃圾桶图标即可删除整个应用。容器将停止,网络将被移除。

警告

默认情况下,当您运行docker compose down时,您的compose文件中的命名卷不会被移除。如果您想要移除这些卷,您需要添加--volumes标志。

当您删除应用堆栈时,Docker Desktop Dashboard不会移除卷。

摘要

在本节中,您了解了Docker Compose以及它如何帮助您简化和共享多服务应用程序的方式。

相关信息:

下一步

接下来,您将学习一些可以用来改进您的 Dockerfile 的最佳实践。