条件化 Docker Compose 的绑定挂载卷

时间:2021-02-04 02:30:38

标签: docker docker-compose docker-volume

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


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

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.

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

我们称之为临时模式

但是通过为该服务定义提供绑定安装卷,我们可以指定一个外部位置来存储数据,因此数据将在服务运行期间保持不变(组合起起伏伏):

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 Compose 文件,而在其他时候,我想在持久模式下运行它。

是否可以以某种方式使 volumes 定义(在 Docker Compose 文件中)有条件?这样有时我可以跑 docker-compose up -d <SPECIFY_EPHEMERAL_MODE_SOMEHOW>,有时我可以跑 docker-compose up -d <SPECIFY_PERSISTENT_MODE_SOMEHOW>

1 个答案:

答案 0 :(得分:1)

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

无需额外设置,Compose 会在主 docker-compose.override.yml 旁边寻找 docker-compose.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 时设置 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 中运行但使用外部数据库的应用程序实际上是可能且合理的。例如,也许您在云环境中运行,并且您的云提供商有一个稍微昂贵的托管数据库服务,可以提供自动快照和故障转移;您可以将生产应用程序配置为使用此托管数据库,并且在容器中完全不保留任何数据。