用于多环境本地开发的 Docker

Posted

技术标签:

【中文标题】用于多环境本地开发的 Docker【英文标题】:Docker for local development with multiple environment 【发布时间】:2021-01-21 23:39:03 【问题描述】:

我正在寻找使用 docker 来模拟我们当前云环境的最低限度。我们有大约 10 个服务(每个都有你自己的 mysql8 数据库、redis、php-fpm 和 nginx)。目前他们每个存储库都有一个docker-compose.yml,但是如果我想测试一个服务需要与另一个服务通信的功能,我不走运。

我的第一种方法是为每个服务创建一个Dockerfile(并使用新的docker-compose.yml一起运行),使用Debian,但我没有走得太远,能够安装nginx,(@ 987654328@ 和依赖项),但是当我进入数据库时​​,它变得很奇怪,我觉得这不是正确的做法。

有没有办法从服务中“包含”每个docker-compose.yml docker-compose.yml? 有更好的方法吗?还是我应该继续使用Dockerfile 并使用docker-compose 在同一个网络上运行它们?

【问题讨论】:

您可以使用external networks配置docker-compose,即用网络A创建项目A然后创建项目B并使用它自己的网络+项目A创建的外部网络。来自项目B的服务配置了外网的可以和项目A中运行的服务进行通信。 如果您确实想在同一个网络中启动所有服务(假设它们都使用默认网络进行配置),那么您可以使用 -f command-line option 或 COMPOSE_FILE 环境变量来包含来自所有 docker-compose.yml 文件的服务,即:COMPOSE_FILE=docker-compose.a.yml:docker-compose.b.yml docker-compose up -d 但是注意如果多个项目指定相同的服务,这将作为覆盖。 【参考方案1】:

TL;DR;

您可以使用external networks 配置docker-compose 以与来自其他项目的服务进行通信,或者(取决于您的项目)使用-f command-line option / COMPOSE_FILE environment variable 指定撰写文件的路径并将所有同一网络内的服务。


使用外部网络

鉴于以下tree 与项目ab

.
├── a
│   └── docker-compose.yml
└── b
    └── docker-compose.yml

项目adocker-compose 设置默认网络的名称:

version: '3.7'
services:
  nginx:
    image: 'nginx'
    container_name: 'nginx_a'
    expose:
    - '80'
networks:
  default:
    name: 'net_a'

并且项目b被配置为使用命名网络net_b和预先存在的net_a外部网络:

version: '3.7'
services:
  nginx:
    image: 'nginx'
    container_name: 'nginx_b'
    expose:
    - '80'
    networks:
    - 'net_a'
    - 'default'
networks:
  default:
    name: 'net_b'
  net_a:
    external: true

...exec'ing 进入nginx_b 容器我们可以到达nginx_a 容器:

注意:这是一个极简主义的例子。外部网络必须存在,然后才能尝试启动配置有预先存在的网络的环境。而不是修改现有项目docker-compose.yml,我建议使用overrides。

配置使nginx_b 容器在两个网络中都有立足之地:

使用-f 命令行选项

使用-f 命令行选项作为替代。它不适用于上述撰写文件,因为两者都指定了 nginx 服务(docker-compose 将覆盖/合并第一个 nginx 服务与第二个服务)。

对项目a使用修改后的docker-compose.yml

version: '3.7'
services:
  nginx_a:
    container_name: 'nginx_a'
    image: 'nginx'
    expose:
    - '80'

...对于项目b

version: '3.7'
services:
  nginx_b:
    image: 'nginx'
    container_name: 'nginx_b'
    expose:
    - '80'

...我们可以将两个环境放在同一个网络中:docker-compose -f a/docker-compose.yml:b/docker-compose.yml up -d:

【讨论】:

感谢您的回复。我决定使用 -f 方法。我发现的唯一问题是服务 A 的 mysql 与服务 B 的 MySQL 崩溃。带有错误消息:Unable to lock ./ibdata1 error: 11 两个服务是否使用相同的命名卷(?)看起来像在这种情况下,第一个实例正确启动,第二个实例(安装相同的卷)无法获得由持有的锁第一次服务。 您使用的是来自本地文件系统的绑定挂载,而不是命名卷。您可以更新每个数据库服务的卷映射以使用命名卷或使用主机上的不同路径。即,将./env/mysql/data:/var/lib/mysql 替换为./db_a/mysql/data:/var/lib/mysql 用于其中一项服务和./db_b/mysql/data:/var/lib/mysql,这样服务就不会尝试挂载同一目录。 是的,但路径 ./env/mysql/data 与运行 docker-compose up 的位置相关(我需要仔细检查)。不过这个想法是存在的,只要这些服务没有安装相同的数量,你就应该是好的。 我刚刚运行了几个测试,路径 ./env/mysql/data 是相对于第一个 docker-compose.yml 文件位置(通过 -f 参数传递),给我错误:build path ...\service_a\service_b\.. either does not exist, is not accessible, or is not a valid URL跨度>

以上是关于用于多环境本地开发的 Docker的主要内容,如果未能解决你的问题,请参考以下文章

在PhpStrom中配置Docker作为本地开发环境

如何基于 docker compose 和 testcontainers 设置 Spring Boot 的本地开发环境属性?

高级工具推荐|使用 Docker 搭建 Laravel 本地环境

面面观 | docker下开发,修改环境变量启动jetty

如何使用Docker构建开发环境

Docker 三剑客之Docker Compose详解