弥补 Docker 与 Kubernetes 之类之间的差距可能是一项艰巨的任务——而且根据你的使用情况,这对你来说可能并不是必需的。如果你希望能够有一个可重复的流程来创建和编排少量容器,那么 Docker Compose 可能非常适合你。在继续之前,请务必安装 Docker Compose。
定义 Docker Compose 服务
当我们开始使用越来越多的功能来运行容器时docker run
,命令可能会变得非常冗长且难以记住。值得庆幸的是,Docker Compose 允许我们使用映射到我们可以传递给各种 Docker 命令的选项的特定键在YAML中编写这些命令。让我们采用一个足够复杂的docker run
命令来启动使用环境变量配置的 MySQL 容器,并将其转换为 YAML docker-compose.yml
。这是我们开始使用的命令:
$ docker run -d --name mysql:5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=secret_password -e MYSQL_DATABASE=linuxacademy mysql
docker-compose.yml
设置一些样板后,我们可以在文件内创建这个容器作为“服务” 。以下是我们的开始: docker-compose.yml
version: "3"services: mysql: image: "mysql" environment: MYSQL_ROOT_PASSWORD: "secret_password" MYSQL_DATABASE: "linuxacademy" ports: - "3306:3306"
文件的语法有几个不同的版本docker-compose.yml
,但我们几乎总是使用最新版本,在撰写本文时是 3.x。从那里,我们声明我们想要定义“服务”,并且此处的任何项目都将是 Docker Compose 将为我们创建并运行的容器。在我们的mysql
服务定义中,我们可以设置键,这些键与我们手动使用时使用的选项非常接近docker run
。值得注意的是,如果某个选项采用列表并且值不包含等号(=
),那么我们将使用 YAML 列表(以 开头-
),否则我们将使用 YAML 键/值对,就像我们在environment
部分中所做的那样。从我们创建文件的目录中,我们可以使用标志docker-compose.yml
在后台创建并运行我们的容器以守护进程化容器:
docker-compose up
-d
$ docker-compose up -dCreating network "docker-compose-example_default" with the default driverCreating docker-compose-example_mysql_1 ... done
我的目录名为docker-compose-example
,Docker Compose 将利用该信息根据目录名称和我们的服务名称创建一个唯一的容器名称。 在我的例子中,我得到了docker-compose-example_mysql_1
。 后面的字符_1
用于处理我们想要运行容器的多个副本的事件。
删除硬编码的环境变量
我们可以对我们的服务进行的一个改进mysql
是不要对环境变量进行硬编码。理想情况下,我们希望将docker-compose.yml
文件添加到源代码控制中,并且我们绝对不想将我们的凭据提交到 git。幸运的是,Docker Compose 为我们提供了一种传递现有环境变量值的好方法。我们需要做的第一件事是从文件中删除值,docker-compose.yml
同时保留键:docker-compose.yml
version: "3"services: mysql: image: "mysql:5.7" environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: ports: - "3306:3306"
为了测试这一点,我们需要删除使用以下命令创建的 Docker Compose 容器docker-compose down
:
$ docker-compose downStopping docker-compose-example_mysql_1 ... doneRemoving docker-compose-example_mysql_1 ... doneRemoving network docker-compose-example_default
接下来,我们将在运行时在线定义环境变量docker-compose up
:
$ MYSQL_ROOT_PASSWORD=secret_password MYSQL_DATABASE=linuxacademy docker-compose up -dCreating network "docker-compose-example_default" with the default driverCreating docker-compose-example_mysql_1 ... done
我们不再在文件中设置这些值,但如果我们检查容器并 grepMYSQL_
环境变量,我们可以看到这些值已正确设置。注意:您可以使用以下方式找到容器的名称docker-compose ps
。这是我看到的:
$ docker inspect docker-compose-example_mysql_1 | grep MYSQL_ "MYSQL_ROOT_PASSWORD=secret_password", "MYSQL_DATABASE=linuxacademy", "MYSQL_MAJOR=5.7", "MYSQL_VERSION=5.7.25-1debian9"
编排容器
了解如何使用 Docker Compose 创建容器使我们非常接近能够编排多个容器。我们将按照相同的步骤创建与我们的mysql
密钥同一级别的另一个对象。在此示例中,让我们创建一个Ghost 博客容器,它将需要并连接到我们的mysql
服务:docker-compose.yml
version: "3"services: mysql: image: "mysql:5.7" environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: ports: - "3306:3306" blog: image: "ghost:2-alpine" ports: - "8080:2368" environment: DATABASE__CLIENT: mysql DATABASE__CONNECTION__HOST: mysql DATABASE__CONNECTION__USER: root DATABASE__CONNECTION__DATABASE: DATABASE__CONNECTION__PASSWORD: depends_on: - mysql
这里要注意的重点是服务depends_on
中的密钥blog
。通过指定它,我们告诉 Docker Composemysql
服务需要在服务之前启动,blog
因为blog
服务需要它才能运行。此外,当我们为博客配置数据库连接时,我们将数据库的“主机”指定为mysql
。这看起来很奇怪,但在 Docker Compose 为我们的容器创建的内部网络上,mysql
其他容器(即我们的blog
容器)可以使用完全限定域名 (FQDN)访问该容器mysql
。我们已经在mysql
运行容器,但我们仍然可以运行docker-compose up
,它将运行我们的附加容器:
$ MYSQL_ROOT_PASSWORD=secret_password MYSQL_DATABASE=linuxacademy DATABASE__CONNECTION__PASSWORD=secret_password DATABASE__CONNECTION__DATABASE=linuxacademy docker-compose up -dPulling blog (ghost:2-alpine)...2-alpine: Pulling from library/ghost169185f82c45: Pull complete62154f231947: Pull completeacf10a8404b6: Pull complete111312b8db58: Pull complete5a8b3dd4622e: Pull complete77aff150715c: Pull complete46a1198e6d9b: Pull completed94cdfbec967: Pull complete0007942647d7: Pull completeRecreating docker-compose-example_mysql_1 ... doneCreating docker-compose-example_blog_1 ... done
现在我们可以通过端口连接到 Docker 主机的 IP 地址来访问我们的博客8080
。
创建卷
我们最后要看的是如何通过安装一个卷来改进我们为博客存储数据的方式,以便数据库写入。此更改将允许我们在删除容器时保留数据mysql
。Docker Compose 使这变得简单,因为它将卷和网络视为顶级对象,就像“服务”一样。让我们创建一个名为的卷db-data
并将其安装在我们的容器中mysql
:docker-compose.yml
version: "3"volumes: db-data: external: falseservices: mysql: image: "mysql:5.7" environment: MYSQL_ROOT_PASSWORD: MYSQL_DATABASE: ports: - "3306:3306" volumes: - "db-data:/var/lib/mysql" blog: image: "ghost:2-alpine" ports: - "8080:2368" environment: DATABASE__CLIENT: mysql DATABASE__CONNECTION__HOST: mysql DATABASE__CONNECTION__USER: root DATABASE__CONNECTION__DATABASE: DATABASE__CONNECTION__PASSWORD: depends_on: - mysql
这对我们来说非常有用,它将为我们创建卷。该external: false
设置告诉 Docker Compose,我们没有在 Docker Compose 的“外部”自行创建卷。为了让我们的mysql
服务使用它,我们需要创建一个新容器。一个简单的方法是运行docker-compose down
:
$ docker-compose downStopping docker-compose-example_blog_1 ... doneStopping docker-compose-example_mysql_1 ... doneRemoving docker-compose-example_blog_1 ... doneRemoving docker-compose-example_mysql_1 ... doneRemoving network docker-compose-example_default
现在我们可以重新创建容器,以便将数据写入卷。
$ MYSQL_ROOT_PASSWORD=secret_password MYSQL_DATABASE=linuxacademy DATABASE__CONNECTION__PASSWORD=secret_password DATABASE__CONNECTION__DATABASE=linuxacademy docker-compose up -dCreating network "docker-compose-example_default" with the default driverCreating docker-compose-example_mysql_1 ... doneCreating docker-compose-example_blog_1 ... done
深入研究 Docker
Docker Compose 非常棒,尤其是作为 Docker 入门和使用Docker Swarm或 Kubernetes 等更复杂系统之间的过渡。如果您认为自己已准备好迈出下一步,或者只是想了解更多信息,我鼓励您查看以下课程:其他资源:
请先 登录后发表评论 ~