条件化 Docker Compose 的绑定安装卷

Conditionalizing bind mounted volumes for Docker Compose

请注意: 我的问题提到了 MySQL,但它本质上是一个 Docker/Docker Compose 音量管理问题,因此应该可以回答任何在该领域具有良好经验的人,无论他们对 MySQL.

的熟悉程度如何

我的 理解 是 Docker 化 MySQL 容器,当从如下 Docker Compose 文件中定义时,将是 ephemeral,这意味着它们将所有数据存储在容器本身(没有绑定挂载等),因此当容器死亡时,数据也会消失:

version: "3.7"
services:
  my-service-db:
    image: mysql:8
    container_name: $MY_SERVICE_DB_HOST
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - $MY_SERVICE_DB_PORT:$MY_SERVICE_DB_PORT
    environment:
      MYSQL_ROOT_PASSWORD: $MY_SERVICE_DB_ROOT_PASSWORD
      MYSQL_DATABASE: my_service_db_$MY_ENV
      MYSQL_USER: $MY_SERVICE_DB_APP_USER
      MYSQL_PASSWORD: $MY_SERVICE_DB_APP_PASSWORD
  other-service-definitions-omitted-for-brevity:
    - etc.

首先,如果那个理解不正确,请先纠正我!假设它或多或少是正确的...

我们称其为临时模式

但是通过为该服务定义提供一个绑定安装卷,我们可以指定一个外部位置来存储数据,因此数据将在服务 运行 中持续存在(组成 ups/downs):

version: "3.7"
services:
  my-service-db:
    image: mysql:8
    container_name: $MY_SERVICE_DB_HOST
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - $MY_SERVICE_DB_PORT:$MY_SERVICE_DB_PORT
    environment:
      MYSQL_ROOT_PASSWORD: $MY_SERVICE_DB_ROOT_PASSWORD
      MYSQL_DATABASE: my_service_db_$MY_ENV
      MYSQL_USER: $MY_SERVICE_DB_APP_USER
      MYSQL_PASSWORD: $MY_SERVICE_DB_APP_PASSWORD
    volumes:
      - ./my-service-db-data:/var/lib/mysql
  other-service-definitions-omitted-for-brevity:
    - etc.

我们称之为 持久模式

有时我想 运行 我的 Docker 在 临时模式 中编写文件,而其他时候, 运行 它持久模式.

是否有可能以某种方式使 volumes 定义(在 Docker Compose 文件内)成为条件?所以有时我可以 运行 docker-compose up -d <SPECIFY_EPHEMERAL_MODE_SOMEHOW>,有时我可以 运行 docker-compose up -d <SPECIFY_PERSISTENT_MODE_SOMEHOW>?

您可以让 multiple Compose files 一起工作,其中您有一些基础文件,然后是扩展基础文件中定义的其他文件。

无需额外设置,Compose 会在主要 docker-compose.yml 旁边查找 docker-compose.override.yml。由于“临时”和“持久”模式之间的唯一区别是 volumes: 声明,您可以拥有一个仅包含以下内容的覆盖文件:

# docker-compose.override.yml
version: '3.8'
services:
  my-service-db:  # matches main docker-compose.yml
    volumes:      # added to base definition
      - ./my-service-db-data:/var/lib/mysql

您还可以使用此技术将实际的数据库凭据和端口发布从主文件移到特定于部署的配置中。将它用于需要在生产中 运行 已知 Docker 图像但在开发中构建它的设置,以及用于使用主机目录覆盖容器内容的设置。

如果您希望文件以其他名称命名,您可以,但您需要在每次 运行 撰写时始终提供 docker-compose -f 选项或设置 COMPOSE_FILE environment variable

docker-compose -f docker-compose.yml -f docker-compose.persistence.yml up -d
docker-compose -f docker-compose.yml -f docker-compose.persistence.yml ps
docker-compose -f docker-compose.yml -f docker-compose.persistence.yml logs app

# Slightly easier (Linux syntax):
export COMPOSE_FILE=docker-compose.yml:docker-compose.persistence.yml
docker-compose up -d

从哲学上讲,您的应用程序的数据需要保存在某处。对于应用程序容器,一个好的做法是让它们完全无状态(它们不挂载 volumes:)并将它们的所有数据推送到数据库中。这意味着数据库需要持久化数据,否则在数据库重启时数据会丢失。

IME 主动希望数据库丢失数据有点不寻常。如果可以直接创建带有种子数据的数据库图像,这会更有趣,但标准图像的构建方式使得这很困难。在测试环境中,我仍然可以看到想要它。

构建 运行 位于 Docker 但使用外部数据库的应用程序实际上是可能的,也是合理的。例如,您可能 运行 在云环境中工作,并且您的云提供商提供稍微昂贵的托管数据库服务,该服务可提供自动快照和故障转移;您可以将生产应用程序配置为使用此托管数据库,并且根本不在容器中保留任何数据。