通过这个Docker Compose教程提升你的技能

如果你想知道如何使用Docker Compose创建可重复使用的Docker容器,那么你来对地方了。在这个逐步 Docker Compose 教程中,你将学会如何创建简单的容器,如何使用 Docker Compose 映射端口,一直到复杂的多容器场景。

你准备好了吗?让我们开始吧!

先决条件

如果你想逐步跟着本教程操作,请确保你具备以下条件:

  1. A fresh install of Ubuntu Server LTS with SSH Enabled. This guide will use Ubuntu Server LTS 20.04.1 as the Docker host machine.
  2. A computer with VS Code installed (optional). This guide will use Visual Studio Code 1.52.1 to SSH to the Docker host and run commands.
  3. 已安装并连接到 Docker 主机的VS Code 官方 SSH 扩展。(可选)

Docker Compose 是什么?

在 Docker 中,单个命令可能会变得非常长。以下面的示例为例。此示例创建了一个名为 bookstack 的软件应用程序的容器。

docker create \
   --name=bookstack \
   -e PUID # 要接管应用程序/文件的用户的UID \
   -e PGID # 要接管应用程序/文件的用户的GID \
   -e DB_USER # 数据库用户 \
   -e DB_PASS # 数据库密码 \
   -e DB_HOST # 数据库主机 \
   -e DB_DATABASE # 要使用的数据库 \
   -e APP_URL # 应用程序将访问的URL(用于正确操作反向代理) \
   -v /host/path/to/config:/config # 任何上传数据的位置 \
   -p 80:80/tcp # Web UI端口 \
   --restart unless-stopped \
   linuxserver/bookstack:version-v0.31.4

随着Docker环境复杂性的增加,实现工作容器设置所需的标志和条件也随之增加。Docker命令行开始变得繁琐且难以调试;特别是一旦多容器设置开始混合在一起时。

Docker Compose是使用配置文件而不是极长的Docker命令来创建可重现的Docker容器的方法。通过使用结构化的配置文件,错误更容易被发现,并且容器交互更容易定义。

当处理容器依赖关系或多容器环境时,Docker Compose迅速变得不可或缺。

Docker Compose 是进入 基础设施即代码(Infrastructure as Code) 的绝佳方式,而无需涉足像 Kubernetes 这样的分布式系统的复杂性。

Docker Compose 使用一种称为 YAML 的配置文件结构。YAML 与 JSON 或 HTML 类似,是一种结构化的、机器可读的语言。YAML 具体着重于尽可能地保持人类可读性,同时保持结构化的强大功能。

然而,YAML 有一个缺点,即制表符和其他空白字符是有意义的,必须正确格式化。VS Code 为你完成了许多这方面的工作,这也是为什么你会看到许多示例在 VS Code 中完成的原因。

安装 Docker Compose

现在让我们开始动手。假设你已连接到 Docker 主机,现在是时候 安装 Docker Compose 了。

Docker Compose 是与 Docker 运行时分开的软件包。但安装 Docker Compose 也将安装 Docker 运行时,一举两得!

要安装 Docker Compose 和 Docker 运行时,请运行以下两个命令。

#更新软件列表(称为存储库),然后安装Docker Compose
#以及所有必需的依赖项。使用-y标志可跳过确认
sudo apt update -y
sudo apt install docker-compose -y
The installation command for Docker Compose

安装完成后,您现在应该创建一个文件夹结构来存储容器。

为Docker Compose创建文件夹结构

在使用Docker Compose创建容器之前,您应该首先创建一个文件夹来存储容器。您不仅应该创建一个文件夹结构来存储容器,而且您会发现各种Docker命令对各种配置文件的位置非常敏感;Docker Compose也不例外。

Docker Compose的最重要组成部分是它的配置文件,称为docker-compose.yaml。正如上面所解释的那样,这个配置文件决定了Docker运行时如何构建容器。

当您运行Docker Compose时,命令会在与命令运行的文件夹相同的位置寻找其配置文件。由于这个要求,最好在运行Docker Compose时创建一个单独的文件夹。

每个文件夹只能有一个Docker Compose配置文件。

为了演示使用Docker Compose创建Docker容器,首先使用一个名为Caddy的小型文件服务器创建一个文件夹结构来存储未来的容器及其配置文件。

是一个文件服务器,类似于,但是是用Go语言编写的。Caddy专门设计用于易用性(并且会自动生成或提供index.html文件)而无需配置。这种组合使得Caddy成为初学者的不错选择。

假设您已登录到Docker主机上,请按照以下方式创建文件夹结构:

  1. 在您的主目录中,创建一个名为的文件夹。这个文件夹将是这个和其他容器的一个很好的占位符。
  2. 文件夹内,创建一个名为的子文件夹。这个文件夹将包含Docker Compose配置文件和Caddy容器本身。
  3. 最后,在容器文件夹内,创建一个名为的空文本文件,它将成为Docker Compose配置文件。

有了文件夹结构和Docker Compose配置文件后,您现在可以开始填写该配置文件了。

创建一个Docker Compose配置文件

在其最基本的形式下,用于caddy容器的文件如下所示。在您喜欢的Linux文本编辑器或使用VS Code中,将下面的代码复制并粘贴到之前创建的Docker Compose配置文件中。

version: "3.7"
services:
  caddy:
    container_name: "caddy"
    image: "caddy:latest"
    ports:
      - "80:80"

让我们逐个介绍所示选项:

  • `version` 指定了 docker-compose 文件的版本。每个新的 Docker Compose 定义都包含对规范的重大更改。因此,版本很重要,这样 Docker Compose 就能知道需要使用哪些功能。版本 3.7 是 Ubuntu 20.04.1 LTS 支持的最新版本。

Docker Compose 3.x 的完整规范可以在此处找到。链接的文档提到了您可以在 Docker Compose 中使用的每个选项。

  • services 包含实际容器的规范。您可以在此部分中定义多个容器。
  • caddy 是第一个容器的名称(这仅供参考)。
  • container_name 定义了 Docker 实际给容器的名称,必须是唯一的。
  • image 是镜像的名称。在这种情况下,caddy 是来自 Docker Hub 的定义。标签后面的名称或数字,由冒号分隔,是版本。

端口映射

特别需要特别提及的是最后一个选项:

ports:
  - "80:80"

在Docker Compose中,ports指令允许您设置从主机到容器的一个或多个映射。例如,您已将主机上的端口80映射到容器中的端口80。但是,您不需要匹配端口号。下面的示例将主机上的端口8800映射到容器中的端口80

ports:
  - "8800:80"

您也可以像下面这样定义多个端口。

ports:
  - "80:80"
  - "443:443"

这样做会将端口80443都映射到主机上(这是Web服务器的常见配置,用于同时提供HTTP和HTTPS服务)。

Docker镜像创建者在创建时定义可用端口。请务必查看您正在Docker Hub上使用的镜像或维护者网站上的文档,以获取可映射端口。如果端口未被使用,映射端口就毫无意义!

考虑到这一点,让我们看看如何实际运行容器。

运行容器

现在您应该在~\containers\caddy文件夹中有docker-compose.yaml文件。现在是创建并启动Caddy容器的时候了。

在您的终端上运行以下命令,它将启动在docker-compose.yaml文件中定义的Docker容器。

# 必须在与文件相同的文件夹中运行此命令。-d标志运行
# 命令*分离*,这将在后台启动容器
sudo docker-compose up -d

您可能注意到,在运行sudo docker-compose up -d时,您无需指定 docker-compose.yaml 文件的位置。Docker Compose 期望您在包含 docker-compose.yaml 文件的文件夹中运行所有命令,因为许多命令是相对于该文件夹的。

现在通过导航到http://<您的 IP>来验证容器是否正在运行。本指南使用http://homelab-docker作为参考。

您可以在下面的动画中通过 SSH 登录到 Docker 主机中的 VS Code,观察到这一过程:

Demonstrating a container created with Docker Compose

成功!您已成功使用 Docker Compose 从配置文件启动了一个容器。完成了这第一步重要的操作后,让我们来看看如何管理容器的状态。

管理分离容器的命令

在前一节中,您使用-d标志启动了 caddy 容器。这样做会使容器处于分离状态。当容器处于分离状态时,容器将继续在后台运行。但是,这会带来一个问题:如果您不再直接控制该容器,该如何管理它?

为解决这个问题,Docker Compose 提供了一系列命令,用于管理使用docker-compose.yaml文件启动的容器:

  • docker-compose restart 用于重新启动当前正在运行的容器。这与实际重新运行 docker-compose up -d 是不同的。Restart 命令将简单地重新启动现有容器,重新运行 docker-compose up -d 命令,并根据需要重新创建容器(如果配置文件已更改)。
  • docker-compose stop 将停止运行的容器,而不销毁容器。类似地,docker-compose start 将重新启动容器。
  • docker-compose down 将停止运行的容器并销毁它们。这是使用挂载卷的绑定挂载功能发挥作用的地方(请阅读下文了解更多)。
  • docker-compose pull 将从存储库中拉取 Docker 镜像的当前版本。如果使用 latest 标签,您可以使用 docker-compose down && sudo docker-compose up -d 来将容器替换为最新版本。使用 docker-compose pull 是一种快速更新容器且最小化停机时间的便捷方式。
  • docker-compose logs 将显示运行中(或已停止)容器的日志。您还可以使用 docker-compose logs <container name> 来查看特定容器的日志(如果在 compose 文件中定义了多个容器)。

A full list of docker-compose commands can be seen by running docker-compose with no additional arguments or referenced here in the documentation.

现在您有了一个正在运行的容器,让我们来看看如何使用在本地机器上保存的内容。

在 Docker Compose 中创建绑定挂载

Bind Mounts是Docker将重要用户数据映射到服务器本地存储的方式。首先,在容器中生成一些要托管的内容:

  1. 在Docker主机上,在~/containers/caddy文件夹内创建一个名为files的新文件夹。

2. 在~/containers/caddy文件夹内创建一个名为index.html的新文件,内容如下。这将是Caddy web服务器提供的主页。

<body><h2>hello world!</h2></body>

3. 修改Docker Compose配置文件如下。下面的示例文件添加了volumes部分,并指定了一个绑定挂载到刚刚创建的files文件夹,以便将其提供给容器使用。

version: "3.7" services: caddy: container_name: "caddy" image: "caddy:latest" ports: - "80:80" volumes: # ./指的是相对于docker-compose文件的文件夹 - "./files:/usr/share/caddy"

4. 再次运行docker-compose up -d。Docker Compose现在将识别到文件已更改并重新创建您的容器。

5. 使用浏览器导航到容器的页面,现在您应该能够看到它正在提供“Hello World!”页面。

您可以在以下动画中看到以下内容:

Creating a bind mount using Docker Compose

您现在正在托管存储在本地计算机上的内容!但是,如果您的内容位于外部来源,比如网络共享,该怎么办呢?

使用Docker Compose和Docker卷

一旦您使用Docker Compose创建了一个简单的容器,您可能需要该容器访问其他地方的文件,比如在网络共享上。如果是这样,您可以在Docker Compose配置文件中直接配置容器使用Docker卷。

为了演示目的,本指南将在Docker主机上创建一个网络文件共享(NFS)服务器。将本地内容作为NFS挂载在演示之外没有实际目的。如果您要挂载一个NFS卷,通常是来自外部源,如NAS或远程服务器。

设置NFS共享

如果您还没有设置NFS共享,请在本教程的Docker主机上立即构建一个。操作步骤如下:

  1. 通过运行apt install nfs-kernel-server -y安装NFS服务器软件包。

2. 运行以下命令将容器添加为NFS导出(类似于Windows CIFS共享)。

# 在/etc/exports配置文件中添加一行以创建NFS共享,用于/home/homelab/containers。此共享仅暴露给本地主机(以防止其他计算机访问) echo '/home/homelab/containers localhost(rw,sync,no_root_squash,no_subtree_check)' | sudo tee -a /etc/exports # 使用新配置重新启动NFS服务器 sudo systemctl restart nfs-kernel-server

3. 现在通过运行 showmount -e localhost 命令来验证主机是否暴露了 NFS 共享。此命令将显示当前公开的任何 NFS 共享以及谁可以访问。

在下面的截图中,您可以看到 /home/homelab/containers 已经暴露出来,但只能被本地主机访问(这与运行 Docker 主机的服务器相同)。

Creating a NFS share in Ubuntu 20.04

如果您在输出中看到文件夹 /home/<username>/containers,则 NFS 共享已设置完成。

定义 Docker 命名卷

创建了 NFS 共享后,现在需要告诉 Docker 如何访问该共享。使用 Docker Compose,您可以通过在 Docker Compose 配置文件中定义一个 命名卷 来实现这一点。

A named volume is a way for Docker to abstract network-based file shares. Network file sharing comes in all sorts of shapes and sizes these days: CIFS (windows) shares, NFS (Linux) shares, AWS S3 Buckets, and more. By creating a Named Volume, Docker does the hard part of figuring out how to talk to the network share and lets the container just treat the share as if it is local storage.

要创建一个命名卷:

  1. 打开 Docker Compose 配置文件(docker-compose.yaml)。如果您正在跟着操作,文件应该位于 ~/containers/caddy 文件夹中。

2. 在 Docker Compose 配置文件中,在 services 部分之后添加一个 volumes 部分。您的配置文件应如下所示。 volumes 部分创建了一个名为 MyWebsite 的命名卷。在该命名卷内,指定了所需的参数(例如 IP、NFS 设置和路径)。 services 部分中的 volumes 参数也已修改,指向命名卷而不是本地文件夹。

version: "3.7"
 services:
   caddy:
     container_name: "caddy"
     image: "caddy:latest"
     ports:
       - "80:80"
     volumes:
       - "MyWebsite:/usr/share/caddy"
 volumes:
   MyWebsite:
     driver_opts:
       type: "nfs"
       o: "addr=localhost,nolock,soft,rw"
       device: ":/home/homelab/containers/caddy/files"

3. 定义了指向 NFS 共享的命名卷后,在 Docker Compose 配置文件中运行 docker-compose up -d 来创建并启动容器。如果一切顺利,容器和网站应该重新启动。

Setting NFS client settings within Docker Compose in VS Code

4. 再次访问容器的页面。index.html 的内容应该显示得就像文件被本地挂载一样。然而,该文件是通过在网络上设置的 NFS 服务器进行挂载的。

Demonstrating access to the index.html file through an NFS share in Docker

现在,由于你可以在 Docker Compose 中挂载外部 Docker 卷,所以可以将各种网络存储引入容器中。然而,Docker Compose 不仅仅可以定义单个容器或卷,我们还可以深入研究更复杂的多容器场景。

本教程将不再使用 caddy 容器,因此你可以使用 docker-compose down 命令删除容器。

在 Docker Compose 中定义多个容器

大多数 Docker 容器并不是在孤立的环境中运行的。Docker 容器通常具有诸如数据库或独立的 Web 服务之类的服务依赖关系,它们通过 API 进行通信。

使用 Docker Compose,你可以将在单个文件中定义的容器组合在一起。通过在单个文件中定义多个容器,容器可以在相关服务之间进行通信,并简化复杂容器布局的组织。

为了演示这样的场景,让我们设置一个名为 BookStack 的热门 Wiki 应用。

BookStack是一款以其易用性和分层布局而闻名的流行维基软件(与平面布局相对,例如mediawiki)。

BookStack,像许多Web应用程序一样,需要一个单独的数据库才能正常运行,以及与数据库通信所需的信息。搭建这样的环境是Docker Compose的强项。

创建Docker Compose配置文件

BookStack没有内部维护的Docker镜像,然而,linuxserver.io维护着一个代表BookStack的声誉良好的Docker Hub镜像。虽然docker hub网站上有推荐的Docker Compose配置文件,但本教程将在解释概念的同时构建一个新的配置文件。

在Docker主机上:

  1. 首先,为BookStack创建一个文件夹。如果您按照前一节的教程操作,应该有一个〜/containers文件夹。在其中创建一个名为bookstack的文件夹。

2. 然后,在bookstack文件夹中创建一个名为docker-compose.yaml的空白Docker Compose配置文件。

Creating the folder structure for Bookstack in VS Code

3. 现在打开Docker Compose配置文件,定义两个容器:bookstack容器和bookstack_db(mariadb)容器。

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"

到目前为止,这个docker-compose.yaml文件主要使用了已经介绍过的概念:你有两个服务(bookstackbookstack_db),两者都有镜像和绑定挂载。bookstack容器将主机端口8080映射到内部端口80。

考虑到Docker容器的极低开销,为每个Web应用程序定义一个单独的数据库容器是一种常见做法。这样做可以实现更好的职责分离。这与传统的数据库设置有明显不同,传统设置中单个数据库安装可能为数百个Web应用程序提供服务。

你在上面的文件中可以看到一个新选项,即depends_on命令。此命令告诉Docker容器应以哪种顺序启动。定义depends_on命令告诉Docker必须先启动bookstack_db容器。

使用环境变量设置容器通信

上一节构建的配置文件还不完整。虽然你已经定义了两个服务(容器),但它们之间没有交流!bookstack容器不知道如何与bookstack_db容器通信。让我们使用环境变量解决这个问题。

环境变量是向Docker容器提供变量的最常见方式。这些是在运行时提供的变量(或在docker-compose.yaml配置文件中定义的变量),用于提供有关容器需要执行的操作的信息。

环境变量由创建Docker镜像的人定义。根据您使用的Docker镜像不同,它们将有所不同,您必须参考创建者的文档,了解要使用哪些环境变量。

有两种定义环境变量的方法:直接在docker-compose.yaml文件中或作为单独的文件。

A separate file is, typically, the recommended method, especially if variables contain sensitive data such as passwords. A docker-compose.yaml file is designed to be shared or even uploaded to a public-facing GitHub repo. Having a separate file for sensitive data reduces the chance of an accidental security breach.

在Docker主机上,现在创建两个环境变量;一个用于bookstack容器,另一个用于bookstack_db容器。

  1. ~/containers/bookstack文件夹中创建一个名为bookstack.env的新文件,内容如下:
APP_URL is the IP address or hostname of your server. This article is using homelab-docker
 APP_URL=http://homelab-docker:8080
 DB_HOST is the container name you gave your container
 DB_HOST=bookstack_db
 DB_USER is defined in the bookstack_DB environment file
 DB_USER=bookstack_user
 DB_PASS is also defined in the bookstack_DB environment file
 DB_PASS=MySecurePassword
 DB_DATABASE is the name of the database within mariadb
 DB_DATABASE=bookstack

2. 在~/containers/bookstack文件夹中创建一个名为bookstack_db.env的新文件,并包含以下内容:

The root password for our database, keep it secret, keep it safe
 MYSQL_ROOT_PASSWORD=MySecureRootPassword
 The database bookstack will be using
 MYSQL_DATABASE=bookstack
 the user bookstack will be using
 MYSQL_USER=bookstack_user
 the password bookstack will be using
 MYSQL_PASSWORD=MySecurePassword

3. 作为最佳实践,确保这两个env文件对其他用户不可读。

chmod 600 bookstack.env bookstack_db.env

您应该更改读取权限,因为bookstack.env和bookstack_db.env文件中都包含敏感数据。

4. 更新~/containers/bookstack/docker-compose.yaml Docker Compose文件,引用下面显示的这两个环境文件。

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"

5. 现在使用Docker Compose启动bookstackbookstack_db容器。

sudo docker-compose up -d

您可以在下面的VS Code中看到本节中执行的上述每个步骤。

Setting up environment variables and the Docker Compose file with VS Code

监视Docker Compose日志

Docker引擎与Docker Compose一起在后台执行许多不同的任务。在处理多个容器时,尤其能够监控发生的情况是有帮助的。

例如,要监控bookstack容器,请使用logs命令。在本教程中,一旦看到日志显示[services.d] done,您就可以转到bookstack URL。

sudo docker-compose logs bookstack
Using the docker-compose logs command
The bookstack welcome screen. Default login is [email protected]/password

在这个阶段,您应该在自己的容器内运行一个完全功能的wiki,带有自己的数据库,完全在Docker内部运行!

只要您有bookstack和bookstack_db文件夹,您可以从头开始重新创建bookstack环境。

Docker Compose和网络

到目前为止,您还没有学到关于容器如何一起工作的通信和网络方面的太多内容。让我们改变这种情况。

当您在单个docker-compose.yaml文件中创建多个容器,就像在前几节中所做的那样,它们都分配到同一个网络中(通常称为name-of-parent-folder_default)。

当您运行docker-compose up -d时,您可以看到为容器创建的网络,如下所示。

The default network created with docker-compose comes up

当所有容器都分配到同一个网络时,Docker在内部为它们创建DNS条目。这就是为什么在前面的示例中,您在环境变量中将数据库称为bookstack_db的原因。那个bookstack_db名称实际上是指向数据库容器的IP地址的DNS条目。

您也不必依赖Docker Compose为您自动生成网络。您可以手动定义内部或外部网络。手动定义网络在您有一个需要与另一个容器通信的容器时非常有用,该容器位于单独的docker-compose.yaml文件中。您可以暴露端口,或者您可以创建一个它们都可以加入的网络!

请注意,当您开始明确定义网络时,您还必须明确定义默认网络。一旦您开始定义网络,Docker Compose将停止自动创建该网络

现在修改bookstack docker-compose.yaml以包含一个外部创建的网络。

  1. 使用docker network create my_external_network创建外部网络。

2. 在docker-compose.yaml中定义外部网络:

version: "3.7"
 services:
   bookstack:
     container_name: "bookstack"
     image: "ghcr.io/linuxserver/bookstack"
     ports:
       - "8080:80"
     volumes:
       - "./files:/usr/share/caddy"
     depends_on:
       - "bookstack_db"
     env_file:
       - "./bookstack.env"
     networks:
       - "my_external_network"
       - "bookstack_default"
   bookstack_db:
     container_name: "bookstack_db"
     image: "mariadb"
     volumes:
       - "./db:/var/lib/mysql"
     env_file:
       - "./bookstack_db.env"
     networks:
       - "bookstack_default"
 networks:
   bookstack_default:
   my_external_network:
     external: true

3. 运行docker-compose up -d重新创建容器。现在,您的两个容器已经加入了两个网络,如下所示。

A highlight of the networks defined within a docker-compose file

bookstack容器现在已加入到一个外部定义的网络中。这使您可以创建另一个容器,在离开Docker之前将bookstack的HTTP流量转换为HTTPS(称为反向代理)。

设置特定用户来运行容器

默认情况下,所有Docker容器都以沙盒化的root用户身份运行。这相当于以默认的管理员用户登录的虚拟机。虽然这通常不是问题,但如果沙盒被入侵,就会存在安全问题。

以root身份运行的另一个问题是文件权限。您可能会注意到,如果您尝试删除bookstack文件夹中的db文件夹,实际上是无法删除的,因为其内容是由root所有的。

虽然大多数镜像不支持以非root用户身份运行,但linuxserver.io镜像特别提供了一个环境变量,用于设置容器内部运行的用户。您可以在bookstack.env配置文件中添加UID=1000GID=1000来实现这一点。

1000:1000是ubuntu中第一个用户的默认用户ID和组ID(您可能不是该用户)。您可以在相关文档:Windows人在Linux世界:用户和文件权限中了解更多关于用户ID和组ID的信息。

您还可以在docker-compose中使用user参数强制指定UID和GID,但这不推荐,因为大多数容器在被强制指定为不同用户时无法正常工作。

设置重启策略

如果您希望使用Docker Compose构建的容器在失败时重新启动,可以通过在docker-compose.yaml文件中的容器设置下添加restart: <option>参数来使用restart策略

restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

添加此参数将导致容器在失败时自动重新启动,以帮助维护正常运行时间,以应对意外的电源问题。

手动为容器设置DNS条目

就像在Windows和Linux上一样,Docker也有一个“hosts文件”。通过在配置文件中使用extra_hosts参数,您可以强制将主机解析为特定IP。当您有DNS约束(如拆分DNS或临时想要与测试服务器交互)时,这可能很有用。

extra_hosts:
  - "somehost:x.x.x.x"
  - "otherhost:x.x.x.x"

运行命令

容器启动后,您可以使用docker-compose run在容器内运行命令。例如,也许您想在bookstack容器内启动Bash终端。要做到这一点,您可以运行以下命令。

docker-compose run web bash

结论

在这个阶段,您应该已经掌握了足够的信息,可以跟随网络上的大多数docker-compose教程。拥有这些知识可以极大地扩展您进入Docker世界和基础设施即代码构建Web应用的能力。

Source:
https://adamtheautomator.com/docker-compose-tutorial/